packages feed

ghc-lib 9.8.5.20250214 → 9.10.1.20240511

raw patch · 335 files changed

+24201/−16880 lines, 335 filesdep ~basedep ~deepseqdep ~ghc-lib-parserPVP ok

version bump matches the API change (PVP)

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

API changes (from Hackage documentation)

- GHC: Opt_LlvmTBAA :: GeneralFlag
- GHC: [rtasmInfo] :: DynFlags -> IORef (Maybe CompilerInfo)
- GHC: [rtccInfo] :: DynFlags -> IORef (Maybe CompilerInfo)
- GHC: [rtldInfo] :: DynFlags -> IORef (Maybe LinkerInfo)
- GHC.Builtin.Names.TH: appE_RDR :: RdrName
- GHC.Builtin.Names.TH: charPrimL_RDR :: RdrName
- GHC.Builtin.Names.TH: conE_RDR :: RdrName
- GHC.Builtin.Names.TH: doublePrimL_RDR :: RdrName
- GHC.Builtin.Names.TH: floatPrimL_RDR :: RdrName
- GHC.Builtin.Names.TH: infixApp_RDR :: RdrName
- GHC.Builtin.Names.TH: infixLDIdKey :: Unique
- GHC.Builtin.Names.TH: infixLDName :: Name
- GHC.Builtin.Names.TH: infixNDIdKey :: Unique
- GHC.Builtin.Names.TH: infixNDName :: Name
- GHC.Builtin.Names.TH: infixRDIdKey :: Unique
- GHC.Builtin.Names.TH: infixRDName :: Name
- GHC.Builtin.Names.TH: intPrimL_RDR :: RdrName
- GHC.Builtin.Names.TH: litE_RDR :: RdrName
- GHC.Builtin.Names.TH: mkNameG_dRDR :: RdrName
- GHC.Builtin.Names.TH: mkNameG_fldRDR :: RdrName
- GHC.Builtin.Names.TH: mkNameG_vRDR :: RdrName
- GHC.Builtin.Names.TH: stringL_RDR :: RdrName
- GHC.Builtin.Names.TH: stringPrimL_RDR :: RdrName
- GHC.Builtin.Names.TH: wordPrimL_RDR :: RdrName
- GHC.CmmToAsm: instance GHC.Base.Applicative GHC.CmmToAsm.CmmOptM
- GHC.CmmToAsm: instance GHC.Base.Functor GHC.CmmToAsm.CmmOptM
- GHC.CmmToAsm: instance GHC.Base.Monad GHC.CmmToAsm.CmmOptM
- GHC.CmmToAsm: instance GHC.CmmToAsm.PIC.CmmMakeDynamicReferenceM GHC.CmmToAsm.CmmOptM
- GHC.CmmToAsm.AArch64.Instr: ANDS :: Operand -> Operand -> Operand -> Instr
- GHC.CmmToAsm.AArch64.Instr: BIC :: Operand -> Operand -> Operand -> Instr
- GHC.CmmToAsm.AArch64.Instr: BICS :: Operand -> Operand -> Operand -> Instr
- GHC.CmmToAsm.AArch64.Instr: CMN :: Operand -> Operand -> Instr
- GHC.CmmToAsm.AArch64.Instr: DMBSY :: Instr
- GHC.CmmToAsm.AArch64.Instr: EON :: Operand -> Operand -> Operand -> Instr
- GHC.CmmToAsm.AArch64.Instr: LDATA :: Section -> RawCmmStatics -> Instr
- GHC.CmmToAsm.AArch64.Instr: LDP :: Format -> Operand -> Operand -> Operand -> Instr
- GHC.CmmToAsm.AArch64.Instr: ORN :: Operand -> Operand -> Operand -> Instr
- GHC.CmmToAsm.AArch64.Instr: ROR :: Operand -> Operand -> Operand -> Instr
- GHC.CmmToAsm.AArch64.Instr: STP :: Format -> Operand -> Operand -> Operand -> Instr
- GHC.CmmToAsm.AArch64.Instr: TST :: Operand -> Operand -> Instr
- GHC.CmmToAsm.AArch64.Instr: canFallthroughTo :: Instr -> BlockId -> Bool
- GHC.CmmToAsm.Instr: canFallthroughTo :: Instruction instr => instr -> BlockId -> Bool
- GHC.CmmToAsm.PPC.Instr: canFallthroughTo :: Instr -> BlockId -> Bool
- GHC.CmmToAsm.X86.Instr: canFallthroughTo :: Instr -> BlockId -> Bool
- GHC.Core.LateCC: Env :: !Module -> !Bool -> !CostCentreState -> !Bool -> Env
- GHC.Core.LateCC: [ccState] :: Env -> !CostCentreState
- GHC.Core.LateCC: [collectCCs] :: Env -> !Bool
- GHC.Core.LateCC: [countEntries] :: Env -> !Bool
- GHC.Core.LateCC: [thisModule] :: Env -> !Module
- GHC.Core.LateCC: addLateCostCentres :: Env -> CoreProgram -> (CoreProgram, Set CostCentre)
- GHC.Core.LateCC: addLateCostCentresMG :: ModGuts -> CoreM ModGuts
- GHC.Core.LateCC: addLateCostCentresPgm :: DynFlags -> Logger -> Module -> CoreProgram -> IO (CoreProgram, Set CostCentre)
- GHC.Core.LateCC: data Env
- GHC.CoreToStg.Prep: instance GHC.Utils.Outputable.Outputable GHC.CoreToStg.Prep.OkToSpec
- GHC.Data.Graph.Inductive.Graph: instance GHC.Read.Read (gr a b) => GHC.Read.Read (GHC.Data.Graph.Inductive.Graph.OrdGr gr a b)
- GHC.Data.Graph.Inductive.Graph: instance GHC.Show.Show (gr a b) => GHC.Show.Show (GHC.Data.Graph.Inductive.Graph.OrdGr gr a b)
- GHC.Driver.Pipeline.Execute: applyAssemblerProg :: DefunctionalizedAssemblerProg -> Logger -> DynFlags -> Platform -> [Option] -> IO ()
- GHC.HsToCore.Monad: EqnInfo :: [Pat GhcTc] -> Origin -> MatchResult CoreExpr -> EquationInfo
- GHC.HsToCore.Monad: [eqn_orig] :: EquationInfo -> Origin
- GHC.HsToCore.Monad: [eqn_pats] :: EquationInfo -> [Pat GhcTc]
- GHC.HsToCore.Monad: [eqn_rhs] :: EquationInfo -> MatchResult CoreExpr
- GHC.HsToCore.Utils: EqnInfo :: [Pat GhcTc] -> Origin -> MatchResult CoreExpr -> EquationInfo
- GHC.HsToCore.Utils: [eqn_orig] :: EquationInfo -> Origin
- GHC.HsToCore.Utils: [eqn_pats] :: EquationInfo -> [Pat GhcTc]
- GHC.HsToCore.Utils: [eqn_rhs] :: EquationInfo -> MatchResult CoreExpr
- GHC.Iface.Ext.Ast: instance (GHC.Iface.Ext.Ast.HasLoc a, GHC.Iface.Ext.Ast.HiePass p) => GHC.Iface.Ext.Ast.HasLoc (Language.Haskell.Syntax.Decls.FamEqn (GHC.Hs.Extension.GhcPass p) a)
- GHC.Iface.Ext.Ast: instance (GHC.Iface.Ext.Ast.HasLoc tm, GHC.Iface.Ext.Ast.HasLoc ty) => GHC.Iface.Ext.Ast.HasLoc (Language.Haskell.Syntax.Type.HsArg p tm ty)
- GHC.Iface.Ext.Ast: instance (GHC.Iface.Ext.Ast.ToHie (GHC.Iface.Ext.Ast.RFContext label), GHC.Iface.Ext.Ast.ToHie arg, GHC.Iface.Ext.Ast.HasLoc arg, Data.Data.Data arg, Data.Data.Data label) => GHC.Iface.Ext.Ast.ToHie (GHC.Iface.Ext.Ast.RContext (GHC.Parser.Annotation.LocatedA (Language.Haskell.Syntax.Pat.HsFieldBind label arg)))
- GHC.Iface.Ext.Ast: instance (GHC.Iface.Ext.Ast.ToHie arg, GHC.Iface.Ext.Ast.HasLoc arg, Data.Data.Data arg, GHC.Iface.Ext.Ast.HiePass p) => GHC.Iface.Ext.Ast.ToHie (GHC.Iface.Ext.Ast.RContext (Language.Haskell.Syntax.Pat.HsRecFields (GHC.Hs.Extension.GhcPass p) arg))
- GHC.Iface.Ext.Ast: instance (GHC.Iface.Ext.Ast.ToHie rhs, GHC.Iface.Ext.Ast.HasLoc rhs) => GHC.Iface.Ext.Ast.ToHie (Language.Haskell.Syntax.Decls.FamEqn GHC.Hs.Extension.GhcRn rhs)
- GHC.Iface.Ext.Ast: instance (GHC.Iface.Ext.Ast.ToHie tm, GHC.Iface.Ext.Ast.ToHie ty) => GHC.Iface.Ext.Ast.ToHie (Language.Haskell.Syntax.Type.HsArg p tm ty)
- GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.HasLoc (GHC.Parser.Annotation.LocatedA a)
- GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.HasLoc (GHC.Parser.Annotation.LocatedN a)
- GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.HasLoc (GHC.Types.SrcLoc.Located a)
- GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.HasLoc (Language.Haskell.Syntax.Decls.HsDataDefn GHC.Hs.Extension.GhcRn)
- GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.HasLoc a => GHC.Iface.Ext.Ast.HasLoc (Language.Haskell.Syntax.Decls.DataDefnCons a)
- GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.HasLoc a => GHC.Iface.Ext.Ast.HasLoc [a]
- GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.HasLoc thing => GHC.Iface.Ext.Ast.HasLoc (GHC.Iface.Ext.Ast.PScoped thing)
- GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.HiePass p => GHC.Iface.Ext.Ast.ToHie (GHC.Iface.Ext.Ast.RFContext (GHC.Parser.Annotation.LocatedAn GHC.Parser.Annotation.NoEpAnns (Language.Haskell.Syntax.Type.AmbiguousFieldOcc (GHC.Hs.Extension.GhcPass p))))
- GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.HiePass p => GHC.Iface.Ext.Ast.ToHie (GHC.Iface.Ext.Ast.RFContext (GHC.Parser.Annotation.LocatedAn GHC.Parser.Annotation.NoEpAnns (Language.Haskell.Syntax.Type.FieldOcc (GHC.Hs.Extension.GhcPass p))))
- GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.HiePass p => GHC.Iface.Ext.Ast.ToHie (Language.Haskell.Syntax.Expr.HsMatchContext (GHC.Hs.Extension.GhcPass p))
- GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.HiePass p => GHC.Iface.Ext.Ast.ToHie (Language.Haskell.Syntax.Expr.HsStmtContext (GHC.Hs.Extension.GhcPass p))
- GHC.Iface.Ext.Utils: mkLScope :: Located a -> Scope
- GHC.Iface.Ext.Utils: mkLScopeA :: GenLocated (SrcSpanAnn' a) e -> Scope
- GHC.Iface.Ext.Utils: mkLScopeN :: LocatedN a -> Scope
- GHC.Iface.Ext.Utils: mkScopeA :: SrcSpanAnn' ann -> Scope
- GHC.Linker.Config: FrameworkOpts :: [String] -> [String] -> FrameworkOpts
- GHC.Linker.Config: [foCmdlineFrameworks] :: FrameworkOpts -> [String]
- GHC.Linker.Config: [foFrameworkPaths] :: FrameworkOpts -> [String]
- GHC.Linker.Config: data FrameworkOpts
- GHC.Linker.ExtraObj: getCompilerInfo :: Logger -> DynFlags -> IO CompilerInfo
- GHC.Plugins: argsHaveFixedRuntimeRep :: Type -> Bool
- GHC.Plugins: extendTvSubstBinderAndInScope :: Subst -> PiTyBinder -> Type -> Subst
- GHC.Plugins: isJoinId_maybe :: Var -> Maybe JoinArity
- GHC.Plugins: lcSubst :: LiftingContext -> Subst
- GHC.Plugins: mkForAllCos :: [(TyCoVar, CoercionN)] -> Coercion -> Coercion
- GHC.Plugins: mkHomoForAllMCo :: TyCoVar -> MCoercion -> MCoercion
- GHC.Plugins: mkSubst :: InScopeSet -> TvSubstEnv -> CvSubstEnv -> IdSubstEnv -> Subst
- GHC.Plugins: type OccSet = FastStringEnv UniqSet NameSpace
- GHC.Rename.Bind: type MiniFixityEnv = FastStringEnv (Located Fixity)
- GHC.Rename.Expr: mkExpandedExpr :: HsExpr GhcRn -> HsExpr GhcRn -> HsExpr GhcRn
- GHC.Rename.Fixity: type MiniFixityEnv = FastStringEnv (Located Fixity)
- GHC.Rename.HsType: rnHsPatSigTypeBindingVars :: HsDocContext -> HsPatSigType GhcPs -> (HsPatSigType GhcRn -> RnM (r, FreeVars)) -> RnM (r, FreeVars)
- GHC.Rename.Utils: isIrrefutableHsPatRn :: forall p. OutputableBndrId p => DynFlags -> LPat (GhcPass p) -> Bool
- GHC.Rename.Utils: warnForallIdentifier :: LocatedN RdrName -> RnM ()
- GHC.Runtime.Interpreter: [LookupSymbolInDLL] :: RemotePtr LoadedDLL -> String -> Message (Maybe (RemotePtr ()))
- GHC.Runtime.Interpreter: lookupSymbolInDLL :: Interp -> RemotePtr LoadedDLL -> FastString -> IO (Maybe (Ptr ()))
- GHC.Runtime.Interpreter.Process: [LookupSymbolInDLL] :: RemotePtr LoadedDLL -> String -> Message (Maybe (RemotePtr ()))
- GHC.StgToCmm.Closure: argPrimRep :: StgArg -> PrimRep
- GHC.StgToCmm.Closure: idPrimRep :: Id -> PrimRep
- GHC.StgToCmm.Closure: isVoidRep :: PrimRep -> Bool
- GHC.StgToCmm.Prof: ldvRecordCreate :: CmmExpr -> FCode ()
- GHC.StgToJS.ExprCtx: ctxAssertEvaluated :: Id -> ExprCtx -> ExprCtx
- GHC.StgToJS.ExprCtx: ctxEvaluatedIds :: ExprCtx -> UniqSet Id
- GHC.StgToJS.FFI: saturateFFI :: Int -> JStat -> JStat
- GHC.StgToJS.Linker.Linker: [lkp_extra_js] :: LinkPlan -> Set FilePath
- GHC.StgToJS.Linker.Linker: [lks_extra_js] :: LinkSpec -> [FilePath]
- GHC.StgToJS.Linker.Linker: [lks_obj_files] :: LinkSpec -> [LinkedObj]
- GHC.StgToJS.Linker.Utils: CPP :: JSOption
- GHC.StgToJS.Linker.Utils: data JSOption
- GHC.StgToJS.Linker.Utils: getOptionsFromJsFile :: FilePath -> IO [JSOption]
- GHC.StgToJS.Linker.Utils: instance GHC.Classes.Eq GHC.StgToJS.Linker.Utils.JSOption
- GHC.StgToJS.Linker.Utils: instance GHC.Classes.Ord GHC.StgToJS.Linker.Utils.JSOption
- GHC.StgToJS.Utils: NoSlot :: SlotCount
- GHC.StgToJS.Utils: OneSlot :: SlotCount
- GHC.StgToJS.Utils: TwoSlots :: SlotCount
- GHC.StgToJS.Utils: altRefs :: UniqFM Id CgStgExpr -> CgStgAlt -> Set Id
- GHC.StgToJS.Utils: argRefs :: UniqFM Id CgStgExpr -> StgArg -> Set Id
- GHC.StgToJS.Utils: argVt :: StgArg -> VarType
- GHC.StgToJS.Utils: assignToTypedExprs :: [TypedExpr] -> [JExpr] -> JStat
- GHC.StgToJS.Utils: assocIdPrimReps :: Id -> [JExpr] -> [(PrimRep, [JExpr])]
- GHC.StgToJS.Utils: assocPrimReps :: [PrimRep] -> [JExpr] -> [(PrimRep, [JExpr])]
- GHC.StgToJS.Utils: bindees :: CgStgBinding -> [Id]
- GHC.StgToJS.Utils: bindingRefs :: UniqFM Id CgStgExpr -> CgStgBinding -> Set Id
- GHC.StgToJS.Utils: data SlotCount
- GHC.StgToJS.Utils: dataConType :: DataCon -> Type
- GHC.StgToJS.Utils: idPrimReps :: Id -> [PrimRep]
- GHC.StgToJS.Utils: idVt :: HasDebugCallStack => Id -> [VarType]
- GHC.StgToJS.Utils: inspectInlineBinding :: UniqSet Id -> CgStgBinding -> UniqSet Id
- GHC.StgToJS.Utils: inspectInlineRhs :: UniqSet Id -> Id -> CgStgRhs -> UniqSet Id
- GHC.StgToJS.Utils: isInlineApp :: UniqSet Id -> Id -> [StgArg] -> Bool
- GHC.StgToJS.Utils: isInlineForeignCall :: ForeignCall -> Bool
- GHC.StgToJS.Utils: isMatchable :: [VarType] -> Bool
- GHC.StgToJS.Utils: isPtr :: VarType -> Bool
- GHC.StgToJS.Utils: isSingleVar :: VarType -> Bool
- GHC.StgToJS.Utils: kindPrimRep' :: HasDebugCallStack => SDoc -> Kind -> [PrimRep]
- GHC.StgToJS.Utils: primRepVt :: HasDebugCallStack => PrimRep -> VarType
- GHC.StgToJS.Utils: primTypeVt :: HasDebugCallStack => Type -> VarType
- GHC.StgToJS.Utils: removeTick :: CgStgExpr -> CgStgExpr
- GHC.StgToJS.Utils: rhsRefs :: UniqFM Id CgStgExpr -> CgStgRhs -> Set Id
- GHC.StgToJS.Utils: stgAltLive :: CgStgAlt -> LiveVars
- GHC.StgToJS.Utils: stgArgLive :: StgArg -> LiveVars
- GHC.StgToJS.Utils: stgBindLive :: CgStgBinding -> [(Id, LiveVars)]
- GHC.StgToJS.Utils: stgBindRhsLive :: CgStgBinding -> LiveVars
- GHC.StgToJS.Utils: stgLetNoEscapeLive :: Bool -> StgBinding -> StgExpr -> LiveVars
- GHC.StgToJS.Utils: stgLneLive :: CgStgBinding -> [Id]
- GHC.StgToJS.Utils: stgTopBindLive :: CgStgTopBinding -> [(Id, LiveVars)]
- GHC.StgToJS.Utils: toTypeList :: [VarType] -> [Int]
- GHC.StgToJS.Utils: tyConPrimRep' :: HasDebugCallStack => TyCon -> [PrimRep]
- GHC.StgToJS.Utils: tyConVt :: HasDebugCallStack => TyCon -> [VarType]
- GHC.StgToJS.Utils: typePrimRep' :: HasDebugCallStack => UnaryType -> [PrimRep]
- GHC.StgToJS.Utils: typePrimReps :: Type -> [PrimRep]
- GHC.StgToJS.Utils: typeVt :: HasDebugCallStack => Type -> [VarType]
- GHC.StgToJS.Utils: uTypeVt :: HasDebugCallStack => UnaryType -> VarType
- GHC.StgToJS.Utils: varSlotCount :: VarType -> SlotCount
- GHC.SysTools.Cpp: [cppUseCc] :: CppOpts -> !Bool
- GHC.SysTools.Info: getAssemblerInfo :: Logger -> DynFlags -> IO CompilerInfo
- GHC.SysTools.Info: getCompilerInfo :: Logger -> DynFlags -> IO CompilerInfo
- GHC.SysTools.Info: getCompilerInfo' :: Logger -> String -> IO CompilerInfo
- GHC.SysTools.Info: getLinkerInfo :: Logger -> DynFlags -> IO LinkerInfo
- GHC.SysTools.Info: getLinkerInfo' :: Logger -> DynFlags -> IO LinkerInfo
- GHC.SysTools.Info: neededLinkArgs :: LinkerInfo -> [Option]
- GHC.SysTools.Tasks: runClang :: Logger -> DynFlags -> [Option] -> IO ()
- GHC.SysTools.Tasks: runLink :: Logger -> TmpFs -> DynFlags -> [Option] -> IO ()
- GHC.SysTools.Tasks: touch :: Logger -> DynFlags -> String -> String -> IO ()
- GHC.Tc.Deriv.Generate: litConTbl :: [(Type, LHsExpr GhcPs -> LHsExpr GhcPs)]
- GHC.Tc.Gen.Head: [eva_at] :: HsExprArg (p :: TcPass) -> !LHsToken "@" GhcRn
- GHC.Tc.Gen.Head: countHsWrapperInvisArgs :: HsWrapper -> Arity
- GHC.Tc.Gen.Head: countLeadingValArgs :: [HsExprArg id] -> Int
- GHC.Tc.Gen.Head: countVisAndInvisValArgs :: [HsExprArg id] -> Arity
- GHC.Tc.Gen.Match: MC :: HsMatchContext GhcTc -> (LocatedA (body GhcRn) -> ExpRhoType -> TcM (LocatedA (body GhcTc))) -> TcMatchCtxt body
- GHC.Tc.Gen.Match: [mc_body] :: TcMatchCtxt body -> LocatedA (body GhcRn) -> ExpRhoType -> TcM (LocatedA (body GhcTc))
- GHC.Tc.Gen.Match: [mc_what] :: TcMatchCtxt body -> HsMatchContext GhcTc
- GHC.Tc.Gen.Match: data TcMatchCtxt body
- GHC.Tc.Gen.Match: tcGRHS :: TcMatchCtxt body -> ExpRhoType -> GRHS GhcRn (LocatedA (body GhcRn)) -> TcM (GRHS GhcTc (LocatedA (body GhcTc)))
- GHC.Tc.Gen.Match: tcMatchLambda :: ExpectedFunTyOrigin -> TcMatchCtxt HsExpr -> MatchGroup GhcRn (LHsExpr GhcRn) -> ExpRhoType -> TcM (HsWrapper, MatchGroup GhcTc (LHsExpr GhcTc))
- GHC.Tc.Gen.Match: tcMatchesCase :: AnnoBody body => TcMatchCtxt body -> Scaled TcSigmaTypeFRR -> MatchGroup GhcRn (LocatedA (body GhcRn)) -> ExpRhoType -> TcM (MatchGroup GhcTc (LocatedA (body GhcTc)))
- GHC.Tc.Gen.Match: tcMatchesFun :: LocatedN Name -> MatchGroup GhcRn (LHsExpr GhcRn) -> ExpRhoType -> TcM (HsWrapper, MatchGroup GhcTc (LHsExpr GhcTc))
- GHC.Tc.Gen.Pat: tcPats :: HsMatchContext GhcTc -> [LPat GhcRn] -> [Scaled ExpSigmaTypeFRR] -> TcM a -> TcM ([LPat GhcTc], a)
- GHC.Tc.Gen.Sig: CompleteSig :: TcId -> UserTypeCtxt -> SrcSpan -> TcIdSigInfo
- GHC.Tc.Gen.Sig: PartialSig :: Name -> LHsSigWcType GhcRn -> UserTypeCtxt -> SrcSpan -> TcIdSigInfo
- GHC.Tc.Gen.Sig: TPSI :: Name -> [InvisTVBinder] -> [InvisTVBinder] -> TcThetaType -> [InvisTVBinder] -> TcThetaType -> TcSigmaType -> TcPatSynInfo
- GHC.Tc.Gen.Sig: [patsig_body_ty] :: TcPatSynInfo -> TcSigmaType
- GHC.Tc.Gen.Sig: [patsig_ex_bndrs] :: TcPatSynInfo -> [InvisTVBinder]
- GHC.Tc.Gen.Sig: [patsig_implicit_bndrs] :: TcPatSynInfo -> [InvisTVBinder]
- GHC.Tc.Gen.Sig: [patsig_name] :: TcPatSynInfo -> Name
- GHC.Tc.Gen.Sig: [patsig_prov] :: TcPatSynInfo -> TcThetaType
- GHC.Tc.Gen.Sig: [patsig_req] :: TcPatSynInfo -> TcThetaType
- GHC.Tc.Gen.Sig: [patsig_univ_bndrs] :: TcPatSynInfo -> [InvisTVBinder]
- GHC.Tc.Gen.Sig: [psig_hs_ty] :: TcIdSigInfo -> LHsSigWcType GhcRn
- GHC.Tc.Gen.Sig: [psig_name] :: TcIdSigInfo -> Name
- GHC.Tc.Gen.Sig: [sig_bndr] :: TcIdSigInfo -> TcId
- GHC.Tc.Gen.Sig: [sig_ctxt] :: TcIdSigInfo -> UserTypeCtxt
- GHC.Tc.Gen.Sig: [sig_loc] :: TcIdSigInfo -> SrcSpan
- GHC.Tc.Gen.Sig: data () => TcIdSigInfo
- GHC.Tc.Gen.Sig: data () => TcIdSigInst
- GHC.Tc.Gen.Sig: data () => TcPatSynInfo
- GHC.Tc.Gen.Sig: tcIdSigName :: TcIdSigInfo -> Name
- GHC.Tc.Utils.Monad: addLocMA :: (a -> TcM b) -> GenLocated (SrcSpanAnn' ann) a -> TcM b
- GHC.Tc.Utils.Monad: wrapLocAM :: (a -> TcM b) -> LocatedAn an a -> TcM (Located b)
- GHC.Tc.Utils.TcMType: newPatSigTyVar :: Name -> Kind -> TcM TcTyVar
- GHC.Tc.Utils.Unify: matchActualFunTySigma :: ExpectedFunTyOrigin -> Maybe TypedThing -> (Arity, [Scaled TcSigmaType]) -> TcRhoType -> TcM (HsWrapper, Scaled TcSigmaTypeFRR, TcSigmaType)
- GHC.Tc.Utils.Unify: matchActualFunTysRho :: ExpectedFunTyOrigin -> CtOrigin -> Maybe TypedThing -> Arity -> TcSigmaType -> TcM (HsWrapper, [Scaled TcSigmaTypeFRR], TcRhoType)
- GHC.Tc.Utils.Unify: tcSkolemiseExpType :: UserTypeCtxt -> ExpSigmaType -> (ExpRhoType -> TcM result) -> TcM (HsWrapper, result)
- GHC.Tc.Utils.Unify: tcSkolemiseScoped :: UserTypeCtxt -> TcSigmaType -> (TcType -> TcM result) -> TcM (HsWrapper, result)
- GHC.Tc.Utils.Unify: tcTopSkolemise :: UserTypeCtxt -> TcSigmaType -> (TcType -> TcM result) -> TcM (HsWrapper, result)
- GHCi.BinaryArray: getArray :: (Binary i, Ix i, MArray IOUArray a IO) => Get (UArray i a)
- GHCi.BinaryArray: putArray :: Binary i => UArray i a -> Put
- GHCi.ResolvedBCO: ResolvedBCO :: Bool -> {-# UNPACK #-} !Int -> UArray Int Word16 -> UArray Int Word64 -> UArray Int Word64 -> SizedSeq ResolvedBCOPtr -> ResolvedBCO
- GHCi.ResolvedBCO: ResolvedBCOPtr :: {-# UNPACK #-} !RemoteRef HValue -> ResolvedBCOPtr
- GHCi.ResolvedBCO: ResolvedBCOPtrBCO :: ResolvedBCO -> ResolvedBCOPtr
- GHCi.ResolvedBCO: ResolvedBCOPtrBreakArray :: {-# UNPACK #-} !RemoteRef BreakArray -> ResolvedBCOPtr
- GHCi.ResolvedBCO: ResolvedBCORef :: {-# UNPACK #-} !Int -> ResolvedBCOPtr
- GHCi.ResolvedBCO: ResolvedBCOStaticPtr :: {-# UNPACK #-} !RemotePtr () -> ResolvedBCOPtr
- GHCi.ResolvedBCO: [resolvedBCOArity] :: ResolvedBCO -> {-# UNPACK #-} !Int
- GHCi.ResolvedBCO: [resolvedBCOBitmap] :: ResolvedBCO -> UArray Int Word64
- GHCi.ResolvedBCO: [resolvedBCOInstrs] :: ResolvedBCO -> UArray Int Word16
- GHCi.ResolvedBCO: [resolvedBCOIsLE] :: ResolvedBCO -> Bool
- GHCi.ResolvedBCO: [resolvedBCOLits] :: ResolvedBCO -> UArray Int Word64
- GHCi.ResolvedBCO: [resolvedBCOPtrs] :: ResolvedBCO -> SizedSeq ResolvedBCOPtr
- GHCi.ResolvedBCO: data ResolvedBCO
- GHCi.ResolvedBCO: data ResolvedBCOPtr
- GHCi.ResolvedBCO: instance Data.Binary.Class.Binary GHCi.ResolvedBCO.ResolvedBCO
- GHCi.ResolvedBCO: instance Data.Binary.Class.Binary GHCi.ResolvedBCO.ResolvedBCOPtr
- GHCi.ResolvedBCO: instance GHC.Generics.Generic GHCi.ResolvedBCO.ResolvedBCO
- GHCi.ResolvedBCO: instance GHC.Generics.Generic GHCi.ResolvedBCO.ResolvedBCOPtr
- GHCi.ResolvedBCO: instance GHC.Show.Show GHCi.ResolvedBCO.ResolvedBCO
- GHCi.ResolvedBCO: instance GHC.Show.Show GHCi.ResolvedBCO.ResolvedBCOPtr
- GHCi.ResolvedBCO: isLittleEndian :: Bool
+ GHC: Opt_DiagnosticsAsJSON :: GeneralFlag
+ GHC: Opt_DisableJsCsources :: GeneralFlag
+ GHC: Opt_DoCleverArgEtaExpansion :: GeneralFlag
+ GHC: Opt_KeepAutoRules :: GeneralFlag
+ GHC: Opt_OrigThunkInfo :: GeneralFlag
+ GHC: Opt_ProfLateOverloadedCcs :: GeneralFlag
+ GHC: Opt_ProfLateoverloadedCallsCCs :: GeneralFlag
+ GHC: [canUseErrorLinks] :: DynFlags -> Bool
+ GHC: [useErrorLinks] :: DynFlags -> OverridingBool
+ GHC.Builtin.Names.TH: dataNamespaceSpecifierDataConKey :: Unique
+ GHC.Builtin.Names.TH: dataNamespaceSpecifierDataConName :: Name
+ GHC.Builtin.Names.TH: infixLWithSpecDIdKey :: Unique
+ GHC.Builtin.Names.TH: infixLWithSpecDName :: Name
+ GHC.Builtin.Names.TH: infixNWithSpecDIdKey :: Unique
+ GHC.Builtin.Names.TH: infixNWithSpecDName :: Name
+ GHC.Builtin.Names.TH: infixRWithSpecDIdKey :: Unique
+ GHC.Builtin.Names.TH: infixRWithSpecDName :: Name
+ GHC.Builtin.Names.TH: invisPIdKey :: Unique
+ GHC.Builtin.Names.TH: invisPName :: Name
+ GHC.Builtin.Names.TH: noNamespaceSpecifierDataConKey :: Unique
+ GHC.Builtin.Names.TH: noNamespaceSpecifierDataConName :: Name
+ GHC.Builtin.Names.TH: pragSCCFunDKey :: Unique
+ GHC.Builtin.Names.TH: pragSCCFunDName :: Name
+ GHC.Builtin.Names.TH: pragSCCFunNamedDKey :: Unique
+ GHC.Builtin.Names.TH: pragSCCFunNamedDName :: Name
+ GHC.Builtin.Names.TH: typeEIdKey :: Unique
+ GHC.Builtin.Names.TH: typeEName :: Name
+ GHC.Builtin.Names.TH: typeNamespaceSpecifierDataConKey :: Unique
+ GHC.Builtin.Names.TH: typeNamespaceSpecifierDataConName :: Name
+ GHC.Builtin.Names.TH: typePIdKey :: Unique
+ GHC.Builtin.Names.TH: typePName :: Name
+ GHC.Cmm.GenericOpt: cmmToCmm :: NCGConfig -> RawCmmDecl -> (RawCmmDecl, [CLabel])
+ GHC.Cmm.GenericOpt: instance GHC.Base.Applicative GHC.Cmm.GenericOpt.CmmOptM
+ GHC.Cmm.GenericOpt: instance GHC.Base.Functor GHC.Cmm.GenericOpt.CmmOptM
+ GHC.Cmm.GenericOpt: instance GHC.Base.Monad GHC.Cmm.GenericOpt.CmmOptM
+ GHC.Cmm.GenericOpt: instance GHC.CmmToAsm.PIC.CmmMakeDynamicReferenceM GHC.Cmm.GenericOpt.CmmOptM
+ GHC.CmmToAsm.AArch64.Instr: DMBISH :: Instr
+ GHC.CmmToAsm.AArch64.Instr: MOVZ :: Operand -> Operand -> Instr
+ GHC.CmmToAsm.AArch64.Instr: reg_zero :: Reg
+ GHC.CmmToAsm.AArch64.Regs: fmtOfRealReg :: RealReg -> Format
+ GHC.CmmToAsm.X86.Instr: SHLD :: Format -> Operand -> Operand -> Operand -> Instr
+ GHC.CmmToAsm.X86.Instr: SHRD :: Format -> Operand -> Operand -> Operand -> Instr
+ GHC.CmmToLlvm.Version: LlvmVersion :: NonEmpty Int -> LlvmVersion
+ GHC.CmmToLlvm.Version: [llvmVersionNE] :: LlvmVersion -> NonEmpty Int
+ GHC.CmmToLlvm.Version: llvmVersionList :: LlvmVersion -> [Int]
+ GHC.CmmToLlvm.Version: llvmVersionStr :: LlvmVersion -> String
+ GHC.CmmToLlvm.Version: llvmVersionSupported :: LlvmVersion -> Bool
+ GHC.CmmToLlvm.Version: newtype () => LlvmVersion
+ GHC.CmmToLlvm.Version: parseLlvmVersion :: String -> Maybe LlvmVersion
+ GHC.CmmToLlvm.Version: supportedLlvmVersionLowerBound :: LlvmVersion
+ GHC.CmmToLlvm.Version: supportedLlvmVersionUpperBound :: LlvmVersion
+ GHC.CmmToLlvm.Version.Bounds: supportedLlvmVersionLowerBound :: LlvmVersion
+ GHC.CmmToLlvm.Version.Bounds: supportedLlvmVersionUpperBound :: LlvmVersion
+ GHC.Core.LateCC: addLateCostCenters :: Logger -> LateCCConfig -> CoreProgram -> IO (CoreProgram, LateCCState (Maybe SrcSpan))
+ GHC.Core.LateCC.OverloadedCalls: overloadedCallsCC :: CoreBind -> LateCCM OverloadedCallsCCState CoreBind
+ GHC.Core.LateCC.TopLevelBinds: topLevelBindsCC :: (CoreExpr -> Bool) -> CoreBind -> LateCCM s CoreBind
+ GHC.Core.LateCC.TopLevelBinds: topLevelBindsCCMG :: ModGuts -> CoreM ModGuts
+ GHC.Core.LateCC.Types: LateCCAllBinds :: LateCCBindSpec
+ GHC.Core.LateCC.Types: LateCCConfig :: !LateCCBindSpec -> !Bool -> !LateCCEnv -> LateCCConfig
+ GHC.Core.LateCC.Types: LateCCEnv :: !Module -> Maybe FastString -> !Bool -> !Bool -> LateCCEnv
+ GHC.Core.LateCC.Types: LateCCNone :: LateCCBindSpec
+ GHC.Core.LateCC.Types: LateCCOverloadedBinds :: LateCCBindSpec
+ GHC.Core.LateCC.Types: LateCCState :: !Set CostCentre -> !CostCentreState -> !s -> LateCCState s
+ GHC.Core.LateCC.Types: [lateCCConfig_env] :: LateCCConfig -> !LateCCEnv
+ GHC.Core.LateCC.Types: [lateCCConfig_overloadedCalls] :: LateCCConfig -> !Bool
+ GHC.Core.LateCC.Types: [lateCCConfig_whichBinds] :: LateCCConfig -> !LateCCBindSpec
+ GHC.Core.LateCC.Types: [lateCCEnv_collectCCs] :: LateCCEnv -> !Bool
+ GHC.Core.LateCC.Types: [lateCCEnv_countEntries] :: LateCCEnv -> !Bool
+ GHC.Core.LateCC.Types: [lateCCEnv_file] :: LateCCEnv -> Maybe FastString
+ GHC.Core.LateCC.Types: [lateCCEnv_module] :: LateCCEnv -> !Module
+ GHC.Core.LateCC.Types: [lateCCState_ccState] :: LateCCState s -> !CostCentreState
+ GHC.Core.LateCC.Types: [lateCCState_ccs] :: LateCCState s -> !Set CostCentre
+ GHC.Core.LateCC.Types: [lateCCState_extra] :: LateCCState s -> !s
+ GHC.Core.LateCC.Types: data LateCCBindSpec
+ GHC.Core.LateCC.Types: data LateCCConfig
+ GHC.Core.LateCC.Types: data LateCCEnv
+ GHC.Core.LateCC.Types: data LateCCState s
+ GHC.Core.LateCC.Types: initLateCCState :: s -> LateCCState s
+ GHC.Core.LateCC.Types: type LateCCM s = ReaderT LateCCEnv (State (LateCCState s))
+ GHC.Core.LateCC.Utils: doLateCostCenters :: LateCCEnv -> LateCCState s -> (CoreBind -> LateCCM s CoreBind) -> CoreProgram -> (CoreProgram, LateCCState s)
+ GHC.Core.LateCC.Utils: getCCFlavour :: FastString -> LateCCM s CCFlavour
+ GHC.Core.LateCC.Utils: insertCC :: FastString -> SrcSpan -> CoreExpr -> LateCCM s CoreExpr
+ GHC.CoreToStg.Prep: [cp_arityOpts] :: CorePrepConfig -> !Maybe ArityOpts
+ GHC.CoreToStg.Prep: instance GHC.Classes.Eq GHC.CoreToStg.Prep.BindInfo
+ GHC.CoreToStg.Prep: instance GHC.Classes.Eq GHC.CoreToStg.Prep.FloatInfo
+ GHC.CoreToStg.Prep: instance GHC.Utils.Outputable.Outputable GHC.CoreToStg.Prep.BindInfo
+ GHC.CoreToStg.Prep: instance GHC.Utils.Outputable.Outputable GHC.CoreToStg.Prep.FloatInfo
+ GHC.Data.Graph.Inductive.Graph: instance forall k1 k2 (gr :: k1 -> k2 -> *) (a :: k1) (b :: k2). GHC.Read.Read (gr a b) => GHC.Read.Read (GHC.Data.Graph.Inductive.Graph.OrdGr gr a b)
+ GHC.Data.Graph.Inductive.Graph: instance forall k1 k2 (gr :: k1 -> k2 -> *) (a :: k1) (b :: k2). GHC.Show.Show (gr a b) => GHC.Show.Show (GHC.Data.Graph.Inductive.Graph.OrdGr gr a b)
+ GHC.Driver.Config.Linker: initLinkerConfig :: DynFlags -> LinkerConfig
+ GHC.Driver.Config.StgToJS: initJSLinkConfig :: DynFlags -> JSLinkConfig
+ GHC.Driver.Pipeline: [T_LlvmAs] :: Bool -> PipeEnv -> HscEnv -> Maybe ModLocation -> FilePath -> TPhase [Char]
+ GHC.Driver.Pipeline.Execute: runGenericAsPhase :: (Logger -> DynFlags -> [Option] -> IO ()) -> [Option] -> Bool -> PipeEnv -> HscEnv -> Maybe ModLocation -> FilePath -> IO FilePath
+ GHC.Driver.Pipeline.Execute: runLlvmAsPhase :: Bool -> PipeEnv -> HscEnv -> Maybe ModLocation -> FilePath -> IO FilePath
+ GHC.HsToCore.Docs: mkExportsDocs :: [(LIE GhcRn, Avails)] -> UniqMap Name (HsDoc GhcRn)
+ GHC.HsToCore.Foreign.Wasm: dsWasmJSExport :: Id -> Coercion -> CLabelString -> DsM (CHeader, CStub, String, Int, [Id], [Binding])
+ GHC.HsToCore.Foreign.Wasm: dsWasmJSImport :: Id -> Coercion -> CImportSpec -> Safety -> DsM ([Binding], CHeader, CStub, [Id])
+ GHC.HsToCore.Match: instance GHC.Show.Show GHC.HsToCore.Match.PatGroup
+ GHC.HsToCore.Monad: EqnDone :: MatchResult CoreExpr -> EquationInfo
+ GHC.HsToCore.Monad: EqnMatch :: LPat GhcTc -> EquationInfo -> EquationInfo
+ GHC.HsToCore.Monad: [eqn_pat] :: EquationInfo -> LPat GhcTc
+ GHC.HsToCore.Monad: [eqn_rest] :: EquationInfo -> EquationInfo
+ GHC.HsToCore.Monad: addMessagesDs :: Messages DsMessage -> DsM ()
+ GHC.HsToCore.Monad: captureMessagesDs :: DsM a -> DsM (Messages DsMessage, a)
+ GHC.HsToCore.Monad: eqnMatchResult :: EquationInfo -> MatchResult CoreExpr
+ GHC.HsToCore.Monad: mkEqnInfo :: [LPat GhcTc] -> MatchResult CoreExpr -> EquationInfo
+ GHC.HsToCore.Monad: prependPats :: [LPat GhcTc] -> EquationInfo -> EquationInfo
+ GHC.HsToCore.Monad: type EquationInfoNE = EquationInfo
+ GHC.HsToCore.Pmc: getNFirstUncovered :: GenerateInhabitingPatternsMode -> [Id] -> Int -> Nablas -> DsM [Nabla]
+ GHC.HsToCore.Pmc: pmcRecSel :: Id -> CoreExpr -> DsM ()
+ GHC.HsToCore.Pmc.Check: checkRecSel :: PmRecSel () -> CheckAction (PmRecSel Id)
+ GHC.HsToCore.Utils: EqnDone :: MatchResult CoreExpr -> EquationInfo
+ GHC.HsToCore.Utils: EqnMatch :: LPat GhcTc -> EquationInfo -> EquationInfo
+ GHC.HsToCore.Utils: [eqn_pat] :: EquationInfo -> LPat GhcTc
+ GHC.HsToCore.Utils: [eqn_rest] :: EquationInfo -> EquationInfo
+ GHC.HsToCore.Utils: combineEqnRhss :: NonEmpty EquationInfo -> DsM (MatchResult CoreExpr)
+ GHC.Iface.Ext.Ast: instance (GHC.Iface.Ext.Ast.ToHie (GHC.Iface.Ext.Ast.RFContext label), GHC.Iface.Ext.Ast.ToHie arg, GHC.Parser.Annotation.HasLoc arg, Data.Data.Data arg, Data.Data.Data label) => GHC.Iface.Ext.Ast.ToHie (GHC.Iface.Ext.Ast.RContext (GHC.Parser.Annotation.LocatedA (Language.Haskell.Syntax.Pat.HsFieldBind label arg)))
+ GHC.Iface.Ext.Ast: instance (GHC.Iface.Ext.Ast.ToHie arg, GHC.Parser.Annotation.HasLoc arg, Data.Data.Data arg, GHC.Iface.Ext.Ast.HiePass p) => GHC.Iface.Ext.Ast.ToHie (GHC.Iface.Ext.Ast.RContext (Language.Haskell.Syntax.Pat.HsRecFields (GHC.Hs.Extension.GhcPass p) arg))
+ GHC.Iface.Ext.Ast: instance (GHC.Iface.Ext.Ast.ToHie rhs, GHC.Parser.Annotation.HasLoc rhs) => GHC.Iface.Ext.Ast.ToHie (Language.Haskell.Syntax.Decls.FamEqn GHC.Hs.Extension.GhcRn rhs)
+ GHC.Iface.Ext.Ast: instance (GHC.Iface.Ext.Ast.ToHie tm, GHC.Iface.Ext.Ast.ToHie ty) => GHC.Iface.Ext.Ast.ToHie (Language.Haskell.Syntax.Type.HsArg (GHC.Hs.Extension.GhcPass p) tm ty)
+ GHC.Iface.Ext.Ast: instance (GHC.Parser.Annotation.HasLoc a, GHC.Iface.Ext.Ast.HiePass p) => GHC.Parser.Annotation.HasLoc (Language.Haskell.Syntax.Decls.FamEqn (GHC.Hs.Extension.GhcPass p) a)
+ GHC.Iface.Ext.Ast: instance (GHC.Parser.Annotation.HasLoc tm, GHC.Parser.Annotation.HasLoc ty) => GHC.Parser.Annotation.HasLoc (Language.Haskell.Syntax.Type.HsArg (GHC.Hs.Extension.GhcPass p) tm ty)
+ GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.HiePass p => GHC.Iface.Ext.Ast.ToHie (GHC.Iface.Ext.Ast.RFContext (GHC.Parser.Annotation.LocatedA (Language.Haskell.Syntax.Type.AmbiguousFieldOcc (GHC.Hs.Extension.GhcPass p))))
+ GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.HiePass p => GHC.Iface.Ext.Ast.ToHie (GHC.Iface.Ext.Ast.RFContext (GHC.Parser.Annotation.LocatedA (Language.Haskell.Syntax.Type.FieldOcc (GHC.Hs.Extension.GhcPass p))))
+ GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.HiePass p => GHC.Iface.Ext.Ast.ToHie (GHC.Parser.Annotation.LocatedA (Language.Haskell.Syntax.Lit.HsOverLit (GHC.Hs.Extension.GhcPass p)))
+ GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.ToHie (GHC.Iface.Ext.Ast.TScoped (Language.Haskell.Syntax.Type.HsTyPat GHC.Hs.Extension.GhcRn))
+ GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.ToHie (GHC.Parser.Annotation.LocatedA GHC.Hs.Expr.SyntaxExprRn)
+ GHC.Iface.Ext.Ast: instance GHC.Iface.Ext.Ast.ToHie (GHC.Parser.Annotation.LocatedA GHC.Hs.Expr.SyntaxExprTc)
+ GHC.Iface.Ext.Ast: instance GHC.Parser.Annotation.HasLoc (Language.Haskell.Syntax.Decls.HsDataDefn GHC.Hs.Extension.GhcRn)
+ GHC.Iface.Ext.Ast: instance GHC.Parser.Annotation.HasLoc a => GHC.Parser.Annotation.HasLoc (Language.Haskell.Syntax.Decls.DataDefnCons a)
+ GHC.Iface.Ext.Ast: instance GHC.Parser.Annotation.HasLoc thing => GHC.Parser.Annotation.HasLoc (GHC.Iface.Ext.Ast.PScoped thing)
+ GHC.Iface.Ext.Utils: locOnlyE :: Monad m => EpaLocation -> ReaderT NodeOrigin m [HieAST a]
+ GHC.Iface.Make: toIfaceWarningTxt :: WarningTxt GhcRn -> IfaceWarningTxt
+ GHC.Iface.Tidy: [opt_keep_auto_rules] :: TidyOpts -> !Bool
+ GHC.JS.Opt.Expr: optExprs :: JStat -> JStat
+ GHC.JS.Opt.Simple: instance GHC.Base.Monoid GHC.JS.Opt.Simple.Multiplicity
+ GHC.JS.Opt.Simple: instance GHC.Base.Monoid GHC.JS.Opt.Simple.VarUsage
+ GHC.JS.Opt.Simple: instance GHC.Base.Monoid GHC.JS.Opt.Simple.VarValue
+ GHC.JS.Opt.Simple: instance GHC.Base.Semigroup GHC.JS.Opt.Simple.Multiplicity
+ GHC.JS.Opt.Simple: instance GHC.Base.Semigroup GHC.JS.Opt.Simple.VarDecl
+ GHC.JS.Opt.Simple: instance GHC.Base.Semigroup GHC.JS.Opt.Simple.VarUsage
+ GHC.JS.Opt.Simple: instance GHC.Base.Semigroup GHC.JS.Opt.Simple.VarValue
+ GHC.JS.Opt.Simple: instance GHC.Classes.Eq GHC.JS.Opt.Simple.Multiplicity
+ GHC.JS.Opt.Simple: instance GHC.Classes.Eq GHC.JS.Opt.Simple.VarDecl
+ GHC.JS.Opt.Simple: instance GHC.Classes.Ord GHC.JS.Opt.Simple.Multiplicity
+ GHC.JS.Opt.Simple: instance GHC.Classes.Ord GHC.JS.Opt.Simple.VarDecl
+ GHC.JS.Opt.Simple: instance GHC.Show.Show GHC.JS.Opt.Simple.Multiplicity
+ GHC.JS.Opt.Simple: instance GHC.Show.Show GHC.JS.Opt.Simple.VarDecl
+ GHC.JS.Opt.Simple: simpleOpt :: JStat -> JStat
+ GHC.Linker.External: LinkerConfig :: String -> [Option] -> [Option] -> TempDir -> (String -> String) -> LinkerConfig
+ GHC.Linker.External: [linkerFilter] :: LinkerConfig -> String -> String
+ GHC.Linker.External: [linkerOptionsPost] :: LinkerConfig -> [Option]
+ GHC.Linker.External: [linkerOptionsPre] :: LinkerConfig -> [Option]
+ GHC.Linker.External: [linkerProgram] :: LinkerConfig -> String
+ GHC.Linker.External: [linkerTempDir] :: LinkerConfig -> TempDir
+ GHC.Linker.External: data () => LinkerConfig
+ GHC.Linker.External: runLink :: Logger -> TmpFs -> LinkerConfig -> [Option] -> IO ()
+ GHC.Llvm: MFBAppend :: ModuleFlagBehavior
+ GHC.Llvm: MFBAppendUnique :: ModuleFlagBehavior
+ GHC.Llvm: MFBError :: ModuleFlagBehavior
+ GHC.Llvm: MFBMax :: ModuleFlagBehavior
+ GHC.Llvm: MFBMin :: ModuleFlagBehavior
+ GHC.Llvm: MFBOverride :: ModuleFlagBehavior
+ GHC.Llvm: MFBRequire :: ModuleFlagBehavior
+ GHC.Llvm: MFBWarning :: ModuleFlagBehavior
+ GHC.Llvm: MetaLit :: !LlvmLit -> MetaExpr
+ GHC.Llvm: ModuleFlag :: ModuleFlagBehavior -> LMString -> MetaExpr -> ModuleFlag
+ GHC.Llvm: [mfBehavior] :: ModuleFlag -> ModuleFlagBehavior
+ GHC.Llvm: [mfName] :: ModuleFlag -> LMString
+ GHC.Llvm: [mfValue] :: ModuleFlag -> MetaExpr
+ GHC.Llvm: data ModuleFlag
+ GHC.Llvm: data ModuleFlagBehavior
+ GHC.Llvm: moduleFlagToMetaExpr :: ModuleFlag -> MetaExpr
+ GHC.Llvm.MetaData: MFBAppend :: ModuleFlagBehavior
+ GHC.Llvm.MetaData: MFBAppendUnique :: ModuleFlagBehavior
+ GHC.Llvm.MetaData: MFBError :: ModuleFlagBehavior
+ GHC.Llvm.MetaData: MFBMax :: ModuleFlagBehavior
+ GHC.Llvm.MetaData: MFBMin :: ModuleFlagBehavior
+ GHC.Llvm.MetaData: MFBOverride :: ModuleFlagBehavior
+ GHC.Llvm.MetaData: MFBRequire :: ModuleFlagBehavior
+ GHC.Llvm.MetaData: MFBWarning :: ModuleFlagBehavior
+ GHC.Llvm.MetaData: MetaLit :: !LlvmLit -> MetaExpr
+ GHC.Llvm.MetaData: ModuleFlag :: ModuleFlagBehavior -> LMString -> MetaExpr -> ModuleFlag
+ GHC.Llvm.MetaData: [mfBehavior] :: ModuleFlag -> ModuleFlagBehavior
+ GHC.Llvm.MetaData: [mfName] :: ModuleFlag -> LMString
+ GHC.Llvm.MetaData: [mfValue] :: ModuleFlag -> MetaExpr
+ GHC.Llvm.MetaData: data ModuleFlag
+ GHC.Llvm.MetaData: data ModuleFlagBehavior
+ GHC.Llvm.MetaData: moduleFlagToMetaExpr :: ModuleFlag -> MetaExpr
+ GHC.Plugins: data () => JoinPointHood
+ GHC.Plugins: data () => OccSet
+ GHC.Plugins: deepUserTypeError_maybe :: Type -> Maybe ErrorMsgType
+ GHC.Plugins: extendLiftingContextCvSubst :: LiftingContext -> CoVar -> Coercion -> LiftingContext
+ GHC.Plugins: idJoinPointHood :: Var -> JoinPointHood
+ GHC.Plugins: isSumTyConName :: Name -> Bool
+ GHC.Plugins: isUnboxedTupleDataConLikeName :: Name -> Bool
+ GHC.Plugins: isUnderscore :: OccName -> Bool
+ GHC.Plugins: lcLookupCoVar :: LiftingContext -> CoVar -> Maybe Coercion
+ GHC.Plugins: mkNakedForAllCo :: TyVar -> ForAllTyFlag -> ForAllTyFlag -> CoercionN -> Coercion -> Coercion
+ GHC.Plugins: mkTCvSubst :: InScopeSet -> TvSubstEnv -> CvSubstEnv -> Subst
+ GHC.Plugins: mkTyCoForAllTy :: TyCoVar -> ForAllTyFlag -> Type -> Type
+ GHC.Plugins: mkTyCoForAllTys :: [ForAllTyBinder] -> Type -> Type
+ GHC.Plugins: splitForAllForAllTyBinder_maybe :: Type -> Maybe (ForAllTyBinder, Type)
+ GHC.Plugins: typeLevity :: HasDebugCallStack => Type -> Levity
+ GHC.Rename.Bind: data MiniFixityEnv
+ GHC.Rename.Bind: emptyMiniFixityEnv :: MiniFixityEnv
+ GHC.Rename.Fixity: MFE :: FastStringEnv (Located Fixity) -> FastStringEnv (Located Fixity) -> MiniFixityEnv
+ GHC.Rename.Fixity: [mfe_data_level_names] :: MiniFixityEnv -> FastStringEnv (Located Fixity)
+ GHC.Rename.Fixity: [mfe_type_level_names] :: MiniFixityEnv -> FastStringEnv (Located Fixity)
+ GHC.Rename.Fixity: data MiniFixityEnv
+ GHC.Rename.Fixity: emptyMiniFixityEnv :: MiniFixityEnv
+ GHC.Rename.Fixity: lookupMiniFixityEnv :: MiniFixityEnv -> Name -> Maybe (Located Fixity)
+ GHC.Rename.HsType: badKindSigErr :: HsDocContext -> LHsType GhcPs -> TcM ()
+ GHC.Rename.HsType: mkHsOpTyRn :: PromotionFlag -> LocatedN Name -> Fixity -> LHsType GhcRn -> LHsType GhcRn -> RnM (HsType GhcRn)
+ GHC.Rename.HsType: rnHsPatSigKind :: HsPatSigTypeScoping -> HsDocContext -> HsPatSigType GhcPs -> (HsPatSigType GhcRn -> RnM (a, FreeVars)) -> RnM (a, FreeVars)
+ GHC.Rename.HsType: rnHsTyLit :: HsTyLit GhcPs -> RnM (HsTyLit GhcRn)
+ GHC.Rename.Module: rnLWarningTxt :: LWarningTxt GhcPs -> RnM (LWarningTxt GhcRn)
+ GHC.Rename.Pat: instance GHC.Base.Applicative GHC.Rename.Pat.TPRnM
+ GHC.Rename.Pat: instance GHC.Base.Functor GHC.Rename.Pat.TPRnM
+ GHC.Rename.Pat: instance GHC.Base.Monad GHC.Rename.Pat.TPRnM
+ GHC.Rename.Pat: instance GHC.Base.Monoid GHC.Rename.Pat.HsTyPatRnBuilder
+ GHC.Rename.Pat: instance GHC.Base.Semigroup GHC.Rename.Pat.HsTyPatRnBuilder
+ GHC.Rename.Splice: checkThLocalTyName :: Name -> RnM ()
+ GHC.Rename.Splice: rnSpliceTyPat :: HsUntypedSplice GhcPs -> RnM ((HsUntypedSplice GhcRn, HsUntypedSpliceResult (LHsType GhcPs)), FreeVars)
+ GHC.Rename.Utils: AllDeprecationWarnings :: DeprecationWarnings
+ GHC.Rename.Utils: ExportDeprecationWarnings :: DeprecationWarnings
+ GHC.Rename.Utils: NoDeprecationWarnings :: DeprecationWarnings
+ GHC.Rename.Utils: data DeprecationWarnings
+ GHC.Rename.Utils: genHsApps' :: LocatedN Name -> [LHsExpr GhcRn] -> HsExpr GhcRn
+ GHC.Rename.Utils: genHsCaseAltDoExp :: (Anno (GRHS (GhcPass p) (LocatedA (body (GhcPass p)))) ~ EpAnnCO, Anno (Match (GhcPass p) (LocatedA (body (GhcPass p)))) ~ SrcSpanAnnA) => HsDoFlavour -> LPat (GhcPass p) -> LocatedA (body (GhcPass p)) -> LMatch (GhcPass p) (LocatedA (body (GhcPass p)))
+ GHC.Rename.Utils: genHsExpApps :: HsExpr GhcRn -> [LHsExpr GhcRn] -> HsExpr GhcRn
+ GHC.Rename.Utils: genHsLamDoExp :: (IsPass p, XMG (GhcPass p) (LHsExpr (GhcPass p)) ~ Origin) => HsDoFlavour -> [LPat (GhcPass p)] -> LHsExpr (GhcPass p) -> LHsExpr (GhcPass p)
+ GHC.Rename.Utils: genHsLet :: HsLocalBindsLR GhcRn GhcRn -> LHsExpr GhcRn -> HsExpr GhcRn
+ GHC.Rename.Utils: genSimpleMatch :: (Anno (Match (GhcPass p) (LocatedA (body (GhcPass p)))) ~ SrcSpanAnnA, Anno (GRHS (GhcPass p) (LocatedA (body (GhcPass p)))) ~ EpAnnCO) => HsMatchContext (LIdP (NoGhcTc (GhcPass p))) -> [LPat (GhcPass p)] -> LocatedA (body (GhcPass p)) -> LMatch (GhcPass p) (LocatedA (body (GhcPass p)))
+ GHC.Rename.Utils: isIrrefutableHsPat :: forall p. OutputableBndrId p => DynFlags -> LPat (GhcPass p) -> Bool
+ GHC.Rename.Utils: warnIfDeprecated :: DeprecationWarnings -> [GlobalRdrElt] -> RnM ()
+ GHC.Runtime.Interpreter: evalBreakInfo :: HomePackageTable -> EvalBreakpoint -> BreakInfo
+ GHC.Stg.InferTags.Rewrite: rewriteOpApp :: InferStgExpr -> RM TgStgExpr
+ GHC.StgToCmm.ArgRep: toArgRepOrV :: Platform -> PrimOrVoidRep -> ArgRep
+ GHC.StgToCmm.Closure: idPrimRep1 :: Id -> PrimOrVoidRep
+ GHC.StgToCmm.Closure: idPrimRepU :: Id -> PrimRep
+ GHC.StgToCmm.Env: mkCgIdInfo :: Id -> LambdaFormInfo -> CmmExpr -> CgIdInfo
+ GHC.StgToCmm.Layout: idArgRep :: Platform -> Id -> ArgRep
+ GHC.StgToCmm.Layout: toArgRepOrV :: Platform -> PrimOrVoidRep -> ArgRep
+ GHC.StgToCmm.Monad: [stgToCmmAllowBigQuot] :: StgToCmmConfig -> !Bool
+ GHC.StgToCmm.Monad: [stgToCmmOrigThunkInfo] :: StgToCmmConfig -> !Bool
+ GHC.StgToCmm.Prof: profHeaderCreate :: CmmExpr -> FCode ()
+ GHC.StgToCmm.Utils: emitAtomicRead :: MemoryOrdering -> LocalReg -> CmmExpr -> FCode ()
+ GHC.StgToCmm.Utils: emitAtomicWrite :: MemoryOrdering -> CmmExpr -> CmmExpr -> FCode ()
+ GHC.StgToJS.Linker.Linker: [lkp_objs_cc] :: LinkPlan -> !Set FilePath
+ GHC.StgToJS.Linker.Linker: [lkp_objs_js] :: LinkPlan -> !Set FilePath
+ GHC.StgToJS.Linker.Linker: [lks_objs_cc] :: LinkSpec -> [FilePath]
+ GHC.StgToJS.Linker.Linker: [lks_objs_hs] :: LinkSpec -> [FilePath]
+ GHC.StgToJS.Linker.Linker: [lks_objs_js] :: LinkSpec -> [FilePath]
+ GHC.StgToJS.Linker.Linker: data ArchiveCache
+ GHC.StgToJS.Linker.Linker: newArchiveCache :: IO ArchiveCache
+ GHC.StgToJS.Regs: foreignRegister :: StgRet -> JStgExpr
+ GHC.StgToJS.Regs: register :: StgReg -> JStgExpr
+ GHC.StgToJS.Utils: idJSRep :: HasDebugCallStack => Id -> [JSRep]
+ GHC.StgToJS.Utils: primOrVoidRepToJSRep :: HasDebugCallStack => PrimOrVoidRep -> JSRep
+ GHC.StgToJS.Utils: primRepToJSRep :: HasDebugCallStack => PrimRep -> JSRep
+ GHC.StgToJS.Utils: typeJSRep :: HasDebugCallStack => Type -> [JSRep]
+ GHC.StgToJS.Utils: unaryTypeJSRep :: HasDebugCallStack => UnaryType -> JSRep
+ GHC.SysTools.Cpp: [useHsCpp] :: CppOpts -> !Bool
+ GHC.SysTools.Tasks: cc_filter :: String -> String
+ GHC.SysTools.Tasks: runHsCpp :: Logger -> DynFlags -> [Option] -> IO ()
+ GHC.SysTools.Tasks: runLlvmAs :: Logger -> DynFlags -> [Option] -> IO ()
+ GHC.Tc.Deriv.Utils: [denv_warn] :: DerivEnv -> Maybe (WarningTxt GhcRn)
+ GHC.Tc.Deriv.Utils: [ds_warn] :: DerivSpec theta -> Maybe (WarningTxt GhcRn)
+ GHC.Tc.Errors: mismatchMsg_ExpectedActuals :: MismatchMsg -> Maybe (Type, Type)
+ GHC.Tc.Gen.Do: expandDoStmts :: HsDoFlavour -> [ExprLStmt GhcRn] -> TcM (LHsExpr GhcRn)
+ GHC.Tc.Gen.Expr: tcPolyLExpr :: LHsExpr GhcRn -> ExpSigmaType -> TcM (LHsExpr GhcTc)
+ GHC.Tc.Gen.Expr: tcPolyLExprSig :: LHsExpr GhcRn -> TcCompleteSig -> TcM (LHsExpr GhcTc)
+ GHC.Tc.Gen.Head: addStmtCtxt :: ExprStmt GhcRn -> TcRn a -> TcRn a
+ GHC.Tc.Gen.Head: leadingValArgs :: [HsExprArg id] -> [EValArg id]
+ GHC.Tc.Gen.HsType: instance GHC.Utils.Outputable.Outputable GHC.Tc.Gen.HsType.ContextKind
+ GHC.Tc.Gen.HsType: tcHsTyPat :: HsTyPat GhcRn -> Kind -> TcM ([(Name, TcTyVar)], [(Name, TcTyVar)], TcType)
+ GHC.Tc.Gen.Match: tcCaseMatches :: (AnnoBody body, Outputable (body GhcTc)) => TcMatchAltChecker body -> Scaled TcSigmaTypeFRR -> MatchGroup GhcRn (LocatedA (body GhcRn)) -> ExpRhoType -> TcM (HsWrapper, MatchGroup GhcTc (LocatedA (body GhcTc)))
+ GHC.Tc.Gen.Match: tcFunBindMatches :: UserTypeCtxt -> Name -> Mult -> MatchGroup GhcRn (LHsExpr GhcRn) -> [ExpPatType] -> ExpRhoType -> TcM (HsWrapper, MatchGroup GhcTc (LHsExpr GhcTc))
+ GHC.Tc.Gen.Match: tcGRHSList :: forall body. AnnoBody body => HsMatchContextRn -> TcMatchAltChecker body -> [LGRHS GhcRn (LocatedA (body GhcRn))] -> ExpRhoType -> TcM [LGRHS GhcTc (LocatedA (body GhcTc))]
+ GHC.Tc.Gen.Match: tcLambdaMatches :: HsExpr GhcRn -> HsLamVariant -> MatchGroup GhcRn (LHsExpr GhcRn) -> [ExpPatType] -> ExpSigmaType -> TcM (HsWrapper, MatchGroup GhcTc (LHsExpr GhcTc))
+ GHC.Tc.Gen.Pat: isIrrefutableHsPatRnTcM :: Bool -> LPat GhcRn -> TcM Bool
+ GHC.Tc.Gen.Pat: tcMatchPats :: forall a. HsMatchContextRn -> [LPat GhcRn] -> [ExpPatType] -> TcM a -> TcM ([LPat GhcTc], a)
+ GHC.Tc.Gen.Sig: TcCompleteSig :: TcCompleteSig -> TcIdSig
+ GHC.Tc.Gen.Sig: TcPartialSig :: TcPartialSig -> TcIdSig
+ GHC.Tc.Gen.Sig: data () => TcIdSig
+ GHC.Tc.Gen.Sig: tcIdSigLoc :: TcIdSig -> SrcSpan
+ GHC.Tc.Gen.Splice: getUntypedSpliceBody :: HsUntypedSpliceResult (HsExpr GhcRn) -> TcM (HsExpr GhcRn)
+ GHC.Tc.Instance.Class: [iw_warn] :: InstanceWhat -> Maybe (WarningTxt GhcRn)
+ GHC.Tc.Solver.Monad: isUnfilledMetaTyVar :: TcTyVar -> TcS Bool
+ GHC.Tc.Solver.Monad: unifyForAllBody :: CtEvidence -> Role -> (UnifyEnv -> TcM a) -> TcS (a, Cts)
+ GHC.Tc.Utils.Concrete: idConcreteTvs :: TcId -> ConcreteTyVars
+ GHC.Tc.Utils.Concrete: unifyConcrete :: HasDebugCallStack => FastString -> ConcreteTvOrigin -> TcType -> TcM TcMCoercionN
+ GHC.Tc.Utils.Instantiate: tcInstSkolTyVarBndrsX :: SkolemInfo -> Subst -> [VarBndr TyCoVar vis] -> TcM (Subst, [VarBndr TyCoVar vis])
+ GHC.Tc.Utils.TcMType: newConcreteTyVarX :: ConcreteTvOrigin -> Subst -> TyVar -> TcM (Subst, TcTyVar)
+ GHC.Tc.Utils.TcMType: newMetaTyVarBndrsX :: Subst -> [VarBndr TyVar vis] -> TcM (Subst, [VarBndr TcTyVar vis])
+ GHC.Tc.Utils.TcMType: newOpenFlexiFRRTyVar :: FixedRuntimeRepContext -> TcM TcTyVar
+ GHC.Tc.Utils.TcMType: newOpenFlexiFRRTyVarTy :: FixedRuntimeRepContext -> TcM TcType
+ GHC.Tc.Utils.TcMType: newPatTyVar :: Name -> Kind -> TcM TcTyVar
+ GHC.Tc.Utils.TcMType: substConcreteTvOrigin :: Subst -> Type -> ConcreteTvOrigin -> ConcreteTvOrigin
+ GHC.Tc.Utils.Unify: Deep :: DeepSubsumptionFlag
+ GHC.Tc.Utils.Unify: Shallow :: DeepSubsumptionFlag
+ GHC.Tc.Utils.Unify: data DeepSubsumptionFlag
+ GHC.Tc.Utils.Unify: getDeepSubsumptionFlag :: TcM DeepSubsumptionFlag
+ GHC.Tc.Utils.Unify: matchActualFunTy :: ExpectedFunTyOrigin -> Maybe TypedThing -> (Arity, TcType) -> TcRhoType -> TcM (HsWrapper, Scaled TcSigmaTypeFRR, TcSigmaType)
+ GHC.Tc.Utils.Unify: matchActualFunTys :: ExpectedFunTyOrigin -> CtOrigin -> Arity -> TcSigmaType -> TcM (HsWrapper, [Scaled TcSigmaTypeFRR], TcRhoType)
+ GHC.Tc.Utils.Unify: tcSkolemise :: DeepSubsumptionFlag -> UserTypeCtxt -> TcSigmaType -> (TcRhoType -> TcM result) -> TcM (HsWrapper, result)
+ GHC.Tc.Utils.Unify: tcSkolemiseCompleteSig :: TcCompleteSig -> ([ExpPatType] -> TcRhoType -> TcM result) -> TcM (HsWrapper, result)
+ GHC.Tc.Utils.Unify: tcSkolemiseExpectedType :: TcSigmaType -> ([ExpPatType] -> TcRhoType -> TcM result) -> TcM (HsWrapper, result)
+ GHC.Utils.Touch: touch :: FilePath -> IO ()
- GHC: DynFlags :: GhcMode -> GhcLink -> !Backend -> {-# UNPACK #-} !GhcNameVersion -> {-# UNPACK #-} !FileSettings -> Platform -> {-# UNPACK #-} !ToolSettings -> {-# UNPACK #-} !PlatformMisc -> [(String, String)] -> TempDir -> Int -> Int -> Int -> Int -> Int -> Maybe String -> [Int] -> Maybe ParMakeCount -> Bool -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> Int -> Int -> Int -> !Int -> Maybe Int -> Maybe Int -> Int -> Maybe Word -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> Bool -> Maybe Int -> Int -> [FilePath] -> ModuleName -> Maybe String -> IntWithInf -> IntWithInf -> Int -> Int -> Int -> UnitId -> Maybe UnitId -> [(ModuleName, Module)] -> Maybe FilePath -> Maybe String -> Set ModuleName -> Set ModuleName -> Ways -> Maybe (String, Int) -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> String -> String -> String -> String -> String -> String -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> DynLibLoader -> !Bool -> FilePath -> Maybe FilePath -> [Option] -> IncludeSpecs -> [String] -> [String] -> [String] -> Maybe String -> RtsOptsEnabled -> Bool -> String -> [ModuleName] -> [(ModuleName, String)] -> [String] -> [ExternalPluginSpec] -> FilePath -> Bool -> Bool -> [ModuleName] -> [String] -> [PackageDBFlag] -> [IgnorePackageFlag] -> [PackageFlag] -> [PackageFlag] -> [TrustFlag] -> Maybe FilePath -> EnumSet DumpFlag -> EnumSet GeneralFlag -> EnumSet WarningFlag -> EnumSet WarningFlag -> WarningCategorySet -> WarningCategorySet -> Maybe Language -> SafeHaskellMode -> Bool -> Bool -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> [OnOff Extension] -> EnumSet Extension -> !UnfoldingOpts -> Int -> Int -> FlushOut -> Maybe FilePath -> Maybe String -> [String] -> Int -> Int -> Bool -> OverridingBool -> Bool -> Scheme -> ProfAuto -> [CallerCcFilter] -> Maybe String -> Maybe SseVersion -> Maybe BmiVersion -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> IORef (Maybe LinkerInfo) -> IORef (Maybe CompilerInfo) -> IORef (Maybe CompilerInfo) -> Int -> Int -> Int -> Bool -> Maybe Int -> Word64 -> Int -> Weights -> DynFlags
+ GHC: DynFlags :: GhcMode -> GhcLink -> !Backend -> {-# UNPACK #-} !GhcNameVersion -> {-# UNPACK #-} !FileSettings -> Platform -> {-# UNPACK #-} !ToolSettings -> {-# UNPACK #-} !PlatformMisc -> [(String, String)] -> TempDir -> Int -> Int -> Int -> Int -> Int -> Maybe String -> [Int] -> Maybe ParMakeCount -> Bool -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> Int -> Int -> Int -> !Int -> Maybe Int -> Maybe Int -> Int -> Maybe Word -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> Bool -> Maybe Int -> Int -> [FilePath] -> ModuleName -> Maybe String -> IntWithInf -> IntWithInf -> Int -> Int -> Int -> UnitId -> Maybe UnitId -> [(ModuleName, Module)] -> Maybe FilePath -> Maybe String -> Set ModuleName -> Set ModuleName -> Ways -> Maybe (String, Int) -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> String -> String -> String -> String -> String -> String -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> DynLibLoader -> !Bool -> FilePath -> Maybe FilePath -> [Option] -> IncludeSpecs -> [String] -> [String] -> [String] -> Maybe String -> RtsOptsEnabled -> Bool -> String -> [ModuleName] -> [(ModuleName, String)] -> [String] -> [ExternalPluginSpec] -> FilePath -> Bool -> Bool -> [ModuleName] -> [String] -> [PackageDBFlag] -> [IgnorePackageFlag] -> [PackageFlag] -> [PackageFlag] -> [TrustFlag] -> Maybe FilePath -> EnumSet DumpFlag -> EnumSet GeneralFlag -> EnumSet WarningFlag -> EnumSet WarningFlag -> WarningCategorySet -> WarningCategorySet -> Maybe Language -> SafeHaskellMode -> Bool -> Bool -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> [OnOff Extension] -> EnumSet Extension -> !UnfoldingOpts -> Int -> Int -> FlushOut -> Maybe FilePath -> Maybe String -> [String] -> Int -> Int -> Bool -> OverridingBool -> Bool -> OverridingBool -> Bool -> Scheme -> ProfAuto -> [CallerCcFilter] -> Maybe String -> Maybe SseVersion -> Maybe BmiVersion -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> Int -> Int -> Int -> Bool -> Maybe Int -> Word64 -> Int -> Weights -> DynFlags
- GHC: type RenamedSource = (HsGroup GhcRn, [LImportDecl GhcRn], Maybe [(LIE GhcRn, Avails)], Maybe (LHsDoc GhcRn))
+ GHC: type RenamedSource = (HsGroup GhcRn, [LImportDecl GhcRn], Maybe [(LIE GhcRn, Avails)], Maybe (LHsDoc GhcRn), Maybe (XRec GhcRn ModuleName))
- GHC.ByteCode.Instr: BRK_FUN :: !Word16 -> RemotePtr ModuleName -> RemotePtr CostCentre -> BCInstr
+ GHC.ByteCode.Instr: BRK_FUN :: ForeignRef BreakArray -> !Word16 -> RemotePtr ModuleName -> RemotePtr CostCentre -> BCInstr
- GHC.ByteCode.Linker: linkBCO :: Interp -> PkgsLoaded -> LinkerEnv -> NameEnv Int -> RemoteRef BreakArray -> UnlinkedBCO -> IO ResolvedBCO
+ GHC.ByteCode.Linker: linkBCO :: Interp -> LinkerEnv -> NameEnv Int -> UnlinkedBCO -> IO ResolvedBCO
- GHC.ByteCode.Linker: lookupIE :: Interp -> PkgsLoaded -> ItblEnv -> Name -> IO (Ptr ())
+ GHC.ByteCode.Linker: lookupIE :: Interp -> ItblEnv -> Name -> IO (Ptr ())
- GHC.Cmm.Utils: typeCmmType :: Platform -> UnaryType -> CmmType
+ GHC.Cmm.Utils: typeCmmType :: Platform -> NvUnaryType -> CmmType
- GHC.Cmm.Utils: typeForeignHint :: UnaryType -> ForeignHint
+ GHC.Cmm.Utils: typeForeignHint :: NvUnaryType -> ForeignHint
- GHC.CmmToAsm.Reg.Linear.AArch64: allocateReg :: HasDebugCallStack => RealReg -> FreeRegs -> FreeRegs
+ GHC.CmmToAsm.Reg.Linear.AArch64: allocateReg :: HasCallStack => RealReg -> FreeRegs -> FreeRegs
- GHC.CmmToAsm.Reg.Linear.AArch64: releaseReg :: HasDebugCallStack => RealReg -> FreeRegs -> FreeRegs
+ GHC.CmmToAsm.Reg.Linear.AArch64: releaseReg :: HasCallStack => RealReg -> FreeRegs -> FreeRegs
- GHC.CmmToAsm.Reg.Liveness: mapEmpty :: IsMap map => map a
+ GHC.CmmToAsm.Reg.Liveness: mapEmpty :: LabelMap v
- GHC.CmmToAsm.Wasm: ncgWasm :: Platform -> ToolSettings -> UniqSupply -> ModLocation -> Handle -> Stream IO RawCmmGroup a -> IO a
+ GHC.CmmToAsm.Wasm: ncgWasm :: NCGConfig -> Logger -> Platform -> ToolSettings -> UniqSupply -> ModLocation -> Handle -> Stream IO RawCmmGroup a -> IO a
- GHC.CoreToStg.Prep: CorePrepConfig :: !Bool -> !LitNumType -> Integer -> Maybe CoreExpr -> CorePrepConfig
+ GHC.CoreToStg.Prep: CorePrepConfig :: !Bool -> !LitNumType -> Integer -> Maybe CoreExpr -> !Maybe ArityOpts -> CorePrepConfig
- GHC.Driver.Pipeline: class () => MonadUse (f :: Type -> Type) (m :: Type -> Type)
+ GHC.Driver.Pipeline: class () => MonadUse (f :: k -> Type) (m :: k -> Type)
- GHC.Driver.Pipeline: use :: MonadUse f m => f a -> m a
+ GHC.Driver.Pipeline: use :: forall (a :: k). MonadUse f m => f a -> m a
- GHC.Driver.Pipeline.Execute: touchObjectFile :: Logger -> DynFlags -> FilePath -> IO ()
+ GHC.Driver.Pipeline.Execute: touchObjectFile :: FilePath -> IO ()
- GHC.HsToCore.GuardedRHSs: dsGRHSs :: HsMatchContext GhcTc -> GRHSs GhcTc (LHsExpr GhcTc) -> Type -> NonEmpty Nablas -> DsM (MatchResult CoreExpr)
+ GHC.HsToCore.GuardedRHSs: dsGRHSs :: HsMatchContextRn -> GRHSs GhcTc (LHsExpr GhcTc) -> Type -> NonEmpty Nablas -> DsM (MatchResult CoreExpr)
- GHC.HsToCore.Match: matchEquations :: HsMatchContext GhcTc -> [MatchId] -> [EquationInfo] -> Type -> DsM CoreExpr
+ GHC.HsToCore.Match: matchEquations :: HsMatchContextRn -> [MatchId] -> [EquationInfo] -> Type -> DsM CoreExpr
- GHC.HsToCore.Match: matchSimply :: CoreExpr -> HsMatchContext GhcTc -> LPat GhcTc -> CoreExpr -> CoreExpr -> DsM CoreExpr
+ GHC.HsToCore.Match: matchSimply :: CoreExpr -> HsMatchContextRn -> Mult -> LPat GhcTc -> CoreExpr -> CoreExpr -> DsM CoreExpr
- GHC.HsToCore.Match: matchSinglePat :: CoreExpr -> HsMatchContext GhcTc -> LPat GhcTc -> Type -> MatchResult CoreExpr -> DsM (MatchResult CoreExpr)
+ GHC.HsToCore.Match: matchSinglePat :: CoreExpr -> HsMatchContextRn -> LPat GhcTc -> Mult -> Type -> MatchResult CoreExpr -> DsM (MatchResult CoreExpr)
- GHC.HsToCore.Match: matchSinglePatVar :: Id -> Maybe CoreExpr -> HsMatchContext GhcTc -> LPat GhcTc -> Type -> MatchResult CoreExpr -> DsM (MatchResult CoreExpr)
+ GHC.HsToCore.Match: matchSinglePatVar :: Id -> Maybe CoreExpr -> HsMatchContextRn -> LPat GhcTc -> Type -> MatchResult CoreExpr -> DsM (MatchResult CoreExpr)
- GHC.HsToCore.Match: matchWrapper :: HsMatchContext GhcTc -> Maybe [LHsExpr GhcTc] -> MatchGroup GhcTc (LHsExpr GhcTc) -> DsM ([Id], CoreExpr)
+ GHC.HsToCore.Match: matchWrapper :: HsMatchContextRn -> Maybe [LHsExpr GhcTc] -> MatchGroup GhcTc (LHsExpr GhcTc) -> DsM ([Id], CoreExpr)
- GHC.HsToCore.Match.Constructor: matchConFamily :: NonEmpty Id -> Type -> NonEmpty (NonEmpty EquationInfo) -> DsM (MatchResult CoreExpr)
+ GHC.HsToCore.Match.Constructor: matchConFamily :: NonEmpty Id -> Type -> NonEmpty (NonEmpty EquationInfoNE) -> DsM (MatchResult CoreExpr)
- GHC.HsToCore.Match.Constructor: matchPatSyn :: NonEmpty Id -> Type -> NonEmpty EquationInfo -> DsM (MatchResult CoreExpr)
+ GHC.HsToCore.Match.Constructor: matchPatSyn :: NonEmpty Id -> Type -> NonEmpty EquationInfoNE -> DsM (MatchResult CoreExpr)
- GHC.HsToCore.Match.Literal: matchLiterals :: NonEmpty Id -> Type -> NonEmpty (NonEmpty EquationInfo) -> DsM (MatchResult CoreExpr)
+ GHC.HsToCore.Match.Literal: matchLiterals :: NonEmpty Id -> Type -> NonEmpty (NonEmpty EquationInfoNE) -> DsM (MatchResult CoreExpr)
- GHC.HsToCore.Match.Literal: matchNPats :: NonEmpty Id -> Type -> NonEmpty EquationInfo -> DsM (MatchResult CoreExpr)
+ GHC.HsToCore.Match.Literal: matchNPats :: NonEmpty Id -> Type -> NonEmpty EquationInfoNE -> DsM (MatchResult CoreExpr)
- GHC.HsToCore.Match.Literal: matchNPlusKPats :: NonEmpty Id -> Type -> NonEmpty EquationInfo -> DsM (MatchResult CoreExpr)
+ GHC.HsToCore.Match.Literal: matchNPlusKPats :: NonEmpty Id -> Type -> NonEmpty EquationInfoNE -> DsM (MatchResult CoreExpr)
- GHC.HsToCore.Monad: DsMatchContext :: HsMatchContext GhcTc -> SrcSpan -> DsMatchContext
+ GHC.HsToCore.Monad: DsMatchContext :: HsMatchContextRn -> SrcSpan -> DsMatchContext
- GHC.HsToCore.Monad: putSrcSpanDsA :: SrcSpanAnn' ann -> DsM a -> DsM a
+ GHC.HsToCore.Monad: putSrcSpanDsA :: EpAnn ann -> DsM a -> DsM a
- GHC.HsToCore.Pmc: isMatchContextPmChecked :: DynFlags -> Origin -> HsMatchContext id -> Bool
+ GHC.HsToCore.Pmc: isMatchContextPmChecked :: DynFlags -> Origin -> HsMatchContext fn -> Bool
- GHC.HsToCore.Pmc: isMatchContextPmChecked_SinglePat :: DynFlags -> Origin -> HsMatchContext id -> LPat GhcTc -> Bool
+ GHC.HsToCore.Pmc: isMatchContextPmChecked_SinglePat :: DynFlags -> Origin -> HsMatchContext fn -> LPat GhcTc -> Bool
- GHC.HsToCore.Pmc: pmcGRHSs :: HsMatchContext GhcTc -> GRHSs GhcTc (LHsExpr GhcTc) -> DsM (NonEmpty Nablas)
+ GHC.HsToCore.Pmc: pmcGRHSs :: HsMatchContextRn -> GRHSs GhcTc (LHsExpr GhcTc) -> DsM (NonEmpty Nablas)
- GHC.HsToCore.Pmc: pmcMatches :: DsMatchContext -> [Id] -> [LMatch GhcTc (LHsExpr GhcTc)] -> DsM [(Nablas, NonEmpty Nablas)]
+ GHC.HsToCore.Pmc: pmcMatches :: Origin -> DsMatchContext -> [Id] -> [LMatch GhcTc (LHsExpr GhcTc)] -> DsM [(Nablas, NonEmpty Nablas)]
- GHC.HsToCore.Pmc.Utils: exhaustive :: DynFlags -> HsMatchContext id -> Bool
+ GHC.HsToCore.Pmc.Utils: exhaustive :: DynFlags -> HsMatchContext fn -> Bool
- GHC.HsToCore.Pmc.Utils: exhaustiveWarningFlag :: HsMatchContext id -> Maybe WarningFlag
+ GHC.HsToCore.Pmc.Utils: exhaustiveWarningFlag :: HsMatchContext fn -> Maybe WarningFlag
- GHC.HsToCore.Pmc.Utils: isMatchContextPmChecked :: DynFlags -> Origin -> HsMatchContext id -> Bool
+ GHC.HsToCore.Pmc.Utils: isMatchContextPmChecked :: DynFlags -> Origin -> HsMatchContext fn -> Bool
- GHC.HsToCore.Pmc.Utils: isMatchContextPmChecked_SinglePat :: DynFlags -> Origin -> HsMatchContext id -> LPat GhcTc -> Bool
+ GHC.HsToCore.Pmc.Utils: isMatchContextPmChecked_SinglePat :: DynFlags -> Origin -> HsMatchContext fn -> LPat GhcTc -> Bool
- GHC.HsToCore.Pmc.Utils: overlapping :: DynFlags -> HsMatchContext id -> Bool
+ GHC.HsToCore.Pmc.Utils: overlapping :: DynFlags -> HsMatchContext fn -> Bool
- GHC.HsToCore.Utils: firstPat :: EquationInfo -> Pat GhcTc
+ GHC.HsToCore.Utils: firstPat :: EquationInfoNE -> Pat GhcTc
- GHC.HsToCore.Utils: mkFailExpr :: HsMatchContext GhcTc -> Type -> DsM CoreExpr
+ GHC.HsToCore.Utils: mkFailExpr :: HsMatchContextRn -> Type -> DsM CoreExpr
- GHC.HsToCore.Utils: mkSelectorBinds :: [[CoreTickish]] -> LPat GhcTc -> CoreExpr -> DsM (Id, [(Id, CoreExpr)])
+ GHC.HsToCore.Utils: mkSelectorBinds :: [[CoreTickish]] -> LPat GhcTc -> HsMatchContextRn -> CoreExpr -> DsM (Id, [(Id, CoreExpr)])
- GHC.HsToCore.Utils: shiftEqns :: Functor f => f EquationInfo -> f EquationInfo
+ GHC.HsToCore.Utils: shiftEqns :: Functor f => f EquationInfoNE -> f EquationInfo
- GHC.Iface.Ext.Utils: makeNodeA :: (Monad m, Data a) => a -> SrcSpanAnn' ann -> ReaderT NodeOrigin m [HieAST b]
+ GHC.Iface.Ext.Utils: makeNodeA :: (Monad m, Data a) => a -> EpAnn ann -> ReaderT NodeOrigin m [HieAST b]
- GHC.Iface.Ext.Utils: mkScope :: SrcSpan -> Scope
+ GHC.Iface.Ext.Utils: mkScope :: HasLoc a => a -> Scope
- GHC.Iface.Tidy: TidyOpts :: !NameCache -> !Bool -> !UnfoldingOpts -> !UnfoldingExposure -> !Bool -> !Bool -> !Maybe StaticPtrOpts -> TidyOpts
+ GHC.Iface.Tidy: TidyOpts :: !NameCache -> !Bool -> !UnfoldingOpts -> !UnfoldingExposure -> !Bool -> !Bool -> !Maybe StaticPtrOpts -> !Bool -> TidyOpts
- GHC.Plugins: Invisible :: Specificity -> ForAllTyFlag
+ GHC.Plugins: Invisible :: !Specificity -> ForAllTyFlag
- GHC.Plugins: asJoinId_maybe :: Id -> Maybe JoinArity -> Id
+ GHC.Plugins: asJoinId_maybe :: Id -> JoinPointHood -> Id
- GHC.Plugins: funArgTy :: Type -> Type
+ GHC.Plugins: funArgTy :: HasDebugCallStack => Type -> Type
- GHC.Plugins: mkForAllCo :: TyCoVar -> CoercionN -> Coercion -> Coercion
+ GHC.Plugins: mkForAllCo :: HasDebugCallStack => TyCoVar -> ForAllTyFlag -> ForAllTyFlag -> CoercionN -> Coercion -> Coercion
- GHC.Plugins: mkHomoForAllCos :: [TyCoVar] -> Coercion -> Coercion
+ GHC.Plugins: mkHomoForAllCos :: [ForAllTyBinder] -> Coercion -> Coercion
- GHC.Plugins: mkLocalCoVar :: HasDebugCallStack => Name -> Type -> CoVar
+ GHC.Plugins: mkLocalCoVar :: Name -> Type -> CoVar
- GHC.Plugins: mkLocalIdOrCoVar :: HasDebugCallStack => Name -> Mult -> Type -> Id
+ GHC.Plugins: mkLocalIdOrCoVar :: Name -> Mult -> Type -> Id
- GHC.Plugins: mkPiTy :: PiTyBinder -> Type -> Type
+ GHC.Plugins: mkPiTy :: HasDebugCallStack => PiTyBinder -> Type -> Type
- GHC.Plugins: mkPiTys :: [PiTyBinder] -> Type -> Type
+ GHC.Plugins: mkPiTys :: HasDebugCallStack => [PiTyBinder] -> Type -> Type
- GHC.Plugins: mkVanillaGlobal :: HasDebugCallStack => Name -> Type -> Id
+ GHC.Plugins: mkVanillaGlobal :: Name -> Type -> Id
- GHC.Plugins: mkVanillaGlobalWithInfo :: HasDebugCallStack => Name -> Type -> IdInfo -> Id
+ GHC.Plugins: mkVanillaGlobalWithInfo :: Name -> Type -> IdInfo -> Id
- GHC.Plugins: promoteCoercion :: Coercion -> CoercionN
+ GHC.Plugins: promoteCoercion :: HasDebugCallStack => Coercion -> CoercionN
- GHC.Plugins: splitAppTys :: Type -> (Type, [Type])
+ GHC.Plugins: splitAppTys :: HasDebugCallStack => Type -> (Type, [Type])
- GHC.Plugins: splitForAllCo_co_maybe :: Coercion -> Maybe (CoVar, Coercion, Coercion)
+ GHC.Plugins: splitForAllCo_co_maybe :: Coercion -> Maybe (CoVar, ForAllTyFlag, ForAllTyFlag, Coercion, Coercion)
- GHC.Plugins: splitForAllCo_maybe :: Coercion -> Maybe (TyCoVar, Coercion, Coercion)
+ GHC.Plugins: splitForAllCo_maybe :: Coercion -> Maybe (TyCoVar, ForAllTyFlag, ForAllTyFlag, Coercion, Coercion)
- GHC.Plugins: splitForAllCo_ty_maybe :: Coercion -> Maybe (TyVar, Coercion, Coercion)
+ GHC.Plugins: splitForAllCo_ty_maybe :: Coercion -> Maybe (TyVar, ForAllTyFlag, ForAllTyFlag, Coercion, Coercion)
- GHC.Plugins: splitTyConAppNoView_maybe :: Type -> Maybe (TyCon, [Type])
+ GHC.Plugins: splitTyConAppNoView_maybe :: HasDebugCallStack => Type -> Maybe (TyCon, [Type])
- GHC.Plugins: substTyAddInScope :: Subst -> Type -> Type
+ GHC.Plugins: substTyAddInScope :: HasDebugCallStack => Subst -> Type -> Type
- GHC.Plugins: substTysWith :: [TyVar] -> [Type] -> [Type] -> [Type]
+ GHC.Plugins: substTysWith :: HasDebugCallStack => [TyVar] -> [Type] -> [Type] -> [Type]
- GHC.Plugins: tcSplitTyConApp_maybe :: HasDebugCallStack => Type -> Maybe (TyCon, [Type])
+ GHC.Plugins: tcSplitTyConApp_maybe :: HasCallStack => Type -> Maybe (TyCon, [Type])
- GHC.Plugins: tyConAppArgs :: HasDebugCallStack => Type -> [Type]
+ GHC.Plugins: tyConAppArgs :: HasCallStack => Type -> [Type]
- GHC.Plugins: type KnotTied ty = ty
+ GHC.Plugins: type KnotTied (ty :: k) = ty
- GHC.Rename.Bind: rnGRHS :: AnnoBody body => HsMatchContext GhcRn -> (LocatedA (body GhcPs) -> RnM (LocatedA (body GhcRn), FreeVars)) -> LGRHS GhcPs (LocatedA (body GhcPs)) -> RnM (LGRHS GhcRn (LocatedA (body GhcRn)), FreeVars)
+ GHC.Rename.Bind: rnGRHS :: AnnoBody body => HsMatchContextRn -> (LocatedA (body GhcPs) -> RnM (LocatedA (body GhcRn), FreeVars)) -> LGRHS GhcPs (LocatedA (body GhcPs)) -> RnM (LGRHS GhcRn (LocatedA (body GhcRn)), FreeVars)
- GHC.Rename.Bind: rnGRHSs :: AnnoBody body => HsMatchContext GhcRn -> (LocatedA (body GhcPs) -> RnM (LocatedA (body GhcRn), FreeVars)) -> GRHSs GhcPs (LocatedA (body GhcPs)) -> RnM (GRHSs GhcRn (LocatedA (body GhcRn)), FreeVars)
+ GHC.Rename.Bind: rnGRHSs :: AnnoBody body => HsMatchContextRn -> (LocatedA (body GhcPs) -> RnM (LocatedA (body GhcRn), FreeVars)) -> GRHSs GhcPs (LocatedA (body GhcPs)) -> RnM (GRHSs GhcRn (LocatedA (body GhcRn)), FreeVars)
- GHC.Rename.Bind: rnMatchGroup :: (Outputable (body GhcPs), AnnoBody body) => HsMatchContext GhcRn -> (LocatedA (body GhcPs) -> RnM (LocatedA (body GhcRn), FreeVars)) -> MatchGroup GhcPs (LocatedA (body GhcPs)) -> RnM (MatchGroup GhcRn (LocatedA (body GhcRn)), FreeVars)
+ GHC.Rename.Bind: rnMatchGroup :: (Outputable (body GhcPs), AnnoBody body) => HsMatchContextRn -> (LocatedA (body GhcPs) -> RnM (LocatedA (body GhcRn), FreeVars)) -> MatchGroup GhcPs (LocatedA (body GhcPs)) -> RnM (MatchGroup GhcRn (LocatedA (body GhcRn)), FreeVars)
- GHC.Rename.Env: lookupLocalTcNames :: HsSigCtxt -> SDoc -> RdrName -> RnM [(RdrName, Name)]
+ GHC.Rename.Env: lookupLocalTcNames :: HsSigCtxt -> SDoc -> NamespaceSpecifier -> RdrName -> RnM [(RdrName, Name)]
- GHC.Rename.Env: lookupLocatedOccRn :: GenLocated (SrcSpanAnn' ann) RdrName -> TcRn (GenLocated (SrcSpanAnn' ann) Name)
+ GHC.Rename.Env: lookupLocatedOccRn :: GenLocated (EpAnn ann) RdrName -> TcRn (GenLocated (EpAnn ann) Name)
- GHC.Rename.Env: lookupLocatedOccRnConstr :: GenLocated (SrcSpanAnn' ann) RdrName -> TcRn (GenLocated (SrcSpanAnn' ann) Name)
+ GHC.Rename.Env: lookupLocatedOccRnConstr :: GenLocated (EpAnn ann) RdrName -> TcRn (GenLocated (EpAnn ann) Name)
- GHC.Rename.Env: lookupLocatedOccRnNone :: GenLocated (SrcSpanAnn' ann) RdrName -> TcRn (GenLocated (SrcSpanAnn' ann) Name)
+ GHC.Rename.Env: lookupLocatedOccRnNone :: GenLocated (EpAnn ann) RdrName -> TcRn (GenLocated (EpAnn ann) Name)
- GHC.Rename.Env: lookupLocatedOccRnRecField :: GenLocated (SrcSpanAnn' ann) RdrName -> TcRn (GenLocated (SrcSpanAnn' ann) Name)
+ GHC.Rename.Env: lookupLocatedOccRnRecField :: GenLocated (EpAnn ann) RdrName -> TcRn (GenLocated (EpAnn ann) Name)
- GHC.Rename.Env: lookupQualifiedDo :: HsStmtContext p -> Name -> RnM (SyntaxExpr GhcRn, FreeVars)
+ GHC.Rename.Env: lookupQualifiedDo :: HsStmtContext fn -> Name -> RnM (SyntaxExpr GhcRn, FreeVars)
- GHC.Rename.Env: lookupQualifiedDoExpr :: HsStmtContext p -> Name -> RnM (HsExpr GhcRn, FreeVars)
+ GHC.Rename.Env: lookupQualifiedDoExpr :: HsStmtContext fn -> Name -> RnM (HsExpr GhcRn, FreeVars)
- GHC.Rename.Env: lookupQualifiedDoName :: HsStmtContext p -> Name -> RnM (Name, FreeVars)
+ GHC.Rename.Env: lookupQualifiedDoName :: HsStmtContext fn -> Name -> RnM (Name, FreeVars)
- GHC.Rename.Env: lookupSigCtxtOccRn :: HsSigCtxt -> SDoc -> GenLocated (SrcSpanAnn' ann) RdrName -> RnM (GenLocated (SrcSpanAnn' ann) Name)
+ GHC.Rename.Env: lookupSigCtxtOccRn :: HsSigCtxt -> SDoc -> GenLocated (EpAnn ann) RdrName -> RnM (GenLocated (EpAnn ann) Name)
- GHC.Rename.Expr: rnStmts :: AnnoBody body => HsStmtContext GhcRn -> (body GhcPs -> RnM (body GhcRn, FreeVars)) -> [LStmt GhcPs (LocatedA (body GhcPs))] -> ([Name] -> RnM (thing, FreeVars)) -> RnM (([LStmt GhcRn (LocatedA (body GhcRn))], thing), FreeVars)
+ GHC.Rename.Expr: rnStmts :: AnnoBody body => HsStmtContextRn -> (body GhcPs -> RnM (body GhcRn, FreeVars)) -> [LStmt GhcPs (LocatedA (body GhcPs))] -> ([Name] -> RnM (thing, FreeVars)) -> RnM (([LStmt GhcRn (LocatedA (body GhcRn))], thing), FreeVars)
- GHC.Rename.HsType: bindHsQTyVars :: forall a b. HsDocContext -> Maybe a -> FreeKiTyVars -> LHsQTyVars GhcPs -> (LHsQTyVars GhcRn -> FreeKiTyVars -> RnM (b, FreeVars)) -> RnM (b, FreeVars)
+ GHC.Rename.HsType: bindHsQTyVars :: forall a b. HsDocContext -> Maybe (a, [Name]) -> FreeKiTyVars -> LHsQTyVars GhcPs -> (LHsQTyVars GhcRn -> FreeKiTyVars -> RnM (b, FreeVars)) -> RnM (b, FreeVars)
- GHC.Rename.Pat: rnPat :: HsMatchContext GhcRn -> LPat GhcPs -> (LPat GhcRn -> RnM (a, FreeVars)) -> RnM (a, FreeVars)
+ GHC.Rename.Pat: rnPat :: forall a. HsMatchContextRn -> LPat GhcPs -> (LPat GhcRn -> RnM (a, FreeVars)) -> RnM (a, FreeVars)
- GHC.Rename.Pat: rnPats :: Traversable f => HsMatchContext GhcRn -> f (LPat GhcPs) -> (f (LPat GhcRn) -> RnM (a, FreeVars)) -> RnM (a, FreeVars)
+ GHC.Rename.Pat: rnPats :: HsMatchContextRn -> [LPat GhcPs] -> ([LPat GhcRn] -> RnM (a, FreeVars)) -> RnM (a, FreeVars)
- GHC.Rename.Utils: checkUnusedRecordWildcard :: SrcSpan -> FreeVars -> Maybe [Name] -> RnM ()
+ GHC.Rename.Utils: checkUnusedRecordWildcard :: SrcSpan -> FreeVars -> Maybe [ImplicitFieldBinders] -> RnM ()
- GHC.Rename.Utils: genHsIntegralLit :: IntegralLit -> LocatedAn an (HsExpr GhcRn)
+ GHC.Rename.Utils: genHsIntegralLit :: NoAnn an => IntegralLit -> LocatedAn an (HsExpr GhcRn)
- GHC.Rename.Utils: genLHsLit :: HsLit GhcRn -> LocatedAn an (HsExpr GhcRn)
+ GHC.Rename.Utils: genLHsLit :: NoAnn an => HsLit GhcRn -> LocatedAn an (HsExpr GhcRn)
- GHC.Rename.Utils: wrapGenSpan :: a -> LocatedAn an a
+ GHC.Rename.Utils: wrapGenSpan :: NoAnn an => a -> LocatedAn an a
- GHC.Runtime.Interpreter: EvalBreak :: Bool -> HValueRef -> Int -> String -> RemoteRef (ResumeContext b) -> RemotePtr CostCentreStack -> EvalStatus_ a b
+ GHC.Runtime.Interpreter: EvalBreak :: HValueRef -> Maybe EvalBreakpoint -> RemoteRef (ResumeContext b) -> RemotePtr CostCentreStack -> EvalStatus_ a b
- GHC.Runtime.Interpreter: [CreateBCOs] :: [ByteString] -> Message [HValueRef]
+ GHC.Runtime.Interpreter: [CreateBCOs] :: [ResolvedBCO] -> Message [HValueRef]
- GHC.Runtime.Interpreter: [LoadDLL] :: String -> Message (Either String (RemotePtr LoadedDLL))
+ GHC.Runtime.Interpreter: [LoadDLL] :: String -> Message (Maybe String)
- GHC.Runtime.Interpreter: loadDLL :: Interp -> String -> IO (Either String (RemotePtr LoadedDLL))
+ GHC.Runtime.Interpreter: loadDLL :: Interp -> String -> IO (Maybe String)
- GHC.Runtime.Interpreter.Process: [CreateBCOs] :: [ByteString] -> Message [HValueRef]
+ GHC.Runtime.Interpreter.Process: [CreateBCOs] :: [ResolvedBCO] -> Message [HValueRef]
- GHC.Runtime.Interpreter.Process: [LoadDLL] :: String -> Message (Either String (RemotePtr LoadedDLL))
+ GHC.Runtime.Interpreter.Process: [LoadDLL] :: String -> Message (Maybe String)
- GHC.Stg.Subst: lookupIdSubst :: HasDebugCallStack => Id -> Subst -> Id
+ GHC.Stg.Subst: lookupIdSubst :: HasCallStack => Id -> Subst -> Id
- GHC.Stg.Subst: noWarnLookupIdSubst :: HasDebugCallStack => Id -> Subst -> Id
+ GHC.Stg.Subst: noWarnLookupIdSubst :: HasCallStack => Id -> Subst -> Id
- GHC.StgToCmm.Layout: mkVirtConstrSizes :: Profile -> [NonVoid PrimRep] -> (WordOff, WordOff)
+ GHC.StgToCmm.Layout: mkVirtConstrSizes :: Profile -> [PrimRep] -> (WordOff, WordOff)
- GHC.StgToCmm.Monad: StgToCmmConfig :: !Profile -> Module -> !TempDir -> !SDocContext -> !Bool -> !Maybe Word -> !Int -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> (FMASign -> Bool) -> !Bool -> Maybe String -> !Bool -> !Bool -> !Bool -> StgToCmmConfig
+ GHC.StgToCmm.Monad: StgToCmmConfig :: !Profile -> Module -> !TempDir -> !SDocContext -> !Bool -> !Maybe Word -> !Int -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> !Bool -> (FMASign -> Bool) -> !Bool -> Maybe String -> !Bool -> !Bool -> !Bool -> StgToCmmConfig
- GHC.StgToCmm.Ticky: tickySlowCallPat :: [PrimRep] -> FCode ()
+ GHC.StgToCmm.Ticky: tickySlowCallPat :: [StgArg] -> FCode ()
- GHC.StgToJS.Apply: genApp :: HasDebugCallStack => ExprCtx -> Id -> [StgArg] -> G (JStat, ExprResult)
+ GHC.StgToJS.Apply: genApp :: HasDebugCallStack => ExprCtx -> Id -> [StgArg] -> G (JStgStat, ExprResult)
- GHC.StgToJS.Apply: rtsApply :: StgToJSConfig -> JStat
+ GHC.StgToJS.Apply: rtsApply :: StgToJSConfig -> JSM JStgStat
- GHC.StgToJS.Arg: genArg :: HasDebugCallStack => StgArg -> G [JExpr]
+ GHC.StgToJS.Arg: genArg :: HasDebugCallStack => StgArg -> G [JStgExpr]
- GHC.StgToJS.Arg: genIdArg :: HasDebugCallStack => Id -> G [JExpr]
+ GHC.StgToJS.Arg: genIdArg :: HasDebugCallStack => Id -> G [JStgExpr]
- GHC.StgToJS.Arg: jsStaticArg :: StaticArg -> JExpr
+ GHC.StgToJS.Arg: jsStaticArg :: StaticArg -> JStgExpr
- GHC.StgToJS.Arg: jsStaticArgs :: [StaticArg] -> JExpr
+ GHC.StgToJS.Arg: jsStaticArgs :: [StaticArg] -> JStgExpr
- GHC.StgToJS.Closure: Closure :: JExpr -> JExpr -> JExpr -> JExpr -> Maybe JExpr -> Closure
+ GHC.StgToJS.Closure: Closure :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> Maybe JStgExpr -> Closure
- GHC.StgToJS.Closure: [clCC] :: Closure -> Maybe JExpr
+ GHC.StgToJS.Closure: [clCC] :: Closure -> Maybe JStgExpr
- GHC.StgToJS.Closure: [clEntry] :: Closure -> JExpr
+ GHC.StgToJS.Closure: [clEntry] :: Closure -> JStgExpr
- GHC.StgToJS.Closure: [clField1] :: Closure -> JExpr
+ GHC.StgToJS.Closure: [clField1] :: Closure -> JStgExpr
- GHC.StgToJS.Closure: [clField2] :: Closure -> JExpr
+ GHC.StgToJS.Closure: [clField2] :: Closure -> JStgExpr
- GHC.StgToJS.Closure: [clMeta] :: Closure -> JExpr
+ GHC.StgToJS.Closure: [clMeta] :: Closure -> JStgExpr
- GHC.StgToJS.Closure: allocClsA :: Int -> JExpr
+ GHC.StgToJS.Closure: allocClsA :: Int -> JStgExpr
- GHC.StgToJS.Closure: allocData :: Int -> JExpr
+ GHC.StgToJS.Closure: allocData :: Int -> JStgExpr
- GHC.StgToJS.Closure: assignClosure :: JExpr -> Closure -> JStat
+ GHC.StgToJS.Closure: assignClosure :: JStgExpr -> Closure -> JStgStat
- GHC.StgToJS.Closure: closure :: ClosureInfo -> JStat -> JStat
+ GHC.StgToJS.Closure: closure :: ClosureInfo -> JSM JStgStat -> JSM JStgStat
- GHC.StgToJS.Closure: closureInfoStat :: Bool -> ClosureInfo -> JStat
+ GHC.StgToJS.Closure: closureInfoStat :: Bool -> ClosureInfo -> JStgStat
- GHC.StgToJS.Closure: conClosure :: Ident -> FastString -> CILayout -> Int -> JStat
+ GHC.StgToJS.Closure: conClosure :: Ident -> FastString -> CILayout -> Int -> JSM JStgStat
- GHC.StgToJS.Closure: copyClosure :: CopyCC -> JExpr -> JExpr -> JStat
+ GHC.StgToJS.Closure: copyClosure :: CopyCC -> JStgExpr -> JStgExpr -> JStgStat
- GHC.StgToJS.Closure: mkClosure :: JExpr -> [JExpr] -> JExpr -> Maybe JExpr -> Closure
+ GHC.StgToJS.Closure: mkClosure :: JStgExpr -> [JStgExpr] -> JStgExpr -> Maybe JStgExpr -> Closure
- GHC.StgToJS.Closure: newClosure :: Closure -> JExpr
+ GHC.StgToJS.Closure: newClosure :: Closure -> JStgExpr
- GHC.StgToJS.DataCon: allocCon :: Ident -> DataCon -> CostCentreStack -> [JExpr] -> G JStat
+ GHC.StgToJS.DataCon: allocCon :: Ident -> DataCon -> CostCentreStack -> [JStgExpr] -> G JStgStat
- GHC.StgToJS.DataCon: allocDynamic :: StgToJSConfig -> Bool -> Ident -> JExpr -> [JExpr] -> Maybe JExpr -> JStat
+ GHC.StgToJS.DataCon: allocDynamic :: StgToJSConfig -> Bool -> Ident -> JStgExpr -> [JStgExpr] -> Maybe JStgExpr -> JStgStat
- GHC.StgToJS.DataCon: allocDynamicE :: Bool -> JExpr -> [JExpr] -> Maybe JExpr -> JExpr
+ GHC.StgToJS.DataCon: allocDynamicE :: Bool -> JStgExpr -> [JStgExpr] -> Maybe JStgExpr -> JStgExpr
- GHC.StgToJS.DataCon: allocUnboxedCon :: DataCon -> [JExpr] -> JExpr
+ GHC.StgToJS.DataCon: allocUnboxedCon :: DataCon -> [JStgExpr] -> JStgExpr
- GHC.StgToJS.DataCon: genCon :: ExprCtx -> DataCon -> [JExpr] -> G JStat
+ GHC.StgToJS.DataCon: genCon :: ExprCtx -> DataCon -> [JStgExpr] -> G JStgStat
- GHC.StgToJS.Expr: genBody :: HasDebugCallStack => ExprCtx -> StgReg -> [Id] -> CgStgExpr -> Type -> G JStat
+ GHC.StgToJS.Expr: genBody :: HasDebugCallStack => ExprCtx -> StgReg -> [Id] -> CgStgExpr -> Type -> G JStgStat
- GHC.StgToJS.Expr: genExpr :: HasDebugCallStack => ExprCtx -> CgStgExpr -> G (JStat, ExprResult)
+ GHC.StgToJS.Expr: genExpr :: HasDebugCallStack => ExprCtx -> CgStgExpr -> G (JStgStat, ExprResult)
- GHC.StgToJS.Expr: loadLiveFun :: [Id] -> G JStat
+ GHC.StgToJS.Expr: loadLiveFun :: [Id] -> G JStgStat
- GHC.StgToJS.ExprCtx: ctxIsEvaluated :: ExprCtx -> Id -> Bool
+ GHC.StgToJS.ExprCtx: ctxIsEvaluated :: Id -> Bool
- GHC.StgToJS.FFI: genForeignCall :: HasDebugCallStack => ExprCtx -> ForeignCall -> Type -> [JExpr] -> [StgArg] -> G (JStat, ExprResult)
+ GHC.StgToJS.FFI: genForeignCall :: HasDebugCallStack => ExprCtx -> ForeignCall -> Type -> [JStgExpr] -> [StgArg] -> G (JStgStat, ExprResult)
- GHC.StgToJS.FFI: genPrimCall :: ExprCtx -> PrimCall -> [StgArg] -> Type -> G (JStat, ExprResult)
+ GHC.StgToJS.FFI: genPrimCall :: ExprCtx -> PrimCall -> [StgArg] -> Type -> G (JStgStat, ExprResult)
- GHC.StgToJS.Heap: closureCC :: JExpr -> JExpr
+ GHC.StgToJS.Heap: closureCC :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: closureEntry :: JExpr -> JExpr
+ GHC.StgToJS.Heap: closureEntry :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: closureField1 :: JExpr -> JExpr
+ GHC.StgToJS.Heap: closureField1 :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: closureField2 :: JExpr -> JExpr
+ GHC.StgToJS.Heap: closureField2 :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: closureMeta :: JExpr -> JExpr
+ GHC.StgToJS.Heap: closureMeta :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: closureType :: JExpr -> JExpr
+ GHC.StgToJS.Heap: closureType :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: conTag :: JExpr -> JExpr
+ GHC.StgToJS.Heap: conTag :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: conTag' :: JExpr -> JExpr
+ GHC.StgToJS.Heap: conTag' :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: entryClosureType :: JExpr -> JExpr
+ GHC.StgToJS.Heap: entryClosureType :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: funArity :: JExpr -> JExpr
+ GHC.StgToJS.Heap: funArity :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: funArity' :: JExpr -> JExpr
+ GHC.StgToJS.Heap: funArity' :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: funOrPapArity :: JExpr -> Maybe JExpr -> JExpr
+ GHC.StgToJS.Heap: funOrPapArity :: JStgExpr -> Maybe JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: isBlackhole :: JExpr -> JExpr
+ GHC.StgToJS.Heap: isBlackhole :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: isCon :: JExpr -> JExpr
+ GHC.StgToJS.Heap: isCon :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: isCon' :: JExpr -> JExpr
+ GHC.StgToJS.Heap: isCon' :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: isFun :: JExpr -> JExpr
+ GHC.StgToJS.Heap: isFun :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: isFun' :: JExpr -> JExpr
+ GHC.StgToJS.Heap: isFun' :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: isObject :: JExpr -> JExpr
+ GHC.StgToJS.Heap: isObject :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: isPap :: JExpr -> JExpr
+ GHC.StgToJS.Heap: isPap :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: isPap' :: JExpr -> JExpr
+ GHC.StgToJS.Heap: isPap' :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: isThunk :: JExpr -> JExpr
+ GHC.StgToJS.Heap: isThunk :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: isThunk' :: JExpr -> JExpr
+ GHC.StgToJS.Heap: isThunk' :: JStgExpr -> JStgExpr
- GHC.StgToJS.Heap: jTyObject :: JExpr
+ GHC.StgToJS.Heap: jTyObject :: JStgExpr
- GHC.StgToJS.Heap: papArity :: JExpr -> JExpr
+ GHC.StgToJS.Heap: papArity :: JStgExpr -> JStgExpr
- GHC.StgToJS.Ids: declVarsForId :: Id -> G JStat
+ GHC.StgToJS.Ids: declVarsForId :: Id -> G JStgStat
- GHC.StgToJS.Ids: varForDataConEntryId :: Id -> G JExpr
+ GHC.StgToJS.Ids: varForDataConEntryId :: Id -> G JStgExpr
- GHC.StgToJS.Ids: varForDataConWorker :: DataCon -> G JExpr
+ GHC.StgToJS.Ids: varForDataConWorker :: DataCon -> G JStgExpr
- GHC.StgToJS.Ids: varForEntryId :: Id -> G JExpr
+ GHC.StgToJS.Ids: varForEntryId :: Id -> G JStgExpr
- GHC.StgToJS.Ids: varForId :: Id -> G JExpr
+ GHC.StgToJS.Ids: varForId :: Id -> G JStgExpr
- GHC.StgToJS.Ids: varForIdN :: Id -> Int -> G JExpr
+ GHC.StgToJS.Ids: varForIdN :: Id -> Int -> G JStgExpr
- GHC.StgToJS.Ids: varsForId :: Id -> G [JExpr]
+ GHC.StgToJS.Ids: varsForId :: Id -> G [JStgExpr]
- GHC.StgToJS.Linker.Linker: LinkPlan :: Map Module LocatedBlockInfo -> Set BlockRef -> Set FilePath -> Set FilePath -> LinkPlan
+ GHC.StgToJS.Linker.Linker: LinkPlan :: Map Module LocatedBlockInfo -> Set BlockRef -> !Set FilePath -> !Set FilePath -> !Set FilePath -> LinkPlan
- GHC.StgToJS.Linker.Linker: LinkSpec :: [UnitId] -> [LinkedObj] -> (ExportedFun -> Bool) -> Set ExportedFun -> [FilePath] -> LinkSpec
+ GHC.StgToJS.Linker.Linker: LinkSpec :: [UnitId] -> (ExportedFun -> Bool) -> Set ExportedFun -> [FilePath] -> [FilePath] -> [FilePath] -> LinkSpec
- GHC.StgToJS.Linker.Linker: [lkp_archives] :: LinkPlan -> Set FilePath
+ GHC.StgToJS.Linker.Linker: [lkp_archives] :: LinkPlan -> !Set FilePath
- GHC.StgToJS.Linker.Linker: computeLinkDependencies :: StgToJSConfig -> UnitEnv -> LinkSpec -> FinderOpts -> FinderCache -> IO LinkPlan
+ GHC.StgToJS.Linker.Linker: computeLinkDependencies :: StgToJSConfig -> UnitEnv -> LinkSpec -> FinderOpts -> FinderCache -> ArchiveCache -> IO LinkPlan
- GHC.StgToJS.Linker.Linker: jsLink :: JSLinkConfig -> StgToJSConfig -> Logger -> FilePath -> LinkPlan -> IO ()
+ GHC.StgToJS.Linker.Linker: jsLink :: JSLinkConfig -> StgToJSConfig -> Logger -> TmpFs -> ArchiveCache -> FilePath -> LinkPlan -> IO ()
- GHC.StgToJS.Linker.Linker: jsLinkBinary :: FinderCache -> JSLinkConfig -> StgToJSConfig -> [FilePath] -> Logger -> DynFlags -> UnitEnv -> [FilePath] -> [UnitId] -> IO ()
+ GHC.StgToJS.Linker.Linker: jsLinkBinary :: FinderCache -> JSLinkConfig -> StgToJSConfig -> Logger -> TmpFs -> DynFlags -> UnitEnv -> [FilePath] -> [UnitId] -> IO ()
- GHC.StgToJS.Literal: genLit :: HasDebugCallStack => Literal -> G [JExpr]
+ GHC.StgToJS.Literal: genLit :: HasDebugCallStack => Literal -> G [JStgExpr]
- GHC.StgToJS.Monad: assertRtsStat :: G JStat -> G JStat
+ GHC.StgToJS.Monad: assertRtsStat :: G JStgStat -> G JStgStat
- GHC.StgToJS.Monad: emitGlobal :: JStat -> G ()
+ GHC.StgToJS.Monad: emitGlobal :: JStgStat -> G ()
- GHC.StgToJS.Monad: emitToplevel :: JStat -> G ()
+ GHC.StgToJS.Monad: emitToplevel :: JStgStat -> G ()
- GHC.StgToJS.Monad: globalOccs :: JStat -> G [GlobalOcc]
+ GHC.StgToJS.Monad: globalOccs :: JStgStat -> G [GlobalOcc]
- GHC.StgToJS.Prim: genPrim :: Bool -> Bool -> Type -> PrimOp -> [JExpr] -> [JExpr] -> PrimRes
+ GHC.StgToJS.Prim: genPrim :: Bool -> Bool -> Type -> PrimOp -> [JStgExpr] -> [JStgExpr] -> JSM PrimRes
- GHC.StgToJS.Profiling: ccsVarJ :: CostCentreStack -> G (Maybe JExpr)
+ GHC.StgToJS.Profiling: ccsVarJ :: CostCentreStack -> G (Maybe JStgExpr)
- GHC.StgToJS.Profiling: enterCostCentreFun :: CostCentreStack -> JStat
+ GHC.StgToJS.Profiling: enterCostCentreFun :: CostCentreStack -> JStgStat
- GHC.StgToJS.Profiling: enterCostCentreThunk :: JStat
+ GHC.StgToJS.Profiling: enterCostCentreThunk :: JStgStat
- GHC.StgToJS.Profiling: jCafCCS :: JExpr
+ GHC.StgToJS.Profiling: jCafCCS :: JStgExpr
- GHC.StgToJS.Profiling: jCurrentCCS :: JExpr
+ GHC.StgToJS.Profiling: jCurrentCCS :: JStgExpr
- GHC.StgToJS.Profiling: jSystemCCS :: JExpr
+ GHC.StgToJS.Profiling: jSystemCCS :: JStgExpr
- GHC.StgToJS.Profiling: profStat :: StgToJSConfig -> JStat -> JStat
+ GHC.StgToJS.Profiling: profStat :: StgToJSConfig -> JStgStat -> JStgStat
- GHC.StgToJS.Profiling: pushRestoreCCS :: JStat
+ GHC.StgToJS.Profiling: pushRestoreCCS :: JStgStat
- GHC.StgToJS.Profiling: setCC :: CostCentre -> Bool -> Bool -> G JStat
+ GHC.StgToJS.Profiling: setCC :: CostCentre -> Bool -> Bool -> G JStgStat
- GHC.StgToJS.Regs: jsReg :: Int -> JExpr
+ GHC.StgToJS.Regs: jsReg :: Int -> JStgExpr
- GHC.StgToJS.Regs: jsRegsFromR1 :: [JExpr]
+ GHC.StgToJS.Regs: jsRegsFromR1 :: [JStgExpr]
- GHC.StgToJS.Regs: jsRegsFromR2 :: [JExpr]
+ GHC.StgToJS.Regs: jsRegsFromR2 :: [JStgExpr]
- GHC.StgToJS.Regs: r1 :: JExpr
+ GHC.StgToJS.Regs: r1 :: JStgExpr
- GHC.StgToJS.Regs: r2 :: JExpr
+ GHC.StgToJS.Regs: r2 :: JStgExpr
- GHC.StgToJS.Regs: r3 :: JExpr
+ GHC.StgToJS.Regs: r3 :: JStgExpr
- GHC.StgToJS.Regs: r4 :: JExpr
+ GHC.StgToJS.Regs: r4 :: JStgExpr
- GHC.StgToJS.Regs: sp :: JExpr
+ GHC.StgToJS.Regs: sp :: JStgExpr
- GHC.StgToJS.Regs: stack :: JExpr
+ GHC.StgToJS.Regs: stack :: JStgExpr
- GHC.StgToJS.Rts.Rts: assignRegs :: StgToJSConfig -> [JExpr] -> JStat
+ GHC.StgToJS.Rts.Rts: assignRegs :: StgToJSConfig -> [JStgExpr] -> JStgStat
- GHC.StgToJS.Rts.Rts: rts :: StgToJSConfig -> JStat
+ GHC.StgToJS.Rts.Rts: rts :: StgToJSConfig -> JSM JStgStat
- GHC.StgToJS.Rts.Types: assertRts :: ToJExpr a => StgToJSConfig -> JExpr -> a -> JStat
+ GHC.StgToJS.Rts.Types: assertRts :: ToJExpr a => StgToJSConfig -> JStgExpr -> a -> JStgStat
- GHC.StgToJS.Rts.Types: clName :: JExpr -> JExpr
+ GHC.StgToJS.Rts.Types: clName :: JStgExpr -> JStgExpr
- GHC.StgToJS.Rts.Types: clTypeName :: JExpr -> JExpr
+ GHC.StgToJS.Rts.Types: clTypeName :: JStgExpr -> JStgExpr
- GHC.StgToJS.Rts.Types: stackFrameSize :: JExpr -> JExpr -> JStat
+ GHC.StgToJS.Rts.Types: stackFrameSize :: JStgExpr -> JStgExpr -> JSM JStgStat
- GHC.StgToJS.Rts.Types: traceRts :: StgToJSConfig -> JExpr -> JStat
+ GHC.StgToJS.Rts.Types: traceRts :: StgToJSConfig -> JStgExpr -> JStgStat
- GHC.StgToJS.Rts.Types: withRegs :: StgReg -> StgReg -> (StgReg -> JStat) -> JStat
+ GHC.StgToJS.Rts.Types: withRegs :: StgReg -> StgReg -> (StgReg -> JStgStat) -> JStgStat
- GHC.StgToJS.Stack: adjSp :: Int -> G JStat
+ GHC.StgToJS.Stack: adjSp :: Int -> G JStgStat
- GHC.StgToJS.Stack: adjSp' :: Int -> JStat
+ GHC.StgToJS.Stack: adjSp' :: Int -> JStgStat
- GHC.StgToJS.Stack: adjSpN :: Int -> G JStat
+ GHC.StgToJS.Stack: adjSpN :: Int -> G JStgStat
- GHC.StgToJS.Stack: adjSpN' :: Int -> JStat
+ GHC.StgToJS.Stack: adjSpN' :: Int -> JStgStat
- GHC.StgToJS.Stack: bhStats :: StgToJSConfig -> Bool -> JStat
+ GHC.StgToJS.Stack: bhStats :: StgToJSConfig -> Bool -> JStgStat
- GHC.StgToJS.Stack: loadSkip :: Int -> [JExpr] -> JStat
+ GHC.StgToJS.Stack: loadSkip :: Int -> [JStgExpr] -> JStgStat
- GHC.StgToJS.Stack: popN :: Int -> G JStat
+ GHC.StgToJS.Stack: popN :: Int -> G JStgStat
- GHC.StgToJS.Stack: popSkip :: Int -> [JExpr] -> JStat
+ GHC.StgToJS.Stack: popSkip :: Int -> [JStgExpr] -> JStgStat
- GHC.StgToJS.Stack: popSkipI :: Int -> [(Ident, StackSlot)] -> G JStat
+ GHC.StgToJS.Stack: popSkipI :: Int -> [(Ident, StackSlot)] -> G JStgStat
- GHC.StgToJS.Stack: push :: [JExpr] -> G JStat
+ GHC.StgToJS.Stack: push :: [JStgExpr] -> G JStgStat
- GHC.StgToJS.Stack: push' :: StgToJSConfig -> [JExpr] -> JStat
+ GHC.StgToJS.Stack: push' :: StgToJSConfig -> [JStgExpr] -> JStgStat
- GHC.StgToJS.Stack: pushLneFrame :: HasDebugCallStack => Int -> ExprCtx -> G JStat
+ GHC.StgToJS.Stack: pushLneFrame :: HasDebugCallStack => Int -> ExprCtx -> G JStgStat
- GHC.StgToJS.Stack: pushN' :: Array Int JExpr
+ GHC.StgToJS.Stack: pushN' :: Array Int JStgExpr
- GHC.StgToJS.Stack: pushNN' :: Array Integer JExpr
+ GHC.StgToJS.Stack: pushNN' :: Array Integer JStgExpr
- GHC.StgToJS.Stack: pushOptimized :: [(JExpr, Bool)] -> G JStat
+ GHC.StgToJS.Stack: pushOptimized :: [(JStgExpr, Bool)] -> G JStgStat
- GHC.StgToJS.Stack: pushOptimized' :: [(Id, Int)] -> G JStat
+ GHC.StgToJS.Stack: pushOptimized' :: [(Id, Int)] -> G JStgStat
- GHC.StgToJS.Stack: updateThunk :: G JStat
+ GHC.StgToJS.Stack: updateThunk :: G JStgStat
- GHC.StgToJS.Stack: updateThunk' :: StgToJSConfig -> JStat
+ GHC.StgToJS.Stack: updateThunk' :: StgToJSConfig -> JStgStat
- GHC.StgToJS.StaticPtr: initStaticPtrs :: [SptEntry] -> G JStat
+ GHC.StgToJS.StaticPtr: initStaticPtrs :: [SptEntry] -> G JStgStat
- GHC.StgToJS.Utils: assignCoerce1 :: [TypedExpr] -> [TypedExpr] -> JStat
+ GHC.StgToJS.Utils: assignCoerce1 :: [TypedExpr] -> [TypedExpr] -> JStgStat
- GHC.StgToJS.Utils: assignToExprCtx :: ExprCtx -> [JExpr] -> JStat
+ GHC.StgToJS.Utils: assignToExprCtx :: ExprCtx -> [JStgExpr] -> JStgStat
- GHC.StgToJS.Utils: assocIdExprs :: Id -> [JExpr] -> [TypedExpr]
+ GHC.StgToJS.Utils: assocIdExprs :: Id -> [JStgExpr] -> [TypedExpr]
- GHC.StgToJS.Utils: fixedLayout :: [VarType] -> CILayout
+ GHC.StgToJS.Utils: fixedLayout :: [JSRep] -> CILayout
- GHC.StgToJS.Utils: isInlineExpr :: UniqSet Id -> CgStgExpr -> (UniqSet Id, Bool)
+ GHC.StgToJS.Utils: isInlineExpr :: CgStgExpr -> Bool
- GHC.StgToJS.Utils: isMultiVar :: VarType -> Bool
+ GHC.StgToJS.Utils: isMultiVar :: JSRep -> Bool
- GHC.StgToJS.Utils: isUnboxable :: VarType -> Bool
+ GHC.StgToJS.Utils: isUnboxable :: JSRep -> Bool
- GHC.StgToJS.Utils: isVoid :: VarType -> Bool
+ GHC.StgToJS.Utils: isVoid :: JSRep -> Bool
- GHC.StgToJS.Utils: stackSlotType :: Id -> VarType
+ GHC.StgToJS.Utils: stackSlotType :: Id -> JSRep
- GHC.StgToJS.Utils: varSize :: VarType -> Int
+ GHC.StgToJS.Utils: varSize :: JSRep -> Int
- GHC.SysTools.Process: runSomethingResponseFile :: Logger -> TmpFs -> DynFlags -> (String -> String) -> String -> String -> [Option] -> Maybe [(String, String)] -> IO ()
+ GHC.SysTools.Process: runSomethingResponseFile :: Logger -> TmpFs -> TempDir -> (String -> String) -> String -> String -> [Option] -> Maybe [(String, String)] -> IO ()
- GHC.SysTools.Tasks: runCpp :: Logger -> DynFlags -> [Option] -> IO ()
+ GHC.SysTools.Tasks: runCpp :: Logger -> TmpFs -> DynFlags -> [Option] -> IO ()
- GHC.Tc.Deriv.Generate: boxConTbl :: [(Type, LHsExpr GhcPs -> LHsExpr GhcPs)]
+ GHC.Tc.Deriv.Generate: boxConTbl :: [(Type, LHsExpr GhcPs)]
- GHC.Tc.Deriv.Utils: DS :: SrcSpan -> Name -> [TyVar] -> theta -> Class -> [Type] -> SkolemInfo -> UserTypeCtxt -> Maybe OverlapMode -> Maybe SrcSpan -> DerivSpecMechanism -> DerivSpec theta
+ GHC.Tc.Deriv.Utils: DS :: SrcSpan -> Name -> [TyVar] -> theta -> Class -> [Type] -> SkolemInfo -> UserTypeCtxt -> Maybe OverlapMode -> Maybe SrcSpan -> DerivSpecMechanism -> Maybe (WarningTxt GhcRn) -> DerivSpec theta
- GHC.Tc.Deriv.Utils: DerivEnv :: Maybe OverlapMode -> [TyVar] -> Class -> [Type] -> DerivContext -> SkolemInfo -> Maybe (DerivStrategy GhcTc) -> DerivEnv
+ GHC.Tc.Deriv.Utils: DerivEnv :: Maybe OverlapMode -> [TyVar] -> Class -> [Type] -> DerivContext -> SkolemInfo -> Maybe (DerivStrategy GhcTc) -> Maybe (WarningTxt GhcRn) -> DerivEnv
- GHC.Tc.Deriv.Utils: substPredSpec :: HasDebugCallStack => Subst -> PredSpec -> PredSpec
+ GHC.Tc.Deriv.Utils: substPredSpec :: HasCallStack => Subst -> PredSpec -> PredSpec
- GHC.Tc.Errors: solverReportMsg_ExpectedActuals :: TcSolverReportMsg -> [(Type, Type)]
+ GHC.Tc.Errors: solverReportMsg_ExpectedActuals :: TcSolverReportMsg -> Maybe (Type, Type)
- GHC.Tc.Errors: warnDefaulting :: TcTyVar -> [Ct] -> Type -> TcM ()
+ GHC.Tc.Errors: warnDefaulting :: [Ct] -> TcTyVar -> Type -> TcM ()
- GHC.Tc.Gen.Bind: tcLocalBinds :: HsLocalBinds GhcRn -> TcM thing -> TcM (HsLocalBinds GhcTc, thing)
+ GHC.Tc.Gen.Bind: tcLocalBinds :: HsLocalBinds GhcRn -> TcM thing -> TcM (HsLocalBinds GhcTc, HsWrapper, thing)
- GHC.Tc.Gen.Bind: tcPolyCheck :: TcPragEnv -> TcIdSigInfo -> LHsBind GhcRn -> TcM (LHsBinds GhcTc, [TcId])
+ GHC.Tc.Gen.Bind: tcPolyCheck :: TcPragEnv -> TcCompleteSig -> LHsBind GhcRn -> TcM (LHsBinds GhcTc, [Scaled TcId])
- GHC.Tc.Gen.Bind: tcValBinds :: TopLevelFlag -> [(RecFlag, LHsBinds GhcRn)] -> [LSig GhcRn] -> TcM thing -> TcM ([(RecFlag, LHsBinds GhcTc)], thing)
+ GHC.Tc.Gen.Bind: tcValBinds :: TopLevelFlag -> [(RecFlag, LHsBinds GhcRn)] -> [LSig GhcRn] -> TcM thing -> TcM ([(RecFlag, LHsBinds GhcTc)], HsWrapper, thing)
- GHC.Tc.Gen.Head: ETypeArg :: AppCtxt -> !LHsToken "@" GhcRn -> LHsWcType GhcRn -> !XETAType p -> HsExprArg (p :: TcPass)
+ GHC.Tc.Gen.Head: ETypeArg :: AppCtxt -> LHsWcType GhcRn -> !XETAType p -> HsExprArg (p :: TcPass)
- GHC.Tc.Gen.Head: VAExpansion :: HsExpr GhcRn -> SrcSpan -> AppCtxt
+ GHC.Tc.Gen.Head: VAExpansion :: HsThingRn -> SrcSpan -> SrcSpan -> AppCtxt
- GHC.Tc.Gen.Head: addArgWrap :: HsWrapper -> [HsExprArg 'TcpInst] -> [HsExprArg 'TcpInst]
+ GHC.Tc.Gen.Head: addArgWrap :: HsWrapper -> [HsExprArg p] -> [HsExprArg p]
- GHC.Tc.Gen.Head: splitHsApps :: HsExpr GhcRn -> ((HsExpr GhcRn, AppCtxt), [HsExprArg 'TcpRn])
+ GHC.Tc.Gen.Head: splitHsApps :: HsExpr GhcRn -> TcM ((HsExpr GhcRn, AppCtxt), [HsExprArg 'TcpRn])
- GHC.Tc.Gen.Head: tcInferAppHead :: (HsExpr GhcRn, AppCtxt) -> [HsExprArg 'TcpRn] -> TcM (HsExpr GhcTc, TcSigmaType)
+ GHC.Tc.Gen.Head: tcInferAppHead :: (HsExpr GhcRn, AppCtxt) -> TcM (HsExpr GhcTc, TcSigmaType)
- GHC.Tc.Gen.Head: tcInferAppHead_maybe :: HsExpr GhcRn -> [HsExprArg 'TcpRn] -> TcM (Maybe (HsExpr GhcTc, TcSigmaType))
+ GHC.Tc.Gen.Head: tcInferAppHead_maybe :: HsExpr GhcRn -> TcM (Maybe (HsExpr GhcTc, TcSigmaType))
- GHC.Tc.Gen.HsType: tcFamTyPats :: TyCon -> HsTyPats GhcRn -> TcM (TcType, TcKind)
+ GHC.Tc.Gen.HsType: tcFamTyPats :: TyCon -> HsFamEqnPats GhcRn -> TcM (TcType, TcKind)
- GHC.Tc.Gen.Match: checkArgCounts :: AnnoBody body => HsMatchContext GhcTc -> MatchGroup GhcRn (LocatedA (body GhcRn)) -> TcM ()
+ GHC.Tc.Gen.Match: checkArgCounts :: AnnoBody body => MatchGroup GhcRn (LocatedA (body GhcRn)) -> TcM VisArity
- GHC.Tc.Gen.Match: tcGRHSsPat :: GRHSs GhcRn (LHsExpr GhcRn) -> ExpRhoType -> TcM (GRHSs GhcTc (LHsExpr GhcTc))
+ GHC.Tc.Gen.Match: tcGRHSsPat :: Mult -> GRHSs GhcRn (LHsExpr GhcRn) -> ExpRhoType -> TcM (GRHSs GhcTc (LHsExpr GhcTc))
- GHC.Tc.Gen.Match: tcStmts :: AnnoBody body => HsStmtContext GhcTc -> TcStmtChecker body rho_type -> [LStmt GhcRn (LocatedA (body GhcRn))] -> rho_type -> TcM [LStmt GhcTc (LocatedA (body GhcTc))]
+ GHC.Tc.Gen.Match: tcStmts :: AnnoBody body => HsStmtContextRn -> TcStmtChecker body rho_type -> [LStmt GhcRn (LocatedA (body GhcRn))] -> rho_type -> TcM [LStmt GhcTc (LocatedA (body GhcTc))]
- GHC.Tc.Gen.Match: tcStmtsAndThen :: AnnoBody body => HsStmtContext GhcTc -> TcStmtChecker body rho_type -> [LStmt GhcRn (LocatedA (body GhcRn))] -> rho_type -> (rho_type -> TcM thing) -> TcM ([LStmt GhcTc (LocatedA (body GhcTc))], thing)
+ GHC.Tc.Gen.Match: tcStmtsAndThen :: AnnoBody body => HsStmtContextRn -> TcStmtChecker body rho_type -> [LStmt GhcRn (LocatedA (body GhcRn))] -> rho_type -> (rho_type -> TcM thing) -> TcM ([LStmt GhcTc (LocatedA (body GhcTc))], thing)
- GHC.Tc.Gen.Match: type TcStmtChecker body rho_type = forall thing. HsStmtContext GhcTc -> Stmt GhcRn (LocatedA (body GhcRn)) -> rho_type -> (rho_type -> TcM thing) -> TcM (Stmt GhcTc (LocatedA (body GhcTc)), thing)
+ GHC.Tc.Gen.Match: type TcStmtChecker body rho_type = forall thing. HsStmtContextRn -> Stmt GhcRn (LocatedA (body GhcRn)) -> rho_type -> (rho_type -> TcM thing) -> TcM (Stmt GhcTc (LocatedA (body GhcTc)), thing)
- GHC.Tc.Gen.Pat: tcCheckPat :: HsMatchContext GhcTc -> LPat GhcRn -> Scaled TcSigmaTypeFRR -> TcM a -> TcM (LPat GhcTc, a)
+ GHC.Tc.Gen.Pat: tcCheckPat :: HsMatchContextRn -> LPat GhcRn -> Scaled TcSigmaTypeFRR -> TcM a -> TcM (LPat GhcTc, a)
- GHC.Tc.Gen.Pat: tcCheckPat_O :: HsMatchContext GhcTc -> CtOrigin -> LPat GhcRn -> Scaled TcSigmaTypeFRR -> TcM a -> TcM (LPat GhcTc, a)
+ GHC.Tc.Gen.Pat: tcCheckPat_O :: HsMatchContextRn -> CtOrigin -> LPat GhcRn -> Scaled TcSigmaTypeFRR -> TcM a -> TcM (LPat GhcTc, a)
- GHC.Tc.Gen.Pat: tcInferPat :: FixedRuntimeRepContext -> HsMatchContext GhcTc -> LPat GhcRn -> TcM a -> TcM ((LPat GhcTc, a), TcSigmaTypeFRR)
+ GHC.Tc.Gen.Pat: tcInferPat :: FixedRuntimeRepContext -> HsMatchContextRn -> LPat GhcRn -> TcM a -> TcM ((LPat GhcTc, a), TcSigmaTypeFRR)
- GHC.Tc.Gen.Sig: TcIdSig :: TcIdSigInfo -> TcSigInfo
+ GHC.Tc.Gen.Sig: TcIdSig :: TcIdSig -> TcSigInfo
- GHC.Tc.Gen.Sig: TcPatSynSig :: TcPatSynInfo -> TcSigInfo
+ GHC.Tc.Gen.Sig: TcPatSynSig :: TcPatSynSig -> TcSigInfo
- GHC.Tc.Gen.Sig: completeSigFromId :: UserTypeCtxt -> Id -> TcIdSigInfo
+ GHC.Tc.Gen.Sig: completeSigFromId :: UserTypeCtxt -> Id -> TcCompleteSig
- GHC.Tc.Gen.Sig: tcInstSig :: TcIdSigInfo -> TcM TcIdSigInst
+ GHC.Tc.Gen.Sig: tcInstSig :: TcIdSig -> TcM TcIdSigInst
- GHC.Tc.Gen.Sig: tcUserTypeSig :: SrcSpan -> LHsSigWcType GhcRn -> Maybe Name -> TcM TcIdSigInfo
+ GHC.Tc.Gen.Sig: tcUserTypeSig :: SrcSpan -> LHsSigWcType GhcRn -> Maybe Name -> TcM TcIdSig
- GHC.Tc.Instance.Class: TopLevInstance :: DFunId -> SafeOverlapping -> InstanceWhat
+ GHC.Tc.Instance.Class: TopLevInstance :: DFunId -> SafeOverlapping -> Maybe (WarningTxt GhcRn) -> InstanceWhat
- GHC.Tc.Module: type RenamedStuff = (Maybe (HsGroup GhcRn, [LImportDecl GhcRn], Maybe [(LIE GhcRn, Avails)], Maybe (LHsDoc GhcRn)))
+ GHC.Tc.Module: type RenamedStuff = (Maybe (HsGroup GhcRn, [LImportDecl GhcRn], Maybe [(LIE GhcRn, Avails)], Maybe (LHsDoc GhcRn), Maybe (XRec GhcRn ModuleName)))
- GHC.Tc.Solver.Monad: matchGlobalInst :: DynFlags -> Bool -> Class -> [Type] -> TcS ClsInstResult
+ GHC.Tc.Solver.Monad: matchGlobalInst :: DynFlags -> Bool -> Class -> [Type] -> CtLoc -> TcS ClsInstResult
- GHC.Tc.TyCl: tcFamTyPats :: TyCon -> HsTyPats GhcRn -> TcM (TcType, TcKind)
+ GHC.Tc.TyCl: tcFamTyPats :: TyCon -> HsFamEqnPats GhcRn -> TcM (TcType, TcKind)
- GHC.Tc.Utils.Env: tcExtendLetEnv :: TopLevelFlag -> TcSigFun -> IsGroupClosed -> [TcId] -> TcM a -> TcM a
+ GHC.Tc.Utils.Env: tcExtendLetEnv :: TopLevelFlag -> TcSigFun -> IsGroupClosed -> [Scaled TcId] -> TcM a -> TcM (a, HsWrapper)
- GHC.Tc.Utils.Instantiate: instantiateSigma :: CtOrigin -> [TyVar] -> TcThetaType -> TcSigmaType -> TcM ([TcTyVar], HsWrapper, TcSigmaType)
+ GHC.Tc.Utils.Instantiate: instantiateSigma :: CtOrigin -> ConcreteTyVars -> [TyVar] -> TcThetaType -> TcSigmaType -> TcM ([TcTyVar], HsWrapper, TcSigmaType)
- GHC.Tc.Utils.Instantiate: mkOverLit :: OverLitVal -> TcM (HsLit GhcTc)
+ GHC.Tc.Utils.Instantiate: mkOverLit :: OverLitVal -> TcM (HsLit (GhcPass p))
- GHC.Tc.Utils.Instantiate: newClsInst :: Maybe OverlapMode -> Name -> [TyVar] -> ThetaType -> Class -> [Type] -> TcM ClsInst
+ GHC.Tc.Utils.Instantiate: newClsInst :: Maybe OverlapMode -> Name -> [TyVar] -> ThetaType -> Class -> [Type] -> Maybe (WarningTxt GhcRn) -> TcM ClsInst
- GHC.Tc.Utils.Instantiate: topSkolemise :: SkolemInfo -> TcSigmaType -> TcM (HsWrapper, [(Name, TyVar)], [EvVar], TcRhoType)
+ GHC.Tc.Utils.Instantiate: topSkolemise :: SkolemInfo -> TcSigmaType -> TcM (HsWrapper, [(Name, TcInvisTVBinder)], [EvVar], TcRhoType)
- GHC.Tc.Utils.Monad: addLocM :: (a -> TcM b) -> Located a -> TcM b
+ GHC.Tc.Utils.Monad: addLocM :: HasLoc t => (a -> TcM b) -> GenLocated t a -> TcM b
- GHC.Tc.Utils.Monad: setSrcSpanA :: SrcSpanAnn' ann -> TcRn a -> TcRn a
+ GHC.Tc.Utils.Monad: setSrcSpanA :: EpAnn ann -> TcRn a -> TcRn a
- GHC.Tc.Utils.Monad: wrapLocFstMA :: (a -> TcM (b, c)) -> GenLocated (SrcSpanAnn' ann) a -> TcM (GenLocated (SrcSpanAnn' ann) b, c)
+ GHC.Tc.Utils.Monad: wrapLocFstMA :: (a -> TcM (b, c)) -> GenLocated (EpAnn ann) a -> TcM (GenLocated (EpAnn ann) b, c)
- GHC.Tc.Utils.Monad: wrapLocM :: (a -> TcM b) -> Located a -> TcM (Located b)
+ GHC.Tc.Utils.Monad: wrapLocM :: HasLoc t => (a -> TcM b) -> GenLocated t a -> TcM (Located b)
- GHC.Tc.Utils.Monad: wrapLocMA :: (a -> TcM b) -> GenLocated (SrcSpanAnn' ann) a -> TcRn (GenLocated (SrcSpanAnn' ann) b)
+ GHC.Tc.Utils.Monad: wrapLocMA :: (a -> TcM b) -> GenLocated (EpAnn ann) a -> TcRn (GenLocated (EpAnn ann) b)
- GHC.Tc.Utils.Monad: wrapLocSndMA :: (a -> TcM (b, c)) -> GenLocated (SrcSpanAnn' ann) a -> TcM (b, GenLocated (SrcSpanAnn' ann) c)
+ GHC.Tc.Utils.Monad: wrapLocSndMA :: (a -> TcM (b, c)) -> GenLocated (EpAnn ann) a -> TcM (b, GenLocated (EpAnn ann) c)
- GHC.Tc.Utils.TcMType: checkingExpType :: String -> ExpType -> TcType
+ GHC.Tc.Utils.TcMType: checkingExpType :: ExpType -> TcType
- GHC.Tc.Utils.TcMType: mkHsCaseAlt :: forall (p :: Pass) body. (Anno (GRHS (GhcPass p) (LocatedA (body (GhcPass p)))) ~ SrcAnn NoEpAnns, Anno (Match (GhcPass p) (LocatedA (body (GhcPass p)))) ~ SrcSpanAnnA) => LPat (GhcPass p) -> LocatedA (body (GhcPass p)) -> LMatch (GhcPass p) (LocatedA (body (GhcPass p)))
+ GHC.Tc.Utils.TcMType: mkHsCaseAlt :: forall (p :: Pass) body. (Anno (GRHS (GhcPass p) (LocatedA (body (GhcPass p)))) ~ EpAnn NoEpAnns, Anno (Match (GhcPass p) (LocatedA (body (GhcPass p)))) ~ SrcSpanAnnA) => LPat (GhcPass p) -> LocatedA (body (GhcPass p)) -> LMatch (GhcPass p) (LocatedA (body (GhcPass p)))
- GHC.Tc.Utils.Unify: matchExpectedFunTys :: forall a. ExpectedFunTyOrigin -> UserTypeCtxt -> Arity -> ExpRhoType -> ([Scaled ExpSigmaTypeFRR] -> ExpRhoType -> TcM a) -> TcM (HsWrapper, a)
+ GHC.Tc.Utils.Unify: matchExpectedFunTys :: forall a. ExpectedFunTyOrigin -> UserTypeCtxt -> VisArity -> ExpSigmaType -> ([ExpPatType] -> ExpRhoType -> TcM a) -> TcM (HsWrapper, a)

Files

compiler/ClosureTypes.h view
@@ -16,6 +16,7 @@  *   - the closure flags table in rts/ClosureFlags.c  *   - isRetainer in rts/RetainerProfile.c  *   - the closure_type_names list in rts/Printer.c+ *   - the ClosureType sum type in libraries/ghc-internal/src/GHC/Internal/ClosureTypes.hs  */  /* CONSTR/THUNK/FUN_$A_$B mean they have $A pointers followed by $B
compiler/CodeGen.Platform.h view
@@ -480,6 +480,7 @@  #endif +-- See also Note [Caller saves and callee-saves regs.] callerSaves :: GlobalReg -> Bool #if defined(CALLER_SAVES_Base) callerSaves BaseReg           = True
compiler/GHC.hs view
@@ -359,9 +359,6 @@ import GHC.Utils.Misc import GHC.Utils.Outputable import GHC.Utils.Panic-#if !defined(javascript_HOST_ARCH)-import GHC.Utils.Panic.Plain-#endif import GHC.Utils.Logger import GHC.Utils.Fingerprint @@ -397,7 +394,6 @@ import GHC.Types.TypeEnv import GHC.Types.BreakInfo import GHC.Types.PkgQual-import GHC.Types.Unique.FM  import GHC.Unit import GHC.Unit.Env@@ -677,7 +673,6 @@ setTopSessionDynFlags dflags = do   hsc_env <- getSession   logger  <- getLogger-  lookup_cache  <- liftIO $ newMVar emptyUFM    -- Interpreter   interp <- if@@ -707,7 +702,7 @@             }          s <- liftIO $ newMVar InterpPending          loader <- liftIO Loader.uninitializedLoader-         return (Just (Interp (ExternalInterp (ExtIServ (ExtInterpState conf s))) loader lookup_cache))+         return (Just (Interp (ExternalInterp (ExtIServ (ExtInterpState conf s))) loader))      -- JavaScript interpreter     | ArchJavaScript <- platformArch (targetPlatform dflags)@@ -725,7 +720,7 @@               , jsInterpFinderOpts  = initFinderOpts dflags               , jsInterpFinderCache = hsc_FC hsc_env               }-         return (Just (Interp (ExternalInterp (ExtJS (ExtInterpState cfg s))) loader lookup_cache))+         return (Just (Interp (ExternalInterp (ExtJS (ExtInterpState cfg s))) loader))      -- Internal interpreter     | otherwise@@ -733,7 +728,7 @@ #if defined(HAVE_INTERNAL_INTERPRETER)      do       loader <- liftIO Loader.uninitializedLoader-      return (Just (Interp InternalInterp loader lookup_cache))+      return (Just (Interp InternalInterp loader)) #else       return Nothing #endif@@ -1162,7 +1157,7 @@  type ParsedSource      = Located (HsModule GhcPs) type RenamedSource     = (HsGroup GhcRn, [LImportDecl GhcRn], Maybe [(LIE GhcRn, Avails)],-                          Maybe (LHsDoc GhcRn))+                          Maybe (LHsDoc GhcRn), Maybe (XRec GhcRn ModuleName)) type TypecheckedSource = LHsBinds GhcTc  -- NOTE:@@ -1997,6 +1992,6 @@   #if !defined(javascript_HOST_ARCH)-foreign import ccall unsafe "ghc_lib_parser_keepCAFsForGHCi"+foreign import ccall unsafe "keepCAFsForGHCi"     c_keepCAFsForGHCi   :: IO Bool #endif
compiler/GHC/Builtin/Names/TH.hs view
@@ -47,6 +47,7 @@     litPName, varPName, tupPName, unboxedTupPName, unboxedSumPName,     conPName, tildePName, bangPName, infixPName,     asPName, wildPName, recPName, listPName, sigPName, viewPName,+    typePName, invisPName,     -- FieldPat     fieldPatName,     -- Match@@ -61,6 +62,7 @@     fromEName, fromThenEName, fromToEName, fromThenToEName,     listEName, sigEName, recConEName, recUpdEName, staticEName, unboundVarEName,     labelEName, implicitParamVarEName, getFieldEName, projectionEName,+    typeEName,     -- FieldExp     fieldExpName,     -- Body@@ -74,10 +76,11 @@     classDName, instanceWithOverlapDName,     standaloneDerivWithStrategyDName, sigDName, kiSigDName, forImpDName,     pragInlDName, pragOpaqueDName, pragSpecDName, pragSpecInlDName, pragSpecInstDName,-    pragRuleDName, pragCompleteDName, pragAnnDName, defaultSigDName, defaultDName,+    pragRuleDName, pragCompleteDName, pragAnnDName, pragSCCFunDName, pragSCCFunNamedDName,+    defaultSigDName, defaultDName,     dataFamilyDName, openTypeFamilyDName, closedTypeFamilyDName,     dataInstDName, newtypeInstDName, tySynInstDName,-    infixLDName, infixRDName, infixNDName,+    infixLWithSpecDName, infixRWithSpecDName, infixNWithSpecDName,     roleAnnotDName, patSynDName, patSynSigDName,     implicitParamBindDName,     -- Cxt@@ -138,6 +141,9 @@     -- Overlap     overlappableDataConName, overlappingDataConName, overlapsDataConName,     incoherentDataConName,+    -- NamespaceSpecifier+    noNamespaceSpecifierDataConName, typeNamespaceSpecifierDataConName,+    dataNamespaceSpecifierDataConName,     -- DerivStrategy     stockStrategyName, anyclassStrategyName,     newtypeStrategyName, viaStrategyName,@@ -156,7 +162,8 @@     liftClassName, quoteClassName,      -- And the tycons-    qTyConName, nameTyConName, patTyConName, fieldPatTyConName, matchTyConName,+    qTyConName, nameTyConName, patTyConName,+    fieldPatTyConName, matchTyConName,     expQTyConName, fieldExpTyConName, predTyConName,     stmtTyConName,  decsTyConName, conTyConName, bangTypeTyConName,     varBangTypeTyConName, typeQTyConName, expTyConName, decTyConName,@@ -268,7 +275,7 @@ -- data Pat = ... litPName, varPName, tupPName, unboxedTupPName, unboxedSumPName, conPName,     infixPName, tildePName, bangPName, asPName, wildPName, recPName, listPName,-    sigPName, viewPName :: Name+    sigPName, viewPName, typePName, invisPName :: Name litPName   = libFun (fsLit "litP")   litPIdKey varPName   = libFun (fsLit "varP")   varPIdKey tupPName   = libFun (fsLit "tupP")   tupPIdKey@@ -284,6 +291,8 @@ listPName  = libFun (fsLit "listP")  listPIdKey sigPName   = libFun (fsLit "sigP")   sigPIdKey viewPName  = libFun (fsLit "viewP")  viewPIdKey+typePName  = libFun (fsLit "typeP")  typePIdKey+invisPName = libFun (fsLit "invisP")  invisPIdKey  -- type FieldPat = ... fieldPatName :: Name@@ -302,7 +311,7 @@     sectionLName, sectionRName, lamEName, lamCaseEName, lamCasesEName, tupEName,     unboxedTupEName, unboxedSumEName, condEName, multiIfEName, letEName,     caseEName, doEName, mdoEName, compEName, staticEName, unboundVarEName,-    labelEName, implicitParamVarEName, getFieldEName, projectionEName :: Name+    labelEName, implicitParamVarEName, getFieldEName, projectionEName, typeEName :: Name varEName              = libFun (fsLit "varE")              varEIdKey conEName              = libFun (fsLit "conE")              conEIdKey litEName              = libFun (fsLit "litE")              litEIdKey@@ -343,6 +352,7 @@ implicitParamVarEName = libFun (fsLit "implicitParamVarE") implicitParamVarEIdKey getFieldEName         = libFun (fsLit "getFieldE")         getFieldEIdKey projectionEName       = libFun (fsLit "projectionE")       projectionEIdKey+typeEName             = libFun (fsLit "typeE")             typeEIdKey  -- type FieldExp = ... fieldExpName :: Name@@ -370,11 +380,12 @@ funDName, valDName, dataDName, newtypeDName, typeDataDName, tySynDName, classDName,     instanceWithOverlapDName, sigDName, kiSigDName, forImpDName, pragInlDName,     pragSpecDName, pragSpecInlDName, pragSpecInstDName, pragRuleDName,-    pragAnnDName, standaloneDerivWithStrategyDName, defaultSigDName, defaultDName,+    pragAnnDName, pragSCCFunDName, pragSCCFunNamedDName,+    standaloneDerivWithStrategyDName, defaultSigDName, defaultDName,     dataInstDName, newtypeInstDName, tySynInstDName, dataFamilyDName,-    openTypeFamilyDName, closedTypeFamilyDName, infixLDName, infixRDName,-    infixNDName, roleAnnotDName, patSynDName, patSynSigDName,-    pragCompleteDName, implicitParamBindDName, pragOpaqueDName :: Name+    openTypeFamilyDName, closedTypeFamilyDName, infixLWithSpecDName,+    infixRWithSpecDName, infixNWithSpecDName, roleAnnotDName, patSynDName,+    patSynSigDName, pragCompleteDName, implicitParamBindDName, pragOpaqueDName :: Name funDName                         = libFun (fsLit "funD")                         funDIdKey valDName                         = libFun (fsLit "valD")                         valDIdKey dataDName                        = libFun (fsLit "dataD")                        dataDIdKey@@ -397,15 +408,17 @@ pragRuleDName                    = libFun (fsLit "pragRuleD")                    pragRuleDIdKey pragCompleteDName                = libFun (fsLit "pragCompleteD")                pragCompleteDIdKey pragAnnDName                     = libFun (fsLit "pragAnnD")                     pragAnnDIdKey+pragSCCFunDName                  = libFun (fsLit "pragSCCFunD")                  pragSCCFunDKey+pragSCCFunNamedDName             = libFun (fsLit "pragSCCFunNamedD")             pragSCCFunNamedDKey dataInstDName                    = libFun (fsLit "dataInstD")                    dataInstDIdKey newtypeInstDName                 = libFun (fsLit "newtypeInstD")                 newtypeInstDIdKey tySynInstDName                   = libFun (fsLit "tySynInstD")                   tySynInstDIdKey openTypeFamilyDName              = libFun (fsLit "openTypeFamilyD")              openTypeFamilyDIdKey closedTypeFamilyDName            = libFun (fsLit "closedTypeFamilyD")            closedTypeFamilyDIdKey dataFamilyDName                  = libFun (fsLit "dataFamilyD")                  dataFamilyDIdKey-infixLDName                      = libFun (fsLit "infixLD")                      infixLDIdKey-infixRDName                      = libFun (fsLit "infixRD")                      infixRDIdKey-infixNDName                      = libFun (fsLit "infixND")                      infixNDIdKey+infixLWithSpecDName              = libFun (fsLit "infixLWithSpecD")              infixLWithSpecDIdKey+infixRWithSpecDName              = libFun (fsLit "infixRWithSpecD")              infixRWithSpecDIdKey+infixNWithSpecDName              = libFun (fsLit "infixNWithSpecD")              infixNWithSpecDIdKey roleAnnotDName                   = libFun (fsLit "roleAnnotD")                   roleAnnotDIdKey patSynDName                      = libFun (fsLit "patSynD")                      patSynDIdKey patSynSigDName                   = libFun (fsLit "patSynSigD")                   patSynSigDIdKey@@ -647,6 +660,17 @@ overlapsDataConName     = thCon (fsLit "Overlaps")     overlapsDataConKey incoherentDataConName   = thCon (fsLit "Incoherent")   incoherentDataConKey +-- data NamespaceSpecifier = ...+noNamespaceSpecifierDataConName,+  typeNamespaceSpecifierDataConName,+  dataNamespaceSpecifierDataConName :: Name+noNamespaceSpecifierDataConName =+  thCon (fsLit "NoNamespaceSpecifier") noNamespaceSpecifierDataConKey+typeNamespaceSpecifierDataConName =+  thCon (fsLit "TypeNamespaceSpecifier") typeNamespaceSpecifierDataConKey+dataNamespaceSpecifierDataConName =+  thCon (fsLit "DataNamespaceSpecifier") dataNamespaceSpecifierDataConKey+ {- ********************************************************************* *                                                                      *                      Class keys@@ -754,6 +778,13 @@ overlapsDataConKey     = mkPreludeDataConUnique 211 incoherentDataConKey   = mkPreludeDataConUnique 212 +-- data NamespaceSpecifier = ...+noNamespaceSpecifierDataConKey,+  typeNamespaceSpecifierDataConKey,+  dataNamespaceSpecifierDataConKey :: Unique+noNamespaceSpecifierDataConKey = mkPreludeDataConUnique 213+typeNamespaceSpecifierDataConKey = mkPreludeDataConUnique 214+dataNamespaceSpecifierDataConKey = mkPreludeDataConUnique 215 {- ********************************************************************* *                                                                      *                      Id keys@@ -808,7 +839,7 @@ -- data Pat = ... litPIdKey, varPIdKey, tupPIdKey, unboxedTupPIdKey, unboxedSumPIdKey, conPIdKey,   infixPIdKey, tildePIdKey, bangPIdKey, asPIdKey, wildPIdKey, recPIdKey,-  listPIdKey, sigPIdKey, viewPIdKey :: Unique+  listPIdKey, sigPIdKey, viewPIdKey, typePIdKey, invisPIdKey :: Unique litPIdKey         = mkPreludeMiscIdUnique 240 varPIdKey         = mkPreludeMiscIdUnique 241 tupPIdKey         = mkPreludeMiscIdUnique 242@@ -824,6 +855,8 @@ listPIdKey        = mkPreludeMiscIdUnique 252 sigPIdKey         = mkPreludeMiscIdUnique 253 viewPIdKey        = mkPreludeMiscIdUnique 254+typePIdKey        = mkPreludeMiscIdUnique 255+invisPIdKey       = mkPreludeMiscIdUnique 256  -- type FieldPat = ... fieldPatIdKey :: Unique@@ -846,7 +879,7 @@     fromEIdKey, fromThenEIdKey, fromToEIdKey, fromThenToEIdKey,     listEIdKey, sigEIdKey, recConEIdKey, recUpdEIdKey, staticEIdKey,     unboundVarEIdKey, labelEIdKey, implicitParamVarEIdKey, mdoEIdKey,-    getFieldEIdKey, projectionEIdKey :: Unique+    getFieldEIdKey, projectionEIdKey, typeEIdKey :: Unique varEIdKey              = mkPreludeMiscIdUnique 270 conEIdKey              = mkPreludeMiscIdUnique 271 litEIdKey              = mkPreludeMiscIdUnique 272@@ -856,7 +889,7 @@ infixAppIdKey          = mkPreludeMiscIdUnique 276 sectionLIdKey          = mkPreludeMiscIdUnique 277 sectionRIdKey          = mkPreludeMiscIdUnique 278-lamEIdKey              = mkPreludeMiscIdUnique 279+lamEIdKey           = mkPreludeMiscIdUnique 279 lamCaseEIdKey          = mkPreludeMiscIdUnique 280 lamCasesEIdKey         = mkPreludeMiscIdUnique 281 tupEIdKey              = mkPreludeMiscIdUnique 282@@ -883,28 +916,29 @@ mdoEIdKey              = mkPreludeMiscIdUnique 303 getFieldEIdKey         = mkPreludeMiscIdUnique 304 projectionEIdKey       = mkPreludeMiscIdUnique 305+typeEIdKey             = mkPreludeMiscIdUnique 306  -- type FieldExp = ... fieldExpIdKey :: Unique-fieldExpIdKey       = mkPreludeMiscIdUnique 306+fieldExpIdKey       = mkPreludeMiscIdUnique 307  -- data Body = ... guardedBIdKey, normalBIdKey :: Unique-guardedBIdKey     = mkPreludeMiscIdUnique 307-normalBIdKey      = mkPreludeMiscIdUnique 308+guardedBIdKey     = mkPreludeMiscIdUnique 308+normalBIdKey      = mkPreludeMiscIdUnique 309  -- data Guard = ... normalGEIdKey, patGEIdKey :: Unique-normalGEIdKey     = mkPreludeMiscIdUnique 309-patGEIdKey        = mkPreludeMiscIdUnique 310+normalGEIdKey     = mkPreludeMiscIdUnique 310+patGEIdKey        = mkPreludeMiscIdUnique 311  -- data Stmt = ... bindSIdKey, letSIdKey, noBindSIdKey, parSIdKey, recSIdKey :: Unique-bindSIdKey       = mkPreludeMiscIdUnique 311-letSIdKey        = mkPreludeMiscIdUnique 312-noBindSIdKey     = mkPreludeMiscIdUnique 313-parSIdKey        = mkPreludeMiscIdUnique 314-recSIdKey        = mkPreludeMiscIdUnique 315+bindSIdKey       = mkPreludeMiscIdUnique 312+letSIdKey        = mkPreludeMiscIdUnique 313+noBindSIdKey     = mkPreludeMiscIdUnique 314+parSIdKey        = mkPreludeMiscIdUnique 315+recSIdKey        = mkPreludeMiscIdUnique 316  -- data Dec = ... funDIdKey, valDIdKey, dataDIdKey, newtypeDIdKey, tySynDIdKey, classDIdKey,@@ -913,9 +947,10 @@     pragRuleDIdKey, pragAnnDIdKey, defaultSigDIdKey, dataFamilyDIdKey,     openTypeFamilyDIdKey, closedTypeFamilyDIdKey, dataInstDIdKey,     newtypeInstDIdKey, tySynInstDIdKey, standaloneDerivWithStrategyDIdKey,-    infixLDIdKey, infixRDIdKey, infixNDIdKey, roleAnnotDIdKey, patSynDIdKey,-    patSynSigDIdKey, pragCompleteDIdKey, implicitParamBindDIdKey,-    kiSigDIdKey, defaultDIdKey, pragOpaqueDIdKey, typeDataDIdKey :: Unique+    infixLWithSpecDIdKey, infixRWithSpecDIdKey, infixNWithSpecDIdKey,+    roleAnnotDIdKey, patSynDIdKey, patSynSigDIdKey, pragCompleteDIdKey,+    implicitParamBindDIdKey, kiSigDIdKey, defaultDIdKey, pragOpaqueDIdKey,+    typeDataDIdKey, pragSCCFunDKey, pragSCCFunNamedDKey :: Unique funDIdKey                         = mkPreludeMiscIdUnique 320 valDIdKey                         = mkPreludeMiscIdUnique 321 dataDIdKey                        = mkPreludeMiscIdUnique 322@@ -938,9 +973,9 @@ newtypeInstDIdKey                 = mkPreludeMiscIdUnique 339 tySynInstDIdKey                   = mkPreludeMiscIdUnique 340 closedTypeFamilyDIdKey            = mkPreludeMiscIdUnique 341-infixLDIdKey                      = mkPreludeMiscIdUnique 342-infixRDIdKey                      = mkPreludeMiscIdUnique 343-infixNDIdKey                      = mkPreludeMiscIdUnique 344+infixLWithSpecDIdKey              = mkPreludeMiscIdUnique 342+infixRWithSpecDIdKey              = mkPreludeMiscIdUnique 343+infixNWithSpecDIdKey              = mkPreludeMiscIdUnique 344 roleAnnotDIdKey                   = mkPreludeMiscIdUnique 345 standaloneDerivWithStrategyDIdKey = mkPreludeMiscIdUnique 346 defaultSigDIdKey                  = mkPreludeMiscIdUnique 347@@ -952,6 +987,8 @@ defaultDIdKey                     = mkPreludeMiscIdUnique 353 pragOpaqueDIdKey                  = mkPreludeMiscIdUnique 354 typeDataDIdKey                    = mkPreludeMiscIdUnique 355+pragSCCFunDKey                    = mkPreludeMiscIdUnique 356+pragSCCFunNamedDKey               = mkPreludeMiscIdUnique 357  -- type Cxt = ... cxtIdKey :: Unique@@ -1147,29 +1184,7 @@ ************************************************************************ -} -lift_RDR, liftTyped_RDR, mkNameG_dRDR, mkNameG_vRDR, mkNameG_fldRDR,-  unsafeCodeCoerce_RDR :: RdrName+lift_RDR, liftTyped_RDR, unsafeCodeCoerce_RDR :: RdrName lift_RDR     = nameRdrName liftName liftTyped_RDR = nameRdrName liftTypedName unsafeCodeCoerce_RDR = nameRdrName unsafeCodeCoerceName-mkNameG_dRDR = nameRdrName mkNameG_dName-mkNameG_vRDR = nameRdrName mkNameG_vName-mkNameG_fldRDR = nameRdrName mkNameG_fldName---- data Exp = ...-conE_RDR, litE_RDR, appE_RDR, infixApp_RDR :: RdrName-conE_RDR     = nameRdrName conEName-litE_RDR     = nameRdrName litEName-appE_RDR     = nameRdrName appEName-infixApp_RDR = nameRdrName infixAppName---- data Lit = ...-stringL_RDR, intPrimL_RDR, wordPrimL_RDR, floatPrimL_RDR,-    doublePrimL_RDR, stringPrimL_RDR, charPrimL_RDR :: RdrName-stringL_RDR     = nameRdrName stringLName-intPrimL_RDR    = nameRdrName intPrimLName-wordPrimL_RDR   = nameRdrName wordPrimLName-floatPrimL_RDR  = nameRdrName floatPrimLName-doublePrimL_RDR = nameRdrName doublePrimLName-stringPrimL_RDR = nameRdrName stringPrimLName-charPrimL_RDR   = nameRdrName charPrimLName
compiler/GHC/Builtin/PrimOps/Casts.hs view
@@ -13,7 +13,6 @@ import GHC.Core.TyCon import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Types.RepType import GHC.Core.Type import GHC.Builtin.Types.Prim
compiler/GHC/Builtin/Types/Literals.hs view
@@ -40,10 +40,10 @@ import GHC.Builtin.Types import GHC.Builtin.Types.Prim  ( mkTemplateAnonTyConBinders ) import GHC.Builtin.Names-                  ( gHC_TYPELITS-                  , gHC_TYPELITS_INTERNAL-                  , gHC_TYPENATS-                  , gHC_TYPENATS_INTERNAL+                  ( gHC_INTERNAL_TYPELITS+                  , gHC_INTERNAL_TYPELITS_INTERNAL+                  , gHC_INTERNAL_TYPENATS+                  , gHC_INTERNAL_TYPENATS_INTERNAL                   , typeNatAddTyFamNameKey                   , typeNatMulTyFamNameKey                   , typeNatExpTyFamNameKey@@ -172,7 +172,7 @@     , sfInteractInert = interactInertAdd     }   where-  name = mkWiredInTyConName UserSyntax gHC_TYPENATS (fsLit "+")+  name = mkWiredInTyConName UserSyntax gHC_INTERNAL_TYPENATS (fsLit "+")             typeNatAddTyFamNameKey typeNatAddTyCon  typeNatSubTyCon :: TyCon@@ -183,7 +183,7 @@     , sfInteractInert = interactInertSub     }   where-  name = mkWiredInTyConName UserSyntax gHC_TYPENATS (fsLit "-")+  name = mkWiredInTyConName UserSyntax gHC_INTERNAL_TYPENATS (fsLit "-")             typeNatSubTyFamNameKey typeNatSubTyCon  typeNatMulTyCon :: TyCon@@ -194,7 +194,7 @@     , sfInteractInert = interactInertMul     }   where-  name = mkWiredInTyConName UserSyntax gHC_TYPENATS (fsLit "*")+  name = mkWiredInTyConName UserSyntax gHC_INTERNAL_TYPENATS (fsLit "*")             typeNatMulTyFamNameKey typeNatMulTyCon  typeNatDivTyCon :: TyCon@@ -205,7 +205,7 @@     , sfInteractInert = interactInertDiv     }   where-  name = mkWiredInTyConName UserSyntax gHC_TYPENATS (fsLit "Div")+  name = mkWiredInTyConName UserSyntax gHC_INTERNAL_TYPENATS (fsLit "Div")             typeNatDivTyFamNameKey typeNatDivTyCon  typeNatModTyCon :: TyCon@@ -216,7 +216,7 @@     , sfInteractInert = interactInertMod     }   where-  name = mkWiredInTyConName UserSyntax gHC_TYPENATS (fsLit "Mod")+  name = mkWiredInTyConName UserSyntax gHC_INTERNAL_TYPENATS (fsLit "Mod")             typeNatModTyFamNameKey typeNatModTyCon  typeNatExpTyCon :: TyCon@@ -227,7 +227,7 @@     , sfInteractInert = interactInertExp     }   where-  name = mkWiredInTyConName UserSyntax gHC_TYPENATS (fsLit "^")+  name = mkWiredInTyConName UserSyntax gHC_INTERNAL_TYPENATS (fsLit "^")                 typeNatExpTyFamNameKey typeNatExpTyCon  typeNatLogTyCon :: TyCon@@ -238,7 +238,7 @@     , sfInteractInert = interactInertLog     }   where-  name = mkWiredInTyConName UserSyntax gHC_TYPENATS (fsLit "Log2")+  name = mkWiredInTyConName UserSyntax gHC_INTERNAL_TYPENATS (fsLit "Log2")             typeNatLogTyFamNameKey typeNatLogTyCon  @@ -254,7 +254,7 @@     NotInjective    where-  name = mkWiredInTyConName UserSyntax gHC_TYPENATS_INTERNAL (fsLit "CmpNat")+  name = mkWiredInTyConName UserSyntax gHC_INTERNAL_TYPENATS_INTERNAL (fsLit "CmpNat")                 typeNatCmpTyFamNameKey typeNatCmpTyCon   ops = BuiltInSynFamily     { sfMatchFam      = matchFamCmpNat@@ -273,7 +273,7 @@     NotInjective    where-  name = mkWiredInTyConName UserSyntax gHC_TYPELITS_INTERNAL (fsLit "CmpSymbol")+  name = mkWiredInTyConName UserSyntax gHC_INTERNAL_TYPELITS_INTERNAL (fsLit "CmpSymbol")                 typeSymbolCmpTyFamNameKey typeSymbolCmpTyCon   ops = BuiltInSynFamily     { sfMatchFam      = matchFamCmpSymbol@@ -289,7 +289,7 @@     , sfInteractInert = interactInertAppendSymbol     }   where-  name = mkWiredInTyConName UserSyntax gHC_TYPELITS (fsLit "AppendSymbol")+  name = mkWiredInTyConName UserSyntax gHC_INTERNAL_TYPELITS (fsLit "AppendSymbol")                 typeSymbolAppendFamNameKey typeSymbolAppendTyCon  typeConsSymbolTyCon :: TyCon@@ -302,7 +302,7 @@     Nothing     (Injective [True, True])   where-  name = mkWiredInTyConName UserSyntax gHC_TYPELITS (fsLit "ConsSymbol")+  name = mkWiredInTyConName UserSyntax gHC_INTERNAL_TYPELITS (fsLit "ConsSymbol")                   typeConsSymbolTyFamNameKey typeConsSymbolTyCon   ops = BuiltInSynFamily       { sfMatchFam      = matchFamConsSymbol@@ -320,7 +320,7 @@     Nothing     (Injective [True])   where-  name = mkWiredInTyConName UserSyntax gHC_TYPELITS (fsLit "UnconsSymbol")+  name = mkWiredInTyConName UserSyntax gHC_INTERNAL_TYPELITS (fsLit "UnconsSymbol")                   typeUnconsSymbolTyFamNameKey typeUnconsSymbolTyCon   ops = BuiltInSynFamily       { sfMatchFam      = matchFamUnconsSymbol@@ -338,7 +338,7 @@     Nothing     (Injective [True])   where-  name = mkWiredInTyConName UserSyntax gHC_TYPELITS (fsLit "CharToNat")+  name = mkWiredInTyConName UserSyntax gHC_INTERNAL_TYPELITS (fsLit "CharToNat")                   typeCharToNatTyFamNameKey typeCharToNatTyCon   ops = BuiltInSynFamily       { sfMatchFam      = matchFamCharToNat@@ -357,7 +357,7 @@     Nothing     (Injective [True])   where-  name = mkWiredInTyConName UserSyntax gHC_TYPELITS (fsLit "NatToChar")+  name = mkWiredInTyConName UserSyntax gHC_INTERNAL_TYPELITS (fsLit "NatToChar")                   typeNatToCharTyFamNameKey typeNatToCharTyCon   ops = BuiltInSynFamily       { sfMatchFam      = matchFamNatToChar@@ -1130,7 +1130,7 @@     Nothing     NotInjective   where-  name = mkWiredInTyConName UserSyntax gHC_TYPELITS_INTERNAL (fsLit "CmpChar")+  name = mkWiredInTyConName UserSyntax gHC_INTERNAL_TYPELITS_INTERNAL (fsLit "CmpChar")                   typeCharCmpTyFamNameKey typeCharCmpTyCon   ops = BuiltInSynFamily       { sfMatchFam      = matchFamCmpChar
compiler/GHC/Builtin/Utils.hs view
@@ -67,7 +67,7 @@ import GHC.Types.Unique.FM import GHC.Types.Unique.Map import GHC.Types.TyThing-import GHC.Types.Unique ( isValidKnownKeyUnique )+import GHC.Types.Unique ( isValidKnownKeyUnique, pprUniqueAlways )  import GHC.Utils.Outputable import GHC.Utils.Misc as Utils@@ -79,7 +79,7 @@ import GHC.Data.List.SetOps  import Control.Applicative ((<|>))-import Data.List        ( intercalate , find )+import Data.List        ( find ) import Data.Maybe  {-@@ -116,12 +116,8 @@ knownKeyNames :: [Name] knownKeyNames   | debugIsOn-  , Just badNamesStr <- knownKeyNamesOkay all_names-  = panic ("badAllKnownKeyNames:\n" ++ badNamesStr)-       -- NB: We can't use ppr here, because this is sometimes evaluated in a-       -- context where there are no DynFlags available, leading to a cryptic-       -- "<<details unavailable>>" error. (This seems to happen only in the-       -- stage 2 compiler, for reasons I [Richard] have no clue of.)+  , Just badNamesDoc <- knownKeyNamesOkay all_names+  = pprPanic "badAllKnownKeyNames" badNamesDoc   | otherwise   = all_names   where@@ -161,16 +157,15 @@                         Nothing -> []  -- | Check the known-key names list of consistency.-knownKeyNamesOkay :: [Name] -> Maybe String+knownKeyNamesOkay :: [Name] -> Maybe SDoc knownKeyNamesOkay all_names   | ns@(_:_) <- filter (not . isValidKnownKeyUnique . getUnique) all_names-  = Just $ "    Out-of-range known-key uniques: ["-        ++ intercalate ", " (map (occNameString . nameOccName) ns) ++-         "]"+  = Just $ text "    Out-of-range known-key uniques: " <>+           brackets (pprWithCommas (ppr . nameOccName) ns)   | null badNamesPairs   = Nothing   | otherwise-  = Just badNamesStr+  = Just badNamesDoc   where     namesEnv      = foldl' (\m n -> extendNameEnv_Acc (:) Utils.singleton m n n)                            emptyUFM all_names@@ -178,14 +173,14 @@     badNamesPairs = nonDetUFMToList badNamesEnv       -- It's OK to use nonDetUFMToList here because the ordering only affects       -- the message when we get a panic-    badNamesStrs  = map pairToStr badNamesPairs-    badNamesStr   = unlines badNamesStrs+    badNamesDoc :: SDoc+    badNamesDoc  = vcat $ map pairToDoc badNamesPairs -    pairToStr (uniq, ns) = "        " ++-                           show uniq ++-                           ": [" ++-                           intercalate ", " (map (occNameString . nameOccName) ns) ++-                           "]"+    pairToDoc :: (Unique, [Name]) -> SDoc+    pairToDoc (uniq, ns) = text "        " <>+                           pprUniqueAlways uniq <>+                           text ": " <>+                           brackets (pprWithCommas (ppr . nameOccName) ns)  -- | Given a 'Unique' lookup its associated 'Name' if it corresponds to a -- known-key thing.
compiler/GHC/ByteCode/Asm.hs view
@@ -43,23 +43,19 @@ import GHC.Platform.Profile  import Control.Monad-import Control.Monad.ST ( runST ) import Control.Monad.Trans.Class import Control.Monad.Trans.State.Strict -import Data.Array.MArray- import qualified Data.Array.Unboxed as Array import Data.Array.Base  ( UArray(..) ) -import Data.Array.Unsafe( castSTUArray )- import Foreign hiding (shiftL, shiftR) import Data.Char        ( ord ) import Data.List        ( genericLength ) import Data.Map.Strict (Map) import Data.Maybe (fromMaybe) import qualified Data.Map.Strict as Map+import GHC.Float (castFloatToWord32, castDoubleToWord64)  -- ----------------------------------------------------------------------------- -- Unlinked BCOs@@ -416,7 +412,7 @@                                                                 tuple_proto                                  p <- ioptr (liftM BCOPtrBCO ul_bco)                                  p_tup <- ioptr (liftM BCOPtrBCO ul_tuple_bco)-                                 info <- int (fromIntegral $+                                 info <- word (fromIntegral $                                               mkNativeCallInfoSig platform call_info)                                  emit bci_PUSH_ALTS_T                                       [Op p, Op info, Op p_tup]@@ -466,21 +462,21 @@                                  emit bci_TESTLT_W [Op np, LabelOp l]   TESTEQ_W  w l            -> do np <- word w                                  emit bci_TESTEQ_W [Op np, LabelOp l]-  TESTLT_I64  i l          -> do np <- int64 i+  TESTLT_I64  i l          -> do np <- word64 (fromIntegral i)                                  emit bci_TESTLT_I64 [Op np, LabelOp l]-  TESTEQ_I64  i l          -> do np <- int64 i+  TESTEQ_I64  i l          -> do np <- word64 (fromIntegral i)                                  emit bci_TESTEQ_I64 [Op np, LabelOp l]-  TESTLT_I32  i l          -> do np <- int (fromIntegral i)+  TESTLT_I32  i l          -> do np <- word (fromIntegral i)                                  emit bci_TESTLT_I32 [Op np, LabelOp l]-  TESTEQ_I32 i l           -> do np <- int (fromIntegral i)+  TESTEQ_I32 i l           -> do np <- word (fromIntegral i)                                  emit bci_TESTEQ_I32 [Op np, LabelOp l]-  TESTLT_I16  i l          -> do np <- int (fromIntegral i)+  TESTLT_I16  i l          -> do np <- word (fromIntegral i)                                  emit bci_TESTLT_I16 [Op np, LabelOp l]-  TESTEQ_I16 i l           -> do np <- int (fromIntegral i)+  TESTEQ_I16 i l           -> do np <- word (fromIntegral i)                                  emit bci_TESTEQ_I16 [Op np, LabelOp l]-  TESTLT_I8  i l           -> do np <- int (fromIntegral i)+  TESTLT_I8  i l           -> do np <- word (fromIntegral i)                                  emit bci_TESTLT_I8 [Op np, LabelOp l]-  TESTEQ_I8 i l            -> do np <- int (fromIntegral i)+  TESTEQ_I8 i l            -> do np <- word (fromIntegral i)                                  emit bci_TESTEQ_I8 [Op np, LabelOp l]   TESTLT_W64  w l          -> do np <- word64 w                                  emit bci_TESTLT_W64 [Op np, LabelOp l]@@ -517,7 +513,7 @@   CCALL off m_addr i       -> do np <- addr m_addr                                  emit bci_CCALL [wOp off, Op np, SmallOp i]   PRIMCALL                 -> emit bci_PRIMCALL []-  BRK_FUN index mod cc     -> do p1 <- ptr BCOPtrBreakArray+  BRK_FUN arr index mod cc -> do p1 <- ptr (BCOPtrBreakArray arr)                                  m <- addr mod                                  np <- addr cc                                  emit bci_BRK_FUN [Op p1, SmallOp index,@@ -530,43 +526,81 @@      -- On Windows, stdcall labels have a suffix indicating the no. of      -- arg words, e.g. foo@8.  testcase: ffi012(ghci)     literal (LitLabel fs _ _) = litlabel fs-    literal LitNullAddr       = int 0+    literal LitNullAddr       = word 0     literal (LitFloat r)      = float (fromRational r)     literal (LitDouble r)     = double (fromRational r)     literal (LitChar c)       = int (ord c)     literal (LitString bs)    = lit [BCONPtrStr bs]        -- LitString requires a zero-terminator when emitted     literal (LitNumber nt i) = case nt of-      LitNumInt     -> int (fromIntegral i)-      LitNumWord    -> int (fromIntegral i)-      LitNumInt8    -> int8 (fromIntegral i)-      LitNumWord8   -> int8 (fromIntegral i)-      LitNumInt16   -> int16 (fromIntegral i)-      LitNumWord16  -> int16 (fromIntegral i)-      LitNumInt32   -> int32 (fromIntegral i)-      LitNumWord32  -> int32 (fromIntegral i)-      LitNumInt64   -> int64 (fromIntegral i)-      LitNumWord64  -> int64 (fromIntegral i)+      LitNumInt     -> word (fromIntegral i)+      LitNumWord    -> word (fromIntegral i)+      LitNumInt8    -> word8 (fromIntegral i)+      LitNumWord8   -> word8 (fromIntegral i)+      LitNumInt16   -> word16 (fromIntegral i)+      LitNumWord16  -> word16 (fromIntegral i)+      LitNumInt32   -> word32 (fromIntegral i)+      LitNumWord32  -> word32 (fromIntegral i)+      LitNumInt64   -> word64 (fromIntegral i)+      LitNumWord64  -> word64 (fromIntegral i)       LitNumBigNat  -> panic "GHC.ByteCode.Asm.literal: LitNumBigNat"      -- We can lower 'LitRubbish' to an arbitrary constant, but @NULL@ is most     -- likely to elicit a crash (rather than corrupt memory) in case absence     -- analysis messed up.-    literal (LitRubbish {}) = int 0+    literal (LitRubbish {}) = word 0      litlabel fs = lit [BCONPtrLbl fs]     addr (RemotePtr a) = words [fromIntegral a]-    float = words . mkLitF platform-    double = words . mkLitD platform-    int = words . mkLitI-    int8 = words . mkLitI64 platform-    int16 = words . mkLitI64 platform-    int32 = words . mkLitI64 platform-    int64 = words . mkLitI64 platform-    word64 = words . mkLitW64 platform     words ws = lit (map BCONPtrWord ws)     word w = words [w]+    word_size  = platformWordSize platform+    word_size_bits = platformWordSizeInBits platform +    -- Make lists of host-sized words for literals, so that when the+    -- words are placed in memory at increasing addresses, the+    -- bit pattern is correct for the host's word size and endianness.+    --+    -- Note that we only support host endianness == target endianness for now,+    -- even with the external interpreter. This would need to be fixed to+    -- support host endianness /= target endianness+    int :: Int -> Assembler Word+    int  i = word (fromIntegral i)++    float :: Float -> Assembler Word+    float f = word32 (castFloatToWord32 f)++    double :: Double -> Assembler Word+    double d = word64 (castDoubleToWord64 d)++    word64 :: Word64 -> Assembler Word+    word64 ww = case word_size of+       PW4 ->+        let !wl = fromIntegral ww+            !wh = fromIntegral (ww `unsafeShiftR` 32)+        in case platformByteOrder platform of+            LittleEndian -> words [wl,wh]+            BigEndian    -> words [wh,wl]+       PW8 -> word (fromIntegral ww)++    word8 :: Word8 -> Assembler Word+    word8  x = case platformByteOrder platform of+      LittleEndian -> word (fromIntegral x)+      BigEndian    -> word (fromIntegral x `unsafeShiftL` (word_size_bits - 8))++    word16 :: Word16 -> Assembler Word+    word16 x = case platformByteOrder platform of+      LittleEndian -> word (fromIntegral x)+      BigEndian    -> word (fromIntegral x `unsafeShiftL` (word_size_bits - 16))++    word32 :: Word32 -> Assembler Word+    word32 x = case platformByteOrder platform of+      LittleEndian -> word (fromIntegral x)+      BigEndian    -> case word_size of+        PW4 -> word (fromIntegral x)+        PW8 -> word (fromIntegral x `unsafeShiftL` 32)++ isLargeW :: Word -> Bool isLargeW n = n > 65535 @@ -647,75 +681,6 @@ mkNativeCallInfoLit :: Platform -> NativeCallInfo -> Literal mkNativeCallInfoLit platform call_info =   mkLitWord platform . fromIntegral $ mkNativeCallInfoSig platform call_info---- Make lists of host-sized words for literals, so that when the--- words are placed in memory at increasing addresses, the--- bit pattern is correct for the host's word size and endianness.-mkLitI   ::             Int    -> [Word]-mkLitF   :: Platform -> Float  -> [Word]-mkLitD   :: Platform -> Double -> [Word]-mkLitI64 :: Platform -> Int64  -> [Word]-mkLitW64 :: Platform -> Word64 -> [Word]--mkLitF platform f = case platformWordSize platform of-  PW4 -> runST $ do-        arr <- newArray_ ((0::Int),0)-        writeArray arr 0 f-        f_arr <- castSTUArray arr-        w0 <- readArray f_arr 0-        return [w0 :: Word]--  PW8 -> runST $ do-        arr <- newArray_ ((0::Int),1)-        writeArray arr 0 f-        -- on 64-bit architectures we read two (32-bit) Float cells when we read-        -- a (64-bit) Word: so we write a dummy value in the second cell to-        -- avoid an out-of-bound read.-        writeArray arr 1 0.0-        f_arr <- castSTUArray arr-        w0 <- readArray f_arr 0-        return [w0 :: Word]--mkLitD platform d = case platformWordSize platform of-   PW4 -> runST (do-        arr <- newArray_ ((0::Int),1)-        writeArray arr 0 d-        d_arr <- castSTUArray arr-        w0 <- readArray d_arr 0-        w1 <- readArray d_arr 1-        return [w0 :: Word, w1]-     )-   PW8 -> runST (do-        arr <- newArray_ ((0::Int),0)-        writeArray arr 0 d-        d_arr <- castSTUArray arr-        w0 <- readArray d_arr 0-        return [w0 :: Word]-     )--mkLitI64 platform ii = case platformWordSize platform of-   PW4 -> runST (do-        arr <- newArray_ ((0::Int),1)-        writeArray arr 0 ii-        d_arr <- castSTUArray arr-        w0 <- readArray d_arr 0-        w1 <- readArray d_arr 1-        return [w0 :: Word,w1]-     )-   PW8 -> [fromIntegral ii :: Word]--mkLitW64 platform ww = case platformWordSize platform of-   PW4 -> runST (do-        arr <- newArray_ ((0::Word),1)-        writeArray arr 0 ww-        d_arr <- castSTUArray arr-        w0 <- readArray d_arr 0-        w1 <- readArray d_arr 1-        return [w0 :: Word,w1]-     )-   PW8 -> [fromIntegral ww :: Word]--mkLitI i = [fromIntegral i :: Word]  iNTERP_STACK_CHECK_THRESH :: Int iNTERP_STACK_CHECK_THRESH = INTERP_STACK_CHECK_THRESH
compiler/GHC/ByteCode/InfoTable.hs view
@@ -25,7 +25,7 @@ import GHC.Core.Multiplicity     ( scaledThing )  import GHC.StgToCmm.Layout  ( mkVirtConstrSizes )-import GHC.StgToCmm.Closure ( tagForCon, NonVoid (..) )+import GHC.StgToCmm.Closure ( tagForCon )  import GHC.Utils.Misc import GHC.Utils.Panic@@ -61,7 +61,7 @@  where   mk_itbl :: DataCon -> Int -> IO (Name,ItblPtr)   mk_itbl dcon conNo = do-     let rep_args = [ NonVoid prim_rep+     let rep_args = [ prim_rep                     | arg <- dataConRepArgTys dcon                     , prim_rep <- typePrimRep (scaledThing arg) ] 
compiler/GHC/ByteCode/Instr.hs view
@@ -30,6 +30,7 @@ import GHC.Stack.CCS (CostCentre)  import GHC.Stg.Syntax+import GHCi.BreakArray (BreakArray) import Language.Haskell.Syntax.Module.Name (ModuleName)  -- ----------------------------------------------------------------------------@@ -82,7 +83,7 @@    | PUSH16_W !ByteOff    | PUSH32_W !ByteOff -   -- Push a (heap) ptr  (these all map to PUSH_G really)+   -- Push a ptr  (these all map to PUSH_G really)    | PUSH_G       Name    | PUSH_PRIMOP  PrimOp    | PUSH_BCO     (ProtoBCO Name)@@ -205,7 +206,8 @@                    -- Note [unboxed tuple bytecodes and tuple_BCO] in GHC.StgToByteCode     -- Breakpoints-   | BRK_FUN         !Word16 (RemotePtr ModuleName) (RemotePtr CostCentre)+   | BRK_FUN          (ForeignRef BreakArray) !Word16 (RemotePtr ModuleName)+                      (RemotePtr CostCentre)  -- ----------------------------------------------------------------------------- -- Printing bytecode instructions@@ -356,7 +358,9 @@    ppr ENTER                 = text "ENTER"    ppr (RETURN pk)           = text "RETURN  " <+> ppr pk    ppr (RETURN_TUPLE)        = text "RETURN_TUPLE"-   ppr (BRK_FUN index _mod_name _cc) = text "BRK_FUN" <+> ppr index <+> text "<module>" <+> text "<cc>"+   ppr (BRK_FUN _ index _ _) = text "BRK_FUN" <+> text "<breakarray>"+                               <+> ppr index <+> text "<module>" <+> text "<cc>"+   -- -----------------------------------------------------------------------------
compiler/GHC/ByteCode/Linker.hs view
@@ -22,10 +22,8 @@ import GHC.ByteCode.Types import GHCi.RemoteTypes import GHCi.ResolvedBCO-import GHCi.BreakArray  import GHC.Builtin.PrimOps-import GHC.Builtin.PrimOps.Ids import GHC.Builtin.Names  import GHC.Unit.Types@@ -36,13 +34,10 @@ import GHC.Linker.Types  import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Outputable  import GHC.Types.Name import GHC.Types.Name.Env-import qualified GHC.Types.Id as Id-import GHC.Types.Unique.DFM  import Language.Haskell.Syntax.Module.Name @@ -57,33 +52,31 @@  linkBCO   :: Interp-  -> PkgsLoaded   -> LinkerEnv   -> NameEnv Int-  -> RemoteRef BreakArray   -> UnlinkedBCO   -> IO ResolvedBCO-linkBCO interp pkgs_loaded le bco_ix breakarray+linkBCO interp le bco_ix            (UnlinkedBCO _ arity insns bitmap lits0 ptrs0) = do   -- fromIntegral Word -> Word64 should be a no op if Word is Word64   -- otherwise it will result in a cast to longlong on 32bit systems.-  lits <- mapM (fmap fromIntegral . lookupLiteral interp pkgs_loaded le) (ssElts lits0)-  ptrs <- mapM (resolvePtr interp pkgs_loaded le bco_ix breakarray) (ssElts ptrs0)+  lits <- mapM (fmap fromIntegral . lookupLiteral interp le) (ssElts lits0)+  ptrs <- mapM (resolvePtr interp le bco_ix) (ssElts ptrs0)   return (ResolvedBCO isLittleEndian arity insns bitmap               (listArray (0, fromIntegral (sizeSS lits0)-1) lits)               (addListToSS emptySS ptrs)) -lookupLiteral :: Interp -> PkgsLoaded -> LinkerEnv -> BCONPtr -> IO Word-lookupLiteral interp pkgs_loaded le ptr = case ptr of+lookupLiteral :: Interp -> LinkerEnv -> BCONPtr -> IO Word+lookupLiteral interp le ptr = case ptr of   BCONPtrWord lit -> return lit   BCONPtrLbl  sym -> do     Ptr a# <- lookupStaticPtr interp sym     return (W# (int2Word# (addr2Int# a#)))   BCONPtrItbl nm -> do-    Ptr a# <- lookupIE interp pkgs_loaded (itbl_env le) nm+    Ptr a# <- lookupIE interp (itbl_env le) nm     return (W# (int2Word# (addr2Int# a#)))   BCONPtrAddr nm -> do-    Ptr a# <- lookupAddr interp pkgs_loaded (addr_env le) nm+    Ptr a# <- lookupAddr interp (addr_env le) nm     return (W# (int2Word# (addr2Int# a#)))   BCONPtrStr _ ->     -- should be eliminated during assembleBCOs@@ -97,19 +90,19 @@     Nothing  -> linkFail "GHC.ByteCode.Linker: can't find label"                   (unpackFS addr_of_label_string) -lookupIE :: Interp -> PkgsLoaded -> ItblEnv -> Name -> IO (Ptr ())-lookupIE interp pkgs_loaded ie con_nm =+lookupIE :: Interp -> ItblEnv -> Name -> IO (Ptr ())+lookupIE interp ie con_nm =   case lookupNameEnv ie con_nm of     Just (_, ItblPtr a) -> return (fromRemotePtr (castRemotePtr a))     Nothing -> do -- try looking up in the object files.        let sym_to_find1 = nameToCLabel con_nm "con_info"-       m <- lookupHsSymbol interp pkgs_loaded con_nm "con_info"+       m <- lookupSymbol interp sym_to_find1        case m of           Just addr -> return addr           Nothing              -> do -- perhaps a nullary constructor?                    let sym_to_find2 = nameToCLabel con_nm "static_info"-                   n <- lookupHsSymbol interp pkgs_loaded con_nm "static_info"+                   n <- lookupSymbol interp sym_to_find2                    case n of                       Just addr -> return addr                       Nothing   -> linkFail "GHC.ByteCode.Linker.lookupIE"@@ -117,36 +110,34 @@                                        unpackFS sym_to_find2)  -- see Note [Generating code for top-level string literal bindings] in GHC.StgToByteCode-lookupAddr :: Interp -> PkgsLoaded -> AddrEnv -> Name -> IO (Ptr ())-lookupAddr interp pkgs_loaded ae addr_nm = do+lookupAddr :: Interp -> AddrEnv -> Name -> IO (Ptr ())+lookupAddr interp ae addr_nm = do   case lookupNameEnv ae addr_nm of     Just (_, AddrPtr ptr) -> return (fromRemotePtr ptr)     Nothing -> do -- try looking up in the object files.       let sym_to_find = nameToCLabel addr_nm "bytes"                           -- see Note [Bytes label] in GHC.Cmm.CLabel-      m <- lookupHsSymbol interp pkgs_loaded addr_nm "bytes"+      m <- lookupSymbol interp sym_to_find       case m of         Just ptr -> return ptr         Nothing -> linkFail "GHC.ByteCode.Linker.lookupAddr"                      (unpackFS sym_to_find) -lookupPrimOp :: Interp -> PkgsLoaded -> PrimOp -> IO (RemotePtr ())-lookupPrimOp interp pkgs_loaded primop = do+lookupPrimOp :: Interp -> PrimOp -> IO (RemotePtr ())+lookupPrimOp interp primop = do   let sym_to_find = primopToCLabel primop "closure"-  m <- lookupHsSymbol interp pkgs_loaded (Id.idName $ primOpId primop) "closure"+  m <- lookupSymbol interp (mkFastString sym_to_find)   case m of     Just p -> return (toRemotePtr p)     Nothing -> linkFail "GHC.ByteCode.Linker.lookupCE(primop)" sym_to_find  resolvePtr   :: Interp-  -> PkgsLoaded   -> LinkerEnv   -> NameEnv Int-  -> RemoteRef BreakArray   -> BCOPtr   -> IO ResolvedBCOPtr-resolvePtr interp pkgs_loaded le bco_ix breakarray ptr = case ptr of+resolvePtr interp le bco_ix ptr = case ptr of   BCOPtrName nm     | Just ix <- lookupNameEnv bco_ix nm     -> return (ResolvedBCORef ix) -- ref to another BCO in this group@@ -158,41 +149,19 @@     -> assertPpr (isExternalName nm) (ppr nm) $        do           let sym_to_find = nameToCLabel nm "closure"-          m <- lookupHsSymbol interp pkgs_loaded nm "closure"+          m <- lookupSymbol interp sym_to_find           case m of             Just p -> return (ResolvedBCOStaticPtr (toRemotePtr p))             Nothing -> linkFail "GHC.ByteCode.Linker.lookupCE" (unpackFS sym_to_find)    BCOPtrPrimOp op-    -> ResolvedBCOStaticPtr <$> lookupPrimOp interp pkgs_loaded op+    -> ResolvedBCOStaticPtr <$> lookupPrimOp interp op    BCOPtrBCO bco-    -> ResolvedBCOPtrBCO <$> linkBCO interp pkgs_loaded le bco_ix breakarray bco--  BCOPtrBreakArray-    -> return (ResolvedBCOPtrBreakArray breakarray)---- | Look up the address of a Haskell symbol in the currently--- loaded units.------ See Note [Looking up symbols in the relevant objects].-lookupHsSymbol :: Interp -> PkgsLoaded -> Name -> String -> IO (Maybe (Ptr ()))-lookupHsSymbol interp pkgs_loaded nm sym_suffix = do-  massertPpr (isExternalName nm) (ppr nm)-  let sym_to_find = nameToCLabel nm sym_suffix-      pkg_id = moduleUnitId $ nameModule nm-      loaded_dlls = maybe [] loaded_pkg_hs_dlls $ lookupUDFM pkgs_loaded pkg_id--      go (dll:dlls) = do-        mb_ptr <- lookupSymbolInDLL interp dll sym_to_find-        case mb_ptr of-          Just ptr -> pure (Just ptr)-          Nothing -> go dlls-      go [] =-        -- See Note [Symbols may not be found in pkgs_loaded] in GHC.Linker.Types-        lookupSymbol interp sym_to_find+    -> ResolvedBCOPtrBCO <$> linkBCO interp le bco_ix bco -  go loaded_dlls+  BCOPtrBreakArray breakarray+    -> withForeignRef breakarray $ \ba -> return (ResolvedBCOPtrBreakArray ba)  linkFail :: String -> String -> IO a linkFail who what
compiler/GHC/Cmm/CommonBlockElim.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE GADTs, BangPatterns, ScopedTypeVariables #-}+{-# LANGUAGE GADTs #-}  module GHC.Cmm.CommonBlockElim   ( elimCommonBlocks@@ -17,7 +17,6 @@ import GHC.Cmm.Dataflow.Block import GHC.Cmm.Dataflow.Graph import GHC.Cmm.Dataflow.Label-import GHC.Cmm.Dataflow.Collections import Data.Functor.Classes (liftEq) import Data.Maybe (mapMaybe) import qualified Data.List as List
compiler/GHC/Cmm/ContFlowOpt.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE GADTs #-}-{-# LANGUAGE BangPatterns #-} module GHC.Cmm.ContFlowOpt     ( cmmCfgOpts     , cmmCfgOptsProc@@ -11,7 +10,6 @@ import GHC.Prelude hiding (succ, unzip, zip)  import GHC.Cmm.Dataflow.Block hiding (blockConcat)-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Graph import GHC.Cmm.Dataflow.Label import GHC.Cmm.BlockId
compiler/GHC/Cmm/Dataflow.hs view
@@ -1,9 +1,5 @@-{-# LANGUAGE BangPatterns #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE MultiParamTypeClasses  #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-}  --@@ -47,7 +43,6 @@  import GHC.Cmm.Dataflow.Block import GHC.Cmm.Dataflow.Graph-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Label  type family   Fact (x :: Extensibility) f :: Type
compiler/GHC/Cmm/DebugBlock.hs view
@@ -47,10 +47,9 @@ import GHC.Utils.Panic import GHC.Types.SrcLoc import GHC.Types.Tickish-import GHC.Utils.Misc      ( seqList )+import GHC.Utils.Misc      ( partitionWith, seqList )  import GHC.Cmm.Dataflow.Block-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Graph import GHC.Cmm.Dataflow.Label @@ -58,7 +57,6 @@ import Data.List     ( minimumBy, nubBy ) import Data.Ord      ( comparing ) import qualified Data.Map as Map-import Data.Either   ( partitionEithers )  -- | Debug information about a block of code. Ticks scope over nested -- blocks.@@ -110,7 +108,7 @@       -- Analyse tick scope structure: Each one is either a top-level       -- tick scope, or the child of another.       (topScopes, childScopes)-        = partitionEithers $ map (\a -> findP a a) $ Map.keys blockCtxs+        = partitionWith (\a -> findP a a) $ Map.keys blockCtxs       findP tsc GlobalScope = Left tsc -- top scope       findP tsc scp | scp' `Map.member` blockCtxs = Right (scp', tsc)                     | otherwise                   = findP tsc scp'@@ -119,9 +117,6 @@               -- recover by copying ticks below.               scp' | SubScope _ scp' <- scp      = scp'                    | CombinedScope scp' _ <- scp = scp'-#if __GLASGOW_HASKELL__ < 901-                   | otherwise                   = panic "findP impossible"-#endif        scopeMap = foldl' (\acc (key, scope) -> insertMulti key scope acc) Map.empty childScopes 
compiler/GHC/Cmm/Dominators.hs view
@@ -32,7 +32,6 @@  import GHC.Cmm.Dataflow import GHC.Cmm.Dataflow.Block-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Graph import GHC.Cmm.Dataflow.Label import GHC.Cmm
+ compiler/GHC/Cmm/GenericOpt.hs view
@@ -0,0 +1,222 @@+-- -----------------------------------------------------------------------------+--+-- (c) The University of Glasgow 1993-2004+--+--+-- -----------------------------------------------------------------------------++{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE UnboxedTuples #-}++module GHC.Cmm.GenericOpt+   ( cmmToCmm+   )+where++import GHC.Prelude hiding (head)+import GHC.Platform+import GHC.CmmToAsm.PIC+import GHC.CmmToAsm.Config+import GHC.CmmToAsm.Types+import GHC.Cmm.BlockId+import GHC.Cmm+import GHC.Cmm.Utils+import GHC.Cmm.Dataflow.Block+import GHC.Cmm.Opt           ( cmmMachOpFold )+import GHC.Cmm.CLabel+import GHC.Data.FastString+import GHC.Unit+import Control.Monad++-- -----------------------------------------------------------------------------+-- Generic Cmm optimiser++{-+Here we do:++  (a) Constant folding+  (c) Position independent code and dynamic linking+        (i)  introduce the appropriate indirections+             and position independent refs+        (ii) compile a list of imported symbols+  (d) Some arch-specific optimizations++(a) will be moving to the new Hoopl pipeline, however, (c) and+(d) are only needed by the native backend and will continue to live+here.++Ideas for other things we could do (put these in Hoopl please!):++  - shortcut jumps-to-jumps+  - simple CSE: if an expr is assigned to a temp, then replace later occs of+    that expr with the temp, until the expr is no longer valid (can push through+    temp assignments, and certain assigns to mem...)+-}++cmmToCmm :: NCGConfig -> RawCmmDecl -> (RawCmmDecl, [CLabel])+cmmToCmm _ top@(CmmData _ _) = (top, [])+cmmToCmm config (CmmProc info lbl live graph)+    = runCmmOpt config $+      do blocks' <- mapM cmmBlockConFold (toBlockList graph)+         return $ CmmProc info lbl live (ofBlockList (g_entry graph) blocks')++type OptMResult a = (# a, [CLabel] #)++pattern OptMResult :: a -> b -> (# a, b #)+pattern OptMResult x y = (# x, y #)+{-# COMPLETE OptMResult #-}++newtype CmmOptM a = CmmOptM (NCGConfig -> [CLabel] -> OptMResult a)+    deriving (Functor)++instance Applicative CmmOptM where+    pure x = CmmOptM $ \_ imports -> OptMResult x imports+    (<*>) = ap++instance Monad CmmOptM where+  (CmmOptM f) >>= g =+    CmmOptM $ \config imports0 ->+                case f config imports0 of+                  OptMResult x imports1 ->+                    case g x of+                      CmmOptM g' -> g' config imports1++instance CmmMakeDynamicReferenceM CmmOptM where+    addImport = addImportCmmOpt++addImportCmmOpt :: CLabel -> CmmOptM ()+addImportCmmOpt lbl = CmmOptM $ \_ imports -> OptMResult () (lbl:imports)++getCmmOptConfig :: CmmOptM NCGConfig+getCmmOptConfig = CmmOptM $ \config imports -> OptMResult config imports++runCmmOpt :: NCGConfig -> CmmOptM a -> (a, [CLabel])+runCmmOpt config (CmmOptM f) =+  case f config [] of+    OptMResult result imports -> (result, imports)++cmmBlockConFold :: CmmBlock -> CmmOptM CmmBlock+cmmBlockConFold block = do+  let (entry, middle, last) = blockSplit block+      stmts = blockToList middle+  stmts' <- mapM cmmStmtConFold stmts+  last' <- cmmStmtConFold last+  return $ blockJoin entry (blockFromList stmts') last'++-- This does three optimizations, but they're very quick to check, so we don't+-- bother turning them off even when the Hoopl code is active.  Since+-- this is on the old Cmm representation, we can't reuse the code either:+--  * reg = reg      --> nop+--  * if 0 then jump --> nop+--  * if 1 then jump --> jump+-- We might be tempted to skip this step entirely of not Opt_PIC, but+-- there is some PowerPC code for the non-PIC case, which would also+-- have to be separated.+cmmStmtConFold :: CmmNode e x -> CmmOptM (CmmNode e x)+cmmStmtConFold stmt+   = case stmt of+        CmmAssign reg src+           -> do src' <- cmmExprConFold DataReference src+                 return $ case src' of+                   CmmReg reg' | reg == reg' -> CmmComment (fsLit "nop")+                   new_src -> CmmAssign reg new_src++        CmmStore addr src align+           -> do addr' <- cmmExprConFold DataReference addr+                 src'  <- cmmExprConFold DataReference src+                 return $ CmmStore addr' src' align++        CmmCall { cml_target = addr }+           -> do addr' <- cmmExprConFold JumpReference addr+                 return $ stmt { cml_target = addr' }++        CmmUnsafeForeignCall target regs args+           -> do target' <- case target of+                              ForeignTarget e conv -> do+                                e' <- cmmExprConFold CallReference e+                                return $ ForeignTarget e' conv+                              PrimTarget _ ->+                                return target+                 args' <- mapM (cmmExprConFold DataReference) args+                 return $ CmmUnsafeForeignCall target' regs args'++        CmmCondBranch test true false likely+           -> do test' <- cmmExprConFold DataReference test+                 return $ case test' of+                   CmmLit (CmmInt 0 _) -> CmmBranch false+                   CmmLit (CmmInt _ _) -> CmmBranch true+                   _other -> CmmCondBranch test' true false likely++        CmmSwitch expr ids+           -> do expr' <- cmmExprConFold DataReference expr+                 return $ CmmSwitch expr' ids++        other+           -> return other++cmmExprConFold :: ReferenceKind -> CmmExpr -> CmmOptM CmmExpr+cmmExprConFold referenceKind expr = do+    config <- getCmmOptConfig++    let expr' = if not (ncgDoConstantFolding config)+                    then expr+                    else cmmExprCon config expr++    cmmExprNative referenceKind expr'++cmmExprCon :: NCGConfig -> CmmExpr -> CmmExpr+cmmExprCon config (CmmLoad addr rep align) = CmmLoad (cmmExprCon config addr) rep align+cmmExprCon config (CmmMachOp mop args)+    = cmmMachOpFold (ncgPlatform config) mop (map (cmmExprCon config) args)+cmmExprCon _ other = other++-- handles both PIC and non-PIC cases... a very strange mixture+-- of things to do.+cmmExprNative :: ReferenceKind -> CmmExpr -> CmmOptM CmmExpr+cmmExprNative referenceKind expr = do+     config <- getCmmOptConfig+     let platform = ncgPlatform config+         arch = platformArch platform+     case expr of+        CmmLoad addr rep align+          -> do addr' <- cmmExprNative DataReference addr+                return $ CmmLoad addr' rep align++        CmmMachOp mop args+          -> do args' <- mapM (cmmExprNative DataReference) args+                return $ CmmMachOp mop args'++        CmmLit (CmmBlock id)+          -> cmmExprNative referenceKind (CmmLit (CmmLabel (infoTblLbl id)))+          -- we must convert block Ids to CLabels here, because we+          -- might have to do the PIC transformation.  Hence we must+          -- not modify BlockIds beyond this point.++        CmmLit (CmmLabel lbl)+          -> cmmMakeDynamicReference config referenceKind lbl+        CmmLit (CmmLabelOff lbl off)+          -> do dynRef <- cmmMakeDynamicReference config referenceKind lbl+                -- need to optimize here, since it's late+                return $ cmmMachOpFold platform (MO_Add (wordWidth platform)) [+                    dynRef,+                    (CmmLit $ CmmInt (fromIntegral off) (wordWidth platform))+                  ]++        -- On powerpc (non-PIC), it's easier to jump directly to a label than+        -- to use the register table, so we replace these registers+        -- with the corresponding labels:+        CmmReg (CmmGlobal (GlobalRegUse EagerBlackholeInfo _))+          | arch == ArchPPC && not (ncgPIC config)+          -> cmmExprNative referenceKind $+             CmmLit (CmmLabel (mkCmmCodeLabel rtsUnitId (fsLit "__stg_EAGER_BLACKHOLE_info")))+        CmmReg (CmmGlobal (GlobalRegUse GCEnter1 _))+          | arch == ArchPPC && not (ncgPIC config)+          -> cmmExprNative referenceKind $+             CmmLit (CmmLabel (mkCmmCodeLabel rtsUnitId (fsLit "__stg_gc_enter_1")))+        CmmReg (CmmGlobal (GlobalRegUse GCFun _))+          | arch == ArchPPC && not (ncgPIC config)+          -> cmmExprNative referenceKind $+             CmmLit (CmmLabel (mkCmmCodeLabel rtsUnitId (fsLit "__stg_gc_fun")))++        other+           -> return other
compiler/GHC/Cmm/Graph.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE BangPatterns, GADTs #-}+{-# LANGUAGE GADTs #-}  module GHC.Cmm.Graph   ( CmmAGraph, CmmAGraphScoped, CgStmt(..)
compiler/GHC/Cmm/Info.hs view
@@ -40,14 +40,13 @@ import GHC.Data.Bitmap import GHC.Data.Stream (Stream) import qualified GHC.Data.Stream as Stream-import GHC.Cmm.Dataflow.Collections+import GHC.Cmm.Dataflow.Label  import GHC.Platform import GHC.Platform.Profile import GHC.Data.Maybe import GHC.Utils.Error (withTimingSilent) import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Types.Unique.Supply import GHC.Utils.Logger import GHC.Utils.Monad@@ -450,7 +449,7 @@ -- | Takes a closure pointer and returns the info table pointer closureInfoPtr :: Platform -> DoAlignSanitisation -> CmmExpr -> CmmExpr closureInfoPtr platform align_check e =-    cmmLoadBWord platform (wordAligned platform align_check e)+    CmmMachOp (MO_RelaxedRead (wordWidth platform)) [wordAligned platform align_check e]  -- | Takes an info pointer (the first word of a closure) and returns its entry -- code
compiler/GHC/Cmm/Info/Build.hs view
@@ -1,11 +1,7 @@-{-# LANGUAGE GADTs, BangPatterns, RecordWildCards,-    GeneralizedNewtypeDeriving, NondecreasingIndentation, TupleSections,-    ScopedTypeVariables, OverloadedStrings, LambdaCase, EmptyCase #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE GADTs, RecordWildCards,+    NondecreasingIndentation,+    OverloadedStrings, LambdaCase #-} {-# LANGUAGE DerivingStrategies #-}-{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE UndecidableInstances #-}  @@ -27,7 +23,6 @@ import GHC.Cmm.Dataflow.Block import GHC.Cmm.Dataflow.Graph import GHC.Cmm.Dataflow.Label-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow import GHC.Unit.Module import GHC.Data.Graph.Directed
compiler/GHC/Cmm/LayoutStack.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE BangPatterns, RecordWildCards, GADTs #-}+{-# LANGUAGE RecordWildCards, GADTs #-} module GHC.Cmm.LayoutStack (        cmmLayoutStack, setInfoTableStackMap   ) where@@ -21,9 +21,8 @@ import GHC.Cmm.Liveness import GHC.Cmm.ProcPoint import GHC.Runtime.Heap.Layout-import GHC.Cmm.Dataflow.Block-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow+import GHC.Cmm.Dataflow.Block import GHC.Cmm.Dataflow.Graph import GHC.Cmm.Dataflow.Label import GHC.Types.Unique.Supply
compiler/GHC/Cmm/Lexer.x view
@@ -62,7 +62,7 @@ @hexadecimal = $hexit+ @exponent    = [eE] [\-\+]? @decimal -@floating_point = @decimal \. @decimal @exponent? | @decimal @exponent+@floating_point = [\-]? (@decimal \. @decimal @exponent? | @decimal @exponent)  @escape      = \\ ([abfnrt\\\'\"\?] | x $hexit{1,2} | $octit{1,3}) @strchar     = ($printable # [\"\\]) | @escape
compiler/GHC/Cmm/Lint.hs view
@@ -18,7 +18,6 @@ import GHC.Platform import GHC.Platform.Regs (callerSaves) import GHC.Cmm.Dataflow.Block-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Graph import GHC.Cmm.Dataflow.Label import GHC.Cmm
compiler/GHC/Cmm/Liveness.hs view
@@ -1,7 +1,4 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE ScopedTypeVariables #-}  module GHC.Cmm.Liveness     ( CmmLocalLive@@ -21,7 +18,6 @@ import GHC.Cmm.BlockId import GHC.Cmm import GHC.Cmm.Dataflow.Block-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow import GHC.Cmm.Dataflow.Label import GHC.Cmm.LRegSet
compiler/GHC/Cmm/Opt.hs view
@@ -213,33 +213,23 @@   = Just $! CmmMachOp op [pic, CmmLit $ cmmOffsetLit lit off ]   where off = fromIntegral (narrowS rep n) --- Make a RegOff if we can. We don't perform this optimization if rep is greater--- than the host word size because we use an Int to store the offset. See--- #24893 and #24700. This should be fixed to ensure that optimizations don't--- depend on the compiler host platform.+-- Make a RegOff if we can cmmMachOpFoldM _ (MO_Add _) [CmmReg reg, CmmLit (CmmInt n rep)]-  | validOffsetRep rep   = Just $! cmmRegOff reg (fromIntegral (narrowS rep n)) cmmMachOpFoldM _ (MO_Add _) [CmmRegOff reg off, CmmLit (CmmInt n rep)]-  | validOffsetRep rep   = Just $! cmmRegOff reg (off + fromIntegral (narrowS rep n)) cmmMachOpFoldM _ (MO_Sub _) [CmmReg reg, CmmLit (CmmInt n rep)]-  | validOffsetRep rep   = Just $! cmmRegOff reg (- fromIntegral (narrowS rep n)) cmmMachOpFoldM _ (MO_Sub _) [CmmRegOff reg off, CmmLit (CmmInt n rep)]-  | validOffsetRep rep   = Just $! cmmRegOff reg (off - fromIntegral (narrowS rep n))  -- Fold label(+/-)offset into a CmmLit where possible  cmmMachOpFoldM _ (MO_Add _) [CmmLit lit, CmmLit (CmmInt i rep)]-  | validOffsetRep rep   = Just $! CmmLit (cmmOffsetLit lit (fromIntegral (narrowU rep i))) cmmMachOpFoldM _ (MO_Add _) [CmmLit (CmmInt i rep), CmmLit lit]-  | validOffsetRep rep   = Just $! CmmLit (cmmOffsetLit lit (fromIntegral (narrowU rep i))) cmmMachOpFoldM _ (MO_Sub _) [CmmLit lit, CmmLit (CmmInt i rep)]-  | validOffsetRep rep   = Just $! CmmLit (cmmOffsetLit lit (fromIntegral (negate (narrowU rep i))))  @@ -419,13 +409,6 @@ -- Anything else is just too hard.  cmmMachOpFoldM _ _ _ = Nothing---- | Check that a literal width is compatible with the host word size used to--- store offsets. This should be fixed properly (using larger types to store--- literal offsets). See #24893-validOffsetRep :: Width -> Bool-validOffsetRep rep = widthInBits rep <= finiteBitSize (undefined :: Int)-  {- Note [Comparison operators] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compiler/GHC/Cmm/Parser.y view
@@ -198,14 +198,15 @@ ---------------  Cmm respects the C11 memory model and distinguishes between non-atomic and-atomic memory accesses. In C11 fashion, atomic accesses can provide a number of-memory ordering guarantees. These are supported in Cmm syntax as follows:+atomic memory accesses. In C11 fashion, atomic accesses can provide a variety of+memory ordering guarantees. These supported as statements in Cmm syntax as+follows:      W_[ptr] = ...;            // a non-atomic store     %relaxed W_[ptr] = ...;   // an atomic store with relaxed ordering semantics     %release W_[ptr] = ...;   // an atomic store with release ordering semantics -    x = W_(ptr);              // a non-atomic load+    x = W_[ptr];              // a non-atomic load     x = %relaxed W_[ptr];     // an atomic load with relaxed ordering     x = %acquire W_[ptr];     // an atomic load with acquire ordering     // or equivalently...@@ -214,6 +215,18 @@ Here we used W_ as an example but these operations can be used on all Cmm types. +Sometimes it is also necessary to perform atomic but non-ordered loads in an+expression context. For this we provide the MO_RelaxedRead MachOp, expressed in+Cmm syntax as++    x = W_![ptr];++This operation and syntax was primarily added to support hand-written Cmm,+where sometimes such atomic loads are unavoidable deep inside expressions (e.g.+see the CHECK_GC macro). Since one should be explicit about program order when+writing operations with ordered semantics, we do not provide similar MachOps+for acquire and release reads.+ See Note [Heap memory barriers] in SMP.h for details.  ----------------------------------------------------------------------------- -}@@ -837,14 +850,12 @@         | STRING                 { do s <- code (newStringCLit $1);                                       return (CmmLit s) }         | reg                    { $1 }-        | type dereference       { do (align, ptr) <- $2; return (CmmLoad ptr $1 align) }+        | type '!' '[' expr ']'  { do ptr <- $4; return (CmmMachOp (MO_RelaxedRead (typeWidth $1)) [ptr]) }+        | type '^' '[' expr ']'  { do ptr <- $4; return (CmmLoad ptr $1 Unaligned) }+        | type '[' expr ']'      { do ptr <- $3; return (CmmLoad ptr $1 NaturallyAligned) }         | '%' NAME '(' exprs0 ')' {% exprOp $2 $4 }         | '(' expr ')'           { $2 } -dereference :: { CmmParse (AlignmentSpec, CmmExpr) }-        : '^' '[' expr ']'       { do ptr <- $3; return (Unaligned, ptr) }-        | '[' expr ']'           { do ptr <- $2; return (NaturallyAligned, ptr) }- -- leaving out the type of a literal gives you the native word size in C-- maybe_ty :: { CmmType }         : {- empty -}                   {% do platform <- PD.getPlatform; return $ bWord platform }@@ -1117,8 +1128,13 @@         ( "fabs32f", (MO_F32_Fabs,) ),         ( "sqrt32f", (MO_F32_Sqrt,) ), -        ( "read_barrier", (MO_ReadBarrier,)),-        ( "write_barrier", (MO_WriteBarrier,)),+        -- TODO: It would be nice to rename the following operations to+        -- acquire_fence and release_fence. Be aware that there'll be issues+        -- with an overlapping token ('acquire') in the lexer.+        ( "fence_acquire", (MO_AcquireFence,)),+        ( "fence_release", (MO_ReleaseFence,)),+        ( "fence_seq_cst", (MO_SeqCstFence,)),+         ( "memcpy", memcpyLikeTweakArgs MO_Memcpy ),         ( "memset", memcpyLikeTweakArgs MO_Memset ),         ( "memmove", memcpyLikeTweakArgs MO_Memmove ),@@ -1259,7 +1275,7 @@   ( fsLit "POP_ARG_REGS",          \[live_regs] -> emitPopArgRegs live_regs ),    ( fsLit "LDV_ENTER",             \[e] -> ldvEnter e ),-  ( fsLit "LDV_RECORD_CREATE",     \[e] -> ldvRecordCreate e ),+  ( fsLit "PROF_HEADER_CREATE",     \[e] -> profHeaderCreate e ),    ( fsLit "PUSH_UPD_FRAME",        \[sp,e] -> emitPushUpdateFrame sp e ),   ( fsLit "SET_HDR",               \[ptr,info,ccs] ->
compiler/GHC/Cmm/Pipeline.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE BangPatterns #-}  module GHC.Cmm.Pipeline (   cmmPipeline@@ -12,7 +11,7 @@ import GHC.Cmm.Config import GHC.Cmm.ContFlowOpt import GHC.Cmm.CommonBlockElim-import GHC.Cmm.Dataflow.Collections+import GHC.Cmm.Dataflow.Label import GHC.Cmm.Info.Build import GHC.Cmm.Lint import GHC.Cmm.LayoutStack@@ -26,11 +25,11 @@ import GHC.Utils.Error import GHC.Utils.Logger import GHC.Utils.Outputable+import GHC.Utils.Misc ( partitionWithM )  import GHC.Platform  import Control.Monad-import Data.Either (partitionEithers)  ----------------------------------------------------------------------------- -- | Top level driver for C-- pipeline@@ -50,9 +49,7 @@   let forceRes (info, group) = info `seq` foldr seq () group   let platform = cmmPlatform cmm_config   withTimingSilent logger (text "Cmm pipeline") forceRes $ do-     tops <- {-# SCC "tops" #-} mapM (cpsTop logger platform cmm_config) prog--     let (procs, data_) = partitionEithers tops+     (procs, data_) <- {-# SCC "tops" #-} partitionWithM (cpsTop logger platform cmm_config) prog      (srtInfo, cmms) <- {-# SCC "doSRTs" #-} doSRTs cmm_config srtInfo procs data_      dumpWith logger Opt_D_dump_cmm_cps "Post CPS Cmm" FormatCMM (pdoc platform cmms) 
compiler/GHC/Cmm/ProcPoint.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE BangPatterns #-} {-# LANGUAGE DisambiguateRecordFields #-} {-# LANGUAGE GADTs #-} @@ -27,7 +26,6 @@ import GHC.Platform import GHC.Types.Unique.Supply import GHC.Cmm.Dataflow.Block-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow import GHC.Cmm.Dataflow.Graph import GHC.Cmm.Dataflow.Label
compiler/GHC/Cmm/Reducibility.hs view
@@ -40,7 +40,6 @@ import GHC.Cmm import GHC.Cmm.BlockId import GHC.Cmm.Dataflow-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Block import GHC.Cmm.Dominators import GHC.Cmm.Dataflow.Graph hiding (addBlock)
compiler/GHC/Cmm/Sink.hs view
@@ -14,7 +14,6 @@ import GHC.Cmm.Utils import GHC.Cmm.Dataflow.Block import GHC.Cmm.Dataflow.Label-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Graph import GHC.Platform.Regs 
compiler/GHC/Cmm/ThreadSanitizer.hs view
@@ -6,7 +6,6 @@  import GHC.Prelude -import GHC.StgToCmm.Utils (get_GlobalReg_addr) import GHC.Platform import GHC.Platform.Regs (activeStgRegs, callerSaves) import GHC.Cmm@@ -24,12 +23,12 @@ import Data.Maybe (fromMaybe)  data Env = Env { platform :: Platform-               , uniques :: [Unique]+               , uniques :: UniqSupply                }  annotateTSAN :: Platform -> CmmGraph -> UniqSM CmmGraph annotateTSAN platform graph = do-    env <- Env platform <$> getUniquesM+    env <- Env platform <$> getUniqueSupplyM     return $ modifyGraph (mapGraphBlocks (annotateBlock env)) graph  mapBlockList :: (forall e' x'. n e' x' -> Block n e' x')@@ -37,11 +36,11 @@ mapBlockList f (BlockCO n rest  ) = f n `blockAppend` mapBlockList f rest mapBlockList f (BlockCC n rest m) = f n `blockAppend` mapBlockList f rest `blockAppend` f m mapBlockList f (BlockOC   rest m) = mapBlockList f rest `blockAppend` f m-mapBlockList _ BNil = BNil-mapBlockList f (BMiddle blk) = f blk-mapBlockList f (BCat a b) = mapBlockList f a `blockAppend` mapBlockList f b-mapBlockList f (BSnoc a n) = mapBlockList f a `blockAppend` f n-mapBlockList f (BCons n a) = f n `blockAppend` mapBlockList f a+mapBlockList _ BNil               = BNil+mapBlockList f (BMiddle blk)      = f blk+mapBlockList f (BCat a b)         = mapBlockList f a `blockAppend` mapBlockList f b+mapBlockList f (BSnoc a n)        = mapBlockList f a `blockAppend` f n+mapBlockList f (BCons n a)        = f n `blockAppend` mapBlockList f a  annotateBlock :: Env -> Block CmmNode e x -> Block CmmNode e x annotateBlock env = mapBlockList (annotateNode env)@@ -85,6 +84,7 @@ annotateExpr env expr =     annotateLoads env (collectExprLoads expr) +-- | A load mentioned in a 'CmmExpr'. data Load = Load CmmType AlignmentSpec CmmExpr  annotateLoads :: Env -> [Load] -> Block CmmNode O O@@ -103,6 +103,9 @@ collectExprLoads (CmmLit _)           = [] collectExprLoads (CmmLoad e ty align) = [Load ty align e] collectExprLoads (CmmReg _)           = []+-- N.B. we don't bother telling TSAN about MO_RelaxedReads+-- since doing so would be inconvenient and they by+-- definition can neither race nor introduce ordering. collectExprLoads (CmmMachOp _op args) = foldMap collectExprLoads args collectExprLoads (CmmStackSlot _ _)   = [] collectExprLoads (CmmRegOff _ _)      = []@@ -114,10 +117,10 @@              -> [CmmActual]     -- ^ arguments              -> Maybe (Block CmmNode O O)                                 -- ^ 'Just' a block of instrumentation, if applicable-annotatePrim env (MO_AtomicRMW w aop)    [dest]   [addr, val] = Just $ tsanAtomicRMW env MemOrderSeqCst aop w addr val dest-annotatePrim env (MO_AtomicRead w mord)  [dest]   [addr]      = Just $ tsanAtomicLoad env mord w addr dest-annotatePrim env (MO_AtomicWrite w mord) []       [addr, val] = Just $ tsanAtomicStore env mord w val addr-annotatePrim env (MO_Xchg w)             [dest]   [addr, val] = Just $ tsanAtomicExchange env MemOrderSeqCst w val addr dest+annotatePrim env (MO_AtomicRMW w aop)    [dest]   [addr, val]  = Just $ tsanAtomicRMW env MemOrderSeqCst aop w addr val dest+annotatePrim env (MO_AtomicRead w mord)  [dest]   [addr]       = Just $ tsanAtomicLoad env mord w addr dest+annotatePrim env (MO_AtomicWrite w mord) []       [addr, val]  = Just $ tsanAtomicStore env mord w val addr+annotatePrim env (MO_Xchg w)             [dest]   [addr, val]  = Just $ tsanAtomicExchange env MemOrderSeqCst w val addr dest annotatePrim env (MO_Cmpxchg w)          [dest]   [addr, expected, new]                                                                = Just $ tsanAtomicCas env MemOrderSeqCst MemOrderSeqCst w addr expected new dest annotatePrim _    _                       _        _           = Nothing@@ -133,14 +136,15 @@     call `blockAppend`     -- perform call     restore                -- restore global registers   where-    -- We are rather conservative here and just save/restore all GlobalRegs.-    (save, restore) = saveRestoreCallerRegs (platform env)+    (save, restore) = saveRestoreCallerRegs gregs_us (platform env) +    (arg_us, gregs_us) = splitUniqSupply (uniques env)+     -- We also must be careful not to mention caller-saved registers in     -- arguments as Cmm-Lint checks this. To accomplish this we instead bind     -- the arguments to local registers.     arg_regs :: [CmmReg]-    arg_regs = zipWith arg_reg (uniques env) args+    arg_regs = zipWith arg_reg (uniqsFromSupply arg_us) args       where         arg_reg :: Unique -> CmmExpr -> CmmReg         arg_reg u expr = CmmLocal $ LocalReg u (cmmExprType (platform env) expr)@@ -150,31 +154,34 @@      call = CmmUnsafeForeignCall ftgt formals (map CmmReg arg_regs) -saveRestoreCallerRegs :: Platform+-- | We save the contents of global registers in locals and allow the+-- register allocator to spill them to the stack around the call.+-- We cannot use the register table for this since we would interface+-- with {SAVE,RESTORE}_THREAD_STATE.+saveRestoreCallerRegs :: UniqSupply -> Platform                       -> (Block CmmNode O O, Block CmmNode O O)-saveRestoreCallerRegs platform =+saveRestoreCallerRegs us platform =     (save, restore)   where-    regs = filter (callerSaves platform) (activeStgRegs platform)--    save = blockFromList (map saveReg regs)--    saveReg :: GlobalReg -> CmmNode O O-    saveReg reg =-      CmmStore (get_GlobalReg_addr platform reg)-               (CmmReg (CmmGlobal (GlobalRegUse reg ty)))-               NaturallyAligned-      where ty = globalRegSpillType platform reg+    regs_to_save :: [GlobalReg]+    regs_to_save = filter (callerSaves platform) (activeStgRegs platform) -    restore = blockFromList (map restoreReg regs)+    nodes :: [(CmmNode O O, CmmNode O O)]+    nodes =+        zipWith mk_reg regs_to_save (uniqsFromSupply us)+      where+        mk_reg :: GlobalReg -> Unique -> (CmmNode O O, CmmNode O O)+        mk_reg reg u =+            let ty = globalRegSpillType platform reg+                greg = CmmGlobal (GlobalRegUse reg ty)+                lreg = CmmLocal (LocalReg u ty)+                save = CmmAssign lreg (CmmReg greg)+                restore = CmmAssign greg (CmmReg lreg)+            in (save, restore) -    restoreReg :: GlobalReg -> CmmNode O O-    restoreReg reg =-      CmmAssign (CmmGlobal (GlobalRegUse reg ty))-                (CmmLoad (get_GlobalReg_addr platform reg)-                         ty-                         NaturallyAligned)-      where ty = globalRegSpillType platform reg+    (save_nodes, restore_nodes) = unzip nodes+    save = blockFromList save_nodes+    restore = blockFromList restore_nodes  -- | Mirrors __tsan_memory_order -- <https://github.com/llvm-mirror/compiler-rt/blob/master/include/sanitizer/tsan_interface_atomic.h#L32>
compiler/GHC/Cmm/Utils.hs view
@@ -1,5 +1,4 @@-{-# LANGUAGE GADTs, RankNTypes #-}-{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-}  {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}@@ -70,7 +69,7 @@ import GHC.Prelude  import GHC.Core.TyCon     ( PrimRep(..), PrimElemRep(..) )-import GHC.Types.RepType  ( UnaryType, SlotTy (..), typePrimRep1 )+import GHC.Types.RepType  ( NvUnaryType, SlotTy (..), typePrimRepU )  import GHC.Platform import GHC.Runtime.Heap.Layout@@ -87,7 +86,6 @@ import GHC.Cmm.Dataflow.Graph import GHC.Cmm.Dataflow.Label import GHC.Cmm.Dataflow.Block-import GHC.Cmm.Dataflow.Collections  --------------------------------------------------- --@@ -97,7 +95,6 @@  primRepCmmType :: Platform -> PrimRep -> CmmType primRepCmmType platform = \case-   VoidRep          -> panic "primRepCmmType:VoidRep"    BoxedRep _       -> gcWord platform    IntRep           -> bWord platform    WordRep          -> bWord platform@@ -136,11 +133,10 @@ primElemRepCmmType FloatElemRep  = f32 primElemRepCmmType DoubleElemRep = f64 -typeCmmType :: Platform -> UnaryType -> CmmType-typeCmmType platform ty = primRepCmmType platform (typePrimRep1 ty)+typeCmmType :: Platform -> NvUnaryType -> CmmType+typeCmmType platform ty = primRepCmmType platform (typePrimRepU ty)  primRepForeignHint :: PrimRep -> ForeignHint-primRepForeignHint VoidRep      = panic "primRepForeignHint:VoidRep" primRepForeignHint (BoxedRep _) = AddrHint primRepForeignHint IntRep       = SignedHint primRepForeignHint Int8Rep      = SignedHint@@ -157,8 +153,8 @@ primRepForeignHint DoubleRep    = NoHint primRepForeignHint (VecRep {})  = NoHint -typeForeignHint :: UnaryType -> ForeignHint-typeForeignHint = primRepForeignHint . typePrimRep1+typeForeignHint :: NvUnaryType -> ForeignHint+typeForeignHint = primRepForeignHint . typePrimRepU  --------------------------------------------------- --
compiler/GHC/CmmToAsm.hs view
@@ -5,17 +5,8 @@ -- -- ----------------------------------------------------------------------------- -{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE PatternSynonyms #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE UnboxedTuples #-}---- | Native code generator+-- | Note [Native code generator]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- -- The native-code generator has machine-independent and -- machine-dependent modules.@@ -23,51 +14,45 @@ -- This module ("GHC.CmmToAsm") is the top-level machine-independent -- module.  Before entering machine-dependent land, we do some -- machine-independent optimisations (defined below) on the--- 'CmmStmts's.+-- 'CmmStmts's. (Which ideally would be folded into CmmOpt ...) -- -- We convert to the machine-specific 'Instr' datatype with -- 'cmmCodeGen', assuming an infinite supply of registers.  We then use--- a machine-independent register allocator ('regAlloc') to rejoin+-- a (mostly) machine-independent register allocator to rejoin -- reality.  Obviously, 'regAlloc' has machine-specific helper--- functions (see about "RegAllocInfo" below).+-- functions (see the used register allocator for details). -- -- Finally, we order the basic blocks of the function so as to minimise -- the number of jumps between blocks, by utilising fallthrough wherever -- possible. ----- The machine-dependent bits break down as follows:+-- The machine-dependent bits are generally contained under+--  GHC/CmmToAsm/<Arch>/* and generally breaks down as follows: -----   * ["MachRegs"]  Everything about the target platform's machine+--   * "Regs": Everything about the target platform's machine --     registers (and immediate operands, and addresses, which tend to --     intermingle/interact with registers). -----   * ["MachInstrs"]  Includes the 'Instr' datatype (possibly should---     have a module of its own), plus a miscellany of other things+--   * "Instr":  Includes the 'Instr' datatype plus a miscellany of other things --     (e.g., 'targetDoubleSize', 'smStablePtrTable', ...) -----   * ["MachCodeGen"]  is where 'Cmm' stuff turns into+--   * "CodeGen":  is where 'Cmm' stuff turns into --     machine instructions. -----   * ["PprMach"] 'pprInstr' turns an 'Instr' into text (well, really+--   * "Ppr": 'pprInstr' turns an 'Instr' into text (well, really --     a 'SDoc'). -----   * ["RegAllocInfo"] In the register allocator, we manipulate---     'MRegsState's, which are 'BitSet's, one bit per machine register.---     When we want to say something about a specific machine register---     (e.g., ``it gets clobbered by this instruction''), we set/unset---     its bit.  Obviously, we do this 'BitSet' thing for efficiency---     reasons.------     The 'RegAllocInfo' module collects together the machine-specific---     info needed to do register allocation.+-- The register allocators lives under GHC.CmmToAsm.Reg.*, there is both a Linear and a Graph+-- based register allocator. Both of which have their own notes describing them. They+-- are mostly platform independent but there are some platform specific files+-- encoding architecture details under Reg/<Allocator>/<Arch.hs> -----    * ["RegisterAlloc"] The (machine-independent) register allocator. -- -} -- module GHC.CmmToAsm    ( nativeCodeGen -   -- * Test-only exports: see trac #12744+   -- * Test-only exports: see #12744    -- used by testGraphNoSpills, which needs to access    -- the register allocator intermediate data structures    -- cmmNativeGen emits@@ -110,11 +95,8 @@ import GHC.Cmm.BlockId import GHC.StgToCmm.CgUtils ( fixStgRegisters ) import GHC.Cmm-import GHC.Cmm.Utils-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Label-import GHC.Cmm.Dataflow.Block-import GHC.Cmm.Opt           ( cmmMachOpFold )+import GHC.Cmm.GenericOpt import GHC.Cmm.CLabel  import GHC.Types.Unique.FM@@ -127,7 +109,6 @@ import GHC.Utils.BufHandle import GHC.Utils.Outputable as Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Error import GHC.Utils.Exception (evaluate) import GHC.Utils.Constants (debugIsOn)@@ -171,7 +152,7 @@       ArchLoongArch64->panic "nativeCodeGen: No NCG for LoongArch64"       ArchUnknown   -> panic "nativeCodeGen: No NCG for unknown arch"       ArchJavaScript-> panic "nativeCodeGen: No NCG for JavaScript"-      ArchWasm32    -> Wasm32.ncgWasm platform ts us modLoc h cmms+      ArchWasm32    -> Wasm32.ncgWasm config logger platform ts us modLoc h cmms  -- | Data accumulated during code generation. Mostly about statistics, -- but also collects debug data for DWARF generation.@@ -949,196 +930,3 @@                       , natm_fileid final_st, final_cfg)           else pprPanic "genMachCode: nonzero final delta" (int final_delta)     }---- -------------------------------------------------------------------------------- Generic Cmm optimiser--{--Here we do:--  (a) Constant folding-  (c) Position independent code and dynamic linking-        (i)  introduce the appropriate indirections-             and position independent refs-        (ii) compile a list of imported symbols-  (d) Some arch-specific optimizations--(a) will be moving to the new Hoopl pipeline, however, (c) and-(d) are only needed by the native backend and will continue to live-here.--Ideas for other things we could do (put these in Hoopl please!):--  - shortcut jumps-to-jumps-  - simple CSE: if an expr is assigned to a temp, then replace later occs of-    that expr with the temp, until the expr is no longer valid (can push through-    temp assignments, and certain assigns to mem...)--}--cmmToCmm :: NCGConfig -> RawCmmDecl -> (RawCmmDecl, [CLabel])-cmmToCmm _ top@(CmmData _ _) = (top, [])-cmmToCmm config (CmmProc info lbl live graph)-    = runCmmOpt config $-      do blocks' <- mapM cmmBlockConFold (toBlockList graph)-         return $ CmmProc info lbl live (ofBlockList (g_entry graph) blocks')--type OptMResult a = (# a, [CLabel] #)--pattern OptMResult :: a -> b -> (# a, b #)-pattern OptMResult x y = (# x, y #)-{-# COMPLETE OptMResult #-}--newtype CmmOptM a = CmmOptM (NCGConfig -> [CLabel] -> OptMResult a)-    deriving (Functor)--instance Applicative CmmOptM where-    pure x = CmmOptM $ \_ imports -> OptMResult x imports-    (<*>) = ap--instance Monad CmmOptM where-  (CmmOptM f) >>= g =-    CmmOptM $ \config imports0 ->-                case f config imports0 of-                  OptMResult x imports1 ->-                    case g x of-                      CmmOptM g' -> g' config imports1--instance CmmMakeDynamicReferenceM CmmOptM where-    addImport = addImportCmmOpt--addImportCmmOpt :: CLabel -> CmmOptM ()-addImportCmmOpt lbl = CmmOptM $ \_ imports -> OptMResult () (lbl:imports)--getCmmOptConfig :: CmmOptM NCGConfig-getCmmOptConfig = CmmOptM $ \config imports -> OptMResult config imports--runCmmOpt :: NCGConfig -> CmmOptM a -> (a, [CLabel])-runCmmOpt config (CmmOptM f) =-  case f config [] of-    OptMResult result imports -> (result, imports)--cmmBlockConFold :: CmmBlock -> CmmOptM CmmBlock-cmmBlockConFold block = do-  let (entry, middle, last) = blockSplit block-      stmts = blockToList middle-  stmts' <- mapM cmmStmtConFold stmts-  last' <- cmmStmtConFold last-  return $ blockJoin entry (blockFromList stmts') last'---- This does three optimizations, but they're very quick to check, so we don't--- bother turning them off even when the Hoopl code is active.  Since--- this is on the old Cmm representation, we can't reuse the code either:---  * reg = reg      --> nop---  * if 0 then jump --> nop---  * if 1 then jump --> jump--- We might be tempted to skip this step entirely of not Opt_PIC, but--- there is some PowerPC code for the non-PIC case, which would also--- have to be separated.-cmmStmtConFold :: CmmNode e x -> CmmOptM (CmmNode e x)-cmmStmtConFold stmt-   = case stmt of-        CmmAssign reg src-           -> do src' <- cmmExprConFold DataReference src-                 return $ case src' of-                   CmmReg reg' | reg == reg' -> CmmComment (fsLit "nop")-                   new_src -> CmmAssign reg new_src--        CmmStore addr src align-           -> do addr' <- cmmExprConFold DataReference addr-                 src'  <- cmmExprConFold DataReference src-                 return $ CmmStore addr' src' align--        CmmCall { cml_target = addr }-           -> do addr' <- cmmExprConFold JumpReference addr-                 return $ stmt { cml_target = addr' }--        CmmUnsafeForeignCall target regs args-           -> do target' <- case target of-                              ForeignTarget e conv -> do-                                e' <- cmmExprConFold CallReference e-                                return $ ForeignTarget e' conv-                              PrimTarget _ ->-                                return target-                 args' <- mapM (cmmExprConFold DataReference) args-                 return $ CmmUnsafeForeignCall target' regs args'--        CmmCondBranch test true false likely-           -> do test' <- cmmExprConFold DataReference test-                 return $ case test' of-                   CmmLit (CmmInt 0 _) -> CmmBranch false-                   CmmLit (CmmInt _ _) -> CmmBranch true-                   _other -> CmmCondBranch test' true false likely--        CmmSwitch expr ids-           -> do expr' <- cmmExprConFold DataReference expr-                 return $ CmmSwitch expr' ids--        other-           -> return other--cmmExprConFold :: ReferenceKind -> CmmExpr -> CmmOptM CmmExpr-cmmExprConFold referenceKind expr = do-    config <- getCmmOptConfig--    let expr' = if not (ncgDoConstantFolding config)-                    then expr-                    else cmmExprCon config expr--    cmmExprNative referenceKind expr'--cmmExprCon :: NCGConfig -> CmmExpr -> CmmExpr-cmmExprCon config (CmmLoad addr rep align) = CmmLoad (cmmExprCon config addr) rep align-cmmExprCon config (CmmMachOp mop args)-    = cmmMachOpFold (ncgPlatform config) mop (map (cmmExprCon config) args)-cmmExprCon _ other = other---- handles both PIC and non-PIC cases... a very strange mixture--- of things to do.-cmmExprNative :: ReferenceKind -> CmmExpr -> CmmOptM CmmExpr-cmmExprNative referenceKind expr = do-     config <- getCmmOptConfig-     let platform = ncgPlatform config-         arch = platformArch platform-     case expr of-        CmmLoad addr rep align-          -> do addr' <- cmmExprNative DataReference addr-                return $ CmmLoad addr' rep align--        CmmMachOp mop args-          -> do args' <- mapM (cmmExprNative DataReference) args-                return $ CmmMachOp mop args'--        CmmLit (CmmBlock id)-          -> cmmExprNative referenceKind (CmmLit (CmmLabel (infoTblLbl id)))-          -- we must convert block Ids to CLabels here, because we-          -- might have to do the PIC transformation.  Hence we must-          -- not modify BlockIds beyond this point.--        CmmLit (CmmLabel lbl)-          -> cmmMakeDynamicReference config referenceKind lbl-        CmmLit (CmmLabelOff lbl off)-          -> do dynRef <- cmmMakeDynamicReference config referenceKind lbl-                -- need to optimize here, since it's late-                return $ cmmMachOpFold platform (MO_Add (wordWidth platform)) [-                    dynRef,-                    (CmmLit $ CmmInt (fromIntegral off) (wordWidth platform))-                  ]--        -- On powerpc (non-PIC), it's easier to jump directly to a label than-        -- to use the register table, so we replace these registers-        -- with the corresponding labels:-        CmmReg (CmmGlobal (GlobalRegUse EagerBlackholeInfo _))-          | arch == ArchPPC && not (ncgPIC config)-          -> cmmExprNative referenceKind $-             CmmLit (CmmLabel (mkCmmCodeLabel rtsUnitId (fsLit "__stg_EAGER_BLACKHOLE_info")))-        CmmReg (CmmGlobal (GlobalRegUse GCEnter1 _))-          | arch == ArchPPC && not (ncgPIC config)-          -> cmmExprNative referenceKind $-             CmmLit (CmmLabel (mkCmmCodeLabel rtsUnitId (fsLit "__stg_gc_enter_1")))-        CmmReg (CmmGlobal (GlobalRegUse GCFun _))-          | arch == ArchPPC && not (ncgPIC config)-          -> cmmExprNative referenceKind $-             CmmLit (CmmLabel (mkCmmCodeLabel rtsUnitId (fsLit "__stg_gc_fun")))--        other-           -> return other
compiler/GHC/CmmToAsm/AArch64.hs view
@@ -47,7 +47,6 @@         patchRegsOfInstr        = AArch64.patchRegsOfInstr         isJumpishInstr          = AArch64.isJumpishInstr         jumpDestsOfInstr        = AArch64.jumpDestsOfInstr-        canFallthroughTo        = AArch64.canFallthroughTo         patchJumpInstr          = AArch64.patchJumpInstr         mkSpillInstr            = AArch64.mkSpillInstr         mkLoadInstr             = AArch64.mkLoadInstr
compiler/GHC/CmmToAsm/AArch64/CodeGen.hs view
@@ -1,9 +1,5 @@ {-# language GADTs #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE BinaryLiterals #-} {-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE NumericUnderscores #-} module GHC.CmmToAsm.AArch64.CodeGen (       cmmTopCodeGen     , generateJumpTableForInstr@@ -63,12 +59,9 @@ import GHC.Data.FastString import GHC.Utils.Misc import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Constants (debugIsOn) import GHC.Utils.Monad (mapAccumLM) -import GHC.Cmm.Dataflow.Collections- -- Note [General layout of an NCG] -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- @cmmTopCodeGen@ will be our main entry point to code gen.  Here we'll get@@ -163,8 +156,9 @@   --      unwinding info. See Ticket 19913   -- code generation may introduce new basic block boundaries, which   -- are indicated by the NEWBLOCK instruction.  We must split up the-  -- instruction stream into basic blocks again.  Also, we extract-  -- LDATAs here too.+  -- instruction stream into basic blocks again. Also, we may extract+  -- LDATAs here too (if they are implemented by AArch64 again - See+  -- PPC how to do that.)   let         (top,other_blocks,statics) = foldrOL mkBlocks ([],[],[]) instrs @@ -175,8 +169,6 @@           -> ([Instr], [GenBasicBlock Instr], [GenCmmDecl RawCmmStatics h g]) mkBlocks (NEWBLOCK id) (instrs,blocks,statics)   = ([], BasicBlock id instrs : blocks, statics)-mkBlocks (LDATA sec dat) (instrs,blocks,statics)-  = (instrs, blocks, CmmData sec dat:statics) mkBlocks instr (instrs,blocks,statics)   = (instr:instrs, blocks, statics) -- -----------------------------------------------------------------------------@@ -197,7 +189,7 @@ -- going back to the exact CmmExpr representation can be laborious and adds -- indirections to find the matches that lead to the assembly. ----- An improvement oculd be to have+-- An improvement could be to have -- --    (pprExpr genericPlatform e) <> parens (text. show e) --@@ -381,9 +373,117 @@     Fixed rep reg code ->         return (reg, rep, code) +{- Note [Aarch64 immediates]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Aarch64 with it's fixed width instruction encoding uses leftover space for+immediates.+If you want the full rundown consult the arch reference document:+"Arm® Architecture Reference Manual" - "C3.4 Data processing - immediate"++The gist of it is that different instructions allow for different immediate encodings.+The ones we care about for better code generation are:++* Simple but potentially repeated bit-patterns for logic instructions.+* 16bit numbers shifted by multiples of 16.+* 12 bit numbers optionally shifted by 12 bits.++It might seem like the ISA allows for 64bit immediates but this isn't the case.+Rather there are some instruction aliases which allow for large unencoded immediates+which will then be transalted to one of the immediate encodings implicitly.++For example mov x1, #0x10000 is allowed but will be assembled to movz x1, #0x1, lsl #16+-}++-- | Move (wide immediate)+-- Allows for 16bit immediate which can be shifted by 0/16/32/48 bits.+-- Used with MOVZ,MOVN, MOVK+-- See Note [Aarch64 immediates]+getMovWideImm :: Integer -> Width -> Maybe Operand+getMovWideImm n w+  -- TODO: Handle sign extension/negatives+  | n <= 0+  = Nothing+  -- Fits in 16 bits+  | sized_n < 2^(16 :: Int)+  = Just $ OpImm (ImmInteger truncated)++  -- 0x0000 0000 xxxx 0000+  | trailing_zeros >= 16 && sized_n < 2^(32 :: Int)+  = Just $ OpImmShift (ImmInteger $ truncated `shiftR` 16) SLSL 16++  -- 0x 0000 xxxx 0000 0000+  | trailing_zeros >= 32 && sized_n < 2^(48 :: Int)+  = Just $ OpImmShift (ImmInteger $ truncated `shiftR` 32) SLSL 32++  -- 0x xxxx 0000 0000 0000+  | trailing_zeros >= 48+  = Just $ OpImmShift (ImmInteger $ truncated `shiftR` 48) SLSL 48++  | otherwise+  = Nothing+  where+    truncated = narrowU w n+    sized_n = fromIntegral truncated :: Word64+    trailing_zeros = countTrailingZeros sized_n++-- | Arithmetic(immediate)+--  Allows for 12bit immediates which can be shifted by 0 or 12 bits.+-- Used with ADD, ADDS, SUB, SUBS, CMP+-- See Note [Aarch64 immediates]+getArithImm :: Integer -> Width -> Maybe Operand+getArithImm n w+  -- TODO: Handle sign extension+  | n <= 0+  = Nothing+  -- Fits in 16 bits+  -- Fits in 12 bits+  | sized_n < 2^(12::Int)+  = Just $ OpImm (ImmInteger truncated)++  -- 12 bits shifted by 12 places.+  | trailing_zeros >= 12 && sized_n < 2^(24::Int)+  = Just $ OpImmShift (ImmInteger $ truncated `shiftR` 12) SLSL 12++  | otherwise+  = Nothing+  where+    sized_n = fromIntegral truncated :: Word64+    truncated = narrowU w n+    trailing_zeros = countTrailingZeros sized_n++-- |  Logical (immediate)+-- Allows encoding of some repeated bitpatterns+-- Used with AND, EOR, ORR+-- and their aliases which includes at least MOV (bitmask immediate)+-- See Note [Aarch64 immediates]+getBitmaskImm :: Integer -> Width -> Maybe Operand+getBitmaskImm n w+  | isAArch64Bitmask (opRegWidth w) truncated = Just $ OpImm (ImmInteger truncated)+  | otherwise = Nothing+  where+    truncated = narrowU w n++-- | Load/store immediate.+-- Depends on the width of the store to some extent.+isOffsetImm :: Int -> Width -> Bool+isOffsetImm off w+  -- 8 bits + sign for unscaled offsets+  | -256 <= off, off <= 255 = True+  -- Offset using 12-bit positive immediate, scaled by width+  -- LDR/STR: imm12: if reg is 32bit: 0 -- 16380 in multiples of 4+  -- LDR/STR: imm12: if reg is 64bit: 0 -- 32760 in multiples of 8+  -- 16-bit: 0 .. 8188, 8-bit: 0 -- 4095+  | 0 <= off, off < 4096 * byte_width, off `mod` byte_width == 0 = True+  | otherwise = False+  where+    byte_width = widthInBytes w++++ -- TODO OPT: we might be able give getRegister --          a hint, what kind of register we want.-getFloatReg :: HasDebugCallStack => CmmExpr -> NatM (Reg, Format, InstrBlock)+getFloatReg :: HasCallStack => CmmExpr -> NatM (Reg, Format, InstrBlock) getFloatReg expr = do   r <- getRegister expr   case r of@@ -503,8 +603,14 @@     CmmLit lit       -> case lit of -        -- TODO handle CmmInt 0 specially, use wzr or xzr.-+        -- Use wzr xzr for CmmInt 0 if the width matches up, otherwise do a move.+        -- TODO: Reenable after https://gitlab.haskell.org/ghc/ghc/-/issues/23632 is fixed.+        -- CmmInt 0 W32 -> do+        --   let format = intFormat W32+        --   return (Fixed format reg_zero (unitOL $ (COMMENT ((text . show $ expr))) ))+        -- CmmInt 0 W64 -> do+        --   let format = intFormat W64+        --   return (Fixed format reg_zero (unitOL $ (COMMENT ((text . show $ expr))) ))         CmmInt i W8 | i >= 0 -> do           return (Any (intFormat W8) (\dst -> unitOL $ annExpr expr (MOV (OpReg W8 dst) (OpImm (ImmInteger (narrowU W8 i))))))         CmmInt i W16 | i >= 0 -> do@@ -519,8 +625,13 @@         -- Those need the upper bits set. We'd either have to explicitly sign         -- or figure out something smarter. Lowered to         -- `MOV dst XZR`+        CmmInt i w | i >= 0+                   , Just imm_op <- getMovWideImm i w -> do+          return (Any (intFormat w) (\dst -> unitOL $ annExpr expr (MOVZ (OpReg w dst) imm_op)))+         CmmInt i w | isNbitEncodeable 16 i, i >= 0 -> do           return (Any (intFormat w) (\dst -> unitOL $ annExpr expr (MOV (OpReg W16 dst) (OpImm (ImmInteger i)))))+         CmmInt i w | isNbitEncodeable 32 i, i >= 0 -> do           let  half0 = fromIntegral (fromIntegral i :: Word16)                half1 = fromIntegral (fromIntegral (i `shiftR` 16) :: Word16)@@ -595,7 +706,6 @@           (op, imm_code) <- litToImm' lit           let rep = cmmLitType plat lit               format = cmmTypeFormat rep-              -- width = typeWidth rep           return (Any format (\dst -> imm_code `snocOL` LDR format (OpReg (formatToWidth format) dst) op))          CmmLabelOff lbl off -> do@@ -619,21 +729,20 @@       -> return (Fixed (cmmTypeFormat (cmmRegType reg))                        (getRegisterReg plat reg)                        nilOL)-    CmmRegOff reg off | isNbitEncodeable 12 (fromIntegral off) -> do-      getRegister' config plat $-            CmmMachOp (MO_Add width) [CmmReg reg, CmmLit (CmmInt (fromIntegral off) width)]-          where width = typeWidth (cmmRegType reg)--    CmmRegOff reg off -> do-      (off_r, _off_format, off_code) <- getSomeReg $ CmmLit (CmmInt (fromIntegral off) width)-      (reg, _format, code) <- getSomeReg $ CmmReg reg-      return $ Any (intFormat width) (\dst -> off_code `appOL` code `snocOL` ADD (OpReg width dst) (OpReg width reg) (OpReg width off_r))-          where width = typeWidth (cmmRegType reg)--+    CmmRegOff reg off ->+      -- If we got here we will load the address into a register either way. So we might as well just expand+      -- and re-use the existing code path to handle "reg + off".+      let !width = cmmRegWidth reg+      in getRegister' config plat (CmmMachOp (MO_Add width) [CmmReg reg, CmmLit (CmmInt (fromIntegral off) width)])      -- for MachOps, see GHC.Cmm.MachOp     -- For CmmMachOp, see GHC.Cmm.Expr++    -- Handle MO_RelaxedRead as a normal CmmLoad, to allow+    -- non-trivial addressing modes to be used.+    CmmMachOp (MO_RelaxedRead w) [e] ->+      getRegister (CmmLoad e (cmmBits w) NaturallyAligned)+     CmmMachOp op [e] -> do       (reg, _format, code) <- getSomeReg e       case op of@@ -702,37 +811,25 @@     -- 0. TODO This should not exist! Rewrite: Reg +- 0 -> Reg     CmmMachOp (MO_Add _) [expr'@(CmmReg (CmmGlobal _r)), CmmLit (CmmInt 0 _)] -> getRegister' config plat expr'     CmmMachOp (MO_Sub _) [expr'@(CmmReg (CmmGlobal _r)), CmmLit (CmmInt 0 _)] -> getRegister' config plat expr'-    -- 1. Compute Reg +/- n directly.-    --    For Add/Sub we can directly encode 12bits, or 12bits lsl #12.-    CmmMachOp (MO_Add w) [(CmmReg reg), CmmLit (CmmInt n _)]-      | n > 0 && n < 4096-      , w == W32 || w == W64 -- Work around #23749-      -> return $ Any (intFormat w) (\d -> unitOL $ annExpr expr (ADD (OpReg w d) (OpReg w' r') (OpImm (ImmInteger n))))-      -- TODO: 12bits lsl #12; e.g. lower 12 bits of n are 0; shift n >> 12, and set lsl to #12.-      where w' = formatToWidth (cmmTypeFormat (cmmRegType reg))-            r' = getRegisterReg plat reg-    CmmMachOp (MO_Sub w) [(CmmReg reg), CmmLit (CmmInt n _)]-      | n > 0 && n < 4096-      , w == W32 || w == W64 -- Work around #23749-      -> return $ Any (intFormat w) (\d -> unitOL $ annExpr expr (SUB (OpReg w d) (OpReg w' r') (OpImm (ImmInteger n))))-      -- TODO: 12bits lsl #12; e.g. lower 12 bits of n are 0; shift n >> 12, and set lsl to #12.-      where w' = formatToWidth (cmmTypeFormat (cmmRegType reg))-            r' = getRegisterReg plat reg+    -- Immediates are handled via `getArithImm` in the generic code path.      CmmMachOp (MO_U_Quot w) [x, y] | w == W8 -> do       (reg_x, _format_x, code_x) <- getSomeReg x       (reg_y, _format_y, code_y) <- getSomeReg y-      return $ Any (intFormat w) (\dst -> code_x `appOL` code_y `snocOL` annExpr expr (UXTB (OpReg w reg_x) (OpReg w reg_x)) `snocOL` (UXTB (OpReg w reg_y) (OpReg w reg_y)) `snocOL` (UDIV (OpReg w dst) (OpReg w reg_x) (OpReg w reg_y)))+      return $ Any (intFormat w) (\dst -> code_x `appOL` code_y `snocOL` annExpr expr (UXTB (OpReg w reg_x) (OpReg w reg_x)) `snocOL`+                                                                        (UXTB (OpReg w reg_y) (OpReg w reg_y)) `snocOL`+                                                                        (UDIV (OpReg w dst) (OpReg w reg_x) (OpReg w reg_y)))     CmmMachOp (MO_U_Quot w) [x, y] | w == W16 -> do       (reg_x, _format_x, code_x) <- getSomeReg x       (reg_y, _format_y, code_y) <- getSomeReg y-      return $ Any (intFormat w) (\dst -> code_x `appOL` code_y `snocOL` annExpr expr (UXTH (OpReg w reg_x) (OpReg w reg_x)) `snocOL` (UXTH (OpReg w reg_y) (OpReg w reg_y)) `snocOL` (UDIV (OpReg w dst) (OpReg w reg_x) (OpReg w reg_y)))+      return $ Any (intFormat w) (\dst -> code_x `appOL` code_y `snocOL` annExpr expr (UXTH (OpReg w reg_x) (OpReg w reg_x)) `snocOL`+                                                                        (UXTH (OpReg w reg_y) (OpReg w reg_y)) `snocOL`+                                                                        (UDIV (OpReg w dst) (OpReg w reg_x) (OpReg w reg_y)))      -- 2. Shifts. x << n, x >> n.-    CmmMachOp (MO_Shl w) [x, (CmmLit (CmmInt n _))] | w == W32, 0 <= n, n < 32 -> do-      (reg_x, _format_x, code_x) <- getSomeReg x-      return $ Any (intFormat w) (\dst -> code_x `snocOL` annExpr expr (LSL (OpReg w dst) (OpReg w reg_x) (OpImm (ImmInteger n))))-    CmmMachOp (MO_Shl w) [x, (CmmLit (CmmInt n _))] | w == W64, 0 <= n, n < 64 -> do+    CmmMachOp (MO_Shl w) [x, (CmmLit (CmmInt n _))]+      | w == W32 || w == W64+      , 0 <= n, n < fromIntegral (widthInBits w) -> do       (reg_x, _format_x, code_x) <- getSomeReg x       return $ Any (intFormat w) (\dst -> code_x `snocOL` annExpr expr (LSL (OpReg w dst) (OpReg w reg_x) (OpImm (ImmInteger n)))) @@ -742,7 +839,8 @@     CmmMachOp (MO_S_Shr w) [x, y] | w == W8 -> do       (reg_x, _format_x, code_x) <- getSomeReg x       (reg_y, _format_y, code_y) <- getSomeReg y-      return $ Any (intFormat w) (\dst -> code_x `appOL` code_y `snocOL` annExpr expr (SXTB (OpReg w reg_x) (OpReg w reg_x)) `snocOL` (ASR (OpReg w dst) (OpReg w reg_x) (OpReg w reg_y)))+      return $ Any (intFormat w) (\dst -> code_x `appOL` code_y `snocOL` annExpr expr (SXTB (OpReg w reg_x) (OpReg w reg_x)) `snocOL`+                                                                         (ASR (OpReg w dst) (OpReg w reg_x) (OpReg w reg_y)))      CmmMachOp (MO_S_Shr w) [x, (CmmLit (CmmInt n _))] | w == W16, 0 <= n, n < 16 -> do       (reg_x, _format_x, code_x) <- getSomeReg x@@ -750,24 +848,23 @@     CmmMachOp (MO_S_Shr w) [x, y] | w == W16 -> do       (reg_x, _format_x, code_x) <- getSomeReg x       (reg_y, _format_y, code_y) <- getSomeReg y-      return $ Any (intFormat w) (\dst -> code_x `appOL` code_y `snocOL` annExpr expr (SXTH (OpReg w reg_x) (OpReg w reg_x)) `snocOL` (ASR (OpReg w dst) (OpReg w reg_x) (OpReg w reg_y)))--    CmmMachOp (MO_S_Shr w) [x, (CmmLit (CmmInt n _))] | w == W32, 0 <= n, n < 32 -> do-      (reg_x, _format_x, code_x) <- getSomeReg x-      return $ Any (intFormat w) (\dst -> code_x `snocOL` annExpr expr (ASR (OpReg w dst) (OpReg w reg_x) (OpImm (ImmInteger n))))+      return $ Any (intFormat w) (\dst -> code_x `appOL` code_y `snocOL` annExpr expr (SXTH (OpReg w reg_x) (OpReg w reg_x)) `snocOL`+                                                                         (ASR (OpReg w dst) (OpReg w reg_x) (OpReg w reg_y))) -    CmmMachOp (MO_S_Shr w) [x, (CmmLit (CmmInt n _))] | w == W64, 0 <= n, n < 64 -> do+    CmmMachOp (MO_S_Shr w) [x, (CmmLit (CmmInt n _))]+      | w == W32 || w == W64+      , 0 <= n, n < fromIntegral (widthInBits w) -> do       (reg_x, _format_x, code_x) <- getSomeReg x       return $ Any (intFormat w) (\dst -> code_x `snocOL` annExpr expr (ASR (OpReg w dst) (OpReg w reg_x) (OpImm (ImmInteger n)))) -     CmmMachOp (MO_U_Shr w) [x, (CmmLit (CmmInt n _))] | w == W8, 0 <= n, n < 8 -> do       (reg_x, _format_x, code_x) <- getSomeReg x       return $ Any (intFormat w) (\dst -> code_x `snocOL` annExpr expr (UBFX (OpReg w dst) (OpReg w reg_x) (OpImm (ImmInteger n)) (OpImm (ImmInteger (8-n)))))     CmmMachOp (MO_U_Shr w) [x, y] | w == W8 -> do       (reg_x, _format_x, code_x) <- getSomeReg x       (reg_y, _format_y, code_y) <- getSomeReg y-      return $ Any (intFormat w) (\dst -> code_x `appOL` code_y `snocOL` annExpr expr (UXTB (OpReg w reg_x) (OpReg w reg_x)) `snocOL` (ASR (OpReg w dst) (OpReg w reg_x) (OpReg w reg_y)))+      return $ Any (intFormat w) (\dst -> code_x `appOL` code_y `snocOL` annExpr expr (UXTB (OpReg w reg_x) (OpReg w reg_x)) `snocOL`+                                                                        (ASR (OpReg w dst) (OpReg w reg_x) (OpReg w reg_y)))      CmmMachOp (MO_U_Shr w) [x, (CmmLit (CmmInt n _))] | w == W16, 0 <= n, n < 16 -> do       (reg_x, _format_x, code_x) <- getSomeReg x@@ -775,23 +872,22 @@     CmmMachOp (MO_U_Shr w) [x, y] | w == W16 -> do       (reg_x, _format_x, code_x) <- getSomeReg x       (reg_y, _format_y, code_y) <- getSomeReg y-      return $ Any (intFormat w) (\dst -> code_x `appOL` code_y `snocOL` annExpr expr (UXTH (OpReg w reg_x) (OpReg w reg_x)) `snocOL` (ASR (OpReg w dst) (OpReg w reg_x) (OpReg w reg_y)))--    CmmMachOp (MO_U_Shr w) [x, (CmmLit (CmmInt n _))] | w == W32, 0 <= n, n < 32 -> do-      (reg_x, _format_x, code_x) <- getSomeReg x-      return $ Any (intFormat w) (\dst -> code_x `snocOL` annExpr expr (LSR (OpReg w dst) (OpReg w reg_x) (OpImm (ImmInteger n))))+      return $ Any (intFormat w) (\dst -> code_x `appOL` code_y `snocOL` annExpr expr (UXTH (OpReg w reg_x) (OpReg w reg_x))+                                                                `snocOL` (ASR (OpReg w dst) (OpReg w reg_x) (OpReg w reg_y))) -    CmmMachOp (MO_U_Shr w) [x, (CmmLit (CmmInt n _))] | w == W64, 0 <= n, n < 64 -> do+    CmmMachOp (MO_U_Shr w) [x, (CmmLit (CmmInt n _))]+      | w == W32 || w == W64+      , 0 <= n, n < fromIntegral (widthInBits w) -> do       (reg_x, _format_x, code_x) <- getSomeReg x       return $ Any (intFormat w) (\dst -> code_x `snocOL` annExpr expr (LSR (OpReg w dst) (OpReg w reg_x) (OpImm (ImmInteger n))))      -- 3. Logic &&, ||-    CmmMachOp (MO_And w) [(CmmReg reg), CmmLit (CmmInt n _)] | isAArch64Bitmask (fromIntegral n) ->+    CmmMachOp (MO_And w) [(CmmReg reg), CmmLit (CmmInt n _)] | isAArch64Bitmask (opRegWidth w') (fromIntegral n) ->       return $ Any (intFormat w) (\d -> unitOL $ annExpr expr (AND (OpReg w d) (OpReg w' r') (OpImm (ImmInteger n))))       where w' = formatToWidth (cmmTypeFormat (cmmRegType reg))             r' = getRegisterReg plat reg -    CmmMachOp (MO_Or w) [(CmmReg reg), CmmLit (CmmInt n _)] | isAArch64Bitmask (fromIntegral n) ->+    CmmMachOp (MO_Or w) [(CmmReg reg), CmmLit (CmmInt n _)] | isAArch64Bitmask (opRegWidth w') (fromIntegral n) ->       return $ Any (intFormat w) (\d -> unitOL $ annExpr expr (ORR (OpReg w d) (OpReg w' r') (OpImm (ImmInteger n))))       where w' = formatToWidth (cmmTypeFormat (cmmRegType reg))             r' = getRegisterReg plat reg@@ -804,22 +900,56 @@           -- withTempFloatReg w op = OpReg w <$> getNewRegNat (floatFormat w) >>= op            -- A "plain" operation.-          bitOp w op = do+          bitOpImm w op encode_imm = do             -- compute x<m> <- x             -- compute x<o> <- y             -- <OP> x<n>, x<m>, x<o>             (reg_x, format_x, code_x) <- getSomeReg x-            (reg_y, format_y, code_y) <- getSomeReg y-            massertPpr (isIntFormat format_x == isIntFormat format_y) $ text "bitOp: incompatible"+            (op_y, format_y, code_y) <- case y of+              CmmLit (CmmInt n w)+                | Just imm_operand_y <- encode_imm n w+                -> return (imm_operand_y, intFormat w, nilOL)+              _ -> do+                  (reg_y, format_y, code_y) <- getSomeReg y+                  return (OpReg w reg_y, format_y, code_y)+            massertPpr (isIntFormat format_x == isIntFormat format_y) $ text "bitOpImm: incompatible"             return $ Any (intFormat w) (\dst ->                 code_x `appOL`                 code_y `appOL`-                op (OpReg w dst) (OpReg w reg_x) (OpReg w reg_y))+                op (OpReg w dst) (OpReg w reg_x) op_y)            -- A (potentially signed) integer operation.           -- In the case of 8- and 16-bit signed arithmetic we must first           -- sign-extend both arguments to 32-bits.           -- See Note [Signed arithmetic on AArch64].+          intOpImm :: Bool -> Width -> (Operand -> Operand -> Operand -> OrdList Instr) -> (Integer -> Width -> Maybe Operand) -> NatM (Register)+          intOpImm {- is signed -} True  w op _encode_imm = intOp True w op+          intOpImm                 False w op  encode_imm = do+              -- compute x<m> <- x+              -- compute x<o> <- y+              -- <OP> x<n>, x<m>, x<o>+              (reg_x, format_x, code_x) <- getSomeReg x+              (op_y, format_y, code_y) <- case y of+                CmmLit (CmmInt n w)+                  | Just imm_operand_y <- encode_imm n w+                  -> return (imm_operand_y, intFormat w, nilOL)+                _ -> do+                    (reg_y, format_y, code_y) <- getSomeReg y+                    return (OpReg w reg_y, format_y, code_y)+              massertPpr (isIntFormat format_x && isIntFormat format_y) $ text "intOp: non-int"+              -- This is the width of the registers on which the operation+              -- should be performed.+              let w' = opRegWidth w+              return $ Any (intFormat w) $ \dst ->+                  code_x `appOL`+                  code_y `appOL`+                  op (OpReg w' dst) (OpReg w' reg_x) (op_y) `appOL`+                  truncateReg w' w dst -- truncate back to the operand's original width++          -- A (potentially signed) integer operation.+          -- In the case of 8- and 16-bit signed arithmetic we must first+          -- sign-extend both arguments to 32-bits.+          -- See Note [Signed arithmetic on AArch64].           intOp is_signed w op = do               -- compute x<m> <- x               -- compute x<o> <- y@@ -860,9 +990,9 @@       case op of         -- Integer operations         -- Add/Sub should only be Integer Options.-        MO_Add w -> intOp False w (\d x y -> unitOL $ annExpr expr (ADD d x y))+        MO_Add w -> intOpImm False w (\d x y -> unitOL $ annExpr expr (ADD d x y)) getArithImm         -- TODO: Handle sub-word case-        MO_Sub w -> intOp False w (\d x y -> unitOL $ annExpr expr (SUB d x y))+        MO_Sub w -> intOpImm False w (\d x y -> unitOL $ annExpr expr (SUB d x y)) getArithImm          -- Note [CSET]         -- ~~~~~~~~~~~@@ -904,8 +1034,8 @@          -- N.B. We needn't sign-extend sub-word size (in)equality comparisons         -- since we don't care about ordering.-        MO_Eq w     -> bitOp w (\d x y -> toOL [ CMP x y, CSET d EQ ])-        MO_Ne w     -> bitOp w (\d x y -> toOL [ CMP x y, CSET d NE ])+        MO_Eq w     -> bitOpImm w (\d x y -> toOL [ CMP x y, CSET d EQ ]) getArithImm+        MO_Ne w     -> bitOpImm w (\d x y -> toOL [ CMP x y, CSET d NE ]) getArithImm          -- Signed multiply/divide         MO_Mul w          -> intOp True w (\d x y -> unitOL $ MUL d x y)@@ -934,10 +1064,10 @@         MO_S_Lt w     -> intOp True  w (\d x y -> toOL [ CMP x y, CSET d SLT ])          -- Unsigned comparisons-        MO_U_Ge w     -> intOp False w (\d x y -> toOL [ CMP x y, CSET d UGE ])-        MO_U_Le w     -> intOp False w (\d x y -> toOL [ CMP x y, CSET d ULE ])-        MO_U_Gt w     -> intOp False w (\d x y -> toOL [ CMP x y, CSET d UGT ])-        MO_U_Lt w     -> intOp False w (\d x y -> toOL [ CMP x y, CSET d ULT ])+        MO_U_Ge w     -> intOpImm False w (\d x y -> toOL [ CMP x y, CSET d UGE ]) getArithImm+        MO_U_Le w     -> intOpImm False w (\d x y -> toOL [ CMP x y, CSET d ULE ]) getArithImm+        MO_U_Gt w     -> intOpImm False w (\d x y -> toOL [ CMP x y, CSET d UGT ]) getArithImm+        MO_U_Lt w     -> intOpImm False w (\d x y -> toOL [ CMP x y, CSET d ULT ]) getArithImm          -- Floating point arithmetic         MO_F_Add w   -> floatOp w (\d x y -> unitOL $ ADD d x y)@@ -960,9 +1090,9 @@         MO_F_Lt w    -> floatCond w (\d x y -> toOL [ CMP x y, CSET d OLT ]) -- x < y <=> y >= x          -- Bitwise operations-        MO_And   w -> bitOp w (\d x y -> unitOL $ AND d x y)-        MO_Or    w -> bitOp w (\d x y -> unitOL $ ORR d x y)-        MO_Xor   w -> bitOp w (\d x y -> unitOL $ EOR d x y)+        MO_And   w -> bitOpImm w (\d x y -> unitOL $ AND d x y) getBitmaskImm+        MO_Or    w -> bitOpImm w (\d x y -> unitOL $ ORR d x y) getBitmaskImm+        MO_Xor   w -> bitOpImm w (\d x y -> unitOL $ EOR d x y) getBitmaskImm         MO_Shl   w -> intOp False w (\d x y -> unitOL $ LSL d x y)         MO_U_Shr w -> intOp False w (\d x y -> unitOL $ LSR d x y)         MO_S_Shr w -> intOp True  w (\d x y -> unitOL $ ASR d x y)@@ -1012,7 +1142,7 @@    where     isNbitEncodeable :: Int -> Integer -> Bool-    isNbitEncodeable n i = let shift = n - 1 in (-1 `shiftL` shift) <= i && i < (1 `shiftL` shift)+    isNbitEncodeable n_bits i = let shift = n_bits - 1 in (-1 `shiftL` shift) <= i && i < (1 `shiftL` shift)      -- N.B. MUL does not set the overflow flag.     -- These implementations are based on output from GCC 11.@@ -1075,13 +1205,16 @@ -- | Is a given number encodable as a bitmask immediate? -- -- https://stackoverflow.com/questions/30904718/range-of-immediate-values-in-armv8-a64-assembly-isAArch64Bitmask :: Integer -> Bool+isAArch64Bitmask :: Width -> Integer -> Bool -- N.B. zero and ~0 are not encodable as bitmask immediates-isAArch64Bitmask 0  = False-isAArch64Bitmask n-  | n == bit 64 - 1 = False-isAArch64Bitmask n  =-    check 64 || check 32 || check 16 || check 8+isAArch64Bitmask width n =+  assert (width `elem` [W32,W64]) $+  case n of+    0 -> False+    _ | n == bit (widthInBits width) - 1+      -> False -- 1111...1111+      | otherwise+      -> (width == W64 && check 64) || check 32 || check 16 || check 8   where     -- Check whether @n@ can be represented as a subpattern of the given     -- width.@@ -1148,20 +1281,8 @@  -- OPTIMIZATION WARNING: Addressing modes. -- Addressing options:--- LDUR/STUR: imm9: -256 - 255-getAmode platform _ (CmmRegOff reg off) | -256 <= off, off <= 255-  = return $ Amode (AddrRegImm reg' off') nilOL-    where reg' = getRegisterReg platform reg-          off' = ImmInt off--- LDR/STR: imm12: if reg is 32bit: 0 -- 16380 in multiples of 4-getAmode platform W32 (CmmRegOff reg off)-  | 0 <= off, off <= 16380, off `mod` 4 == 0-  = return $ Amode (AddrRegImm reg' off') nilOL-    where reg' = getRegisterReg platform reg-          off' = ImmInt off--- LDR/STR: imm12: if reg is 64bit: 0 -- 32760 in multiples of 8-getAmode platform W64 (CmmRegOff reg off)-  | 0 <= off, off <= 32760, off `mod` 8 == 0+getAmode platform w (CmmRegOff reg off)+  | isOffsetImm off w   = return $ Amode (AddrRegImm reg' off') nilOL     where reg' = getRegisterReg platform reg           off' = ImmInt off@@ -1170,15 +1291,15 @@ -- CmmStore (CmmMachOp (MO_Add w) [CmmLoad expr, CmmLit (CmmInt n w')]) (expr2) -- E.g. a CmmStoreOff really. This can be translated to `str $expr2, [$expr, #n ] -- for `n` in range.-getAmode _platform _ (CmmMachOp (MO_Add _w) [expr, CmmLit (CmmInt off _w')])-  | -256 <= off, off <= 255+getAmode _platform w (CmmMachOp (MO_Add _w) [expr, CmmLit (CmmInt off _w')])+  | isOffsetImm (fromIntegral off) w   = do (reg, _format, code) <- getSomeReg expr        return $ Amode (AddrRegImm reg (ImmInteger off)) code -getAmode _platform _ (CmmMachOp (MO_Sub _w) [expr, CmmLit (CmmInt off _w')])-  | -256 <= -off, -off <= 255+getAmode _platform w (CmmMachOp (MO_Sub _w) [expr, CmmLit (CmmInt off _w')])+  | isOffsetImm (fromIntegral $ -off) w   = do (reg, _format, code) <- getSomeReg expr-       return $ Amode (AddrRegImm reg (ImmInteger (-off))) code+       return $ Amode (AddrRegImm reg (ImmInteger $ -off)) code  -- Generic case getAmode _platform _ expr@@ -1605,9 +1726,9 @@         MO_U_Mul2     _w -> unsupported mop          -- Memory Ordering-        -- TODO DMBSY is probably *way* too much!-        MO_ReadBarrier      ->  return (unitOL DMBSY, Nothing)-        MO_WriteBarrier     ->  return (unitOL DMBSY, Nothing)+        MO_AcquireFence     ->  return (unitOL DMBISH, Nothing)+        MO_ReleaseFence     ->  return (unitOL DMBISH, Nothing)+        MO_SeqCstFence      ->  return (unitOL DMBISH, Nothing)         MO_Touch            ->  return (nilOL, Nothing) -- Keep variables live (when using interior pointers)         -- Prefetch         MO_Prefetch_Data _n -> return (nilOL, Nothing) -- Prefetch hint.
compiler/GHC/CmmToAsm/AArch64/Instr.hs view
@@ -18,7 +18,6 @@  import GHC.Platform.Regs import GHC.Cmm.BlockId-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Label import GHC.Cmm import GHC.Cmm.CLabel@@ -79,7 +78,6 @@    -- 1. Arithmetic Instructions ------------------------------------------------   ADD dst src1 src2        -> usage (regOp src1 ++ regOp src2, regOp dst)-  CMN l r                  -> usage (regOp l ++ regOp r, [])   CMP l r                  -> usage (regOp l ++ regOp r, [])   MSUB dst src1 src2 src3  -> usage (regOp src1 ++ regOp src2 ++ regOp src3, regOp dst)   MUL dst src1 src2        -> usage (regOp src1 ++ regOp src2, regOp dst)@@ -102,18 +100,14 @@   -- 3. Logical and Move Instructions ------------------------------------------   AND dst src1 src2        -> usage (regOp src1 ++ regOp src2, regOp dst)   ASR dst src1 src2        -> usage (regOp src1 ++ regOp src2, regOp dst)-  BIC dst src1 src2        -> usage (regOp src1 ++ regOp src2, regOp dst)-  BICS dst src1 src2       -> usage (regOp src1 ++ regOp src2, regOp dst)-  EON dst src1 src2        -> usage (regOp src1 ++ regOp src2, regOp dst)   EOR dst src1 src2        -> usage (regOp src1 ++ regOp src2, regOp dst)   LSL dst src1 src2        -> usage (regOp src1 ++ regOp src2, regOp dst)   LSR dst src1 src2        -> usage (regOp src1 ++ regOp src2, regOp dst)   MOV dst src              -> usage (regOp src, regOp dst)   MOVK dst src             -> usage (regOp src, regOp dst)+  MOVZ dst src             -> usage (regOp src, regOp dst)   MVN dst src              -> usage (regOp src, regOp dst)   ORR dst src1 src2        -> usage (regOp src1 ++ regOp src2, regOp dst)-  ROR dst src1 src2        -> usage (regOp src1 ++ regOp src2, regOp dst)-  TST src1 src2            -> usage (regOp src1 ++ regOp src2, [])   -- 4. Branch Instructions ----------------------------------------------------   J t                      -> usage (regTarget t, [])   B t                      -> usage (regTarget t, [])@@ -130,12 +124,9 @@   STLR _ src dst           -> usage (regOp src ++ regOp dst, [])   LDR _ dst src            -> usage (regOp src, regOp dst)   LDAR _ dst src           -> usage (regOp src, regOp dst)-  -- TODO is this right? see STR, which I'm only partial about being right?-  STP _ src1 src2 dst      -> usage (regOp src1 ++ regOp src2 ++ regOp dst, [])-  LDP _ dst1 dst2 src      -> usage (regOp src, regOp dst1 ++ regOp dst2)    -- 8. Synchronization Instructions --------------------------------------------  DMBSY                    -> usage ([], [])+  DMBISH                   -> usage ([], [])    -- 9. Floating Point Instructions --------------------------------------------   FCVT dst src             -> usage (regOp src, regOp dst)@@ -176,8 +167,6 @@         interesting _        (RegReal (RealRegSingle (-1))) = False         interesting platform (RegReal (RealRegSingle i))    = freeReg platform i --- Note [AArch64 Register assignments]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- Save caller save registers -- This is x0-x18 --@@ -200,8 +189,6 @@ -- '---------------------------------------------------------------------------------------------------------------------------------------------------------------' -- IR: Indirect result location register, IP: Intra-procedure register, PL: Platform register, FP: Frame pointer, LR: Link register, SP: Stack pointer -- BR: Base, SL: SpLim------ TODO: The zero register is currently mapped to -1 but should get it's own separate number. callerSavedRegisters :: [Reg] callerSavedRegisters     = map regSingle [0..18]@@ -221,7 +208,6 @@     DELTA{}             -> instr     -- 1. Arithmetic Instructions ----------------------------------------------     ADD o1 o2 o3   -> ADD (patchOp o1) (patchOp o2) (patchOp o3)-    CMN o1 o2      -> CMN (patchOp o1) (patchOp o2)     CMP o1 o2      -> CMP (patchOp o1) (patchOp o2)     MSUB o1 o2 o3 o4 -> MSUB (patchOp o1) (patchOp o2) (patchOp o3) (patchOp o4)     MUL o1 o2 o3   -> MUL (patchOp o1) (patchOp o2) (patchOp o3)@@ -244,20 +230,15 @@      -- 3. Logical and Move Instructions ----------------------------------------     AND o1 o2 o3   -> AND  (patchOp o1) (patchOp o2) (patchOp o3)-    ANDS o1 o2 o3  -> ANDS (patchOp o1) (patchOp o2) (patchOp o3)     ASR o1 o2 o3   -> ASR  (patchOp o1) (patchOp o2) (patchOp o3)-    BIC o1 o2 o3   -> BIC  (patchOp o1) (patchOp o2) (patchOp o3)-    BICS o1 o2 o3  -> BICS (patchOp o1) (patchOp o2) (patchOp o3)-    EON o1 o2 o3   -> EON  (patchOp o1) (patchOp o2) (patchOp o3)     EOR o1 o2 o3   -> EOR  (patchOp o1) (patchOp o2) (patchOp o3)     LSL o1 o2 o3   -> LSL  (patchOp o1) (patchOp o2) (patchOp o3)     LSR o1 o2 o3   -> LSR  (patchOp o1) (patchOp o2) (patchOp o3)     MOV o1 o2      -> MOV  (patchOp o1) (patchOp o2)     MOVK o1 o2     -> MOVK (patchOp o1) (patchOp o2)+    MOVZ o1 o2     -> MOVZ (patchOp o1) (patchOp o2)     MVN o1 o2      -> MVN  (patchOp o1) (patchOp o2)     ORR o1 o2 o3   -> ORR  (patchOp o1) (patchOp o2) (patchOp o3)-    ROR o1 o2 o3   -> ROR  (patchOp o1) (patchOp o2) (patchOp o3)-    TST o1 o2      -> TST  (patchOp o1) (patchOp o2)      -- 4. Branch Instructions --------------------------------------------------     J t            -> J (patchTarget t)@@ -275,11 +256,9 @@     STLR f o1 o2   -> STLR f (patchOp o1) (patchOp o2)     LDR f o1 o2    -> LDR f (patchOp o1) (patchOp o2)     LDAR f o1 o2   -> LDAR f (patchOp o1) (patchOp o2)-    STP f o1 o2 o3 -> STP f (patchOp o1) (patchOp o2) (patchOp o3)-    LDP f o1 o2 o3 -> LDP f (patchOp o1) (patchOp o2) (patchOp o3)      -- 8. Synchronization Instructions ------------------------------------------    DMBSY          -> DMBSY+    DMBISH         -> DMBISH      -- 9. Floating Point Instructions ------------------------------------------     FCVT o1 o2     -> FCVT (patchOp o1) (patchOp o2)@@ -332,12 +311,6 @@ jumpDestsOfInstr (BCOND _ t) = [ id | TBlock id <- [t]] jumpDestsOfInstr _ = [] -canFallthroughTo :: Instr -> BlockId -> Bool-canFallthroughTo (ANN _ i) bid = canFallthroughTo i bid-canFallthroughTo (J (TBlock target)) bid = bid == target-canFallthroughTo (B (TBlock target)) bid = bid == target-canFallthroughTo _ _ = False- -- | Change the destination of this jump instruction. -- Used in the linear allocator when adding fixup blocks for join -- points.@@ -389,9 +362,8 @@     where         a .&~. b = a .&. (complement b) -        fmt = case reg of-            RegReal (RealRegSingle n) | n < 32 -> II64-            _                                  -> FF64+        fmt = fmtOfRealReg (case reg of { RegReal r -> r; _ -> panic "Expected real reg"})+         mkIp0SpillAddr imm = ANN (text "Spill: IP0 <- SP + " <> int imm) $ ADD ip0 sp (OpImm (ImmInt imm))         mkStrSp imm = ANN (text "Spill@" <> int (off - delta)) $ STR fmt (OpReg W64 reg) (OpAddr (AddrRegImm (regSingle 31) (ImmInt imm)))         mkStrIp0 imm = ANN (text "Spill@" <> int (off - delta)) $ STR fmt (OpReg W64 reg) (OpAddr (AddrRegImm (regSingle 16) (ImmInt imm)))@@ -416,9 +388,7 @@     where         a .&~. b = a .&. (complement b) -        fmt = case reg of-            RegReal (RealRegSingle n) | n < 32 -> II64-            _                                  -> FF64+        fmt = fmtOfRealReg (case reg of { RegReal r -> r; _ -> panic "Expected real reg"})          mkIp0SpillAddr imm = ANN (text "Reload: IP0 <- SP + " <> int imm) $ ADD ip0 sp (OpImm (ImmInt imm))         mkLdrSp imm = ANN (text "Reload@" <> int (off - delta)) $ LDR fmt (OpReg W64 reg) (OpAddr (AddrRegImm (regSingle 31) (ImmInt imm)))@@ -441,7 +411,6 @@     COMMENT{}   -> True     MULTILINE_COMMENT{} -> True     LOCATION{}  -> True-    LDATA{}     -> True     NEWBLOCK{}  -> True     DELTA{}     -> True     PUSH_STACK_FRAME -> True@@ -544,11 +513,6 @@     -- location pseudo-op (file, line, col, name)     | LOCATION Int Int Int String -    -- some static data spat out during code-    -- generation.  Will be extracted before-    -- pretty-printing.-    | LDATA   Section RawCmmStatics-     -- start a new basic block.  Useful during     -- codegen, removed later.  Preceding     -- instruction should be a jump, as per the@@ -575,7 +539,6 @@     -- | ADDS Operand Operand Operand -- rd = rn + rm     -- | ADR ...     -- | ADRP ...-    | CMN Operand Operand -- rd + op2     | CMP Operand Operand -- rd - op2     -- | MADD ...     -- | MNEG ...@@ -616,31 +579,22 @@      -- 3. Logical and Move Instructions ----------------------------------------     | AND Operand Operand Operand -- rd = rn & op2-    | ANDS Operand Operand Operand -- rd = rn & op2     | ASR Operand Operand Operand -- rd = rn ≫ rm  or  rd = rn ≫ #i, i is 6 bits-    | BIC Operand Operand Operand -- rd = rn & ~op2-    | BICS Operand Operand Operand -- rd = rn & ~op2-    | EON Operand Operand Operand -- rd = rn ⊕ ~op2     | EOR Operand Operand Operand -- rd = rn ⊕ op2     | LSL Operand Operand Operand -- rd = rn ≪ rm  or rd = rn ≪ #i, i is 6 bits     | LSR Operand Operand Operand -- rd = rn ≫ rm  or rd = rn ≫ #i, i is 6 bits     | MOV Operand Operand -- rd = rn  or  rd = #i     | MOVK Operand Operand     -- | MOVN Operand Operand-    -- | MOVZ Operand Operand+    | MOVZ Operand Operand     | MVN Operand Operand -- rd = ~rn-    | ORN Operand Operand Operand -- rd = rn | ~op2     | ORR Operand Operand Operand -- rd = rn | op2-    | ROR Operand Operand Operand -- rd = rn ≫ rm  or  rd = rn ≫ #i, i is 6 bits-    | TST Operand Operand -- rn & op2     -- Load and stores.     -- TODO STR/LDR might want to change to STP/LDP with XZR for the second register.     | STR Format Operand Operand -- str Xn, address-mode // Xn -> *addr     | STLR Format Operand Operand -- stlr Xn, address-mode // Xn -> *addr     | LDR Format Operand Operand -- ldr Xn, address-mode // Xn <- *addr     | LDAR Format Operand Operand -- ldar Xn, address-mode // Xn <- *addr-    | STP Format Operand Operand Operand -- stp Xn, Xm, address-mode // Xn -> *addr, Xm -> *(addr + 8)-    | LDP Format Operand Operand Operand -- stp Xn, Xm, address-mode // Xn <- *addr, Xm <- *(addr + 8)      -- Conditional instructions     | CSET Operand Cond   -- if(cond) op <- 1 else op <- 0@@ -654,7 +608,7 @@     | BCOND Cond Target   -- branch with condition. b.<cond>      -- 8. Synchronization Instructions ------------------------------------------    | DMBSY+    | DMBISH     -- 9. Floating Point Instructions     -- Float ConVerT     | FCVT Operand Operand@@ -680,7 +634,6 @@       MULTILINE_COMMENT{} -> "COMMENT"       ANN{} -> "ANN"       LOCATION{} -> "LOCATION"-      LDATA{} -> "LDATA"       NEWBLOCK{} -> "NEWBLOCK"       DELTA{} -> "DELTA"       SXTB{} -> "SXTB"@@ -690,7 +643,6 @@       PUSH_STACK_FRAME{} -> "PUSH_STACK_FRAME"       POP_STACK_FRAME{} -> "POP_STACK_FRAME"       ADD{} -> "ADD"-      CMN{} -> "CMN"       CMP{} -> "CMP"       MSUB{} -> "MSUB"       MUL{} -> "MUL"@@ -705,27 +657,19 @@       SBFX{} -> "SBFX"       UBFX{} -> "UBFX"       AND{} -> "AND"-      ANDS{} -> "ANDS"       ASR{} -> "ASR"-      BIC{} -> "BIC"-      BICS{} -> "BICS"-      EON{} -> "EON"       EOR{} -> "EOR"       LSL{} -> "LSL"       LSR{} -> "LSR"       MOV{} -> "MOV"       MOVK{} -> "MOVK"+      MOVZ{} -> "MOVZ"       MVN{} -> "MVN"-      ORN{} -> "ORN"       ORR{} -> "ORR"-      ROR{} -> "ROR"-      TST{} -> "TST"       STR{} -> "STR"       STLR{} -> "STLR"       LDR{} -> "LDR"       LDAR{} -> "LDAR"-      STP{} -> "STP"-      LDP{} -> "LDP"       CSET{} -> "CSET"       CBZ{} -> "CBZ"       CBNZ{} -> "CBNZ"@@ -733,7 +677,7 @@       B{} -> "B"       BL{} -> "BL"       BCOND{} -> "BCOND"-      DMBSY{} -> "DMBSY"+      DMBISH{} -> "DMBISH"       FCVT{} -> "FCVT"       SCVTF{} -> "SCVTF"       FCVTZS{} -> "FCVTZS"@@ -788,6 +732,9 @@ wzr = OpReg W32 (RegReal (RealRegSingle (-1))) sp  = OpReg W64 (RegReal (RealRegSingle 31)) ip0 = OpReg W64 (RegReal (RealRegSingle 16))++reg_zero :: Reg+reg_zero = RegReal (RealRegSingle (-1))  _x :: Int -> Operand _x i = OpReg W64 (RegReal (RealRegSingle i))
compiler/GHC/CmmToAsm/AArch64/Ppr.hs view
@@ -16,7 +16,6 @@ import GHC.CmmToAsm.Utils  import GHC.Cmm hiding (topInfoTable)-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Label  import GHC.Cmm.BlockId@@ -317,7 +316,6 @@          | w == W64 = text "sp"          | w == W32 = text "wsp" -    -- See Note [AArch64 Register assignments]     ppr_reg_no w i          | i < 0, w == W32 = text "wzr"          | i < 0, w == W64 = text "xzr"@@ -358,7 +356,6 @@                       -- in the final instruction stream. But we still want to be able to                       -- print it for debugging purposes.                       line (text "BLOCK " <> pprAsmLabel platform (blockLbl blockid))-  LDATA _ _  -> panic "pprInstr: LDATA"    -- Pseudo Instructions ------------------------------------------------------- @@ -372,7 +369,6 @@   ADD  o1 o2 o3     | isFloatOp o1 && isFloatOp o2 && isFloatOp o3 -> op3 (text "\tfadd") o1 o2 o3     | otherwise -> op3 (text "\tadd") o1 o2 o3-  CMN  o1 o2    -> op2 (text "\tcmn") o1 o2   CMP  o1 o2     | isFloatOp o1 && isFloatOp o2 -> op2 (text "\tfcmp") o1 o2     | otherwise -> op2 (text "\tcmp") o1 o2@@ -407,11 +403,7 @@    -- 3. Logical and Move Instructions ------------------------------------------   AND o1 o2 o3  -> op3 (text "\tand") o1 o2 o3-  ANDS o1 o2 o3 -> op3 (text "\tands") o1 o2 o3   ASR o1 o2 o3  -> op3 (text "\tasr") o1 o2 o3-  BIC o1 o2 o3  -> op3 (text "\tbic") o1 o2 o3-  BICS o1 o2 o3 -> op3 (text "\tbics") o1 o2 o3-  EON o1 o2 o3  -> op3 (text "\teon") o1 o2 o3   EOR o1 o2 o3  -> op3 (text "\teor") o1 o2 o3   LSL o1 o2 o3  -> op3 (text "\tlsl") o1 o2 o3   LSR o1 o2 o3  -> op3 (text "\tlsr") o1 o2 o3@@ -419,11 +411,9 @@     | isFloatOp o1 || isFloatOp o2 -> op2 (text "\tfmov") o1 o2     | otherwise                    -> op2 (text "\tmov") o1 o2   MOVK o1 o2    -> op2 (text "\tmovk") o1 o2+  MOVZ o1 o2    -> op2 (text "\tmovz") o1 o2   MVN o1 o2     -> op2 (text "\tmvn") o1 o2-  ORN o1 o2 o3  -> op3 (text "\torn") o1 o2 o3   ORR o1 o2 o3  -> op3 (text "\torr") o1 o2 o3-  ROR o1 o2 o3  -> op3 (text "\tror") o1 o2 o3-  TST o1 o2     -> op2 (text "\ttst") o1 o2    -- 4. Branch Instructions ----------------------------------------------------   J t            -> pprInstr platform (B t)@@ -527,11 +517,9 @@   LDR _f o1 o2 -> op2 (text "\tldr") o1 o2   LDAR _f o1 o2 -> op2 (text "\tldar") o1 o2 -  STP _f o1 o2 o3 -> op3 (text "\tstp") o1 o2 o3-  LDP _f o1 o2 o3 -> op3 (text "\tldp") o1 o2 o3-   -- 8. Synchronization Instructions --------------------------------------------  DMBSY -> line $ text "\tdmb sy"+  DMBISH -> line $ text "\tdmb ish"+   -- 9. Floating Point Instructions --------------------------------------------   FCVT o1 o2 -> op2 (text "\tfcvt") o1 o2   SCVTF o1 o2 -> op2 (text "\tscvtf") o1 o2
compiler/GHC/CmmToAsm/AArch64/Regs.hs view
@@ -17,7 +17,6 @@ import GHC.Utils.Panic import GHC.Platform --- TODO: Should this include the zero register? allMachRegNos   :: [RegNo] allMachRegNos   = [0..31] ++ [32..63] -- allocatableRegs is allMachRegNos with the fixed-use regs removed.@@ -78,6 +77,8 @@                 -- narrow to the width: a CmmInt might be out of                 -- range, but we assume that ImmInteger only contains                 -- in-range values.  A signed value should be fine here.+                -- AK: We do call this with out of range values, however+                -- it just truncates as we would expect. litToImm (CmmFloat f W32)    = ImmFloat f litToImm (CmmFloat f W64)    = ImmDouble f litToImm (CmmLabel l)        = ImmCLbl l@@ -147,6 +148,13 @@ classOfRealReg (RealRegSingle i)         | i < 32        = RcInteger         | otherwise     = RcDouble++fmtOfRealReg :: RealReg -> Format+fmtOfRealReg real_reg =+  case classOfRealReg real_reg of+            RcInteger -> II64+            RcDouble  -> FF64+            RcFloat   -> panic "No float regs on arm"  regDotColor :: RealReg -> SDoc regDotColor reg
compiler/GHC/CmmToAsm/BlockLayout.hs view
@@ -26,7 +26,6 @@  import GHC.Cmm import GHC.Cmm.BlockId-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Label  import GHC.Types.Unique.FM@@ -38,7 +37,6 @@  import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Misc  import Data.List (sortOn, sortBy, nub)@@ -739,10 +737,6 @@             = [masterChain]             | (rest,entry) <- breakChainAt entry masterChain             = [entry,rest]-#if __GLASGOW_HASKELL__ <= 810-            | otherwise = pprPanic "Entry point eliminated" $-                            ppr masterChain-#endif          blockList             = assert (noDups [masterChain])@@ -777,9 +771,10 @@ dropJumps _    [] = [] dropJumps info (BasicBlock lbl ins:todo)     | Just ins <- nonEmpty ins --This can happen because of shortcutting+    , [dest] <- jumpDestsOfInstr (NE.last ins)     , BasicBlock nextLbl _ : _ <- todo-    , canFallthroughTo (NE.last ins) nextLbl-    , not (mapMember nextLbl info)+    , not (mapMember dest info)+    , nextLbl == dest     = BasicBlock lbl (NE.init ins) : dropJumps info todo     | otherwise     = BasicBlock lbl ins : dropJumps info todo
compiler/GHC/CmmToAsm/CFG.hs view
@@ -48,7 +48,6 @@ import GHC.Cmm as Cmm  import GHC.Cmm.Switch-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Label import GHC.Cmm.Dataflow.Block import qualified GHC.Cmm.Dataflow.Graph as G@@ -76,7 +75,6 @@  import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain -- DEBUGGING ONLY --import GHC.Cmm.DebugBlock --import GHC.Data.OrdList
compiler/GHC/CmmToAsm/CFG/Dominators.hs view
@@ -1,7 +1,3 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE RankNTypes #-} {-# LANGUAGE Strict #-}  {- |
compiler/GHC/CmmToAsm/Dwarf.hs view
@@ -29,7 +29,6 @@ import System.FilePath  import qualified GHC.Cmm.Dataflow.Label as H-import qualified GHC.Cmm.Dataflow.Collections as H  -- | Generate DWARF/debug information dwarfGen :: IsDoc doc => String -> NCGConfig -> ModLocation -> UniqSupply -> [DebugBlock]
compiler/GHC/CmmToAsm/Instr.hs view
@@ -71,16 +71,10 @@                 :: instr -> Bool  -        -- | Give the possible *local block* destinations of this jump instruction.+        -- | Give the possible destinations of this jump instruction.         --      Must be defined for all jumpish instructions.         jumpDestsOfInstr                 :: instr -> [BlockId]--        -- | Check if the instr always transfers control flow-        -- to the given block. Used by code layout to eliminate-        -- jumps that can be replaced by fall through.-        canFallthroughTo-                :: instr -> BlockId -> Bool           -- | Change the destination of this jump instruction.
compiler/GHC/CmmToAsm/Monad.hs view
@@ -55,7 +55,6 @@ import GHC.CmmToAsm.Types  import GHC.Cmm.BlockId-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Label import GHC.Cmm.CLabel           ( CLabel ) import GHC.Cmm.DebugBlock@@ -79,15 +78,8 @@     cmmTopCodeGen             :: RawCmmDecl -> NatM [NatCmmDecl statics instr],     generateJumpTableForInstr :: instr -> Maybe (NatCmmDecl statics instr),     getJumpDestBlockId        :: jumpDest -> Maybe BlockId,-    -- | Does this jump always jump to a single destination and is shortcutable?-    ---    -- We use this to determine shortcutable instructions - See Note [What is shortcutting]-    -- Note that if we return a destination here we *most* support the relevant shortcutting in-    -- shortcutStatics for jump tables and shortcutJump for the instructions itself.     canShortcut               :: instr -> Maybe jumpDest,-    -- | Replace references to blockIds with other destinations - used to update jump tables.     shortcutStatics           :: (BlockId -> Maybe jumpDest) -> statics -> statics,-    -- | Change the jump destination(s) of an instruction.     shortcutJump              :: (BlockId -> Maybe jumpDest) -> instr -> instr,     -- | 'Module' is only for printing internal labels. See Note [Internal proc     -- labels] in CLabel.@@ -112,25 +104,6 @@     -- ^ Turn the sequence of @jcc l1; jmp l2@ into @jncc l2; \<block_l1>@     -- when possible.     }--{- Note [supporting shortcutting]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-For the concept of shortcutting see Note [What is shortcutting].--In order to support shortcutting across multiple backends uniformly we-use canShortcut, shortcutStatics and shortcutJump.--canShortcut tells us if the backend support shortcutting of a instruction-and if so what destination we should retarget instruction to instead.--shortcutStatics exists to allow us to update jump destinations in jump tables.--shortcutJump updates the instructions itself.--A backend can opt out of those by always returning Nothing for canShortcut-and implementing shortcutStatics/shortcutJump as \_ x -> x---}  {- Note [pprNatCmmDeclS and pprNatCmmDeclH] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compiler/GHC/CmmToAsm/PIC.hs view
@@ -60,7 +60,7 @@ import GHC.CmmToAsm.Types  -import GHC.Cmm.Dataflow.Collections+import GHC.Cmm.Dataflow.Label import GHC.Cmm import GHC.Cmm.CLabel import GHC.Cmm.Utils (cmmLoadBWord)
compiler/GHC/CmmToAsm/PPC.hs view
@@ -46,7 +46,6 @@    patchRegsOfInstr    = PPC.patchRegsOfInstr    isJumpishInstr      = PPC.isJumpishInstr    jumpDestsOfInstr    = PPC.jumpDestsOfInstr-   canFallthroughTo    = PPC.canFallthroughTo    patchJumpInstr      = PPC.patchJumpInstr    mkSpillInstr        = PPC.mkSpillInstr    mkLoadInstr         = PPC.mkLoadInstr
compiler/GHC/CmmToAsm/PPC/CodeGen.hs view
@@ -61,7 +61,6 @@ import GHC.Data.OrdList import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain  import Control.Monad    ( mapAndUnzipM, when ) import Data.Word@@ -504,6 +503,9 @@     Amode addr addr_code <- getAmode DS mem     return (Any II64 (\dst -> addr_code `snocOL` LA II32 dst addr)) +getRegister' config platform (CmmMachOp (MO_RelaxedRead w) [e]) =+      getRegister' config platform (CmmLoad e (cmmBits w) NaturallyAligned)+ getRegister' config platform (CmmMachOp mop [x]) -- unary MachOps   = case mop of       MO_Not rep   -> triv_ucode_int rep NOT@@ -1126,10 +1128,12 @@          -> [CmmFormal]        -- where to put the result          -> [CmmActual]        -- arguments (of mixed type)          -> NatM InstrBlock-genCCall (PrimTarget MO_ReadBarrier) _ _+genCCall (PrimTarget MO_AcquireFence) _ _  = return $ unitOL LWSYNC-genCCall (PrimTarget MO_WriteBarrier) _ _+genCCall (PrimTarget MO_ReleaseFence) _ _  = return $ unitOL LWSYNC+genCCall (PrimTarget MO_SeqCstFence) _ _+ = return $ unitOL HWSYNC  genCCall (PrimTarget MO_Touch) _ _  = return $ nilOL@@ -1766,7 +1770,7 @@                                 _ -> panic "genCall': unknown calling conv."          argReps = map (cmmExprType platform) args-        (_, argHints) = foreignTargetHints target+        (argHints, _) = foreignTargetHints target          roundTo a x | x `mod` a == 0 = x                     | otherwise = x + a - (x `mod` a)@@ -2094,8 +2098,9 @@                     MO_AddIntC {}    -> unsupported                     MO_SubIntC {}    -> unsupported                     MO_U_Mul2 {}     -> unsupported-                    MO_ReadBarrier   -> unsupported-                    MO_WriteBarrier  -> unsupported+                    MO_AcquireFence  -> unsupported+                    MO_ReleaseFence  -> unsupported+                    MO_SeqCstFence   -> unsupported                     MO_Touch         -> unsupported                     MO_Prefetch_Data _ -> unsupported                 unsupported = panic ("outOfLineCmmOp: " ++ show mop
compiler/GHC/CmmToAsm/PPC/Instr.hs view
@@ -22,7 +22,6 @@    , patchJumpInstr    , patchRegsOfInstr    , jumpDestsOfInstr-   , canFallthroughTo    , takeRegRegMoveInstr    , takeDeltaInstr    , mkRegRegMoveInstr@@ -48,7 +47,6 @@  import GHC.Platform.Regs import GHC.Cmm.BlockId-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Label import GHC.Cmm import GHC.Cmm.Info@@ -510,13 +508,6 @@     BL{}        -> True     JMP{}       -> True     _           -> False--canFallthroughTo :: Instr -> BlockId -> Bool-canFallthroughTo instr bid- = case instr of-        BCC _ target _      -> target == bid-        BCCFAR _ target _   -> target == bid-        _                   -> False   -- | Checks whether this instruction is a jump/branch instruction.
compiler/GHC/CmmToAsm/PPC/Ppr.hs view
@@ -29,7 +29,6 @@ import GHC.CmmToAsm.Utils  import GHC.Cmm hiding (topInfoTable)-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Label  import GHC.Cmm.BlockId
compiler/GHC/CmmToAsm/Reg/Graph.hs view
@@ -385,11 +385,6 @@         , RegReal _             <- r2         = graph -#if __GLASGOW_HASKELL__ <= 810-        | otherwise-        = panic "graphAddCoalesce"-#endif-  -- | Patch registers in code using the reg -> reg mapping in this graph. patchRegsFromGraph
compiler/GHC/CmmToAsm/Reg/Graph/Spill.hs view
@@ -15,7 +15,7 @@ import GHC.Platform.Reg import GHC.Cmm hiding (RegSet) import GHC.Cmm.BlockId-import GHC.Cmm.Dataflow.Collections+import GHC.Cmm.Dataflow.Label  import GHC.Utils.Monad import GHC.Utils.Monad.State.Strict
compiler/GHC/CmmToAsm/Reg/Graph/SpillClean.hs view
@@ -49,7 +49,7 @@ import GHC.Utils.Outputable import GHC.Utils.Panic import GHC.Platform-import GHC.Cmm.Dataflow.Collections+import GHC.Cmm.Dataflow.Label  import Data.List (nub, foldl1', find) import Data.Maybe@@ -398,12 +398,6 @@                         $ IntSet.toList slotsReloadedByTargets                  cleanBackward liveSlotsOnEntry noReloads' (li : acc) instrs--#if __GLASGOW_HASKELL__ <= 810-        -- some other instruction-        | otherwise-        = cleanBackward liveSlotsOnEntry noReloads (li : acc) instrs-#endif   -- | Combine the associations from all the inward control flow edges.
compiler/GHC/CmmToAsm/Reg/Graph/SpillCost.hs view
@@ -24,7 +24,6 @@  import GHC.Data.Graph.Base -import GHC.Cmm.Dataflow.Collections (mapLookup) import GHC.Cmm.Dataflow.Label import GHC.Cmm import GHC.Types.Unique.FM
compiler/GHC/CmmToAsm/Reg/Graph/Stats.hs view
@@ -1,8 +1,3 @@-{-# LANGUAGE BangPatterns, DeriveFunctor #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FlexibleContexts #-}-  {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} 
compiler/GHC/CmmToAsm/Reg/Graph/TrivColorable.hs view
@@ -102,7 +102,8 @@         -> Triv VirtualReg RegClass RealReg  trivColorable platform virtualRegSqueeze realRegSqueeze RcInteger conflicts exclusions-        | let cALLOCATABLE_REGS_INTEGER+        | -- Allocatable are all regs of this class, where freeReg == True (MachRegs.h)+          let cALLOCATABLE_REGS_INTEGER                   =        (case platformArch platform of                             ArchX86       -> 3                             ArchX86_64    -> 5@@ -110,6 +111,9 @@                             ArchPPC_64 _  -> 15                             ArchARM _ _ _ -> panic "trivColorable ArchARM"                             -- N.B. x18 is reserved by the platform on AArch64/Darwin+                            -- 32 - Base - Sp - Hp - R1..R6 - SpLim - IP0 - SP - LR - FP - X18+                            -- -> 32 - 15 = 17+                            -- (one stack pointer for Haskell, one for C)                             ArchAArch64   -> 17                             ArchAlpha     -> panic "trivColorable ArchAlpha"                             ArchMipseb    -> panic "trivColorable ArchMipseb"@@ -174,13 +178,12 @@                             ArchX86_64    -> 10                             -- in x86_64 there are 16 XMM registers                             -- xmm0 .. xmm15, here 10 is a-                            -- "dont need to solve conflicts" count that+                            -- "don't need to solve conflicts" count that                             -- was chosen at some point in the past.                             ArchPPC       -> 26                             ArchPPC_64 _  -> 20                             ArchARM _ _ _ -> panic "trivColorable ArchARM"-                            ArchAArch64   -> 24 -- 32 - F1 .. F4, D1..D4 - it's odd but see Note [AArch64 Register assignments] for our reg use.-                                                -- Seems we reserve different registers for D1..D4 and F1 .. F4 somehow, we should fix this.+                            ArchAArch64   -> 28 -- 32 - D1..D4                             ArchAlpha     -> panic "trivColorable ArchAlpha"                             ArchMipseb    -> panic "trivColorable ArchMipseb"                             ArchMipsel    -> panic "trivColorable ArchMipsel"
compiler/GHC/CmmToAsm/Reg/Linear.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE BangPatterns, ScopedTypeVariables #-}-{-# LANGUAGE ConstraintKinds #-}  {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} @@ -124,7 +122,7 @@ import GHC.Platform.Reg.Class (RegClass(..))  import GHC.Cmm.BlockId-import GHC.Cmm.Dataflow.Collections+import GHC.Cmm.Dataflow.Label import GHC.Cmm hiding (RegSet)  import GHC.Data.Graph.Directed
compiler/GHC/CmmToAsm/Reg/Linear/AArch64.hs view
@@ -8,11 +8,11 @@  import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Misc( HasDebugCallStack ) import GHC.Platform  import Data.Word +import GHC.Stack -- AArch64 has 32 64bit general purpose register r0..r30, and zr/sp -- AArch64 has 32 128bit floating point registers v0..v31 as part of the NEON -- extension in Armv8-A.@@ -65,7 +65,7 @@ showBits w = map (\i -> if testBit w i then '1' else '0') [0..31]  -- FR instance implementation (See Linear.FreeRegs)-allocateReg :: HasDebugCallStack => RealReg -> FreeRegs -> FreeRegs+allocateReg :: HasCallStack => RealReg -> FreeRegs -> FreeRegs allocateReg (RealRegSingle r) (FreeRegs g f)     | r > 31 && testBit f (r - 32) = FreeRegs g (clearBit f (r - 32))     | r < 32 && testBit g r = FreeRegs (clearBit g r) f@@ -127,7 +127,7 @@ initFreeRegs :: Platform -> FreeRegs initFreeRegs platform = foldl' (flip releaseReg) noFreeRegs (allocatableRegs platform) -releaseReg :: HasDebugCallStack => RealReg -> FreeRegs -> FreeRegs+releaseReg :: HasCallStack => RealReg -> FreeRegs -> FreeRegs releaseReg (RealRegSingle r) (FreeRegs g f)   | r > 31 && testBit f (r - 32) = pprPanic "Linear.AArch64.releaseReg" (text  "can't release non-allocated reg v" <> int (r - 32))   | r < 32 && testBit g r = pprPanic "Linear.AArch64.releaseReg" (text "can't release non-allocated reg x" <> int r)
compiler/GHC/CmmToAsm/Reg/Linear/Base.hs view
@@ -34,7 +34,7 @@ import GHC.Types.Unique.FM import GHC.Types.Unique.Supply import GHC.Cmm.BlockId-import GHC.Cmm.Dataflow.Collections+import GHC.Cmm.Dataflow.Label import GHC.CmmToAsm.Reg.Utils  data ReadingOrWriting = Reading | Writing deriving (Eq,Ord)
compiler/GHC/CmmToAsm/Reg/Linear/JoinToTargets.hs view
@@ -23,7 +23,7 @@ import GHC.Platform.Reg  import GHC.Cmm.BlockId-import GHC.Cmm.Dataflow.Collections+import GHC.Cmm.Dataflow.Label import GHC.Data.Graph.Directed import GHC.Utils.Panic import GHC.Utils.Monad (concatMapM)
compiler/GHC/CmmToAsm/Reg/Liveness.hs view
@@ -1,10 +1,4 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances #-}   {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}@@ -52,7 +46,6 @@ import GHC.CmmToAsm.Utils  import GHC.Cmm.BlockId-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Label import GHC.Cmm hiding (RegSet, emptyRegSet) @@ -133,11 +126,6 @@                 Instr instr     -> isJumpishInstr instr                 _               -> False -        canFallthroughTo i bid-         = case i of-                Instr instr     -> canFallthroughTo instr bid-                _               -> False-         jumpDestsOfInstr i          = case i of                 Instr instr     -> jumpDestsOfInstr instr@@ -1006,7 +994,7 @@ livenessBack _        liveregs _        done []  = (liveregs, done)  livenessBack platform liveregs blockmap acc (instr : instrs)- = let  (liveregs', instr')     = liveness1 platform liveregs blockmap instr+ = let  !(!liveregs', instr')     = liveness1 platform liveregs blockmap instr    in   livenessBack platform liveregs' blockmap (instr' : acc) instrs  @@ -1029,15 +1017,15 @@         = (liveregs1, LiveInstr instr                         (Just $ Liveness                         { liveBorn      = emptyUniqSet-                        , liveDieRead   = mkUniqSet r_dying-                        , liveDieWrite  = mkUniqSet w_dying }))+                        , liveDieRead   = r_dying+                        , liveDieWrite  = w_dying }))          | otherwise         = (liveregs_br, LiveInstr instr                         (Just $ Liveness                         { liveBorn      = emptyUniqSet                         , liveDieRead   = mkUniqSet r_dying_br-                        , liveDieWrite  = mkUniqSet w_dying }))+                        , liveDieWrite  = w_dying }))          where             !(RU read written) = regUsageOfInstr platform instr@@ -1049,10 +1037,12 @@              -- registers that are not live beyond this point, are recorded             --  as dying here.-            r_dying     = [ reg | reg <- read, reg `notElem` written,+            r_dying     = mkUniqSet+                          [ reg | reg <- read, reg `notElem` written,                               not (elementOfUniqSet reg liveregs) ] -            w_dying     = [ reg | reg <- written,+            w_dying     = mkUniqSet+                          [ reg | reg <- written,                              not (elementOfUniqSet reg liveregs) ]              -- union in the live regs from all the jump destinations of this@@ -1072,6 +1062,6 @@             -- registers that are live only in the branch targets should             -- be listed as dying here.             live_branch_only = live_from_branch `minusUniqSet` liveregs-            r_dying_br  = nonDetEltsUniqSet (mkUniqSet r_dying `unionUniqSets`+            r_dying_br  = nonDetEltsUniqSet (r_dying `unionUniqSets`                                              live_branch_only)                           -- See Note [Unique Determinism and code generation]
compiler/GHC/CmmToAsm/Utils.hs view
@@ -7,7 +7,6 @@ import GHC.Prelude  import GHC.Cmm.BlockId-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Label import GHC.Cmm hiding (topInfoTable) 
compiler/GHC/CmmToAsm/Wasm.hs view
@@ -1,26 +1,35 @@ {-# LANGUAGE DataKinds #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE Strict #-}+{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}  module GHC.CmmToAsm.Wasm (ncgWasm) where  import Data.ByteString.Builder+import Data.ByteString.Lazy.Char8 (unpack) import Data.Maybe import Data.Semigroup import GHC.Cmm+import GHC.Cmm.ContFlowOpt+import GHC.Cmm.GenericOpt+import GHC.CmmToAsm.Config import GHC.CmmToAsm.Wasm.Asm import GHC.CmmToAsm.Wasm.FromCmm import GHC.CmmToAsm.Wasm.Types import GHC.Data.Stream (Stream, StreamS (..), runStream)+import GHC.Driver.DynFlags import GHC.Platform import GHC.Prelude import GHC.Settings import GHC.Types.Unique.Supply import GHC.Unit-import GHC.Utils.CliOption+import GHC.Utils.Logger+import GHC.Utils.Outputable (text) import System.IO  ncgWasm ::+  NCGConfig ->+  Logger ->   Platform ->   ToolSettings ->   UniqSupply ->@@ -28,27 +37,45 @@   Handle ->   Stream IO RawCmmGroup a ->   IO a-ncgWasm platform ts us loc h cmms = do-  (r, s) <- streamCmmGroups platform us cmms-  hPutBuilder h $ "# " <> string7 (fromJust $ ml_hs_file loc) <> "\n\n"-  hPutBuilder h $ execWasmAsmM do_tail_call $ asmTellEverything TagI32 s+ncgWasm ncg_config logger platform ts us loc h cmms = do+  (r, s) <- streamCmmGroups ncg_config platform us cmms+  outputWasm $ "# " <> string7 (fromJust $ ml_hs_file loc) <> "\n\n"+  outputWasm $ execWasmAsmM do_tail_call $ asmTellEverything TagI32 s   pure r   where     -- See Note [WasmTailCall]     do_tail_call = doTailCall ts +    outputWasm builder = do+      putDumpFileMaybe+        logger+        Opt_D_dump_asm+        "Asm Code"+        FormatASM+        (text . unpack $ toLazyByteString builder)+      hPutBuilder h builder+ streamCmmGroups ::+  NCGConfig ->   Platform ->   UniqSupply ->   Stream IO RawCmmGroup a ->   IO (a, WasmCodeGenState 'I32)-streamCmmGroups platform us cmms =-  go (initialWasmCodeGenState platform us) $-    runStream cmms+streamCmmGroups ncg_config platform us cmms =+  go (initialWasmCodeGenState platform us) $ runStream cmms   where     go s (Done r) = pure (r, s)     go s (Effect m) = m >>= go s-    go s (Yield cmm k) = go (wasmExecM (onCmmGroup cmm) s) k+    go s (Yield decls k) = go (wasmExecM (onCmmGroup $ map opt decls) s) k+      where+        -- Run the generic cmm optimizations like other NCGs, followed+        -- by a late control-flow optimization pass that does shrink+        -- the CFG block count in some cases.+        opt decl = case decl of+          CmmData {} -> decl+          CmmProc {} -> CmmProc info lbl live $ cmmCfgOpts False graph+            where+              (CmmProc info lbl live graph, _) = cmmToCmm ncg_config decl  doTailCall :: ToolSettings -> Bool doTailCall ts = Option "-mtail-call" `elem` as_args
compiler/GHC/CmmToAsm/Wasm/Asm.hs view
@@ -12,6 +12,7 @@ import Data.ByteString (ByteString) import qualified Data.ByteString as BS import Data.ByteString.Builder+import qualified Data.ByteString.Char8 as BS8 import Data.Coerce import Data.Foldable import qualified GHC.Data.Word64Set as WS@@ -25,6 +26,7 @@ import GHC.Data.FastString import GHC.Float import GHC.Prelude+import GHC.Settings.Config (cProjectVersion) import GHC.Types.Basic import GHC.Types.Unique import GHC.Types.Unique.Map@@ -450,7 +452,8 @@ asmTellCtors :: WasmTypeTag w -> [SymName] -> WasmAsmM () asmTellCtors _ [] = mempty asmTellCtors ty_word syms = do-  asmTellSectionHeader ".init_array"+  -- See Note [JSFFI initialization] for details+  asmTellSectionHeader ".init_array.101"   asmTellAlign $ alignmentFromWordType ty_word   for_ syms $ \sym ->     asmTellTabLine $@@ -485,7 +488,7 @@         asmTellVec           [ do               asmTellBS "ghc"-              asmTellBS "9.6"+              asmTellBS $ BS8.pack cProjectVersion           ]     ] 
compiler/GHC/CmmToAsm/Wasm/FromCmm.hs view
@@ -628,6 +628,7 @@   WasmCodeGenM     w     (SomeWasmExpr w)+lower_CmmMachOp lbl (MO_RelaxedRead w0) [x] = lower_CmmExpr lbl (CmmLoad x (cmmBits w0) NaturallyAligned) lower_CmmMachOp lbl (MO_Add w0) xs = lower_MO_Bin_Homo_Trunc WasmAdd lbl w0 xs lower_CmmMachOp lbl (MO_Sub w0) xs = lower_MO_Bin_Homo_Trunc WasmSub lbl w0 xs lower_CmmMachOp lbl (MO_Eq w0) xs = lower_MO_Bin_Rel WasmEq lbl (cmmBits w0) xs@@ -1186,8 +1187,9 @@ lower_CallishMachOp lbl MO_F32_Fabs rs xs = lower_CMO_Un_Homo lbl "fabsf" rs xs lower_CallishMachOp lbl MO_F32_Sqrt rs xs = lower_CMO_Un_Homo lbl "sqrtf" rs xs lower_CallishMachOp lbl (MO_UF_Conv w0) rs xs = lower_MO_UF_Conv lbl w0 rs xs-lower_CallishMachOp _ MO_ReadBarrier _ _ = pure $ WasmStatements WasmNop-lower_CallishMachOp _ MO_WriteBarrier _ _ = pure $ WasmStatements WasmNop+lower_CallishMachOp _ MO_AcquireFence _ _ = pure $ WasmStatements WasmNop+lower_CallishMachOp _ MO_ReleaseFence _ _ = pure $ WasmStatements WasmNop+lower_CallishMachOp _ MO_SeqCstFence _ _ = pure $ WasmStatements WasmNop lower_CallishMachOp _ MO_Touch _ _ = pure $ WasmStatements WasmNop lower_CallishMachOp _ (MO_Prefetch_Data {}) _ _ = pure $ WasmStatements WasmNop lower_CallishMachOp lbl (MO_Memcpy {}) [] xs = do
compiler/GHC/CmmToAsm/X86.hs view
@@ -51,7 +51,6 @@    patchRegsOfInstr        = X86.patchRegsOfInstr    isJumpishInstr          = X86.isJumpishInstr    jumpDestsOfInstr        = X86.jumpDestsOfInstr-   canFallthroughTo        = X86.canFallthroughTo    patchJumpInstr          = X86.patchJumpInstr    mkSpillInstr            = X86.mkSpillInstr    mkLoadInstr             = X86.mkLoadInstr
compiler/GHC/CmmToAsm/X86/CodeGen.hs view
@@ -1,8 +1,6 @@-{-# LANGUAGE BangPatterns #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE NondecreasingIndentation #-}-{-# LANGUAGE TupleSections #-}  {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} @@ -67,7 +65,6 @@ import GHC.Cmm.Switch import GHC.Cmm import GHC.Cmm.Dataflow.Block-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Graph import GHC.Cmm.Dataflow.Label import GHC.Cmm.CLabel@@ -80,7 +77,6 @@ import GHC.Utils.Outputable import GHC.Utils.Constants (debugIsOn) import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Data.FastString import GHC.Utils.Misc import GHC.Types.Unique.Supply ( getUniqueM )@@ -524,7 +520,6 @@ assignReg_I64Code _ _    = panic "assignReg_I64Code(i386): invalid lvalue" - iselExpr64 :: HasDebugCallStack => CmmExpr -> NatM (RegCode64 InstrBlock) iselExpr64 (CmmLit (CmmInt i _)) = do   Reg64 rhi rlo <- getNewReg64@@ -551,7 +546,6 @@   let Reg64 hi lo = localReg64 local_reg   return (RegCode64 nilOL hi lo) --- we handle addition, but rather badly iselExpr64 (CmmMachOp (MO_Add _) [e1, CmmLit (CmmInt i _)]) = do    RegCode64 code1 r1hi r1lo <- iselExpr64 e1    Reg64 rhi rlo <- getNewReg64@@ -591,14 +585,34 @@                        SBB II32 (OpReg r2hi) (OpReg rhi) ]    return (RegCode64 code rhi rlo) -iselExpr64 (CmmMachOp (MO_UU_Conv _ W64) [expr]) = do+iselExpr64 (CmmMachOp (MO_UU_Conv W32 W64) [expr]) = do      code <- getAnyReg expr      Reg64 r_dst_hi r_dst_lo <- getNewReg64      return $ RegCode64 (code r_dst_lo `snocOL`-                          MOV II32 (OpImm (ImmInt 0)) (OpReg r_dst_hi))+                          XOR II32 (OpReg r_dst_hi) (OpReg r_dst_hi))                           r_dst_hi                           r_dst_lo +iselExpr64 (CmmMachOp (MO_UU_Conv W16 W64) [expr]) = do+     (rsrc, code) <- getByteReg expr+     Reg64 r_dst_hi r_dst_lo <- getNewReg64+     return $ RegCode64 (code `appOL` toOL [+                          MOVZxL II16 (OpReg rsrc) (OpReg r_dst_lo),+                          XOR    II32 (OpReg r_dst_hi) (OpReg r_dst_hi)+                          ])+                          r_dst_hi+                          r_dst_lo++iselExpr64 (CmmMachOp (MO_UU_Conv W8 W64) [expr]) = do+     (rsrc, code) <- getByteReg expr+     Reg64 r_dst_hi r_dst_lo <- getNewReg64+     return $ RegCode64 (code `appOL` toOL [+                          MOVZxL II8 (OpReg rsrc) (OpReg r_dst_lo),+                          XOR    II32 (OpReg r_dst_hi) (OpReg r_dst_hi)+                          ])+                          r_dst_hi+                          r_dst_lo+ iselExpr64 (CmmMachOp (MO_SS_Conv W32 W64) [expr]) = do      code <- getAnyReg expr      Reg64 r_dst_hi r_dst_lo <- getNewReg64@@ -610,11 +624,208 @@                           r_dst_hi                           r_dst_lo +iselExpr64 (CmmMachOp (MO_SS_Conv W16 W64) [expr]) = do+     (r, code) <- getByteReg expr+     Reg64 r_dst_hi r_dst_lo <- getNewReg64+     return $ RegCode64 (code `appOL` toOL [+                          MOVSxL II16 (OpReg r) (OpReg eax),+                          CLTD II32,+                          MOV II32 (OpReg eax) (OpReg r_dst_lo),+                          MOV II32 (OpReg edx) (OpReg r_dst_hi)])+                          r_dst_hi+                          r_dst_lo++iselExpr64 (CmmMachOp (MO_SS_Conv W8 W64) [expr]) = do+     (r, code) <- getByteReg expr+     Reg64 r_dst_hi r_dst_lo <- getNewReg64+     return $ RegCode64 (code `appOL` toOL [+                          MOVSxL II8 (OpReg r) (OpReg eax),+                          CLTD II32,+                          MOV II32 (OpReg eax) (OpReg r_dst_lo),+                          MOV II32 (OpReg edx) (OpReg r_dst_hi)])+                          r_dst_hi+                          r_dst_lo++iselExpr64 (CmmMachOp (MO_S_Neg _) [expr]) = do+   RegCode64 code rhi rlo <- iselExpr64 expr+   Reg64 rohi rolo <- getNewReg64+   let+        ocode = code `appOL`+                toOL [ MOV II32 (OpReg rlo) (OpReg rolo),+                       XOR II32 (OpReg rohi) (OpReg rohi),+                       NEGI II32 (OpReg rolo),+                       SBB II32 (OpReg rhi) (OpReg rohi) ]+   return (RegCode64 ocode rohi rolo)++-- To multiply two 64-bit numbers we use the following decomposition (in C notation):+--+--     ((r1hi << 32) + r1lo) * ((r2hi << 32) + r2lo)+--      = ((r2lo * r1hi) << 32)+--      + ((r1lo * r2hi) << 32)+--      + r1lo * r2lo+--+-- Note that @(r1hi * r2hi) << 64@ can be dropped because it overflows completely.++iselExpr64 (CmmMachOp (MO_Mul _) [e1,e2]) = do+   RegCode64 code1 r1hi r1lo <- iselExpr64 e1+   RegCode64 code2 r2hi r2lo <- iselExpr64 e2+   Reg64 rhi rlo <- getNewReg64+   tmp <- getNewRegNat II32+   let+        code =  code1 `appOL`+                code2 `appOL`+                toOL [ MOV  II32 (OpReg r1lo) (OpReg eax),+                       MOV  II32 (OpReg r2lo) (OpReg tmp),+                       MOV  II32 (OpReg r1hi) (OpReg rhi),+                       IMUL II32 (OpReg tmp) (OpReg rhi),+                       MOV  II32 (OpReg r2hi) (OpReg rlo),+                       IMUL II32 (OpReg eax) (OpReg rlo),+                       ADD  II32 (OpReg rlo) (OpReg rhi),+                       MUL2 II32 (OpReg tmp),+                       ADD  II32 (OpReg edx) (OpReg rhi),+                       MOV  II32 (OpReg eax) (OpReg rlo)+                     ]+   return (RegCode64 code rhi rlo)++iselExpr64 (CmmMachOp (MO_S_MulMayOflo W64) _) = do+   -- Performance sensitive users won't use 32 bit so let's keep it simple:+   -- We always return a (usually false) positive.+   Reg64 rhi rlo <- getNewReg64+   let code = toOL   [+                       MOV  II32 (OpImm (ImmInt 1)) (OpReg rhi),+                       MOV  II32 (OpImm (ImmInt 1)) (OpReg rlo)+                     ]+   return (RegCode64 code rhi rlo)+++-- To shift a 64-bit number to the left we use the SHLD and SHL instructions.+-- We use SHLD to shift the bits in @rhi@ to the left while copying+-- high bits from @rlo@ to fill the new space in the low bits of @rhi@.+-- That leaves @rlo@ unchanged, so we use SHL to shift the bits of @rlo@ left.+-- However, both these instructions only use the lowest 5 bits from %cl to do+-- their shifting. So if the sixth bit (0x32) is set then we additionally move+-- the contents of @rlo@ to @rhi@ and clear @rlo@.++iselExpr64 (CmmMachOp (MO_Shl _) [e1,e2]) = do+   RegCode64 code1 r1hi r1lo <- iselExpr64 e1+   code2 <- getAnyReg e2+   Reg64 rhi rlo <- getNewReg64+   lbl1 <- newBlockId+   lbl2 <- newBlockId+   let+        code =  code1 `appOL`+                code2 ecx `appOL`+                toOL [ MOV II32 (OpReg r1lo) (OpReg rlo),+                       MOV II32 (OpReg r1hi) (OpReg rhi),+                       SHLD II32 (OpReg ecx) (OpReg rlo) (OpReg rhi),+                       SHL II32 (OpReg ecx) (OpReg rlo),+                       TEST II32 (OpImm (ImmInt 32)) (OpReg ecx),+                       JXX EQQ lbl2,+                       JXX ALWAYS lbl1,+                       NEWBLOCK lbl1,+                       MOV II32 (OpReg rlo) (OpReg rhi),+                       XOR II32 (OpReg rlo) (OpReg rlo),+                       JXX ALWAYS lbl2,+                       NEWBLOCK lbl2+                     ]+   return (RegCode64 code rhi rlo)++-- Similar to above, however now we're shifting to the right+-- and we're doing a signed shift which means that @rhi@ needs+-- to be set to either 0 if @rhi@ is positive or 0xffffffff otherwise,+-- and if the sixth bit of %cl is set (so the shift amount is more than 32).+-- To accomplish that we shift @rhi@ by 31.++iselExpr64 (CmmMachOp (MO_S_Shr _) [e1,e2]) = do+   RegCode64 code1 r1hi r1lo <- iselExpr64 e1+   (r2, code2) <- getSomeReg e2+   Reg64 rhi rlo <- getNewReg64+   lbl1 <- newBlockId+   lbl2 <- newBlockId+   let+        code =  code1 `appOL`+                code2 `appOL`+                toOL [ MOV II32 (OpReg r1lo) (OpReg rlo),+                       MOV II32 (OpReg r1hi) (OpReg rhi),+                       MOV II32 (OpReg r2) (OpReg ecx),+                       SHRD II32 (OpReg ecx) (OpReg rhi) (OpReg rlo),+                       SAR II32 (OpReg ecx) (OpReg rhi),+                       TEST II32 (OpImm (ImmInt 32)) (OpReg ecx),+                       JXX EQQ lbl2,+                       JXX ALWAYS lbl1,+                       NEWBLOCK lbl1,+                       MOV II32 (OpReg rhi) (OpReg rlo),+                       SAR II32 (OpImm (ImmInt 31)) (OpReg rhi),+                       JXX ALWAYS lbl2,+                       NEWBLOCK lbl2+                     ]+   return (RegCode64 code rhi rlo)++-- Similar to the above.++iselExpr64 (CmmMachOp (MO_U_Shr _) [e1,e2]) = do+   RegCode64 code1 r1hi r1lo <- iselExpr64 e1+   (r2, code2) <- getSomeReg e2+   Reg64 rhi rlo <- getNewReg64+   lbl1 <- newBlockId+   lbl2 <- newBlockId+   let+        code =  code1 `appOL`+                code2 `appOL`+                toOL [ MOV II32 (OpReg r1lo) (OpReg rlo),+                       MOV II32 (OpReg r1hi) (OpReg rhi),+                       MOV II32 (OpReg r2) (OpReg ecx),+                       SHRD II32 (OpReg ecx) (OpReg rhi) (OpReg rlo),+                       SHR II32 (OpReg ecx) (OpReg rhi),+                       TEST II32 (OpImm (ImmInt 32)) (OpReg ecx),+                       JXX EQQ lbl2,+                       JXX ALWAYS lbl1,+                       NEWBLOCK lbl1,+                       MOV II32 (OpReg rhi) (OpReg rlo),+                       XOR II32 (OpReg rhi) (OpReg rhi),+                       JXX ALWAYS lbl2,+                       NEWBLOCK lbl2+                     ]+   return (RegCode64 code rhi rlo)++iselExpr64 (CmmMachOp (MO_And _) [e1,e2]) = iselExpr64ParallelBin AND e1 e2+iselExpr64 (CmmMachOp (MO_Or  _) [e1,e2]) = iselExpr64ParallelBin OR  e1 e2+iselExpr64 (CmmMachOp (MO_Xor _) [e1,e2]) = iselExpr64ParallelBin XOR e1 e2++iselExpr64 (CmmMachOp (MO_Not _) [e1]) = do+   RegCode64 code1 r1hi r1lo <- iselExpr64 e1+   Reg64 rhi rlo <- getNewReg64+   let+        code =  code1 `appOL`+                toOL [ MOV II32 (OpReg r1lo) (OpReg rlo),+                       MOV II32 (OpReg r1hi) (OpReg rhi),+                       NOT II32 (OpReg rlo),+                       NOT II32 (OpReg rhi)+                     ]+   return (RegCode64 code rhi rlo)++iselExpr64 (CmmRegOff r i) = iselExpr64 (mangleIndexTree r i)+ iselExpr64 expr    = do       platform <- getPlatform-      pprPanic "iselExpr64(i386)" (pdoc platform expr)+      pprPanic "iselExpr64(i386)" (pdoc platform expr $+$ text (show expr)) +iselExpr64ParallelBin :: (Format -> Operand -> Operand -> Instr)+                      -> CmmExpr -> CmmExpr -> NatM (RegCode64 (OrdList Instr))+iselExpr64ParallelBin op e1 e2 = do+   RegCode64 code1 r1hi r1lo <- iselExpr64 e1+   RegCode64 code2 r2hi r2lo <- iselExpr64 e2+   Reg64 rhi rlo <- getNewReg64+   let+        code =  code1 `appOL`+                code2 `appOL`+                toOL [ MOV II32 (OpReg r1lo) (OpReg rlo),+                       MOV II32 (OpReg r1hi) (OpReg rhi),+                       op  II32 (OpReg r2lo) (OpReg rlo),+                       op  II32 (OpReg r2hi) (OpReg rhi)+                     ]+   return (RegCode64 code rhi rlo)  -------------------------------------------------------------------------------- getRegister :: CmmExpr -> NatM Register@@ -648,6 +859,9 @@ getRegister' platform is32Bit (CmmRegOff r n)   = getRegister' platform is32Bit $ mangleIndexTree r n +getRegister' platform is32Bit (CmmMachOp (MO_RelaxedRead w) [e])+  = getRegister' platform is32Bit (CmmLoad e (cmmBits w) NaturallyAligned)+ getRegister' platform is32Bit (CmmMachOp (MO_AlignmentCheck align _) [e])   = addAlignmentCheck align <$> getRegister' platform is32Bit e @@ -676,6 +890,18 @@   RegCode64 code _rhi rlo <- iselExpr64 x   return $ Fixed II32 rlo code +getRegister' _ is32Bit (CmmMachOp (MO_UU_Conv W64 W8) [x])+ | is32Bit = do+  RegCode64 code _rhi rlo <- iselExpr64 x+  ro <- getNewRegNat II8+  return $ Fixed II8 ro (code `appOL` toOL [ MOVZxL II8 (OpReg rlo) (OpReg ro) ])++getRegister' _ is32Bit (CmmMachOp (MO_UU_Conv W64 W16) [x])+ | is32Bit = do+  RegCode64 code _rhi rlo <- iselExpr64 x+  ro <- getNewRegNat II16+  return $ Fixed II16 ro (code `appOL` toOL [ MOVZxL II16 (OpReg rlo) (OpReg ro) ])+ getRegister' _ _ (CmmLit lit@(CmmFloat f w)) =   float_const_sse2  where   float_const_sse2@@ -1658,7 +1884,28 @@   MO_U_Le _ -> LEU   _other -> pprPanic "machOpToCond" (pprMachOp mo) +{-  Note [64-bit integer comparisons on 32-bit]+    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +    When doing these comparisons there are 2 kinds of+    comparisons.++    * Comparison for equality (or lack thereof)++    We use xor to check if high/low bits are+    equal. Then combine the results using or.++    * Other comparisons:++    We first compare the low registers+    and use a subtraction with borrow to compare the high registers.++    For signed numbers the condition is determined by+    the sign and overflow flags agreeing or not+    and for unsigned numbers the condition is the carry flag.++-}+ -- @cond(Int|Flt)Code@: Turn a boolean expression into a condition, to be -- passed back up the tree. @@ -1668,6 +1915,68 @@  condIntCode' :: Platform -> Cond -> CmmExpr -> CmmExpr -> NatM CondCode +-- 64-bit integer comparisons on 32-bit+-- See Note [64-bit integer comparisons on 32-bit]+condIntCode' platform cond x y+  | target32Bit platform && isWord64 (cmmExprType platform x) = do++  RegCode64 code1 r1hi r1lo <- iselExpr64 x+  RegCode64 code2 r2hi r2lo <- iselExpr64 y++  -- we mustn't clobber r1/r2 so we use temporaries+  tmp1 <- getNewRegNat II32+  tmp2 <- getNewRegNat II32++  let (cond', cmpCode) = intComparison cond r1hi r1lo r2hi r2lo tmp1 tmp2+  return $ CondCode False cond' (code1 `appOL` code2 `appOL` cmpCode)++  where+    intComparison cond r1_hi r1_lo r2_hi r2_lo tmp1 tmp2 =+      case cond of+        -- These don't occur as argument of condIntCode'+        ALWAYS  -> panic "impossible"+        NEG     -> panic "impossible"+        POS     -> panic "impossible"+        CARRY   -> panic "impossible"+        OFLO    -> panic "impossible"+        PARITY  -> panic "impossible"+        NOTPARITY -> panic "impossible"+        -- Special case #1 x == y and x != y+        EQQ -> (EQQ, cmpExact)+        NE  -> (NE, cmpExact)+        -- [x >= y]+        GE  -> (GE, cmpGE)+        GEU -> (GEU, cmpGE)+        -- [x >  y]+        GTT -> (LTT, cmpLE)+        GU  -> (LU, cmpLE)+        -- [x <= y]+        LE  -> (GE, cmpLE)+        LEU -> (GEU, cmpLE)+        -- [x <  y]+        LTT -> (LTT, cmpGE)+        LU  -> (LU, cmpGE)+      where+        cmpExact :: OrdList Instr+        cmpExact =+          toOL+            [ MOV II32 (OpReg r1_hi) (OpReg tmp1)+            , MOV II32 (OpReg r1_lo) (OpReg tmp2)+            , XOR II32 (OpReg r2_hi) (OpReg tmp1)+            , XOR II32 (OpReg r2_lo) (OpReg tmp2)+            , OR  II32 (OpReg tmp1)  (OpReg tmp2)+            ]+        cmpGE = toOL+            [ MOV II32 (OpReg r1_hi) (OpReg tmp1)+            , CMP II32 (OpReg r2_lo) (OpReg r1_lo)+            , SBB II32 (OpReg r2_hi) (OpReg tmp1)+            ]+        cmpLE = toOL+            [ MOV II32 (OpReg r2_hi) (OpReg tmp1)+            , CMP II32 (OpReg r1_lo) (OpReg r2_lo)+            , SBB II32 (OpReg r1_hi) (OpReg tmp1)+            ]+ -- memory vs immediate condIntCode' platform cond (CmmLoad x pk _) (CmmLit lit)  | is32BitLit platform lit = do@@ -1882,36 +2191,6 @@ codes are set according to the supplied comparison operation. -} -{-  Note [64-bit integer comparisons on 32-bit]-    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--    When doing these comparisons there are 2 kinds of-    comparisons.--    * Comparison for equality (or lack thereof)--    We use xor to check if high/low bits are-    equal. Then combine the results using or and-    perform a single conditional jump based on the-    result.--    * Other comparisons:--    We map all other comparisons to the >= operation.-    Why? Because it's easy to encode it with a single-    conditional jump.--    We do this by first computing [r1_lo - r2_lo]-    and use the carry flag to compute-    [r1_high - r2_high - CF].--    At which point if r1 >= r2 then the result will be-    positive. Otherwise negative so we can branch on this-    condition.---}-- genCondBranch     :: BlockId      -- the source of the jump     -> BlockId      -- the true branch target@@ -1927,67 +2206,6 @@ genCondBranch' :: Bool -> BlockId -> BlockId -> BlockId -> CmmExpr                -> NatM InstrBlock --- 64-bit integer comparisons on 32-bit--- See Note [64-bit integer comparisons on 32-bit]-genCondBranch' is32Bit _bid true false (CmmMachOp mop [e1,e2])-  | is32Bit, Just W64 <- maybeIntComparison mop = do--  RegCode64 code1 r1hi r1lo <- iselExpr64 e1-  RegCode64 code2 r2hi r2lo <- iselExpr64 e2-  let cond = machOpToCond mop :: Cond--  -- we mustn't clobber r1/r2 so we use temporaries-  tmp1 <- getNewRegNat II32-  tmp2 <- getNewRegNat II32--  let cmpCode = intComparison cond true false r1hi r1lo r2hi r2lo tmp1 tmp2-  return $ code1 `appOL` code2 `appOL` cmpCode--  where-    intComparison cond true false r1_hi r1_lo r2_hi r2_lo tmp1 tmp2 =-      case cond of-        -- Impossible results of machOpToCond-        ALWAYS  -> panic "impossible"-        NEG     -> panic "impossible"-        POS     -> panic "impossible"-        CARRY   -> panic "impossible"-        OFLO    -> panic "impossible"-        PARITY  -> panic "impossible"-        NOTPARITY -> panic "impossible"-        -- Special case #1 x == y and x != y-        EQQ -> cmpExact-        NE  -> cmpExact-        -- [x >= y]-        GE  -> cmpGE-        GEU -> cmpGE-        -- [x >  y] <==> ![y >= x]-        GTT -> intComparison GE  false true r2_hi r2_lo r1_hi r1_lo tmp1 tmp2-        GU  -> intComparison GEU false true r2_hi r2_lo r1_hi r1_lo tmp1 tmp2-        -- [x <= y] <==> [y >= x]-        LE  -> intComparison GE  true false r2_hi r2_lo r1_hi r1_lo tmp1 tmp2-        LEU -> intComparison GEU true false r2_hi r2_lo r1_hi r1_lo tmp1 tmp2-        -- [x <  y] <==> ![x >= x]-        LTT -> intComparison GE  false true r1_hi r1_lo r2_hi r2_lo tmp1 tmp2-        LU  -> intComparison GEU false true r1_hi r1_lo r2_hi r2_lo tmp1 tmp2-      where-        cmpExact :: OrdList Instr-        cmpExact =-          toOL-            [ MOV II32 (OpReg r1_hi) (OpReg tmp1)-            , MOV II32 (OpReg r1_lo) (OpReg tmp2)-            , XOR II32 (OpReg r2_hi) (OpReg tmp1)-            , XOR II32 (OpReg r2_lo) (OpReg tmp2)-            , OR  II32 (OpReg tmp1)  (OpReg tmp2)-            , JXX cond true-            , JXX ALWAYS false-            ]-        cmpGE = toOL-            [ MOV II32 (OpReg r1_hi) (OpReg tmp1)-            , CMP II32 (OpReg r2_lo) (OpReg r1_lo)-            , SBB II32 (OpReg r2_hi) (OpReg tmp1)-            , JXX cond true-            , JXX ALWAYS false ]- genCondBranch' _ bid id false bool = do   CondCode is_float cond cond_code <- getCondCode bool   use_sse2 <- sse2Enabled@@ -2182,8 +2400,9 @@ genSimplePrim bid (MO_Memmove align)   []      [dst,src,n]    = genMemMove bid align dst src n genSimplePrim bid (MO_Memcmp align)    [res]   [dst,src,n]    = genMemCmp  bid align res dst src n genSimplePrim bid (MO_Memset align)    []      [dst,c,n]      = genMemSet  bid align dst c n-genSimplePrim _   MO_ReadBarrier       []      []             = return nilOL -- barriers compile to no code on x86/x86-64;-genSimplePrim _   MO_WriteBarrier      []      []             = return nilOL -- we keep it this long in order to prevent earlier optimisations.+genSimplePrim _   MO_AcquireFence      []      []             = return nilOL -- barriers compile to no code on x86/x86-64;+genSimplePrim _   MO_ReleaseFence      []      []             = return nilOL -- we keep it this long in order to prevent earlier optimisations.+genSimplePrim _   MO_SeqCstFence       []      []             = return $ unitOL MFENCE genSimplePrim _   MO_Touch             []      [_]            = return nilOL genSimplePrim _   (MO_Prefetch_Data n) []      [src]          = genPrefetchData n src genSimplePrim _   (MO_BSwap width)     [dst]   [src]          = genByteSwap width dst src@@ -2441,11 +2660,10 @@            -> [CmmFormal]       -- ^ where to put the result            -> [CmmActual]       -- ^ arguments (of mixed type)            -> NatM InstrBlock-genCCall32 addr conv@(ForeignConvention _ argHints _ _) dest_regs args = do+genCCall32 addr conv dest_regs args = do         config <- getConfig         let platform = ncgPlatform config-            args_hints = zip args (argHints ++ repeat NoHint)-            prom_args = map (maybePromoteCArg platform W32) args_hints+            prom_args = map (maybePromoteCArg platform W32) args              -- If the size is smaller than the word, we widen things (see maybePromoteCArg)             arg_size_bytes :: CmmType -> Int@@ -2599,11 +2817,10 @@            -> [CmmFormal]       -- ^ where to put the result            -> [CmmActual]       -- ^ arguments (of mixed type)            -> NatM InstrBlock-genCCall64 addr conv@(ForeignConvention _ argHints _ _) dest_regs args = do+genCCall64 addr conv dest_regs args = do     platform <- getPlatform     -- load up the register arguments-    let args_hints = zip args (argHints ++ repeat NoHint)-    let prom_args = map (maybePromoteCArg platform W32) args_hints+    let prom_args = map (maybePromoteCArg platform W32) args      let load_args :: [CmmExpr]                   -> [Reg]         -- int regs avail for args@@ -2841,11 +3058,9 @@             assign_code dest_regs)  -maybePromoteCArg :: Platform -> Width -> (CmmExpr, ForeignHint) -> CmmExpr-maybePromoteCArg platform wto (arg, hint)- | wfrom < wto = case hint of-     SignedHint -> CmmMachOp (MO_SS_Conv wfrom wto) [arg]-     _          -> CmmMachOp (MO_UU_Conv wfrom wto) [arg]+maybePromoteCArg :: Platform -> Width -> CmmExpr -> CmmExpr+maybePromoteCArg platform wto arg+ | wfrom < wto = CmmMachOp (MO_UU_Conv wfrom wto) [arg]  | otherwise   = arg  where    wfrom = cmmExprWidth platform arg@@ -3822,13 +4037,13 @@  genMemMove :: BlockId -> p -> CmmActual -> CmmActual -> CmmActual -> NatM InstrBlock genMemMove bid _align dst src n = do-  -- TODO: generate inline assembly when under a given treshold (similarly to+  -- TODO: generate inline assembly when under a given threshold (similarly to   -- memcpy and memset)   genLibCCall bid (fsLit "memmove") [] [dst,src,n]  genMemCmp :: BlockId -> p -> CmmFormal -> CmmActual -> CmmActual -> CmmActual -> NatM InstrBlock genMemCmp bid _align res dst src n = do-  -- TODO: generate inline assembly when under a given treshold (similarly to+  -- TODO: generate inline assembly when under a given threshold (similarly to   -- memcpy and memset)   genLibCCall bid (fsLit "memcmp") [res] [dst,src,n] @@ -4479,4 +4694,3 @@           , SETCC cond (OpReg dst_r)           , MOVZxL II8 (OpReg dst_r) (OpReg dst_r)           ]-
compiler/GHC/CmmToAsm/X86/Instr.hs view
@@ -31,7 +31,6 @@    , mkSpillInstr    , mkRegRegMoveInstr    , jumpDestsOfInstr-   , canFallthroughTo    , patchRegsOfInstr    , patchJumpInstr    , isMetaInstr@@ -54,7 +53,6 @@ import GHC.CmmToAsm.Config  import GHC.Cmm.BlockId-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Label import GHC.Platform.Regs import GHC.Cmm@@ -250,6 +248,8 @@         | SHL         Format Operand{-amount-} Operand         | SAR         Format Operand{-amount-} Operand         | SHR         Format Operand{-amount-} Operand+        | SHRD        Format Operand{-amount-} Operand Operand+        | SHLD        Format Operand{-amount-} Operand Operand          | BT          Format Imm Operand         | NOP@@ -258,7 +258,7 @@         -- We need to support the FSTP (x87 store and pop) instruction         -- so that we can correctly read off the return value of an         -- x86 CDECL C function call when its floating point.-        -- so we dont include a register argument, and just use st(0)+        -- so we don't include a register argument, and just use st(0)         -- this instruction is used ONLY for return values of C ffi calls         -- in x86_32 abi         | X87Store         Format  AddrMode -- st(0), dst@@ -402,6 +402,8 @@     SHL    _ imm dst    -> usageRM imm dst     SAR    _ imm dst    -> usageRM imm dst     SHR    _ imm dst    -> usageRM imm dst+    SHLD   _ imm dst1 dst2 -> usageRMM imm dst1 dst2+    SHRD   _ imm dst1 dst2 -> usageRMM imm dst1 dst2     BT     _ _   src    -> mkRUR (use_R src [])      PUSH   _ op         -> mkRUR (use_R op [])@@ -571,6 +573,8 @@     SHL  fmt imm dst     -> patch1 (SHL fmt imm) dst     SAR  fmt imm dst     -> patch1 (SAR fmt imm) dst     SHR  fmt imm dst     -> patch1 (SHR fmt imm) dst+    SHLD fmt imm dst1 dst2 -> patch2 (SHLD fmt imm) dst1 dst2+    SHRD fmt imm dst1 dst2 -> patch2 (SHRD fmt imm) dst1 dst2     BT   fmt imm src     -> patch1 (BT  fmt imm) src     TEST fmt src dst     -> patch2 (TEST fmt) src dst     CMP  fmt src dst     -> patch2 (CMP  fmt) src dst@@ -665,17 +669,6 @@         CALL{}          -> True         _               -> False -canFallthroughTo :: Instr -> BlockId -> Bool-canFallthroughTo insn bid-  = case insn of-    JXX _ target          -> bid == target-    JMP_TBL _ targets _ _ -> all isTargetBid targets-    _                     -> False-  where-    isTargetBid target = case target of-      Nothing                      -> True-      Just (DestBlockId target) -> target == bid-      _                  -> False  jumpDestsOfInstr         :: Instr
compiler/GHC/CmmToAsm/X86/Ppr.hs view
@@ -32,7 +32,6 @@ import GHC.CmmToAsm.Ppr  import GHC.Cmm              hiding (topInfoTable)-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Label import GHC.Cmm.BlockId import GHC.Cmm.CLabel@@ -732,6 +731,12 @@    SHR format src dst       -> pprShift (text "shr") format src dst +   SHLD format src dst1 dst2+      -> pprShift2 (text "shld") format src dst1 dst2++   SHRD format src dst1 dst2+      -> pprShift2 (text "shrd") format src dst1 dst2+    BT format imm src       -> pprFormatImmOp (text "bt") format imm src @@ -1068,6 +1073,17 @@            pprOperand platform II8 src,  -- src is 8-bit sized            comma,            pprOperand platform format dest+       ]++   pprShift2 :: Line doc -> Format -> Operand -> Operand -> Operand -> doc+   pprShift2 name format src dest1 dest2+     = line $ hcat [+           pprMnemonic name format,+           pprOperand platform II8 src,  -- src is 8-bit sized+           comma,+           pprOperand platform format dest1,+           comma,+           pprOperand platform format dest2        ]  
compiler/GHC/CmmToAsm/X86/Regs.hs view
@@ -246,7 +246,7 @@             | otherwise             -> panic "X86.Reg.classOfRealReg registerSingle too high"  -- | Get the name of the register with this number.--- NOTE: fixme, we dont track which "way" the XMM registers are used+-- NOTE: fixme, we don't track which "way" the XMM registers are used showReg :: Platform -> RegNo -> String showReg platform n         | n >= firstxmm && n <= lastxmm  platform = "%xmm" ++ show (n-firstxmm)
compiler/GHC/CmmToC.hs view
@@ -38,8 +38,8 @@ import GHC.Cmm.CLabel import GHC.Cmm hiding (pprBBlock, pprStatic) import GHC.Cmm.Dataflow.Block-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dataflow.Graph+import GHC.Cmm.Dataflow.Label import GHC.Cmm.Utils import GHC.Cmm.Switch import GHC.Cmm.InitFini@@ -261,6 +261,13 @@     CmmUnsafeForeignCall (PrimTarget MO_Touch) _results _args -> empty     CmmUnsafeForeignCall (PrimTarget (MO_Prefetch_Data _)) _results _args -> empty +    CmmUnsafeForeignCall (PrimTarget MO_ReleaseFence) [] [] ->+        text "__atomic_thread_fence(__ATOMIC_RELEASE);"+    CmmUnsafeForeignCall (PrimTarget MO_AcquireFence) [] [] ->+        text "__atomic_thread_fence(__ATOMIC_ACQUIRE);"+    CmmUnsafeForeignCall (PrimTarget MO_SeqCstFence) [] [] ->+        text "__atomic_thread_fence(__ATOMIC_SEQ_CST);"+     CmmUnsafeForeignCall target@(PrimTarget op) results args ->         fn_call       where@@ -433,6 +440,9 @@   where isMulMayOfloOp (MO_S_MulMayOflo _) = True         isMulMayOfloOp _ = False +pprMachOpApp platform (MO_RelaxedRead w) [x]+  = pprExpr platform (CmmLoad x (cmmBits w) NaturallyAligned)+ pprMachOpApp platform mop args   | Just ty <- machOpNeedsCast platform mop (map (cmmExprType platform) args)   = ty <> parens (pprMachOpApp' platform mop args)@@ -790,6 +800,11 @@         MO_SF_Conv _from to -> parens (machRep_F_CType to)         MO_FS_Conv _from to -> parens (machRep_S_CType platform to) +        MO_RelaxedRead _ -> pprTrace "offending mop:"+                                (text "MO_RelaxedRead")+                                (panic $ "PprC.pprMachOp_for_C: MO_S_MulMayOflo"+                                      ++ " should have been handled earlier!")+         MO_S_MulMayOflo _ -> pprTrace "offending mop:"                                 (text "MO_S_MulMayOflo")                                 (panic $ "PprC.pprMachOp_for_C: MO_S_MulMayOflo"@@ -944,8 +959,9 @@         MO_F32_ExpM1    -> text "expm1f"         MO_F32_Sqrt     -> text "sqrtf"         MO_F32_Fabs     -> text "fabsf"-        MO_ReadBarrier  -> text "load_load_barrier"-        MO_WriteBarrier -> text "write_barrier"+        MO_AcquireFence -> unsupported+        MO_ReleaseFence -> unsupported+        MO_SeqCstFence  -> unsupported         MO_Memcpy _     -> text "__builtin_memcpy"         MO_Memset _     -> text "__builtin_memset"         MO_Memmove _    -> text "__builtin_memmove"@@ -1513,12 +1529,15 @@ pprCtorArray :: Platform -> InitOrFini -> [CLabel] -> SDoc pprCtorArray platform initOrFini lbls =        decls-    <> text "static __attribute__((" <> attribute <> text "))"-    <> text "void _hs_" <> attribute <> text "()"+    <> text "static __attribute__((" <> text attribute <> text "))"+    <> text "void _hs_" <> text suffix <> text "()"     <> braces body   where     body = vcat [ pprCLabel platform lbl <> text " ();" | lbl <- lbls ]     decls = vcat [ text "void" <+> pprCLabel platform lbl <> text " (void);" | lbl <- lbls ]-    attribute = case initOrFini of-                  IsInitArray -> text "constructor"-                  IsFiniArray -> text "destructor"+    (attribute, suffix) = case initOrFini of+                  IsInitArray+                    -- See Note [JSFFI initialization] for details+                    | ArchWasm32 <- platformArch platform -> ("constructor(101)", "constructor")+                    | otherwise -> ("constructor", "constructor")+                  IsFiniArray -> ("destructor", "destructor")
compiler/GHC/CmmToLlvm.hs view
@@ -21,10 +21,11 @@ import GHC.CmmToLlvm.Ppr import GHC.CmmToLlvm.Regs import GHC.CmmToLlvm.Mangler+import GHC.CmmToLlvm.Version  import GHC.StgToCmm.CgUtils ( fixStgRegisters ) import GHC.Cmm-import GHC.Cmm.Dataflow.Collections+import GHC.Cmm.Dataflow.Label  import GHC.Utils.BufHandle import GHC.Driver.DynFlags@@ -196,7 +197,7 @@  cmmMetaLlvmPrelude :: LlvmM () cmmMetaLlvmPrelude = do-  metas <- flip mapM stgTBAA $ \(uniq, name, parent) -> do+  tbaa_metas <- flip mapM stgTBAA $ \(uniq, name, parent) -> do     -- Generate / lookup meta data IDs     tbaaId <- getMetaUniqueId     setUniqMeta uniq tbaaId@@ -209,9 +210,36 @@               -- just a name on its own. Previously `null` was accepted as the               -- name.               Nothing -> [ MetaStr name ]++  platform <- getPlatform   cfg <- getConfig+  let stack_alignment_metas =+          case platformArch platform of+            ArchX86_64 | llvmCgAvxEnabled cfg -> [mkStackAlignmentMeta 32]+            _                                 -> []+  module_flags_metas <- mkModuleFlagsMeta stack_alignment_metas+  let metas = tbaa_metas ++ module_flags_metas+  cfg <- getConfig   renderLlvm (ppLlvmMetas cfg metas)              (ppLlvmMetas cfg metas)++mkNamedMeta :: LMString -> [MetaExpr] -> LlvmM [MetaDecl]+mkNamedMeta name exprs = do+    (ids, decls) <- unzip <$> mapM f exprs+    return $ decls ++ [MetaNamed name ids]+  where+    f expr = do+      i <- getMetaUniqueId+      return (i, MetaUnnamed i expr)++mkModuleFlagsMeta :: [ModuleFlag] -> LlvmM [MetaDecl]+mkModuleFlagsMeta =+    mkNamedMeta "llvm.module.flags" . map moduleFlagToMetaExpr++mkStackAlignmentMeta :: Integer -> ModuleFlag+mkStackAlignmentMeta alignment =+    ModuleFlag MFBError "override-stack-alignment" (MetaLit $ LMIntLit alignment i32)+  -- ----------------------------------------------------------------------------- -- | Marks variables as used where necessary
compiler/GHC/CmmToLlvm/Base.hs view
@@ -41,6 +41,7 @@ import GHC.Llvm import GHC.CmmToLlvm.Regs import GHC.CmmToLlvm.Config+import GHC.CmmToLlvm.Version  import GHC.Cmm.CLabel import GHC.Platform.Regs ( activeStgRegs, globalRegMaybe )@@ -412,7 +413,7 @@ -- so as to make sure they have the most general type in the case that -- user code also uses these functions but with a different type than GHC -- internally. (Main offender is treating return type as 'void' instead of--- 'void *'). Fixes trac #5486.+-- 'void *'). Fixes #5486. ghcInternalFunctions :: LlvmM () ghcInternalFunctions = do     platform <- getPlatform
compiler/GHC/CmmToLlvm/CodeGen.hs view
@@ -24,7 +24,7 @@ import GHC.Cmm.Switch import GHC.Cmm.Dataflow.Block import GHC.Cmm.Dataflow.Graph-import GHC.Cmm.Dataflow.Collections+import GHC.Cmm.Dataflow.Label  import GHC.Data.FastString import GHC.Data.OrdList@@ -34,7 +34,6 @@ import GHC.Types.Unique  import GHC.Utils.Outputable-import GHC.Utils.Panic.Plain (massert) import qualified GHC.Utils.Panic as Panic import GHC.Utils.Misc @@ -172,31 +171,17 @@         fty = LMFunction funSig     in getInstrinct2 fname fty --- | Memory barrier instruction for LLVM >= 3.0-barrier :: LlvmM StmtData-barrier = do-    let s = Fence False SyncSeqCst-    return (unitOL s, [])---- | Insert a 'barrier', unless the target platform is in the provided list of---   exceptions (where no code will be emitted instead).-barrierUnless :: [Arch] -> LlvmM StmtData-barrierUnless exs = do-    platform <- getPlatform-    if platformArch platform `elem` exs-        then return (nilOL, [])-        else barrier- -- | Foreign Calls genCall :: ForeignTarget -> [CmmFormal] -> [CmmActual] -> LlvmM StmtData  -- Barriers need to be handled specially as they are implemented as LLVM -- intrinsic functions.-genCall (PrimTarget MO_ReadBarrier) _ _ =-    barrierUnless [ArchX86, ArchX86_64]--genCall (PrimTarget MO_WriteBarrier) _ _ =-    barrierUnless [ArchX86, ArchX86_64]+genCall (PrimTarget MO_AcquireFence) _ _ = runStmtsDecls $+    statement $ Fence False SyncAcquire+genCall (PrimTarget MO_ReleaseFence) _ _ = runStmtsDecls $+    statement $ Fence False SyncRelease+genCall (PrimTarget MO_SeqCstFence) _ _ = runStmtsDecls $+    statement $ Fence False SyncSeqCst  genCall (PrimTarget MO_Touch) _ _ =     return (nilOL, [])@@ -560,7 +545,7 @@                             , MO_AddWordC w                             , MO_SubWordC w                             ]-    massert valid+    Panic.massert valid     let width = widthToLlvmInt w     -- This will do most of the work of generating the call to the intrinsic and     -- extracting the values from the struct.@@ -1009,8 +994,11 @@     -- We support MO_U_Mul2 through ordinary LLVM mul instruction, see the     -- appropriate case of genCall.     MO_U_Mul2 {}     -> unsupported-    MO_ReadBarrier   -> unsupported-    MO_WriteBarrier  -> unsupported++    MO_ReleaseFence  -> unsupported+    MO_AcquireFence  -> unsupported+    MO_SeqCstFence   -> unsupported+     MO_Touch         -> unsupported     MO_UF_Conv _     -> unsupported @@ -1442,6 +1430,8 @@             all0s = LMLitVar $ LMVectorLit (replicate len all0)         in negateVec vecty all0s LM_MO_FSub +    MO_RelaxedRead w -> exprToVar (CmmLoad x (cmmBits w) NaturallyAligned)+     MO_AlignmentCheck _ _ -> panic "-falignment-sanitisation is not supported by -fllvm"      -- Handle unsupported cases explicitly so we get a warning@@ -1699,12 +1689,9 @@      MO_VF_Neg {} -> panicOp -    MO_AlignmentCheck {} -> panicOp+    MO_RelaxedRead {} -> panicOp -#if __GLASGOW_HASKELL__ < 811-    MO_VF_Extract {} -> panicOp-    MO_V_Extract {} -> panicOp-#endif+    MO_AlignmentCheck {} -> panicOp      where         binLlvmOp ty binOp allow_y_cast = do
+ compiler/GHC/CmmToLlvm/Version.hs view
@@ -0,0 +1,43 @@+module GHC.CmmToLlvm.Version+  ( LlvmVersion(..)+  , supportedLlvmVersionLowerBound+  , supportedLlvmVersionUpperBound+  , parseLlvmVersion+  , llvmVersionSupported+  , llvmVersionStr+  , llvmVersionList+  )+where++import GHC.Prelude++import GHC.CmmToLlvm.Version.Type+import GHC.CmmToLlvm.Version.Bounds++import Data.Char (isDigit)+import Data.List (intercalate)+import qualified Data.List.NonEmpty as NE++parseLlvmVersion :: String -> Maybe LlvmVersion+parseLlvmVersion =+    fmap LlvmVersion . NE.nonEmpty . go [] . dropWhile (not . isDigit)+  where+    go vs s+      | null ver_str+      = reverse vs+      | '.' : rest' <- rest+      = go (read ver_str : vs) rest'+      | otherwise+      = reverse (read ver_str : vs)+      where+        (ver_str, rest) = span isDigit s++llvmVersionSupported :: LlvmVersion -> Bool+llvmVersionSupported v =+  v >= supportedLlvmVersionLowerBound && v < supportedLlvmVersionUpperBound++llvmVersionStr :: LlvmVersion -> String+llvmVersionStr = intercalate "." . map show . llvmVersionList++llvmVersionList :: LlvmVersion -> [Int]+llvmVersionList = NE.toList . llvmVersionNE
+ compiler/GHC/CmmToLlvm/Version/Bounds.hs view
@@ -0,0 +1,19 @@+module GHC.CmmToLlvm.Version.Bounds+  ( supportedLlvmVersionLowerBound+  , supportedLlvmVersionUpperBound+  )+where++import GHC.Prelude ()++import GHC.CmmToLlvm.Version.Type++import qualified Data.List.NonEmpty as NE++-- | The (inclusive) lower bound on the LLVM Version that is currently supported.+supportedLlvmVersionLowerBound :: LlvmVersion+supportedLlvmVersionLowerBound = LlvmVersion (13 NE.:| [])++-- | The (not-inclusive) upper bound  bound on the LLVM Version that is currently supported.+supportedLlvmVersionUpperBound :: LlvmVersion+supportedLlvmVersionUpperBound = LlvmVersion (16 NE.:| [])
compiler/GHC/Core/LateCC.hs view
@@ -1,167 +1,90 @@-{-# LANGUAGE DerivingStrategies #-}-{-# LANGUAGE TupleSections #-}+{-# LANGUAGE RecordWildCards #-} --- | Adds cost-centers after the core piple has run.+-- | Adds cost-centers after the core pipline has run. module GHC.Core.LateCC-    ( addLateCostCentresMG-    , addLateCostCentresPgm-    , addLateCostCentres -- Might be useful for API users-    , Env(..)+    ( -- * Inserting cost centres+      addLateCostCenters     ) where -import Control.Applicative-import Control.Monad-import qualified Data.Set as S- import GHC.Prelude-import GHC.Types.CostCentre-import GHC.Types.CostCentre.State-import GHC.Types.Name hiding (varName)-import GHC.Types.Tickish-import GHC.Unit.Module.ModGuts-import GHC.Types.Var-import GHC.Unit.Types-import GHC.Data.FastString-import GHC.Core-import GHC.Core.Opt.Monad-import GHC.Core.Utils (mkTick)-import GHC.Types.Id-import GHC.Driver.DynFlags +import GHC.Core+import GHC.Core.LateCC.OverloadedCalls+import GHC.Core.LateCC.TopLevelBinds+import GHC.Core.LateCC.Types+import GHC.Core.LateCC.Utils+import GHC.Core.Seq+import qualified GHC.Data.Strict as Strict+import GHC.Core.Utils+import GHC.Tc.Utils.TcType+import GHC.Types.SrcLoc+import GHC.Utils.Error import GHC.Utils.Logger import GHC.Utils.Outputable-import GHC.Utils.Misc-import GHC.Utils.Error (withTiming)-import GHC.Utils.Monad.State.Strict --{- Note [Collecting late cost centres]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Usually cost centres defined by a module are collected-during tidy by collectCostCentres. However with `-fprof-late`-we insert cost centres after inlining. So we keep a list of-all the cost centres we inserted and combine that with the list-of cost centres found during tidy.--To avoid overhead when using -fprof-inline there is a flag to stop-us from collecting them here when we run this pass before tidy.--Note [Adding late cost centres]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-The basic idea is very simple. For every top level binder-`f = rhs` we compile it as if the user had written-`f = {-# SCC f #-} rhs`.--If we do this after unfoldings for `f` have been created this-doesn't impact core-level optimizations at all. If we do it-before the cost centre will be included in the unfolding and-might inhibit optimizations at the call site. For this reason-we provide flags for both approaches as they have different-tradeoffs.--We also don't add a cost centre for any binder that is a constructor-worker or wrapper. These will never meaningfully enrich the resulting-profile so we improve efficiency by omitting those.---}--addLateCostCentresMG :: ModGuts -> CoreM ModGuts-addLateCostCentresMG guts = do-  dflags <- getDynFlags-  let env :: Env-      env = Env-        { thisModule = mg_module guts-        , ccState = newCostCentreState-        , countEntries = gopt Opt_ProfCountEntries dflags-        , collectCCs = False -- See Note [Collecting late cost centres]-        }-  let guts' = guts { mg_binds = fst (addLateCostCentres env (mg_binds guts))-                   }-  return guts'--addLateCostCentresPgm :: DynFlags -> Logger -> Module -> CoreProgram -> IO (CoreProgram, S.Set CostCentre)-addLateCostCentresPgm dflags logger mod binds =-  withTiming logger-               (text "LateCC"<+>brackets (ppr mod))-               (\(a,b) -> a `seqList` (b `seq` ())) $ do-  let env = Env-        { thisModule = mod-        , ccState = newCostCentreState-        , countEntries = gopt Opt_ProfCountEntries dflags-        , collectCCs = True -- See Note [Collecting late cost centres]-        }-      (binds', ccs) = addLateCostCentres env binds-  when (dopt Opt_D_dump_late_cc dflags || dopt Opt_D_verbose_core2core dflags) $-    putDumpFileMaybe logger Opt_D_dump_late_cc "LateCC" FormatCore (vcat (map ppr binds'))-  return (binds', ccs)+-- | Late cost center insertion logic used by the driver+addLateCostCenters ::+     Logger+  -- ^ Logger+  -> LateCCConfig+  -- ^ Late cost center configuration+  -> CoreProgram+  -- ^ The program+  -> IO (CoreProgram, LateCCState (Strict.Maybe SrcSpan))+addLateCostCenters logger LateCCConfig{..} core_binds = do -addLateCostCentres :: Env -> CoreProgram -> (CoreProgram,S.Set CostCentre)-addLateCostCentres env binds =-  let (binds', state) = runState (mapM (doBind env) binds) initLateCCState-  in (binds',lcs_ccs state)+    -- If top-level late CCs are enabled via either -fprof-late or+    -- -fprof-late-overloaded, add them+    (top_level_cc_binds, top_level_late_cc_state) <-+      case lateCCConfig_whichBinds of+        LateCCNone ->+          return (core_binds, initLateCCState ())+        _ ->+          withTiming+            logger+            (text "LateTopLevelCCs" <+> brackets (ppr this_mod))+            (\(binds, late_cc_state) -> seqBinds binds `seq` late_cc_state `seq` ())+            $ {-# SCC lateTopLevelCCs #-} do+              pure $+                doLateCostCenters+                  lateCCConfig_env+                  (initLateCCState ())+                  (topLevelBindsCC top_level_cc_pred)+                  core_binds +    -- If overloaded call CCs are enabled via -fprof-late-overloaded-calls, add+    -- them+    (late_cc_binds, late_cc_state) <-+      if lateCCConfig_overloadedCalls then+        withTiming+            logger+            (text "LateOverloadedCallsCCs" <+> brackets (ppr this_mod))+            (\(binds, late_cc_state) -> seqBinds binds `seq` late_cc_state `seq` ())+            $ {-# SCC lateoverloadedCallsCCs #-} do+              pure $+                doLateCostCenters+                  lateCCConfig_env+                  (top_level_late_cc_state { lateCCState_extra = Strict.Nothing })+                  overloadedCallsCC+                  top_level_cc_binds+      else+        return+          ( top_level_cc_binds+          , top_level_late_cc_state { lateCCState_extra = Strict.Nothing }+          ) -doBind :: Env -> CoreBind -> M CoreBind-doBind env (NonRec b rhs) = NonRec b <$> doBndr env b rhs-doBind env (Rec bs) = Rec <$> mapM doPair bs+    return (late_cc_binds, late_cc_state)   where-    doPair :: ((Id, CoreExpr) -> M (Id, CoreExpr))-    doPair (b,rhs) = (b,) <$> doBndr env b rhs--doBndr :: Env -> Id -> CoreExpr -> M CoreExpr-doBndr env bndr rhs-  -- Cost centres on constructor workers are pretty much useless-  -- so we don't emit them if we are looking at the rhs of a constructor-  -- binding.-  | Just _ <- isDataConId_maybe bndr = pure rhs-  | otherwise = doBndr' env bndr rhs----- We want to put the cost centre below the lambda as we only care about executions of the RHS.-doBndr' :: Env -> Id -> CoreExpr -> State LateCCState CoreExpr-doBndr' env bndr (Lam b rhs) = Lam b <$> doBndr' env bndr rhs-doBndr' env bndr rhs = do-    let name = idName bndr-        name_loc = nameSrcSpan name-        cc_name = getOccFS name-        count = countEntries env-    cc_flavour <- getCCFlavour cc_name-    let cc_mod = thisModule env-        bndrCC = NormalCC cc_flavour cc_name cc_mod name_loc-        note = ProfNote bndrCC count True-    addCC env bndrCC-    return $ mkTick note rhs--data LateCCState = LateCCState-    { lcs_state :: !CostCentreState-    , lcs_ccs   :: S.Set CostCentre-    }-type M = State LateCCState--initLateCCState :: LateCCState-initLateCCState = LateCCState newCostCentreState mempty--getCCFlavour :: FastString -> M CCFlavour-getCCFlavour name = mkLateCCFlavour <$> getCCIndex' name--getCCIndex' :: FastString -> M CostCentreIndex-getCCIndex' name = do-  state <- get-  let (index,cc_state') = getCCIndex name (lcs_state state)-  put (state { lcs_state = cc_state'})-  return index--addCC :: Env -> CostCentre -> M ()-addCC !env cc = do-    state <- get-    when (collectCCs env) $ do-        let ccs' = S.insert cc (lcs_ccs state)-        put (state { lcs_ccs = ccs'})--data Env = Env-  { thisModule  :: !Module-  , countEntries:: !Bool-  , ccState     :: !CostCentreState-  , collectCCs  :: !Bool-  }+    top_level_cc_pred :: CoreExpr -> Bool+    top_level_cc_pred =+        case lateCCConfig_whichBinds of+          LateCCAllBinds ->+            const True+          LateCCOverloadedBinds ->+            isOverloadedTy . exprType+          LateCCNone ->+            -- This is here for completeness, we won't actually use this+            -- predicate in this case since we'll shortcut.+            const False +    this_mod = lateCCEnv_module lateCCConfig_env
+ compiler/GHC/Core/LateCC/OverloadedCalls.hs view
@@ -0,0 +1,204 @@+{-# LANGUAGE LambdaCase    #-}+{-# LANGUAGE TupleSections #-}++module GHC.Core.LateCC.OverloadedCalls+  ( overloadedCallsCC+  ) where++import GHC.Prelude++import Control.Monad.Trans.Class+import Control.Monad.Trans.Reader+import Control.Monad.Trans.State.Strict+import qualified GHC.Data.Strict as Strict++import GHC.Data.FastString+import GHC.Core+import GHC.Core.LateCC.Utils+import GHC.Core.LateCC.Types+import GHC.Core.Make+import GHC.Core.Predicate+import GHC.Core.Type+import GHC.Core.Utils+import GHC.Tc.Utils.TcType+import GHC.Types.Id+import GHC.Types.Name+import GHC.Types.SrcLoc+import GHC.Types.Tickish+import GHC.Types.Var+import GHC.Utils.Outputable++type OverloadedCallsCCState = Strict.Maybe SrcSpan++-- | Insert cost centres on function applications with dictionary arguments. The+-- source locations attached to the cost centres is approximated based on the+-- "closest" source note encountered in the traversal.+overloadedCallsCC :: CoreBind -> LateCCM OverloadedCallsCCState CoreBind+overloadedCallsCC =+    processBind+  where+    processBind :: CoreBind -> LateCCM OverloadedCallsCCState CoreBind+    processBind core_bind =+        case core_bind of+          NonRec b e ->+            NonRec b <$> wrap_if_join b (processExpr e)+          Rec es ->+            Rec <$> mapM (\(b,e) -> (b,) <$> wrap_if_join b (processExpr e)) es+      where+        -- If an overloaded function is turned into a join point, we won't add+        -- SCCs directly to calls since it makes them non-tail calls. Instead,+        -- we look for join points here and add an SCC to their RHS if they are+        -- overloaded.+        wrap_if_join ::+             CoreBndr+          -> LateCCM OverloadedCallsCCState CoreExpr+          -> LateCCM OverloadedCallsCCState CoreExpr+        wrap_if_join b pexpr = do+            expr <- pexpr+            if isJoinId b && isOverloadedTy (exprType expr) then do+              let+                cc_name :: FastString+                cc_name = fsLit "join-rhs-" `appendFS` getOccFS b++              cc_srcspan <-+                fmap (Strict.fromMaybe (UnhelpfulSpan UnhelpfulNoLocationInfo)) $+                  lift $ gets lateCCState_extra++              insertCC cc_name cc_srcspan expr+            else+              return expr+++    processExpr :: CoreExpr -> LateCCM OverloadedCallsCCState CoreExpr+    processExpr expr =+      case expr of+        -- The case we care about: Application+        app@App{} -> do+          -- Here we have some application like `f v1 ... vN`, where v1 ... vN+          -- should be the function's type arguments followed by the value+          -- arguments. To determine if the `f` is an overloaded function, we+          -- check if any of the arguments v1 ... vN are dictionaries.+          let+            (f, xs) = collectArgs app+            resultTy = applyTypeToArgs empty (exprType f) xs++          -- Recursively process the arguments first for no particular reason+          args <- mapM processExpr xs+          let app' = mkCoreApps f args++          if+              -- Check if any of the arguments are dictionaries+              any isDictExpr args++              -- Avoid instrumenting dictionary functions, which may be+              -- overloaded if there are superclasses, by checking if the result+              -- type of the function is a dictionary type.+            && not (isDictTy resultTy)++              -- Avoid instrumenting constraint selectors like eq_sel+            && (typeTypeOrConstraint resultTy /= ConstraintLike)++              -- Avoid instrumenting join points.+              -- (See comment in processBind above)+            && not (isJoinVarExpr f)+          then do+            -- Extract a name and source location from the function being+            -- applied+            let+              cc_name :: FastString+              cc_name =+                fsLit $ maybe "<no name available>" getOccString (exprName app)++            cc_srcspan <-+              fmap (Strict.fromMaybe (UnhelpfulSpan UnhelpfulNoLocationInfo)) $+                lift $ gets lateCCState_extra++            insertCC cc_name cc_srcspan app'+          else+            return app'++        -- For recursive constructors of Expr, we traverse the nested Exprs+        Lam b e ->+          mkCoreLams [b] <$> processExpr e+        Let b e ->+          mkCoreLet <$> processBind b <*> processExpr e+        Case e b t alts ->+              Case+          <$> processExpr e+          <*> pure b+          <*> pure t+          <*> mapM processAlt alts+        Cast e co ->+          mkCast <$> processExpr e <*> pure co+        Tick t e -> do+          trackSourceNote t $+            mkTick t <$> processExpr e++        -- For non-recursive constructors of Expr, we do nothing+        x -> return x++    processAlt :: CoreAlt -> LateCCM OverloadedCallsCCState CoreAlt+    processAlt (Alt c bs e) = Alt c bs <$> processExpr e++    trackSourceNote :: CoreTickish -> LateCCM OverloadedCallsCCState a -> LateCCM OverloadedCallsCCState a+    trackSourceNote tick act =+      case tick of+        SourceNote rss _ -> do+          -- Prefer source notes from the current file+          in_current_file <-+            maybe False ((== EQ) . lexicalCompareFS (srcSpanFile rss)) <$>+              asks lateCCEnv_file+          if not in_current_file then+            act+          else do+            loc <- lift $ gets lateCCState_extra+            lift . modify $ \s ->+              s { lateCCState_extra =+                    Strict.Just $ RealSrcSpan rss mempty+                }+            x <- act+            lift . modify $ \s ->+              s { lateCCState_extra = loc+                }+            return x+        _ ->+          act++    -- Utility functions++    -- Extract a Name from an expression. If it is an application, attempt to+    -- extract a name from the applied function. If it is a variable, return the+    -- Name of the variable. If it is a tick/cast, attempt to extract a Name+    -- from the expression held in the tick/cast. Otherwise return Nothing.+    exprName :: CoreExpr -> Maybe Name+    exprName =+        \case+          App f _ ->+            exprName f+          Var f ->+            Just (idName f)+          Tick _ e ->+            exprName e+          Cast e _ ->+            exprName e+          _ ->+            Nothing++    -- Determine whether an expression is a dictionary+    isDictExpr :: CoreExpr -> Bool+    isDictExpr =+        maybe False isDictTy . exprType'+      where+        exprType' :: CoreExpr -> Maybe Type+        exprType' = \case+            Type{} -> Nothing+            expr -> Just $ exprType expr++    -- Determine whether an expression is a join variable+    isJoinVarExpr :: CoreExpr -> Bool+    isJoinVarExpr =+        \case+          Var var -> isJoinId var+          Tick _ e -> isJoinVarExpr e+          Cast e _ -> isJoinVarExpr e+          _ -> False
+ compiler/GHC/Core/LateCC/TopLevelBinds.hs view
@@ -0,0 +1,106 @@+{-# LANGUAGE TupleSections #-}+module GHC.Core.LateCC.TopLevelBinds where++import GHC.Prelude++import GHC.Core+-- import GHC.Core.LateCC+import GHC.Core.LateCC.Types+import GHC.Core.LateCC.Utils+import GHC.Core.Opt.Monad+import GHC.Driver.DynFlags+import GHC.Types.Id+import GHC.Types.Name+import GHC.Unit.Module.ModGuts++{- Note [Collecting late cost centres]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Usually cost centres defined by a module are collected+during tidy by collectCostCentres. However with `-fprof-late`+we insert cost centres after inlining. So we keep a list of+all the cost centres we inserted and combine that with the list+of cost centres found during tidy.++To avoid overhead when using -fprof-inline there is a flag to stop+us from collecting them here when we run this pass before tidy.++Note [Adding late cost centres to top level bindings]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+The basic idea is very simple. For every top level binder+`f = rhs` we compile it as if the user had written+`f = {-# SCC f #-} rhs`.++If we do this after unfoldings for `f` have been created this+doesn't impact core-level optimizations at all. If we do it+before the cost centre will be included in the unfolding and+might inhibit optimizations at the call site. For this reason+we provide flags for both approaches as they have different+tradeoffs.++We also don't add a cost centre for any binder that is a constructor+worker or wrapper. These will never meaningfully enrich the resulting+profile so we improve efficiency by omitting those.++-}++-- | Add late cost centres directly to the 'ModGuts'. This is used inside the+-- core pipeline with the -fprof-late-inline flag. It should not be used after+-- tidy, since it does not manually track inserted cost centers. See+-- Note [Collecting late cost centres].+topLevelBindsCCMG :: ModGuts -> CoreM ModGuts+topLevelBindsCCMG guts = do+    dflags <- getDynFlags+    let+      env =+        LateCCEnv+          { lateCCEnv_module = mg_module guts++            -- We don't use this for topLevelBindsCC, so Nothing is okay+          , lateCCEnv_file = Nothing++          , lateCCEnv_countEntries= gopt Opt_ProfCountEntries dflags+          , lateCCEnv_collectCCs = False+          }+      guts' =+        guts+          { mg_binds =+              fst+                ( doLateCostCenters+                    env+                    (initLateCCState ())+                    (topLevelBindsCC (const True))+                    (mg_binds guts)+                )+          }+    return guts'++-- | Insert cost centres on top-level bindings in the module, depending on+-- whether or not they satisfy the given predicate.+topLevelBindsCC :: (CoreExpr -> Bool) -> CoreBind -> LateCCM s CoreBind+topLevelBindsCC pred core_bind =+    case core_bind of+      NonRec b rhs ->+        NonRec b <$> doBndr b rhs+      Rec bs ->+        Rec <$> mapM doPair bs+  where+    doPair :: ((Id, CoreExpr) -> LateCCM s (Id, CoreExpr))+    doPair (b,rhs) = (b,) <$> doBndr b rhs++    doBndr :: Id -> CoreExpr -> LateCCM s CoreExpr+    doBndr bndr rhs+      -- Cost centres on constructor workers are pretty much useless+      -- so we don't emit them if we are looking at the rhs of a constructor+      -- binding.+      | Just _ <- isDataConId_maybe bndr = pure rhs+      | otherwise = if pred rhs then addCC bndr rhs else pure rhs++    -- We want to put the cost centre below the lambda as we only care about+    -- executions of the RHS.+    addCC :: Id -> CoreExpr -> LateCCM s CoreExpr+    addCC bndr (Lam b rhs) = Lam b <$> addCC bndr rhs+    addCC bndr rhs = do+      let name = idName bndr+          cc_loc = nameSrcSpan name+          cc_name = getOccFS name+      insertCC cc_name cc_loc rhs
+ compiler/GHC/Core/LateCC/Types.hs view
@@ -0,0 +1,74 @@+-- | Types related to late cost center insertion+module GHC.Core.LateCC.Types+  ( LateCCConfig(..)+  , LateCCBindSpec(..)+  , LateCCEnv(..)+  , LateCCState(..)+  , initLateCCState+  , LateCCM+  ) where++import GHC.Prelude++import Control.Monad.Trans.Reader+import Control.Monad.Trans.State.Strict+import qualified Data.Set as S++import GHC.Data.FastString+import GHC.Types.CostCentre+import GHC.Types.CostCentre.State+import GHC.Unit.Types++-- | Late cost center insertion configuration.+--+-- Specifies whether cost centers are added to overloaded function call sites+-- and/or top-level bindings, and which top-level bindings they are added to.+-- Also holds the cost center insertion environment.+data LateCCConfig =+      LateCCConfig+        { lateCCConfig_whichBinds :: !LateCCBindSpec+        , lateCCConfig_overloadedCalls :: !Bool+        , lateCCConfig_env :: !LateCCEnv+        }++-- | The types of top-level bindings we support adding cost centers to.+data LateCCBindSpec =+      LateCCNone+    | LateCCAllBinds+    | LateCCOverloadedBinds++-- | Late cost centre insertion environment+data LateCCEnv = LateCCEnv+  { lateCCEnv_module :: !Module+    -- ^ Current module+  , lateCCEnv_file :: Maybe FastString+    -- ^ Current file, if we have one+  , lateCCEnv_countEntries:: !Bool+    -- ^ Whether the inserted cost centers should count entries+  , lateCCEnv_collectCCs  :: !Bool+    -- ^ Whether to collect the cost centres we insert. See+    -- Note [Collecting late cost centres]++  }++-- | Late cost centre insertion state, indexed by some extra state type that an+-- insertion method may require.+data LateCCState s = LateCCState+    { lateCCState_ccs :: !(S.Set CostCentre)+      -- ^ Cost centres that have been inserted+    , lateCCState_ccState :: !CostCentreState+      -- ^ Per-module state tracking for cost centre indices+    , lateCCState_extra :: !s+    }++-- | The empty late cost centre insertion state+initLateCCState :: s -> LateCCState s+initLateCCState s =+    LateCCState+      { lateCCState_ccState = newCostCentreState+      , lateCCState_ccs = mempty+      , lateCCState_extra = s+      }++-- | Late cost centre insertion monad+type LateCCM s = ReaderT LateCCEnv (State (LateCCState s))
+ compiler/GHC/Core/LateCC/Utils.hs view
@@ -0,0 +1,80 @@+module GHC.Core.LateCC.Utils+  ( -- * Inserting cost centres+    doLateCostCenters -- Might be useful for API users++    -- ** Helpers for defining insertion methods+  , getCCFlavour+  , insertCC+  ) where++import GHC.Prelude++import Control.Monad+import Control.Monad.Trans.Class+import Control.Monad.Trans.Reader+import Control.Monad.Trans.State.Strict+import qualified Data.Set as S++import GHC.Core+import GHC.Core.LateCC.Types+import GHC.Core.Utils+import GHC.Data.FastString+import GHC.Types.CostCentre+import GHC.Types.CostCentre.State+import GHC.Types.SrcLoc+import GHC.Types.Tickish++-- | Insert cost centres into the 'CoreProgram' using the provided environment,+-- initial state, and insertion method.+doLateCostCenters+  :: LateCCEnv+  -- ^ Environment to run the insertion in+  -> LateCCState s+  -- ^ Initial state to run the insertion with+  -> (CoreBind -> LateCCM s CoreBind)+  -- ^ Insertion method+  -> CoreProgram+  -- ^ Bindings to consider+  -> (CoreProgram, LateCCState s)+doLateCostCenters env state method binds =+    runLateCC env state $ mapM method binds++-- | Evaluate late cost centre insertion+runLateCC :: LateCCEnv -> LateCCState s -> LateCCM s a -> (a, LateCCState s)+runLateCC env state = (`runState` state) . (`runReaderT` env)++-- | Given the name of a cost centre, get its flavour+getCCFlavour :: FastString -> LateCCM s CCFlavour+getCCFlavour name = mkLateCCFlavour <$> getCCIndex' name+  where+    getCCIndex' :: FastString -> LateCCM s CostCentreIndex+    getCCIndex' name = do+      cc_state <- lift $ gets lateCCState_ccState+      let (index, cc_state') = getCCIndex name cc_state+      lift . modify $ \s -> s { lateCCState_ccState = cc_state'}+      return index++-- | Insert a cost centre with the specified name and source span on the given+-- expression. The inserted cost centre will be appropriately tracked in the+-- late cost centre state.+insertCC+  :: FastString+  -- ^ Name of the cost centre to insert+  -> SrcSpan+  -- ^ Source location to associate with the cost centre+  -> CoreExpr+  -- ^ Expression to wrap in the cost centre+  -> LateCCM s CoreExpr+insertCC cc_name cc_loc expr = do+    cc_flavour <- getCCFlavour cc_name+    env <- ask+    let+      cc_mod = lateCCEnv_module env+      cc = NormalCC cc_flavour cc_name cc_mod cc_loc+      note = ProfNote cc (lateCCEnv_countEntries env) True+    when (lateCCEnv_collectCCs env) $ do+        lift . modify $ \s ->+          s { lateCCState_ccs = S.insert cc (lateCCState_ccs s)+            }+    return $ mkTick note expr+
compiler/GHC/Core/Opt/CSE.hs view
@@ -14,7 +14,7 @@ import GHC.Types.Id     ( Id, idType, idHasRules, zapStableUnfolding                         , idInlineActivation, setInlineActivation                         , zapIdOccInfo, zapIdUsageInfo, idInlinePragma-                        , isJoinId, isJoinId_maybe, idUnfolding )+                        , isJoinId, idJoinPointHood, idUnfolding ) import GHC.Core.Utils   ( mkAltExpr                         , exprIsTickedString                         , stripTicksE, stripTicksT, mkTicks )@@ -43,7 +43,7 @@ When we then see         y1 = C a b         y2 = C y1 b-we replace the C a b with x1.  But then we *dont* want to+we replace the C a b with x1.  But then we *don't* want to add   x1 -> y1  to the mapping.  Rather, we want the reverse, y1 -> x1 so that a subsequent binding         y2 = C y1 b@@ -436,7 +436,7 @@       -- See Note [Take care with literal strings]   = (env_body', (out_id', in_rhs)) -  | Just arity <- isJoinId_maybe out_id+  | JoinPoint arity <- idJoinPointHood out_id       -- See Note [Look inside join-point binders]   = let (params, in_body) = collectNBinders arity in_rhs         (env', params') = addBinders env_rhs params
compiler/GHC/Core/Opt/CallArity.hs view
@@ -2,7 +2,6 @@ -- Copyright (c) 2014 Joachim Breitner -- -{-# LANGUAGE BangPatterns #-}  module GHC.Core.Opt.CallArity     ( callArityAnalProgram
compiler/GHC/Core/Opt/DmdAnal.hs view
@@ -47,7 +47,6 @@  import GHC.Utils.Misc import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Outputable  import Data.List        ( mapAccumL )@@ -88,7 +87,7 @@ -- | Outputs a new copy of the Core program in which binders have been annotated -- with demand and strictness information. ----- Note: use `seqBinds` on the result to avoid leaks due to lazyness (cf Note+-- Note: use `seqBinds` on the result to avoid leaks due to laziness (cf Note -- [Stamp out space leaks in demand analysis]) dmdAnalProgram :: DmdAnalOpts -> FamInstEnvs -> [CoreRule] -> CoreProgram -> CoreProgram dmdAnalProgram opts fam_envs rules binds@@ -1130,9 +1129,9 @@ thresholdArity :: Id -> CoreExpr -> Arity -- See Note [Demand signatures are computed for a threshold arity based on idArity] thresholdArity fn rhs-  = case isJoinId_maybe fn of-      Just join_arity -> count isId $ fst $ collectNBinders join_arity rhs-      Nothing         -> idArity fn+  = case idJoinPointHood fn of+      JoinPoint join_arity -> count isId $ fst $ collectNBinders join_arity rhs+      NotJoinPoint         -> idArity fn  -- | The result type after applying 'idArity' many arguments. Returns 'Nothing' -- when the type doesn't have exactly 'idArity' many arrows.@@ -1403,7 +1402,7 @@ Now if f is subsequently inlined, we'll use 'g' and ... disaster.  SOLUTION: if f has a stable unfolding, treat every free variable as a-/demand root/, that is: Analyse it as if it was a variable occuring in a+/demand root/, that is: Analyse it as if it was a variable occurring in a 'topDmd' context. This is done in `demandRoot` (which we also use for exported top-level ids). Do the same for Ids free in the RHS of any RULES for f. @@ -1948,6 +1947,7 @@               -- manifest arity for join points   = -- pprTrace "finaliseArgBoxities" (     --   vcat [text "function:" <+> ppr fn+    --        , text "max" <+> ppr max_wkr_args     --        , text "dmds before:" <+> ppr (map idDemandInfo (filter isId bndrs))     --        , text "dmds after: " <+>  ppr arg_dmds' ]) $     (arg_dmds', set_lam_dmds arg_dmds' rhs)@@ -2159,7 +2159,7 @@              in ...f @a (% sel1 d, sel2 d %)   and all the tuple building and taking apart will disappear. -Wrinkle (DNB2): we /do/ wnat to unbox equality dictionaries,+Wrinkle (DNB2): we /do/ want to unbox equality dictionaries,   for (~), (~~), and Coercible (#23398).  Their payload is a single unboxed   coercion.  We never want to specialise on `(t1 ~ t2)`.  All that would do is   to make a copy of the function's RHS with a particular coercion.  Unlike@@ -2349,7 +2349,7 @@         -- L demand doesn't get both'd with the Bot coming up from the inner         -- call to f.  So we just get an L demand for x for g. -setBndrsDemandInfo :: HasDebugCallStack => [Var] -> [Demand] -> [Var]+setBndrsDemandInfo :: HasCallStack => [Var] -> [Demand] -> [Var] setBndrsDemandInfo (b:bs) ds   | isTyVar b = b : setBndrsDemandInfo bs ds setBndrsDemandInfo (b:bs) (d:ds) =
compiler/GHC/Core/Opt/Exitify.hs view
@@ -36,20 +36,24 @@ -}  import GHC.Prelude+import GHC.Builtin.Uniques+import GHC.Core+import GHC.Core.Utils+import GHC.Core.FVs+import GHC.Core.Type+ import GHC.Types.Var import GHC.Types.Id import GHC.Types.Id.Info-import GHC.Core-import GHC.Core.Utils-import GHC.Utils.Monad.State.Strict-import GHC.Builtin.Uniques import GHC.Types.Var.Set import GHC.Types.Var.Env-import GHC.Core.FVs-import GHC.Data.FastString-import GHC.Core.Type+import GHC.Types.Basic( JoinPointHood(..) )++import GHC.Utils.Monad.State.Strict import GHC.Utils.Misc( mapSnd ) +import GHC.Data.FastString+ import Data.Bifunctor import Control.Monad @@ -160,7 +164,7 @@     go captured (_, AnnLet ann_bind body)         -- join point, RHS and body are in tail-call position         | AnnNonRec j rhs <- ann_bind-        , Just join_arity <- isJoinId_maybe j+        , JoinPoint join_arity <- idJoinPointHood j         = do let (params, join_body) = collectNAnnBndrs join_arity rhs              join_body' <- go (captured ++ params) join_body              let rhs' = mkLams params join_body'
compiler/GHC/Core/Opt/FloatIn.hs view
@@ -29,7 +29,7 @@ import GHC.Core.Type  import GHC.Types.Basic      ( RecFlag(..), isRec )-import GHC.Types.Id         ( idType, isJoinId, isJoinId_maybe )+import GHC.Types.Id         ( idType, isJoinId, idJoinPointHood ) import GHC.Types.Tickish import GHC.Types.Var import GHC.Types.Var.Set@@ -234,6 +234,29 @@ we're careful not to float into the target of a jump (though we can float into the arguments just fine). +Floating in can /enhance/ join points.  Consider this (#3458)+    f2 x = let g :: Int -> Int+               g y = if y==0 then y+x else g (y-1)+           in case g x of+                0 -> True+                _ -> False++Here `g` is not a join point. But if we float inwards it becomes one!  We+float in; the occurrence analyser identifies `g` as a join point; the Simplifier+retains that property, so we get+    f2 x = case (joinrec+                    g y = if y==0 then y+x else g (y-1)+                 in jump g x) of+              0 -> True+              _ -> False++Now that outer case gets pushed into the RHS of the joinrec, giving+    f2 x = joinrec g y = if y==0+                         then case y+x of { 0 -> True; _ -> False }+                         else jump g (y-1)+           in jump g x+Nice!+ Note [Floating in past a lambda group] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ * We must be careful about floating inside a value lambda.@@ -322,7 +345,7 @@  * In fiExpr (AnnCase ...). Remember to include the case_bndr in the   binders.  Again, no need to delete the alt binders from the rhs-  free vars, beause any bindings mentioning them will be dropped+  free vars, because any bindings mentioning them will be dropped   here unconditionally. -} @@ -423,6 +446,30 @@ array indexing operations, which have a single DEFAULT alternative without any binders, to be floated inward. +In particular, we want to be able to transform++  case indexIntArray# arr i of vi {+    __DEFAULT -> case <# j n of _ {+      __DEFAULT -> False+      1# -> case indexIntArray# arr j of vj {+        __DEFAULT -> ... vi ... vj ...+      }+    }+  }++by floating in `indexIntArray# arr i` to produce++  case <# j n of _ {+    __DEFAULT -> False+    1# -> case indexIntArray# arr i of vi {+      __DEFAULT -> case indexIntArray# arr j of vj {+        __DEFAULT -> ... vi ... vj ...+      }+    }+  }++...which skips the `indexIntArray# arr i` call entirely in the out-of-bounds branch.+ SIMD primops for unpacking SIMD vectors into an unboxed tuple of unboxed scalars also need to be floated inward, but unpacks have a single non-DEFAULT alternative that binds the elements of the tuple. We now therefore also support@@ -431,12 +478,11 @@ But there are wrinkles  * Which unlifted cases do we float?-  See Note [PrimOp can_fail and has_side_effects] in GHC.Builtin.PrimOps which-  explains:-   - We can float in can_fail primops (which concerns imprecise exceptions),-     but we can't float them out.-   - But we can float a has_side_effects primop, but NOT inside a lambda,-     so for now we don't float them at all. Hence exprOkForSideEffects.+  See Note [Transformations affected by primop effects] in GHC.Builtin.PrimOps+  which explains:+   - We can float in or discard CanFail primops, but we can't float them out.+   - We don't want to discard a synchronous exception or side effect+     so we don't float those at all. Hence exprOkToDiscard.    - Throwing precise exceptions is a special case of the previous point: We      may /never/ float in a call to (something that ultimately calls)      'raiseIO#'.@@ -448,7 +494,7 @@   ===>     f (case a /# b of r -> F# r)   because that creates a new thunk that wasn't there before.  And-  because it can't be floated out (can_fail), the thunk will stay+  because it can't be floated out (CanFail), the thunk will stay   there.  Disaster!  (This happened in nofib 'simple' and 'scs'.)    Solution: only float cases into the branches of other cases, and@@ -477,7 +523,7 @@ fiExpr platform to_drop (_, AnnCase scrut case_bndr _ [AnnAlt con alt_bndrs rhs])   | isUnliftedType (idType case_bndr)      -- binders have a fixed RuntimeRep so it's OK to call isUnliftedType-  , exprOkForSideEffects (deAnnotate scrut)+  , exprOkToDiscard (deAnnotate scrut)       -- See Note [Floating primops]   = wrapFloats shared_binds $     fiExpr platform (case_float : rhs_binds) rhs@@ -599,7 +645,7 @@ ------------------ fiRhs :: Platform -> RevFloatInBinds -> CoreBndr -> CoreExprWithFVs -> CoreExpr fiRhs platform to_drop bndr rhs-  | Just join_arity <- isJoinId_maybe bndr+  | JoinPoint join_arity <- idJoinPointHood bndr   , let (bndrs, body) = collectNAnnBndrs join_arity rhs   = mkLams bndrs (fiExpr platform to_drop body)   | otherwise
compiler/GHC/Core/Opt/FloatOut.hs view
@@ -22,7 +22,7 @@ import GHC.Utils.Logger import GHC.Types.Id      ( Id, idType, --                           idArity, isDeadEndId,-                           isJoinId, isJoinId_maybe )+                           isJoinId, idJoinPointHood ) import GHC.Types.Tickish import GHC.Core.Opt.SetLevels import GHC.Types.Unique.Supply ( UniqSupply )@@ -487,7 +487,7 @@          -> LevelledExpr          -> (FloatStats, FloatBinds, CoreExpr) floatRhs bndr rhs-  | Just join_arity <- isJoinId_maybe bndr+  | JoinPoint join_arity <- idJoinPointHood bndr   , Just (bndrs, body) <- try_collect join_arity rhs []   = case bndrs of       []                -> floatExpr rhs
compiler/GHC/Core/Opt/Pipeline.hs view
@@ -43,7 +43,7 @@ import GHC.Core.Opt.Exitify      ( exitifyProgram ) import GHC.Core.Opt.WorkWrap     ( wwTopBinds ) import GHC.Core.Opt.CallerCC     ( addCallerCostCentres )-import GHC.Core.LateCC           (addLateCostCentresMG)+import GHC.Core.LateCC.TopLevelBinds (topLevelBindsCCMG) import GHC.Core.Seq (seqBinds) import GHC.Core.FamInstEnv @@ -463,12 +463,17 @@   let fam_envs = (p_fam_env, mg_fam_inst_env guts)   let updateBinds  f = return $ guts { mg_binds = f (mg_binds guts) }   let updateBindsM f = f (mg_binds guts) >>= \b' -> return $ guts { mg_binds = b' }+  -- Important to force this now as name_ppr_ctx lives through an entire phase in+  -- the optimiser and if it's not forced then the entire previous `ModGuts` will+  -- be retained until the end of the phase. (See #24328 for more analysis)+  let !rdr_env = mg_rdr_env guts   let name_ppr_ctx =         mkNamePprCtx           (initPromotionTickContext dflags)           (hsc_unit_env hsc_env)-          (mg_rdr_env guts)+          rdr_env +   case pass of     CoreDoSimplify opts       -> {-# SCC "Simplify" #-}                                  liftIOWithCount $ simplifyPgm logger (hsc_unit_env hsc_env) name_ppr_ctx opts guts@@ -515,7 +520,7 @@                                  addCallerCostCentres guts      CoreAddLateCcs            -> {-# SCC "AddLateCcs" #-}-                                 addLateCostCentresMG guts+                                 topLevelBindsCCMG guts      CoreDoPrintCore           -> {-# SCC "PrintCore" #-}                                  liftIO $ printCore logger (mg_binds guts) >> return guts@@ -567,7 +572,7 @@                , dmd_max_worker_args = maxWorkerArgs dflags                }       binds_plus_dmds = dmdAnalProgram opts fam_envs rules binds-  Logger.putDumpFileMaybe logger Opt_D_dump_str_signatures "Strictness signatures" FormatText $+  Logger.putDumpFileMaybe logger Opt_D_dump_dmd_signatures "Demand signatures" FormatText $     dumpIdInfoOfProgram (hasPprDebug dflags) (ppr . zapDmdEnvSig . dmdSigInfo) binds_plus_dmds   -- See Note [Stamp out space leaks in demand analysis] in GHC.Core.Opt.DmdAnal   seqBinds binds_plus_dmds `seq` return binds_plus_dmds
compiler/GHC/Core/Opt/SetLevels.hs view
@@ -15,7 +15,7 @@    outwards (@FloatOut@).  2. We also let-ify many expressions (notably case scrutinees), so they-   will have a fighting chance of being floated sensible.+   will have a fighting chance of being floated sensibly.  3. Note [Need for cloning during float-out]    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -44,13 +44,33 @@         case x of wild { p -> ...wild... }    we substitute x for wild in the RHS of the case alternatives:         case x of wild { p -> ...x... }-   This means that a sub-expression involving x is not "trapped" inside the RHS.+   This means that a sub-expression involving x is not "trapped" inside the RHS+   (i.e. it can now be floated out, whereas if it mentioned wild it could not).    And it's not inconvenient because we already have a substitution. -  Note that this is EXACTLY BACKWARDS from the what the simplifier does.-  The simplifier tries to get rid of occurrences of x, in favour of wild,-  in the hope that there will only be one remaining occurrence of x, namely-  the scrutinee of the case, and we can inline it.+   For example, consider:++      f x = letrec go y = case x of z { (a,b) -> ...(expensive z)... }+              in ...++   If we do the reverse binder-swap we get++      f x = letrec go y = case x of z { (a,b) -> ...(expensive x)... }+              in ...++   and now we can float out:++      f x = let t = expensive x+              in letrec go y = case x of z { (a,b) -> ...(t)... }+              in ...++   Now (expensive x) is computed once, rather than once each time around the 'go' loop.++   Note that this is EXACTLY BACKWARDS from the what the simplifier does.+   The simplifier tries to get rid of occurrences of x, in favour of wild,+   in the hope that there will only be one remaining occurrence of x, namely+   the scrutinee of the case, and we can inline it.+ -}  module GHC.Core.Opt.SetLevels (@@ -67,12 +87,7 @@  import GHC.Core import GHC.Core.Opt.Monad ( FloatOutSwitches(..) )-import GHC.Core.Utils   ( exprType, exprIsHNF-                        , exprOkForSpeculation-                        , exprIsTopLevelBindable-                        , collectMakeStaticArgs-                        , mkLamTypes, extendInScopeSetBndrs-                        )+import GHC.Core.Utils import GHC.Core.Opt.Arity   ( exprBotStrictness_maybe, isOneShotBndr ) import GHC.Core.FVs     -- all of it import GHC.Core.Subst@@ -110,7 +125,6 @@ import GHC.Utils.Misc import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain  import Data.Maybe @@ -302,7 +316,7 @@ --     there is no need call substAndLvlBndrs here lvl_top env is_rec bndr rhs   = do { rhs' <- lvlRhs env is_rec (isDeadEndId bndr)-                                   Nothing  -- Not a join point+                                   NotJoinPoint                                    (freeVars rhs)        ; return (stayPut tOP_LEVEL bndr, rhs') } @@ -514,7 +528,7 @@   * The test we perform is exprIsHNF, and /not/ exprOkForSpeculation. -     - exrpIsHNF catches the key case of an evaluated variable+     - exprIsHNF catches the key case of an evaluated variable       - exprOkForSpeculation is /false/ of an evaluated variable;        See Note [exprOkForSpeculation and evaluated variables] in GHC.Core.Utils@@ -629,7 +643,8 @@   = lvlExpr env e     -- See Note [Case MFEs]  lvlMFE env strict_ctxt ann_expr-  |  floatTopLvlOnly env && not (isTopLvl dest_lvl)+  | not float_me+  || floatTopLvlOnly env && not (isTopLvl dest_lvl)          -- Only floating to the top level is allowed.   || hasFreeJoin env fvs   -- If there is a free join, don't float                            -- See Note [Free join points]@@ -638,17 +653,18 @@          -- how it will be represented at runtime.          -- See Note [Representation polymorphism invariants] in GHC.Core   || notWorthFloating expr abs_vars-  || not float_me-  =     -- Don't float it out+         -- Test notWorhtFloating last;+         -- See Note [Large free-variable sets]+  = -- Don't float it out     lvlExpr env ann_expr    |  float_is_new_lam || exprIsTopLevelBindable expr expr_ty          -- No wrapping needed if the type is lifted, or is a literal string          -- or if we are wrapping it in one or more value lambdas   = do { expr1 <- lvlFloatRhs abs_vars dest_lvl rhs_env NonRecursive-                              is_bot_lam join_arity_maybe ann_expr+                              is_bot_lam NotJoinPoint ann_expr                   -- Treat the expr just like a right-hand side-       ; var <- newLvlVar expr1 join_arity_maybe is_mk_static+       ; var <- newLvlVar expr1 NotJoinPoint is_mk_static        ; let var2 = annotateBotStr var float_n_lams mb_bot_str        ; return (Let (NonRec (TB var2 (FloatMe dest_lvl)) expr1)                      (mkVarApps (Var var2) abs_vars)) }@@ -669,7 +685,7 @@                          Case expr1 (stayPut l1r ubx_bndr) box_ty                              [Alt DEFAULT [] (App boxing_expr (Var ubx_bndr))] -       ; var <- newLvlVar float_rhs Nothing is_mk_static+       ; var <- newLvlVar float_rhs NotJoinPoint is_mk_static        ; let l1u      = incMinorLvlFrom env              use_expr = Case (mkVarApps (Var var) abs_vars)                              (stayPut l1u bx_bndr) expr_ty@@ -706,8 +722,6 @@      (rhs_env, abs_vars_w_lvls) = lvlLamBndrs env dest_lvl abs_vars -    join_arity_maybe = Nothing-     is_mk_static = isJust (collectMakeStaticArgs expr)         -- Yuk: See Note [Grand plan for static forms] in GHC.Iface.Tidy.StaticPtrTable @@ -810,6 +824,28 @@ important in some nofib programs (gcd is an example).  [SPJ note: I think this is obsolete; the flag seems always on.] +Note [Large free-variable sets]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+In #24471 we had something like+     x1 = I# 1+     ...+     x1000 = I# 1000+     foo = f x1 (f x2 (f x3 ....))+So every sub-expression in `foo` has lots and lots of free variables.  But+none of these sub-expressions float anywhere; the entire float-out pass is a+no-op.++In lvlMFE, we want to find out quickly if the MFE is not-floatable; that is+the common case.  In #24471 it turned out that we were testing `abs_vars` (a+relatively complicated calculation that takes at least O(n-free-vars) time to+compute) for every sub-expression.++Better instead to test `float_me` early. That still involves looking at+dest_lvl, which means looking at every free variable, but the constant factor+is a lot better.++ToDo: find a way to fix the bad asymptotic complexity.+ Note [Floating join point bindings] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Mostly we only float a join point if it can /stay/ a join point.  But@@ -1028,25 +1064,25 @@ notWorthFloating e abs_vars   = go e (count isId abs_vars)   where-    go (Var {}) n    = n >= 0-    go (Lit lit) n   = assert (n==0) $-                       litIsTrivial lit   -- Note [Floating literals]-    go (Tick t e) n  = not (tickishIsCode t) && go e n-    go (Cast e _)  n = go e n+    go (Var {}) n               = n >= 0+    go (Lit lit) n              = assert (n==0) $+                                  litIsTrivial lit   -- Note [Floating literals]+    go (Type {}) _              = True+    go (Coercion {}) _          = True     go (App e arg) n        -- See Note [Floating applications to coercions]-       | Type {} <- arg = go e n-       | n==0           = False-       | is_triv arg    = go e (n-1)-       | otherwise      = False-    go _ _              = False--    is_triv (Lit {})              = True        -- Treat all literals as trivial-    is_triv (Var {})              = True        -- (ie not worth floating)-    is_triv (Cast e _)            = is_triv e-    is_triv (App e (Type {}))     = is_triv e   -- See Note [Floating applications to coercions]-    is_triv (Tick t e)            = not (tickishIsCode t) && is_triv e-    is_triv _                     = False+       | not (isRuntimeArg arg) = go e n+       | n==0                   = False+       | exprIsTrivial arg      = go e (n-1) -- NB: exprIsTrivial arg = go arg 0+       | otherwise              = False+    go (Tick t e) n             = not (tickishIsCode t) && go e n+    go (Cast e _)  n            = go e n+    go (Case e b _ as) n+      | null as+      = go e n     -- See Note [Empty case is trivial]+      | Just rhs <- isUnsafeEqualityCase e b as+      = go rhs n   -- See (U2) of Note [Implementing unsafeCoerce] in base:Unsafe.Coerce+    go _ _                      = False  {- Note [Floating literals]@@ -1157,8 +1193,8 @@         -- NB: not isBottomThunk!  See Note [Bottoming floats] point (3)      n_extra    = count isId abs_vars-    mb_join_arity = isJoinId_maybe bndr-    is_join       = isJust mb_join_arity+    mb_join_arity = idJoinPointHood bndr+    is_join       = isJoinPoint mb_join_arity  lvlBind env (AnnRec pairs)   |  floatTopLvlOnly env && not (isTopLvl dest_lvl)@@ -1173,7 +1209,7 @@   =    -- No float     do { let bind_lvl       = incMinorLvl (le_ctxt_lvl env)              (env', bndrs') = substAndLvlBndrs Recursive env bind_lvl bndrs-             lvl_rhs (b,r)  = lvlRhs env' Recursive is_bot (isJoinId_maybe b) r+             lvl_rhs (b,r)  = lvlRhs env' Recursive is_bot (idJoinPointHood b) r        ; rhss' <- mapM lvl_rhs pairs        ; return (Rec (bndrs' `zip` rhss'), env') } @@ -1236,8 +1272,8 @@                                         is_bot (get_join bndr)                                         rhs -    get_join bndr | need_zap  = Nothing-                  | otherwise = isJoinId_maybe bndr+    get_join bndr | need_zap  = NotJoinPoint+                  | otherwise = idJoinPointHood bndr     need_zap = dest_lvl `ltLvl` joinCeilingLevel env          -- Finding the free vars of the binding group is annoying@@ -1264,7 +1300,7 @@ lvlRhs :: LevelEnv        -> RecFlag        -> Bool               -- Is this a bottoming function-       -> Maybe JoinArity+       -> JoinPointHood        -> CoreExprWithFVs        -> LvlM LevelledExpr lvlRhs env rec_flag is_bot mb_join_arity expr@@ -1273,7 +1309,7 @@  lvlFloatRhs :: [OutVar] -> Level -> LevelEnv -> RecFlag             -> Bool   -- Binding is for a bottoming function-            -> Maybe JoinArity+            -> JoinPointHood             -> CoreExprWithFVs             -> LvlM (Expr LevelledBndr) -- Ignores the le_ctxt_lvl in env; treats dest_lvl as the baseline@@ -1284,13 +1320,13 @@                   else lvlExpr body_env      body        ; return (mkLams bndrs' body') }   where-    (bndrs, body)     | Just join_arity <- mb_join_arity+    (bndrs, body)     | JoinPoint join_arity <- mb_join_arity                       = collectNAnnBndrs join_arity rhs                       | otherwise                       = collectAnnBndrs rhs     (env1, bndrs1)    = substBndrsSL NonRecursive env bndrs     all_bndrs         = abs_vars ++ bndrs1-    (body_env, bndrs') | Just _ <- mb_join_arity+    (body_env, bndrs') | JoinPoint {} <- mb_join_arity                       = lvlJoinBndrs env1 dest_lvl rec all_bndrs                       | otherwise                       = case lvlLamBndrs env1 dest_lvl all_bndrs of@@ -1721,14 +1757,14 @@     -- but we may need to adjust its arity     dest_is_top = isTopLvl dest_lvl     transfer_join_info bndr new_bndr-      | Just join_arity <- isJoinId_maybe bndr+      | JoinPoint join_arity <- idJoinPointHood bndr       , not dest_is_top       = new_bndr `asJoinId` join_arity + length abs_vars       | otherwise       = new_bndr  newLvlVar :: LevelledExpr        -- The RHS of the new binding-          -> Maybe JoinArity     -- Its join arity, if it is a join point+          -> JoinPointHood       -- Its join arity, if it is a join point           -> Bool                -- True <=> the RHS looks like (makeStatic ...)           -> LvlM Id newLvlVar lvld_rhs join_arity_maybe is_mk_static
compiler/GHC/Core/Opt/SpecConstr.hs view
@@ -67,12 +67,10 @@ import GHC.Types.Unique( hasKey )  import GHC.Data.Maybe     ( orElse, catMaybes, isJust, isNothing )-import GHC.Data.Pair import GHC.Data.FastString  import GHC.Utils.Misc import GHC.Utils.Outputable-import GHC.Utils.Panic.Plain import GHC.Utils.Panic import GHC.Utils.Constants (debugIsOn) import GHC.Utils.Monad@@ -82,8 +80,8 @@ import GHC.Exts( SpecConstrAnnotation(..) ) import GHC.Serialized   ( deserializeWithData ) -import Control.Monad    ( zipWithM )-import Data.List (nubBy, sortBy, partition, dropWhileEnd, mapAccumL )+import Control.Monad+import Data.List ( sortBy, partition, dropWhileEnd, mapAccumL ) import Data.Maybe( mapMaybe ) import Data.Ord( comparing ) import Data.Tuple@@ -520,14 +518,17 @@ ForceSpecConstr arguments are spotted in scExpr' and scTopBinds which then set sc_force to True when calling specLoop. This flag does four things: -  * Ignore specConstrThreshold, to specialise functions of arbitrary size+(FS1) Ignore specConstrThreshold, to specialise functions of arbitrary size         (see scTopBind)-  * Ignore specConstrCount, to make arbitrary numbers of specialisations+(FS2) Ignore specConstrCount, to make arbitrary numbers of specialisations         (see specialise)-  * Specialise even for arguments that are not scrutinised in the loop+(FS3) Specialise even for arguments that are not scrutinised in the loop         (see argToPat; #4448)-  * Only specialise on recursive types a finite number of times-        (see is_too_recursive; #5550; Note [Limit recursive specialisation])+(FS4) Only specialise on recursive types a finite number of times+        (see sc_recursive; #5550; Note [Limit recursive specialisation])+(FS5) Lift the restriction on the maximum number of arguments which+        the optimisation will specialise.+        (see `too_many_worker_args` in `callsToNewPats`; #14003)  The flag holds only for specialising a single binding group, and NOT for nested bindings.  (So really it should be passed around explicitly@@ -788,48 +789,71 @@ *                                                                      * ************************************************************************ -Note [Work-free values only in environment]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-The sc_vals field keeps track of in-scope value bindings, so-that if we come across (case x of Just y ->...) we can reduce the-case from knowing that x is bound to a pair.+Note [ConVal work-free-ness]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~+The sc_vals field keeps track of in-scope value bindings, and is used in+two ways: -But only *work-free* values are ok here. For example if the envt had-    x -> Just (expensive v)-then we do NOT want to expand to-     let y = expensive v in ...-because the x-binding still exists and we've now duplicated (expensive v).+(1) To do case-of-known-constructor in a case expression.  E.g. if sc_vals+    includes [x :-> ConVal Just e], then we can simplify+      case x of Just y -> ...+    with the case-of-known-constructor transformation. (Yes this is+    done by the Simplifier, but SpecConstr creates new opportunities when+    it makes a specialised RHS for a function.) -This seldom happens because let-bound constructor applications are-ANF-ised, but it can happen as a result of on-the-fly transformations in-SpecConstr itself.  Here is #7865:+    For (1) it is crucial that the arguments are /work-free/; see (CV1)+    below. -        let {-          a'_shr =-            case xs_af8 of _ {-              [] -> acc_af6;-              : ds_dgt [Dmd=<L,A>] ds_dgu [Dmd=<L,A>] ->-                (expensive x_af7, x_af7-            } } in-        let {-          ds_sht =-            case a'_shr of _ { (p'_afd, q'_afe) ->-            TSpecConstr_DoubleInline.recursive-              (GHC.Types.: @ GHC.Types.Int x_af7 wild_X6) (q'_afe, p'_afd)-            } } in+(2) To figure out call pattresns. E.g. if sc_vals includes+    [x :-> ConVal Just e], and we have call (f x), then we might want+    to specialise `f (Just _)` -When processed knowing that xs_af8 was bound to a cons, we simplify to-   a'_shr = (expensive x_af7, x_af7)-and we do NOT want to inline that at the occurrence of a'_shr in ds_sht.-(There are other occurrences of a'_shr.)  No no no.+    For (2) it is /not/ important that the constructor arguments are work-free;+    indeed, it would be bad to insist on that. For example+       let x = Just <expensive>+       in ....(f x)...+    Here we want to specialise for `f (Just _)`, and we won't do so if we+    don't allow [x :-> ConVal Just e] into the environment.  Does this ever happen?+    Yes: see #24282. -It would be possible to do some on-the-fly ANF-ising, so that a'_shr turned-into a work-free value again, thus-   a1 = expensive x_af7-   a'_shr = (a1, x_af7)-but that's more work, so until its shown to be important I'm going to-leave it for now.+    (Yes, the Simplifier will ANF that let-binding, but SpecConstr can+    make more: see (CV1) for an example.) +Wrinkle:++(CV1) Why is work-free-ness important for (1)?  In the example in (1) above, of `e` is+      expensive, we do /not/ want to simplify+         case x of { Just y -> ... }  ==>   let y = e in ...+      because the x-binding still exists and we've now duplicated `e`.++      This seldom happens because let-bound constructor applications are ANF-ised, but+      it can happen as a result of on-the-fly transformations in SpecConstr itself.+      Here is #7865:++              let { a'_shr =+                      case xs_af8 of _ {+                        [] -> acc_af6;+                        : ds_dgt [Dmd=<L,A>] ds_dgu [Dmd=<L,A>] ->+                          (expensive x_af7, x_af7+                      } } in+              let { ds_sht =+                      case a'_shr of _ { (p'_afd, q'_afe) ->+                      TSpecConstr_DoubleInline.recursive+                        (GHC.Types.: @ GHC.Types.Int x_af7 wild_X6) (q'_afe, p'_afd)+                      } } in++      When processed knowing that xs_af8 was bound to a cons, we simplify to+         a'_shr = (expensive x_af7, x_af7)+      and we do NOT want to inline that at the occurrence of a'_shr in ds_sht.+      (There are other occurrences of a'_shr.)  No no no.++      It would be possible to do some on-the-fly ANF-ising, so that a'_shr turned+      into a work-free value again, thus+         a1 = expensive x_af7+         a'_shr = (a1, x_af7)+      but that's more work, so until its shown to be important I'm going to+      leave it for now.+ Note [Making SpecConstr keener] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Consider this, in (perf/should_run/T9339)@@ -909,10 +933,6 @@                    sc_vals      :: ValueEnv,                         -- Domain is OutIds (*after* applying the substitution)                         -- Used even for top-level bindings (but not imported ones)-                        -- The range of the ValueEnv is *work-free* values-                        -- such as (\x. blah), or (Just v)-                        -- but NOT (Just (expensive v))-                        -- See Note [Work-free values only in environment]                     sc_annotations :: UniqFM Name SpecConstrAnnotation              }@@ -921,15 +941,23 @@ type HowBoundEnv = VarEnv HowBound      -- Domain is OutVars  ----------------------type ValueEnv = IdEnv Value             -- Domain is OutIds-data Value    = ConVal AltCon [CoreArg] -- _Saturated_ constructors-                                        --   The AltCon is never DEFAULT-              | LambdaVal               -- Inlinable lambdas or PAPs+type ValueEnv = IdEnv Value            -- Domain is OutIds +data Value = ConVal            -- Constructor application+                  Bool             -- True <=> all args are work-free+                                   --      See Note [ConVal work-free-ness]+                  AltCon           -- Never DEFAULT+                  [CoreArg]        -- Saturates the constructor+           | LambdaVal         -- Inlinable lambdas or PAPs+ instance Outputable Value where-   ppr (ConVal con args) = ppr con <+> interpp'SP args-   ppr LambdaVal         = text "<Lambda>"+   ppr LambdaVal            = text "<Lambda>"+   ppr (ConVal wf con args) = ppr con <> braces pp_wf <+> interpp'SP args+     where+       pp_wf | wf        = text "wf"+             | otherwise = text "not-wf" + --------------------- initScOpts :: DynFlags -> Module -> SpecConstrOpts initScOpts dflags this_mod = SpecConstrOpts@@ -1057,11 +1085,10 @@                        (subst', bndr') = substBndr (sc_subst env) bndr  extendValEnv :: ScEnv -> Id -> Maybe Value -> ScEnv-extendValEnv env _  Nothing   = env-extendValEnv env id (Just cv)- | valueIsWorkFree cv      -- Don't duplicate work!!  #7865- = env { sc_vals = extendVarEnv (sc_vals env) id cv }-extendValEnv env _ _ = env+extendValEnv env id mb_val+  = case mb_val of+      Nothing -> env+      Just cv -> env { sc_vals = extendVarEnv (sc_vals env) id cv }  extendCaseBndrs :: ScEnv -> OutExpr -> OutId -> AltCon -> [Var] -> (ScEnv, [Var]) -- When we encounter@@ -1088,8 +1115,8 @@     cval = case con of                 DEFAULT    -> Nothing-                LitAlt {}  -> Just (ConVal con [])-                DataAlt {} -> Just (ConVal con vanilla_args)+                LitAlt {}  -> Just (ConVal True con [])+                DataAlt {} -> Just (ConVal True con vanilla_args)                       where                         vanilla_args = map Type (tyConAppArgs (idType case_bndr)) ++                                        varsToCoreExprs alt_bndrs@@ -1275,7 +1302,7 @@ deadArgOcc NoOcc         = True  specialisableArgOcc :: ArgOcc -> Bool--- | Does this occurence represent one worth specializing for.+-- | Does this occurrence represent one worth specializing for. specialisableArgOcc UnkOcc        = False specialisableArgOcc NoOcc         = False specialisableArgOcc (ScrutOcc {}) = True@@ -1404,7 +1431,7 @@ scBind top_lvl env (Rec prs) do_body   | isTopLevel top_lvl   , Just threshold <- sc_size (sc_opts env)-  , not force_spec+  , not force_spec -- See Note [Forcing specialisation], point (FS1)   , not (all (couldBeSmallEnoughToInline (sc_uf_opts (sc_opts env)) threshold) rhss)   = -- Do no specialisation if the RHSs are too big     -- ToDo: I'm honestly not sure of the rationale of this size-testing, nor@@ -1496,8 +1523,11 @@ scExpr' env (Case scrut b ty alts)   = do  { (scrut_usg, scrut') <- scExpr env scrut         ; case isValue (sc_vals env) scrut' of-                Just (ConVal con args) -> sc_con_app con args scrut'-                _other                 -> sc_vanilla scrut_usg scrut'+                Just (ConVal args_are_work_free con args)+                   | args_are_work_free -> sc_con_app con args scrut'+                     -- Don't duplicate work!!  #7865+                     -- See Note [ConVal work-free-ness] (1)+                _other -> sc_vanilla scrut_usg scrut'         }   where     sc_con_app con args scrut'  -- Known constructor; simplify@@ -1767,6 +1797,7 @@       , sc_force env || isNothing (sc_count opts)            -- If both of these are false, the sc_count            -- threshold will prevent non-termination+           -- See Note [Forcing specialisation], point (FS4) and (FS2)       , any ((> the_limit) . si_n_specs) spec_infos       = -- Give up on specialisation, but don't forget to include the rhs_usg         -- for the unspecialised function, since it may now be called@@ -1934,8 +1965,8 @@                   = calcSpecInfo fn arg_bndrs call_pat extra_bndrs                spec_arity = count isId spec_lam_args-              spec_join_arity | isJoinId fn = Just (length spec_call_args)-                              | otherwise   = Nothing+              spec_join_arity | isJoinId fn = JoinPoint (length spec_call_args)+                              | otherwise   = NotJoinPoint               spec_id    = asWorkerLikeId $                            mkLocalId spec_name ManyTy                                      (mkLamTypes spec_lam_args spec_body_ty)@@ -1946,6 +1977,7 @@                              `asJoinId_maybe` spec_join_arity          -- Conditionally use result of new worker-wrapper transform+        -- mkSeqs: see Note [SpecConstr and strict fields]               spec_rhs = mkLams spec_lam_args (mkSeqs cbv_args spec_body_ty spec_body)               rule_rhs = mkVarApps (Var spec_id) spec_call_args               inline_act = idInlineActivation fn@@ -2243,7 +2275,7 @@  * The list of argument patterns, cp_args, is no longer than the   visible lambdas of the binding, ri_arg_occs.  This is done via-  the zipWithM in callToPats.+  the zipWithM in callToPat.  * The list of argument patterns can certainly be shorter than the   lambdas in the function definition (under-saturated).  For example@@ -2253,7 +2285,7 @@  * In fact we deliberately shrink the list of argument patterns,   cp_args, by trimming off all the boring ones at the end (see-  `dropWhileEnd is_boring` in callToPats).  Since the RULE only+  `dropWhileEnd is_boring` in callToPat).  Since the RULE only   applies when it is saturated, this shrinking makes the RULE more   applicable.  But it does mean that the argument patterns do not   necessarily saturate the lambdas of the function.@@ -2296,68 +2328,55 @@ Consider (#14270) a call like      let f = e-    in ... f (K @(a |> co)) ...+    in ... f (K @(a |> cv)) ... -where 'co' is a coercion variable not in scope at f's definition site.+where 'cv' is a coercion variable not in scope at f's definition site. If we aren't careful we'll get -    let $sf a co = e (K @(a |> co))-        RULE "SC:f" forall a co.  f (K @(a |> co)) = $sf a co+    let $sf a cv = e (K @(a |> cv))+        RULE "SC:f" forall a cv.  f (K @(a |> cv)) = $sf a co         f = e     in ... -But alas, when we match the call we won't bind 'co', because type-matching-(for good reasons) discards casts).--I don't know how to solve this, so for now I'm just discarding any-call patterns that-  * Mentions a coercion variable in a type argument-  * That is not in scope at the binding of the function--I think this is very rare.+But alas, when we match the call we may fail to bind 'co', because the rule+matcher in GHC.Core.Rules cannot reliably bind coercion variables that appear+in casts (see Note [Casts in the template] in GHC.Core.Rules). -It is important (e.g. #14936) that this /only/ applies to-coercions mentioned in casts.  We don't want to be discombobulated-by casts in terms!  For example, consider-   f ((e1,e2) |> sym co)-where, say,-   f  :: Foo -> blah-   co :: Foo ~R (Int,Int)+This seems intractable (see #23209). So: -Here we definitely do want to specialise for that pair!  We do not-match on the structure of the coercion; instead we just match on a-coercion variable, so the RULE looks like+* Key point: we /never/ quantify over coercion variables in a SpecConstr rule.+  If we would need to quantify over a coercion variable, we just discard the+  call pattern. See the test for `bad_covars` in callToPat. -   forall (x::Int, y::Int, co :: (Int,Int) ~R Foo)-     f ((x,y) |> co) = $sf x y co+* However (#14936) we /do/ still allow casts in call patterns. For example+     f ((e1,e2) |> sym co)+  where, say,+     f  :: Foo -> blah   -- Foo is a newtype+     f = f_rhs+     co :: Foo ~R (Int,Int)+  We want to specialise on that pair! -Often the body of f looks like-   f arg = ...(case arg |> co' of-                (x,y) -> blah)...+So for our function f, we might generate+  RULE forall x y.  f ((x,y) |> co) = $sf x y+  $sf x y = f_rhs ((x,y) |> co) -so that the specialised f will turn into-   $sf x y co = let arg = (x,y) |> co-                in ...(case arg>| co' of-                         (x,y) -> blah)....+This works provided the free vars of `co` are either in-scope at the+definition of `f`, or quantified. For the latter, suppose `f` was polymorphic: -which will simplify to not use 'co' at all.  But we can't guarantee-that co will end up unused, so we still pass it.  Absence analysis-may remove it later.+     f2  :: Foo2 a -> blah   -- Foo is a newtype+     f2 = f2_rhs+     co2 :: Foo a ~R (a,a) -Note that this /also/ discards the call pattern if we have a cast in a-/term/, although in fact Rules.match does make a very flaky and-fragile attempt to match coercions.  e.g. a call like-    f (Maybe Age) (Nothing |> co) blah-    where co :: Maybe Int ~ Maybe Age-will be discarded.  It's extremely fragile to match on the form of a-coercion, so I think it's better just not to try.  A more complicated-alternative would be to discard calls that mention coercion variables-only in kind-casts, but I'm doing the simple thing for now.+Then it's fine for `co2` to mention `a`.  We'll get+  RULE forall a (x::a) (y::a).  f2 @a ((x,y) |> co2) = $sf2 a x y+  $sf2 @a x y = f2_rhs ((x,y) |> co2) -}  data CallPat = CP { cp_qvars :: [Var]           -- Quantified variables                   , cp_args  :: [CoreExpr]      -- Arguments                   , cp_strict_args :: [Var] }   -- Arguments we want to pass unlifted even if they are boxed+                                                -- See Note [SpecConstr and strict fields]+      -- See Note [SpecConstr call patterns]  instance Outputable CallPat where@@ -2378,23 +2397,30 @@ -- The "New" in the name means "patterns that are not already covered -- by an existing specialisation" callsToNewPats env fn spec_info@(SI { si_specs = done_specs }) bndr_occs calls-  = do  { mb_pats <- mapM (callToPats env bndr_occs) calls+  = do  { mb_pats <- mapM (callToPat env bndr_occs) calls          ; let have_boring_call = any isNothing mb_pats                good_pats :: [CallPat]               good_pats = catMaybes mb_pats +              in_scope = getSubstInScope (sc_subst env)+               -- Remove patterns we have already done               new_pats = filterOut is_done good_pats-              is_done p = any (samePat p . os_pat) done_specs+              is_done p = any is_better done_specs+                 where+                   is_better done = betterPat in_scope (os_pat done) p                -- Remove duplicates-              non_dups = nubBy samePat new_pats+              non_dups = subsumePats in_scope new_pats                -- Remove ones that have too many worker variables-              small_pats = filterOut too_big non_dups-              too_big (CP { cp_qvars = vars, cp_args = args })+              small_pats = filterOut too_many_worker_args non_dups++              too_many_worker_args _+                | sc_force env = False -- See (FS5) of Note [Forcing specialisation]+              too_many_worker_args (CP { cp_qvars = vars, cp_args = args })                 = not (isWorkerSmallEnough (sc_max_args $ sc_opts env) (valArgCount args) vars)                   -- We are about to construct w/w pair in 'spec_one'.                   -- Omit specialisation leading to high arity workers.@@ -2404,6 +2430,10 @@               (pats_were_discarded, trimmed_pats) = trim_pats env fn spec_info small_pats  --        ; pprTraceM "callsToPats" (vcat [ text "calls to" <+> ppr fn <> colon <+> ppr calls+--                                        , text "good_pats:" <+> ppr good_pats+--                                        , text "new_pats:" <+> ppr new_pats+--                                        , text "non_dups:" <+> ppr non_dups+--                                        , text "small_pats:" <+> ppr small_pats --                                        , text "done_specs:" <+> ppr (map os_pat done_specs) --                                        , text "trimmed_pats:" <+> ppr trimmed_pats ]) @@ -2471,12 +2501,12 @@                , text "Discarding:" <+> ppr (drop n_remaining sorted_pats) ]  -callToPats :: ScEnv -> [ArgOcc] -> Call -> UniqSM (Maybe CallPat)+callToPat :: ScEnv -> [ArgOcc] -> Call -> UniqSM (Maybe CallPat)         -- The [Var] is the variables to quantify over in the rule         --      Type variables come first, since they may scope         --      over the following term variables         -- The [CoreExpr] are the argument patterns for the rule-callToPats env bndr_occs call@(Call fn args con_env)+callToPat env bndr_occs call@(Call fn args con_env)   = do  { let in_scope = getSubstInScope (sc_subst env)          ; arg_tripples <- zipWith3M (argToPat env in_scope con_env) args bndr_occs (map (const NotMarkedStrict) args)@@ -2507,32 +2537,25 @@                 -- See Note [Free type variables of the qvar types]                 -- See Note [Shadowing in SpecConstr] at the top -              (ktvs, ids)   = partition isTyVar qvars-              qvars'        = scopedSort ktvs ++ map sanitise ids+              (qktvs, qids) = partition isTyVar qvars+              qvars'        = scopedSort qktvs ++ map sanitise qids                 -- Order into kind variables, type variables, term variables                 -- The kind of a type variable may mention a kind variable                 -- and the type of a term variable may mention a type variable -              sanitise id   = updateIdTypeAndMult expandTypeSynonyms id+              sanitise id = updateIdTypeAndMult expandTypeSynonyms id                 -- See Note [Free type variables of the qvar types] -         -- Check for bad coercion variables: see Note [SpecConstr and casts]-        ; let bad_covars :: CoVarSet-              bad_covars = mapUnionVarSet get_bad_covars pats-              get_bad_covars :: CoreArg -> CoVarSet-              get_bad_covars (Type ty) = filterVarSet bad_covar (tyCoVarsOfType ty)-              get_bad_covars _         = emptyVarSet-              bad_covar v = isId v && not (is_in_scope v)--        ; warnPprTrace (not (isEmptyVarSet bad_covars))+        ; let bad_covars = filter isCoVar qids+        ; warnPprTrace (not (null bad_covars))               "SpecConstr: bad covars"               (ppr bad_covars $$ ppr call) $ -          if interesting && isEmptyVarSet bad_covars+          if interesting && null bad_covars           then do { let cp_res = CP { cp_qvars = qvars', cp_args = pats                                     , cp_strict_args = concat cbv_ids }---                  ; pprTraceM "callToPatsOut" $+--                  ; pprTraceM "callToPatOut" $ --                    vcat [ text "fn:" <+> ppr fn --                         , text "args:" <+> ppr args --                         , text "bndr_occs:" <+> ppr bndr_occs@@ -2600,44 +2623,22 @@         -- Here we can specialise for f (v,w)         -- because the rule-matcher will look through the let. -{- Disabled; see Note [Matching cases] in "GHC.Core.Rules"-argToPat env in_scope val_env (Case scrut _ _ [(_, _, rhs)]) arg_occ-  | exprOkForSpeculation scrut  -- See Note [Matching cases] in "GHC.Core.Rules"-  = argToPat env in_scope val_env rhs arg_occ--}-+   -- Casts: see Note [SpecConstr and casts] argToPat1 env in_scope val_env (Cast arg co) arg_occ arg_str   | not (ignoreType env ty2)   = do  { (interesting, arg', strict_args) <- argToPat env in_scope val_env arg arg_occ arg_str         ; if not interesting then                 wildCardPat ty2 arg_str-          else do-        { -- Make a wild-card pattern for the coercion-          uniq <- getUniqueM-        ; let co_name = mkSysTvName uniq (fsLit "sg")-              co_var  = mkCoVar co_name (mkCoercionType Representational ty1 ty2)-        ; return (interesting, Cast arg' (mkCoVarCo co_var), strict_args) } }-  where-    Pair ty1 ty2 = coercionKind co----{-      Disabling lambda specialisation for now-        It's fragile, and the spec_loop can be infinite-argToPat in_scope val_env arg arg_occ-  | is_value_lam arg-  = return (True, arg)+          else+                return (interesting, Cast arg' co, strict_args) }   where-    is_value_lam (Lam v e)         -- Spot a value lambda, even if-        | isId v       = True      -- it is inside a type lambda-        | otherwise    = is_value_lam e-    is_value_lam other = False--}+    ty2 = coercionRKind co    -- Check for a constructor application   -- NB: this *precedes* the Var case, so that we catch nullary constrs argToPat1 env in_scope val_env arg arg_occ _arg_str-  | Just (ConVal (DataAlt dc) args) <- isValue val_env arg+  | Just (ConVal _wf (DataAlt dc) args) <- isValue val_env arg+    -- Ignore `_wf` here; see Note [ConVal work-free-ness] (2)   , not (ignoreDataCon env dc)        -- See Note [NoSpecConstr]   , Just arg_occs <- mb_scrut dc   = do { let (ty_args, rest_args) = splitAtList (dataConUnivTyVars dc) args@@ -2687,6 +2688,7 @@   -- In that case it counts as "interesting" argToPat1 env in_scope val_env (Var v) arg_occ arg_str   | sc_force env || specialisableArgOcc arg_occ  -- (a)+    -- See Note [Forcing specialisation], point (FS3)   , is_value                                     -- (b)        -- Ignoring sc_keen here to avoid gratuitously incurring Note [Reboxing]        -- So sc_keen focused just on f (I# x), where we have freshly-allocated@@ -2720,6 +2722,25 @@         --       f x y = letrec g z = ... in g (x,y)         -- We don't want to specialise for that *particular* x,y ++{- Disabled; see Note [Matching cases] in "GHC.Core.Rules"+argToPat env in_scope val_env (Case scrut _ _ [(_, _, rhs)]) arg_occ+  | exprOkForSpeculation scrut  -- See Note [Matching cases] in "GHC.Core.Rules"+  = argToPat env in_scope val_env rhs arg_occ+-}++{-      Disabling lambda specialisation for now+        It's fragile, and the spec_loop can be infinite+argToPat in_scope val_env arg arg_occ+  | is_value_lam arg+  = return (True, arg)+  where+    is_value_lam (Lam v e)         -- Spot a value lambda, even if+        | isId v       = True      -- it is inside a type lambda+        | otherwise    = is_value_lam e+    is_value_lam other = False+-}+   -- The default case: make a wild-card   -- We use this for coercions too argToPat1 _env _in_scope _val_env arg _arg_occ arg_str@@ -2735,7 +2756,7 @@ isValue :: ValueEnv -> CoreExpr -> Maybe Value isValue _env (Lit lit)   | litIsLifted lit = Nothing-  | otherwise       = Just (ConVal (LitAlt lit) [])+  | otherwise       = Just (ConVal True (LitAlt lit) [])  isValue env (Var v)   | Just cval <- lookupVarEnv env v@@ -2766,7 +2787,7 @@         DataConWorkId con | args `lengthAtLeast` dataConRepArity con                 -- Check saturated; might be > because the                 --                  arity excludes type args-                -> Just (ConVal (DataAlt con) args)+                -> Just (ConVal (all exprIsWorkFree args) (DataAlt con) args)          DFunId {} -> Just LambdaVal         -- DFunId: see Note [Specialising on dictionaries]@@ -2779,44 +2800,82 @@  isValue _env _expr = Nothing -valueIsWorkFree :: Value -> Bool-valueIsWorkFree LambdaVal       = True-valueIsWorkFree (ConVal _ args) = all exprIsWorkFree args+betterPat :: InScopeSet -> CallPat -> CallPat -> Bool+-- pat1    f @a   (Just @a   (x::a))+--      is better than+-- pat2    f @Int (Just @Int (x::Int))+-- That is, we can instantiate pat1 to get pat2, using only type instantiate+-- See Note [Pattern duplicate elimination]+betterPat is (CP { cp_qvars = vs1, cp_args = as1 })+             (CP { cp_qvars = vs2, cp_args = as2 })+  | equalLength as1 as2+  = case matchExprs ise vs1 as1 as2 of+      Just (_, ms) -> all exprIsTrivial ms+      Nothing      -> False -samePat :: CallPat -> CallPat -> Bool-samePat (CP { cp_qvars = vs1, cp_args = as1 })-        (CP { cp_qvars = vs2, cp_args = as2 })-  = all2 same as1 as2+  | otherwise -- We must handle patterns of unequal length separately (#24282)+  = False  -- For the pattern with more args, the last arg is "interesting"+           -- but the corresponding one on the other is "not interesting";+           -- So we can't get from one to the other with only exprIsTrivial+           -- instantiation.  Example nofib/spectral/ansi, function `loop`:+           --    P1: loop (I# x) (a : b)+           --    P2: loop (I# y)           -- Pattern eta-reduced+           -- Neither is better than the other, in the sense of betterPat   where-    -- If the args are the same, their strictness marks will be too so we don't compare those.-    same (Var v1) (Var v2)-        | v1 `elem` vs1 = v2 `elem` vs2-        | v2 `elem` vs2 = False-        | otherwise     = v1 == v2+    ise = ISE (is `extendInScopeSetList` vs2) (const noUnfolding) -    same (Lit l1)    (Lit l2)    = l1==l2-    same (App f1 a1) (App f2 a2) = same f1 f2 && same a1 a2+subsumePats :: InScopeSet -> [CallPat] -> [CallPat]+-- Remove any patterns subsumed by others+-- See Note [Pattern duplicate elimination]+-- Other than deleting subsumed patterns, this operation is a no-op;+-- in particular it does not reverse the input.  It should not matter+-- but in #24282 it did; doing it this way keeps the existing behaviour.+subsumePats is pats = foldl add [] pats+  where+    add :: [CallPat] -> CallPat -> [CallPat]+    add []        ci                         = [ci]+    add (ci1:cis) ci2 | betterPat is ci1 ci2 = ci1 : cis+                      | betterPat is ci2 ci1 = ci2 : cis+                      | otherwise            = ci1 : add cis ci2 -    same (Type {}) (Type {}) = True     -- Note [Ignore type differences]-    same (Coercion {}) (Coercion {}) = True-    same (Tick _ e1) e2 = same e1 e2  -- Ignore casts and notes-    same (Cast e1 _) e2 = same e1 e2-    same e1 (Tick _ e2) = same e1 e2-    same e1 (Cast e2 _) = same e1 e2+{-+Note [Pattern duplicate elimination]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider f :: (a,a) -> blah, and two calls+   f @Int  (x,y)+   f @Bool (p,q) -    same e1 e2 = warnPprTrace (bad e1 || bad e2) "samePat" (ppr e1 $$ ppr e2) $-                 False  -- Let, lambda, case should not occur-    bad (Case {}) = True-    bad (Let {})  = True-    bad (Lam {})  = True-    bad _other    = False+The danger is that we'll generate two *essentially identical* specialisations,+both for pairs, but with different types instantiating `a` (see #24229). -{--Note [Ignore type differences]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We do not want to generate specialisations where the call patterns-differ only in their type arguments!  Not only is it utterly useless,-but it also means that (with polymorphic recursion) we can generate-an infinite number of specialisations. Example is Data.Sequence.adjustTree,-I think.+But we'll only make a `CallPat` for an argument (a,b) if `foo` scrutinises+that argument.  So SpecConstr should never need to specialise f's polymorphic+type arguments.  Even with only one of these calls we should be able to+generalise to the `CallPat`++  cp_qvars = [a, r::a, s::a], cp_args = [@a (r,s)]++Doing so isn't trivial, though.++For now we content ourselves with a simpler plan: eliminate a call pattern+if another pattern subsumes it; this is done by `subsumePats`.+For example here are two patterns++  cp_qvars = [a, r::a, s::a],  cp_args = [@a (r,s)]+  cp_qvars = [x::Int, y::Int], cp_args = [@Int (x,y)]++The first can be instantiated to the second, /by instantiating types only/.+This subsumption relationship is checked by `betterPat`.  Note that if+we have++  cp_qvars = [a, r::a, s::a], cp_args = [@a (r,s)]+  cp_qvars = [],              cp_args = [@Bool (True,False)]++the first does *not* subsume the second; the second is more specific.++In our initial example with `f @Int` and `f @Bool` neither subsumes the other,+so we will get two essentially-identical specialisations. Boo.  We rely on our+crude throttling mechanisms to stop this getting out of control -- with+polymorphic recursion we can generate an infinite number of specialisations.+Example is Data.Sequence.adjustTree, I think. -}
compiler/GHC/Core/Opt/Specialise.hs view
@@ -60,7 +60,6 @@ import GHC.Utils.Misc import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain( assert )  import GHC.Unit.Module( Module ) import GHC.Unit.Module.ModGuts@@ -2900,7 +2899,7 @@ is a top-level dictionary-former.  This actually happened in #22459, because of (MP1) of Note [Specialising polymorphic dictionaries]. -How can we speicalise $wsplit?  We might try+How can we specialise $wsplit?  We might try     RULE "SPEC" forall (d :: C T). $wsplit @T d = $s$wsplit 
compiler/GHC/Core/Opt/WorkWrap.hs view
@@ -35,7 +35,6 @@ import GHC.Utils.Misc import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Monad import GHC.Core.DataCon @@ -830,8 +829,8 @@       -- inl_act:    see Note [Worker activation]       -- inl_rule:   it does not make sense for workers to be constructorlike. -    work_join_arity | isJoinId fn_id = Just join_arity-                    | otherwise      = Nothing+    work_join_arity | isJoinId fn_id = JoinPoint join_arity+                    | otherwise      = NotJoinPoint       -- worker is join point iff wrapper is join point       -- (see Note [Don't w/w join points for CPR]) 
compiler/GHC/Core/Opt/WorkWrap/Utils.hs view
@@ -55,7 +55,6 @@ import GHC.Utils.Misc import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain  import Control.Applicative ( (<|>) ) import Control.Monad ( zipWithM )
compiler/GHC/CoreToStg.hs view
@@ -41,7 +41,7 @@ import GHC.Types.Literal import GHC.Types.ForeignCall import GHC.Types.IPE-import GHC.Types.Demand    ( isUsedOnceDmd )+import GHC.Types.Demand    ( isAtMostOnceDmd ) import GHC.Types.SrcLoc    ( mkGeneralSrcSpan )  import GHC.Unit.Module@@ -54,10 +54,8 @@ import GHC.Utils.Monad import GHC.Utils.Misc (HasDebugCallStack) import GHC.Utils.Panic-import GHC.Utils.Panic.Plain  import Control.Monad (ap)-import Data.Maybe (fromMaybe)  -- Note [Live vs free] -- ~~~~~~~~~~~~~~~~~~~@@ -429,30 +427,23 @@   = coreToStgExpr expr  -- Cases require a little more real work.--{--coreToStgExpr (Case scrut _ _ [])+coreToStgExpr (Case scrut bndr _ alts)+  | null alts+  -- See Note [Empty case alternatives] in GHC.Core If the case+  -- alternatives are empty, the scrutinee must diverge or raise an+  -- exception, so we can just dive into it.+  --+  -- Of course this may seg-fault if the scrutinee *does* return.  A+  -- belt-and-braces approach would be to move this case into the+  -- code generator, and put a return point anyway that calls a+  -- runtime system error function.   = coreToStgExpr scrut-    -- See Note [Empty case alternatives] in GHC.Core If the case-    -- alternatives are empty, the scrutinee must diverge or raise an-    -- exception, so we can just dive into it.-    ---    -- Of course this may seg-fault if the scrutinee *does* return.  A-    -- belt-and-braces approach would be to move this case into the-    -- code generator, and put a return point anyway that calls a-    -- runtime system error function. -coreToStgExpr e0@(Case scrut bndr _ [alt]) = do-  | isUnsafeEqualityProof scrut-  , isDeadBinder bndr -- We can only discard the case if the case-binder is dead-                      -- It usually is, but see #18227-  , (_,_,rhs) <- alt+  | Just rhs <- isUnsafeEqualityCase scrut bndr alts+  -- See (U2) in Note [Implementing unsafeCoerce] in base:Unsafe.Coerce   = coreToStgExpr rhs-    -- See (U2) in Note [Implementing unsafeCoerce] in base:Unsafe.Coerce--} --- The normal case for case-expressions-coreToStgExpr (Case scrut bndr _ alts)+  | otherwise   = do { scrut2 <- coreToStgExpr scrut        ; alts2 <- extendVarEnvCts [(bndr, LambdaBound)] (mapM vars_alt alts)        ; return (StgCase scrut2 bndr (mkStgAltType bndr alts) alts2) }@@ -539,8 +530,10 @@         res_ty = exprType (mkApps (Var f) args)         app = case idDetails f of                 DataConWorkId dc-                  | saturated    -> StgConApp dc NoNumber args'-                                      (dropRuntimeRepArgs (fromMaybe [] (tyConAppArgs_maybe res_ty)))+                  | saturated    -> if isUnboxedSumDataCon dc then+                                      StgConApp dc NoNumber args' (sumPrimReps args)+                                    else+                                      StgConApp dc NoNumber args' []                  -- Some primitive operator that might be implemented as a library call.                 -- As noted by Note [Eta expanding primops] in GHC.Builtin.PrimOps@@ -565,9 +558,19 @@         tapp = foldr add_tick app (map (coreToStgTick res_ty) ticks ++ ticks')      -- Forcing these fixes a leak in the code generator, noticed while-    -- profiling for trac #4367+    -- profiling for #4367     app `seq` return tapp ++-- Given Core arguments to an unboxed sum datacon, return the 'PrimRep's+-- of every alternative. For example, in (#_|#) @LiftedRep @IntRep @Int @Int# 0+-- the arguments are [Type LiftedRep, Type IntRep, Type Int, Type Int#, 0]+-- and we return the list [[LiftedRep], [IntRep]].+-- See Note [Representations in StgConApp] in GHC.Stg.Unarise.+sumPrimReps :: [CoreArg] -> [[PrimRep]]+sumPrimReps (Type ty : args) | isRuntimeRepKindedTy ty+  = runtimeRepPrimRep (text "sumPrimReps") ty : sumPrimReps args+sumPrimReps _ = [] -- --------------------------------------------------------------------------- -- Argument lists -- This is the guy that turns applications into A-normal form@@ -578,11 +581,7 @@ -- CoreArgs may not immediately look trivial, e.g., `case e of {}` or -- `case unsafeequalityProof of UnsafeRefl -> e` might intervene. -- Good thing we can just call `trivial_expr_fold` here.-getStgArgFromTrivialArg e-  | Just s <- exprIsTickedString_maybe e -- This case is just for backport to GHC 9.8,-  = StgLitArg (LitString s)              -- where we used to treat strings as valid StgArgs-  | otherwise-  = trivial_expr_fold StgVarArg StgLitArg panic panic e+getStgArgFromTrivialArg e = trivial_expr_fold StgVarArg StgLitArg panic panic e   where     panic = pprPanic "getStgArgFromTrivialArg" (ppr e) @@ -614,21 +613,21 @@         ticks' = map (coreToStgTick arg_ty) (stripTicksT (not . tickishIsCode) arg)         arg' = getStgArgFromTrivialArg arg         arg_rep = typePrimRep arg_ty-        stg_arg_rep = typePrimRep (stgArgType arg')+        stg_arg_rep = stgArgRep arg'         bad_args = not (primRepsCompatible platform arg_rep stg_arg_rep)      massertPpr (length ticks' <= 1) (text "More than one Tick in trivial arg:" <+> ppr arg)-    warnPprTrace bad_args "Dangerous-looking argument. Probable cause: bad unsafeCoerce#" (ppr arg) (return ())+    warnPprTraceM bad_args "Dangerous-looking argument. Probable cause: bad unsafeCoerce#" (ppr arg)      return (arg' : stg_args, ticks' ++ ticks)  coreToStgTick :: Type -- type of the ticked expression               -> CoreTickish               -> StgTickish-coreToStgTick _ty (HpcTick m i)           = HpcTick m i-coreToStgTick _ty (SourceNote span nm)    = SourceNote span nm-coreToStgTick _ty (ProfNote cc cnt scope) = ProfNote cc cnt scope-coreToStgTick !ty (Breakpoint _ bid fvs)  = Breakpoint ty bid fvs+coreToStgTick _ty (HpcTick m i)                = HpcTick m i+coreToStgTick _ty (SourceNote span nm)         = SourceNote span nm+coreToStgTick _ty (ProfNote cc cnt scope)      = ProfNote cc cnt scope+coreToStgTick !ty (Breakpoint _ bid fvs modl)  = Breakpoint ty bid fvs modl  -- --------------------------------------------------------------------------- -- The magic for lets:@@ -747,8 +746,8 @@   where     (ticks, unticked_rhs) = stripStgTicksTop (not . tickishIsCode) rhs -    upd_flag | isUsedOnceDmd (idDemandInfo bndr) = SingleEntry-             | otherwise                         = Updatable+    upd_flag | isAtMostOnceDmd (idDemandInfo bndr) = SingleEntry+             | otherwise                           = Updatable      -- CAF cost centres generated for -fcaf-all     caf_cc = mkAutoCC bndr modl@@ -793,8 +792,8 @@   where     (ticks, unticked_rhs) = stripStgTicksTop (not . tickishIsCode) rhs -    upd_flag | isUsedOnceDmd (idDemandInfo bndr) = SingleEntry-             | otherwise                         = Updatable+    upd_flag | isAtMostOnceDmd (idDemandInfo bndr) = SingleEntry+             | otherwise                           = Updatable    {-     SDM: disabled.  Eval/Apply can't handle functions with arity zero very@@ -958,6 +957,9 @@  -- | If the argument expression is (potential chain of) 'App', return the head -- of the app chain, and collect ticks/args along the chain.+-- INVARIANT: If the app head is trivial, return the atomic Var/Lit that was+-- wrapped in casts, empty case, ticks, etc.+-- So keep in sync with 'exprIsTrivial'. myCollectArgs :: HasDebugCallStack => CoreExpr -> (CoreExpr, [CoreArg], [CoreTickish]) myCollectArgs expr   = go expr [] []@@ -969,8 +971,16 @@                                 -- See Note [Ticks in applications]                                 go e as (t:ts) -- ticks can appear in type apps     go (Cast e _)       as ts = go e as ts+    go (Case e b _ alts) as ts  -- Just like in exprIsTrivial!+                                -- Otherwise we fall over in case we encounter+                                -- `(case f a of {}) b` in the future.+       | null alts+       = assertPpr (null as) (ppr e $$ ppr as $$ ppr expr) $+                   go e [] ts -- NB: Empty case discards arguments+       | Just rhs <- isUnsafeEqualityCase e b alts+       = go rhs as ts         -- Discards unsafeCoerce in App heads     go (Lam b e)        as ts-       | isTyVar b            = go e as ts -- Note [Collect args]+       | isTyVar b            = go e (drop 1 as) ts -- Note [Collect args]     go e                as ts = (e, as, ts)  {- Note [Collect args]
compiler/GHC/CoreToStg/Prep.hs view
@@ -1,2283 +1,2530 @@-{-# LANGUAGE BangPatterns #-}--{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}--{--(c) The University of Glasgow, 1994-2006---Core pass to saturate constructors and PrimOps--}--module GHC.CoreToStg.Prep-   ( CorePrepConfig (..)-   , CorePrepPgmConfig (..)-   , corePrepPgm-   , corePrepExpr-   , mkConvertNumLiteral-   )-where--import GHC.Prelude--import GHC.Platform--import GHC.Driver.Flags--import GHC.Tc.Utils.Env-import GHC.Unit--import GHC.Builtin.Names-import GHC.Builtin.Types--import GHC.Core.Utils-import GHC.Core.Opt.Arity-import GHC.Core.Lint    ( EndPassConfig(..), endPassIO )-import GHC.Core-import GHC.Core.Make hiding( FloatBind(..) )   -- We use our own FloatBind here-import GHC.Core.Type-import GHC.Core.Coercion-import GHC.Core.TyCon-import GHC.Core.DataCon-import GHC.Core.Opt.OccurAnal-import GHC.Core.TyCo.Rep( UnivCoProvenance(..) )--import GHC.Data.Maybe-import GHC.Data.OrdList-import GHC.Data.FastString-import GHC.Data.Pair-import GHC.Data.Graph.UnVar--import GHC.Utils.Error-import GHC.Utils.Misc-import GHC.Utils.Panic-import GHC.Utils.Panic.Plain-import GHC.Utils.Outputable-import GHC.Utils.Monad  ( mapAccumLM )-import GHC.Utils.Logger--import GHC.Types.Demand-import GHC.Types.Var-import GHC.Types.Var.Env-import GHC.Types.Id-import GHC.Types.Id.Info-import GHC.Types.Id.Make ( realWorldPrimId )-import GHC.Types.Basic-import GHC.Types.Name   ( Name, NamedThing(..), nameSrcSpan, isInternalName )-import GHC.Types.SrcLoc ( SrcSpan(..), realSrcLocSpan, mkRealSrcLoc )-import GHC.Types.Literal-import GHC.Types.Tickish-import GHC.Types.TyThing-import GHC.Types.Unique.Supply--import Data.List        ( unfoldr )-import Data.Functor.Identity-import Control.Monad--{--Note [CorePrep Overview]-~~~~~~~~~~~~~~~~~~~~~~~~--The goal of this pass is to prepare for code generation.--1.  Saturate constructor and primop applications.--2.  Convert to A-normal form; that is, function arguments-    are always variables.--    * Use case for strict arguments:-        f E ==> case E of x -> f x-        (where f is strict)--    * Use let for non-trivial lazy arguments-        f E ==> let x = E in f x-        (were f is lazy and x is non-trivial)--3.  Similarly, convert any unboxed lets into cases.-    [I'm experimenting with leaving 'ok-for-speculation'-     rhss in let-form right up to this point.]--4.  Ensure that *value* lambdas only occur as the RHS of a binding-    (The code generator can't deal with anything else.)-    Type lambdas are ok, however, because the code gen discards them.--5.  [Not any more; nuked Jun 2002] Do the seq/par munging.--6.  Clone all local Ids.-    This means that all such Ids are unique, rather than the-    weaker guarantee of no clashes which the simplifier provides.-    And that is what the code generator needs.--    We don't clone TyVars or CoVars. The code gen doesn't need that,-    and doing so would be tiresome because then we'd need-    to substitute in types and coercions.--    We need to clone ids for two reasons:-    + Things associated with labels in the final code must be truly unique in-      order to avoid labels being shadowed in the final output.-    + Even binders without info tables like function arguments or alternative-      bound binders must be unique at least in their type/unique combination.-      We only emit a single declaration for each binder when compiling to C-      so if binders are not unique we would either get duplicate declarations-      or misstyped variables. The later happend in #22402.-    + We heavily use unique-keyed maps in the backend which can go wrong when-      ids with the same unique are meant to represent the same variable.--7.  Give each dynamic CCall occurrence a fresh unique; this is-    rather like the cloning step above.--8.  Inject bindings for the "implicit" Ids:-        * Constructor wrappers-        * Constructor workers-    We want curried definitions for all of these in case they-    aren't inlined by some caller.-- 9. Convert bignum literals into their core representation.--10. Uphold tick consistency while doing this: We move ticks out of-    (non-type) applications where we can, and make sure that we-    annotate according to scoping rules when floating.--11. Collect cost centres (including cost centres in unfoldings) if we're in-    profiling mode. We have to do this here because we won't have unfoldings-    after this pass (see `trimUnfolding` and Note [Drop unfoldings and rules].--12. Eliminate case clutter in favour of unsafe coercions.-    See Note [Unsafe coercions]--13. Eliminate some magic Ids, specifically-     runRW# (\s. e)  ==>  e[readWorldId/s]-             lazy e  ==>  e (see Note [lazyId magic] in GHC.Types.Id.Make)-         noinline e  ==>  e-           nospec e  ==>  e-     ToDo:  keepAlive# ...-    This is done in cpeApp--This is all done modulo type applications and abstractions, so that-when type erasure is done for conversion to STG, we don't end up with-any trivial or useless bindings.--Note [Unsafe coercions]-~~~~~~~~~~~~~~~~~~~~~~~-CorePrep does these two transformations:--1. Convert empty case to cast with an unsafe coercion-          (case e of {}) ===>  e |> unsafe-co-   See Note [Empty case alternatives] in GHC.Core: if the case-   alternatives are empty, the scrutinee must diverge or raise an-   exception, so we can just dive into it.--   Of course, if the scrutinee *does* return, we may get a seg-fault.-   A belt-and-braces approach would be to persist empty-alternative-   cases to code generator, and put a return point anyway that calls a-   runtime system error function.--   Notice that eliminating empty case can lead to an ill-kinded coercion-       case error @Int "foo" of {}  :: Int#-       ===> error @Int "foo" |> unsafe-co-       where unsafe-co :: Int ~ Int#-   But that's fine because the expression diverges anyway. And it's-   no different to what happened before.--2. Eliminate unsafeEqualityProof in favour of an unsafe coercion-           case unsafeEqualityProof of UnsafeRefl g -> e-           ===>  e[unsafe-co/g]-   See (U2) in Note [Implementing unsafeCoerce] in base:Unsafe.Coerce--   Note that this requires us to substitute 'unsafe-co' for 'g', and-   that is the main (current) reason for cpe_tyco_env in CorePrepEnv.-   Tiresome, but not difficult.--These transformations get rid of "case clutter", leaving only casts.-We are doing no further significant transformations, so the reasons-for the case forms have disappeared. And it is extremely helpful for-the ANF-ery, CoreToStg, and backends, if trivial expressions really do-look trivial. #19700 was an example.--In both cases, the "unsafe-co" is just (UnivCo ty1 ty2 (CorePrepProv b)),-The boolean 'b' says whether the unsafe coercion is supposed to be-kind-homogeneous (yes for (2), no for (1).  This information is used-/only/ by Lint.--Note [CorePrep invariants]-~~~~~~~~~~~~~~~~~~~~~~~~~~-Here is the syntax of the Core produced by CorePrep:--    Trivial expressions-       arg ::= lit |  var-              | arg ty  |  /\a. arg-              | truv co  |  /\c. arg  |  arg |> co--    Applications-       app ::= lit  |  var  |  app arg  |  app ty  | app co | app |> co--    Expressions-       body ::= app-              | let(rec) x = rhs in body     -- Boxed only-              | case body of pat -> body-              | /\a. body | /\c. body-              | body |> co--    Right hand sides (only place where value lambdas can occur)-       rhs ::= /\a.rhs  |  \x.rhs  |  body--We define a synonym for each of these non-terminals.  Functions-with the corresponding name produce a result in that syntax.--}--type CpeArg  = CoreExpr    -- Non-terminal 'arg'-type CpeApp  = CoreExpr    -- Non-terminal 'app'-type CpeBody = CoreExpr    -- Non-terminal 'body'-type CpeRhs  = CoreExpr    -- Non-terminal 'rhs'--{--************************************************************************-*                                                                      *-                Top level stuff-*                                                                      *-************************************************************************--}--data CorePrepPgmConfig = CorePrepPgmConfig-  { cpPgm_endPassConfig     :: !EndPassConfig-  , cpPgm_generateDebugInfo :: !Bool-  }--corePrepPgm :: Logger-            -> CorePrepConfig-            -> CorePrepPgmConfig-            -> Module -> ModLocation -> CoreProgram -> [TyCon]-            -> IO CoreProgram-corePrepPgm logger cp_cfg pgm_cfg-            this_mod mod_loc binds data_tycons =-    withTiming logger-               (text "CorePrep"<+>brackets (ppr this_mod))-               (\a -> a `seqList` ()) $ do-    us <- mkSplitUniqSupply 's'-    let initialCorePrepEnv = mkInitialCorePrepEnv cp_cfg--    let-        implicit_binds = mkDataConWorkers-          (cpPgm_generateDebugInfo pgm_cfg)-          mod_loc data_tycons-            -- NB: we must feed mkImplicitBinds through corePrep too-            -- so that they are suitably cloned and eta-expanded--        binds_out = initUs_ us $ do-                      floats1 <- corePrepTopBinds initialCorePrepEnv binds-                      floats2 <- corePrepTopBinds initialCorePrepEnv implicit_binds-                      return (deFloatTop (floats1 `appendFloats` floats2))--    endPassIO logger (cpPgm_endPassConfig pgm_cfg)-              binds_out []-    return binds_out--corePrepExpr :: Logger -> CorePrepConfig -> CoreExpr -> IO CoreExpr-corePrepExpr logger config expr = do-    withTiming logger (text "CorePrep [expr]") (\e -> e `seq` ()) $ do-      us <- mkSplitUniqSupply 's'-      let initialCorePrepEnv = mkInitialCorePrepEnv config-      let new_expr = initUs_ us (cpeBodyNF initialCorePrepEnv expr)-      putDumpFileMaybe logger Opt_D_dump_prep "CorePrep" FormatCore (ppr new_expr)-      return new_expr--corePrepTopBinds :: CorePrepEnv -> [CoreBind] -> UniqSM Floats--- Note [Floating out of top level bindings]-corePrepTopBinds initialCorePrepEnv binds-  = go initialCorePrepEnv binds-  where-    go _   []             = return emptyFloats-    go env (bind : binds) = do (env', floats, maybe_new_bind)-                                 <- cpeBind TopLevel env bind-                               massert (isNothing maybe_new_bind)-                                 -- Only join points get returned this way by-                                 -- cpeBind, and no join point may float to top-                               floatss <- go env' binds-                               return (floats `appendFloats` floatss)--mkDataConWorkers :: Bool -> ModLocation -> [TyCon] -> [CoreBind]--- See Note [Data constructor workers]--- c.f. Note [Injecting implicit bindings] in GHC.Iface.Tidy-mkDataConWorkers generate_debug_info mod_loc data_tycons-  = [ NonRec id (tick_it (getName data_con) (Var id))-                                -- The ice is thin here, but it works-    | tycon <- data_tycons,     -- CorePrep will eta-expand it-      data_con <- tyConDataCons tycon,-      let id = dataConWorkId data_con-    ]- where-   -- If we want to generate debug info, we put a source note on the-   -- worker. This is useful, especially for heap profiling.-   tick_it name-     | not generate_debug_info               = id-     | RealSrcSpan span _ <- nameSrcSpan name = tick span-     | Just file <- ml_hs_file mod_loc       = tick (span1 file)-     | otherwise                             = tick (span1 "???")-     where tick span  = Tick $ SourceNote span $-             LexicalFastString $ mkFastString $ renderWithContext defaultSDocContext $ ppr name-           span1 file = realSrcLocSpan $ mkRealSrcLoc (mkFastString file) 1 1--{--Note [Floating out of top level bindings]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-NB: we do need to float out of top-level bindings-Consider        x = length [True,False]-We want to get-                s1 = False : []-                s2 = True  : s1-                x  = length s2--We return a *list* of bindings, because we may start with-        x* = f (g y)-where x is demanded, in which case we want to finish with-        a = g y-        x* = f a-And then x will actually end up case-bound--Note [Join points and floating]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Join points can float out of other join points but not out of value bindings:--  let z =-    let  w = ... in -- can float-    join k = ... in -- can't float-    ... jump k ...-  join j x1 ... xn =-    let  y = ... in -- can float (but don't want to)-    join h = ... in -- can float (but not much point)-    ... jump h ...-  in ...--Here, the jump to h remains valid if h is floated outward, but the jump to k-does not.--We don't float *out* of join points. It would only be safe to float out of-nullary join points (or ones where the arguments are all either type arguments-or dead binders). Nullary join points aren't ever recursive, so they're always-effectively one-shot functions, which we don't float out of. We *could* float-join points from nullary join points, but there's no clear benefit at this-stage.--Note [Data constructor workers]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Create any necessary "implicit" bindings for data con workers.  We-create the rather strange (non-recursive!) binding--        $wC = \x y -> $wC x y--i.e. a curried constructor that allocates.  This means that we can-treat the worker for a constructor like any other function in the rest-of the compiler.  The point here is that CoreToStg will generate a-StgConApp for the RHS, rather than a call to the worker (which would-give a loop).  As Lennart says: the ice is thin here, but it works.--Hmm.  Should we create bindings for dictionary constructors?  They are-always fully applied, and the bindings are just there to support-partial applications. But it's easier to let them through.---Note [Dead code in CorePrep]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Imagine that we got an input program like this (see #4962):--  f :: Show b => Int -> (Int, b -> Maybe Int -> Int)-  f x = (g True (Just x) + g () (Just x), g)-    where-      g :: Show a => a -> Maybe Int -> Int-      g _ Nothing = x-      g y (Just z) = if z > 100 then g y (Just (z + length (show y))) else g y unknown--After specialisation and SpecConstr, we would get something like this:--  f :: Show b => Int -> (Int, b -> Maybe Int -> Int)-  f x = (g$Bool_True_Just x + g$Unit_Unit_Just x, g)-    where-      {-# RULES g $dBool = g$Bool-                g $dUnit = g$Unit #-}-      g = ...-      {-# RULES forall x. g$Bool True (Just x) = g$Bool_True_Just x #-}-      g$Bool = ...-      {-# RULES forall x. g$Unit () (Just x) = g$Unit_Unit_Just x #-}-      g$Unit = ...-      g$Bool_True_Just = ...-      g$Unit_Unit_Just = ...--Note that the g$Bool and g$Unit functions are actually dead code: they-are only kept alive by the occurrence analyser because they are-referred to by the rules of g, which is being kept alive by the fact-that it is used (unspecialised) in the returned pair.--However, at the CorePrep stage there is no way that the rules for g-will ever fire, and it really seems like a shame to produce an output-program that goes to the trouble of allocating a closure for the-unreachable g$Bool and g$Unit functions.--The way we fix this is to:- * In cloneBndr, drop all unfoldings/rules-- * In deFloatTop, run a simple dead code analyser on each top-level-   RHS to drop the dead local bindings.--The reason we don't just OccAnal the whole output of CorePrep is that-the tidier ensures that all top-level binders are GlobalIds, so they-don't show up in the free variables any longer. So if you run the-occurrence analyser on the output of CoreTidy (or later) you e.g. turn-this program:--  Rec {-  f = ... f ...-  }--Into this one:--  f = ... f ...--(Since f is not considered to be free in its own RHS.)---Note [keepAlive# magic]-~~~~~~~~~~~~~~~~~~~~~~~-When interacting with foreign code, it is often necessary for the user to-extend the lifetime of a heap object beyond the lifetime that would be apparent-from the on-heap references alone. For instance, a program like:--  foreign import safe "hello" hello :: ByteArray# -> IO ()--  callForeign :: IO ()-  callForeign = IO $ \s0 ->-    case newByteArray# n# s0 of (# s1, barr #) ->-      unIO hello barr s1--As-written this program is susceptible to memory-unsafety since there are-no references to `barr` visible to the garbage collector. Consequently, if a-garbage collection happens during the execution of the C function `hello`, it-may be that the array is freed while in use by the foreign function.--To address this, we introduced a new primop, keepAlive#, which "scopes over"-the computation needing the kept-alive value:--  keepAlive# :: forall (ra :: RuntimeRep) (rb :: RuntimeRep) (a :: TYPE a) (b :: TYPE b).-                a -> State# RealWorld -> (State# RealWorld -> b) -> b--When entered, an application (keepAlive# x s k) will apply `k` to the state-token, evaluating it to WHNF. However, during the course of this evaluation-will *guarantee* that `x` is considered to be alive.--There are a few things to note here:-- - we are RuntimeRep-polymorphic in the value to be kept-alive. This is-   necessary since we will often (but not always) be keeping alive something-   unlifted (like a ByteArray#)-- - we are RuntimeRep-polymorphic in the result value since the result may take-   many forms (e.g. a boxed value, a raw state token, or a (# State s, result #).--We implement this operation by desugaring to touch# during CorePrep (see-GHC.CoreToStg.Prep.cpeApp). Specifically,--  keepAlive# x s0 k--is transformed to:--  case k s0 of r ->-  case touch# x realWorld# of s1 ->-    r--Operationally, `keepAlive# x s k` is equivalent to pushing a stack frame with a-pointer to `x` and entering `k s0`. This compilation strategy is safe-because we do no optimization on STG that would drop or re-order the-continuation containing the `touch#`. However, if we were to become more-aggressive in our STG pipeline then we would need to revisit this.--Beyond this CorePrep transformation, there is very little special about-keepAlive#. However, we did explore (and eventually gave up on)-an optimisation which would allow unboxing of constructed product results,-which we describe below.---Lost optimisation: CPR unboxing----------------------------------One unfortunate property of this approach is that the simplifier is unable to-unbox the result of a keepAlive# expression. For instance, consider the program:--  case keepAlive# arr s0 (-         \s1 -> case peekInt arr s1 of-                  (# s2, r #) -> I# r-  ) of-    I# x -> ...--This is a surprisingly common pattern, previously used, e.g., in-GHC.IO.Buffer.readWord8Buf. While exploring ideas, we briefly played around-with optimising this away by pushing strict contexts (like the-`case [] of I# x -> ...` above) into keepAlive#'s continuation. While this can-recover unboxing, it can also unfortunately in general change the asymptotic-memory (namely stack) behavior of the program. For instance, consider--  writeN =-    ...-      case keepAlive# x s0 (\s1 -> something s1) of-        (# s2, x #) ->-          writeN ...--As it is tail-recursive, this program will run in constant space. However, if-we push outer case into the continuation we get:--  writeN =--      case keepAlive# x s0 (\s1 ->-        case something s1 of-          (# s2, x #) ->-            writeN ...-      ) of-        ...--Which ends up building a stack which is linear in the recursion depth. For this-reason, we ended up giving up on this optimisation.---Historical note: touch# and its inadequacy--------------------------------------------Prior to the introduction of `keepAlive#` we instead addressed the need for-lifetime extension with the `touch#` primop:--    touch# :: a -> State# s -> State# s--This operation would ensure that the `a` value passed as the first argument was-considered "alive" at the time the primop application is entered.--For instance, the user might modify `callForeign` as:--  callForeign :: IO ()-  callForeign s0 = IO $ \s0 ->-    case newByteArray# n# s0 of (# s1, barr #) ->-    case unIO hello barr s1 of (# s2, () #) ->-    case touch# barr s2 of s3 ->-      (# s3, () #)--However, in #14346 we discovered that this primop is insufficient in the-presence of simplification. For instance, consider a program like:--  callForeign :: IO ()-  callForeign s0 = IO $ \s0 ->-    case newByteArray# n# s0 of (# s1, barr #) ->-    case unIO (forever $ hello barr) s1 of (# s2, () #) ->-    case touch# barr s2 of s3 ->-      (# s3, () #)--In this case the Simplifier may realize that (forever $ hello barr)-will never return and consequently that the `touch#` that follows is dead code.-As such, it will be dropped, resulting in memory unsoundness.-This unsoundness lead to the introduction of keepAlive#.----Other related tickets:-- - #15544- - #17760- - #14375- - #15260- - #18061--************************************************************************-*                                                                      *-                The main code-*                                                                      *-************************************************************************--}--cpeBind :: TopLevelFlag -> CorePrepEnv -> CoreBind-        -> UniqSM (CorePrepEnv,-                   Floats,         -- Floating value bindings-                   Maybe CoreBind) -- Just bind' <=> returned new bind; no float-                                   -- Nothing <=> added bind' to floats instead-cpeBind top_lvl env (NonRec bndr rhs)-  | not (isJoinId bndr)-  = do { (env1, bndr1) <- cpCloneBndr env bndr-       ; let dmd         = idDemandInfo bndr-             is_unlifted = isUnliftedType (idType bndr)-       ; (floats, rhs1) <- cpePair top_lvl NonRecursive-                                   dmd is_unlifted-                                   env bndr1 rhs-       -- See Note [Inlining in CorePrep]-       ; let triv_rhs = exprIsTrivial rhs1-             env2    | triv_rhs  = extendCorePrepEnvExpr env1 bndr rhs1-                     | otherwise = env1-             floats1 | triv_rhs, isInternalName (idName bndr)-                     = floats-                     | otherwise-                     = addFloat floats new_float--             new_float = mkFloat env dmd is_unlifted bndr1 rhs1--       ; return (env2, floats1, Nothing) }--  | otherwise -- A join point; see Note [Join points and floating]-  = assert (not (isTopLevel top_lvl)) $ -- can't have top-level join point-    do { (_, bndr1) <- cpCloneBndr env bndr-       ; (bndr2, rhs1) <- cpeJoinPair env bndr1 rhs-       ; return (extendCorePrepEnv env bndr bndr2,-                 emptyFloats,-                 Just (NonRec bndr2 rhs1)) }--cpeBind top_lvl env (Rec pairs)-  | not (isJoinId (head bndrs))-  = do { (env, bndrs1) <- cpCloneBndrs env bndrs-       ; let env' = enterRecGroupRHSs env bndrs1-       ; stuff <- zipWithM (cpePair top_lvl Recursive topDmd False env')-                           bndrs1 rhss--       ; let (floats_s, rhss1) = unzip stuff-             all_pairs = foldrOL add_float (bndrs1 `zip` rhss1)-                                           (concatFloats floats_s)-       -- use env below, so that we reset cpe_rec_ids-       ; return (extendCorePrepEnvList env (bndrs `zip` bndrs1),-                 unitFloat (FloatLet (Rec all_pairs)),-                 Nothing) }--  | otherwise -- See Note [Join points and floating]-  = do { (env, bndrs1) <- cpCloneBndrs env bndrs-       ; let env' = enterRecGroupRHSs env bndrs1-       ; pairs1 <- zipWithM (cpeJoinPair env') bndrs1 rhss--       ; let bndrs2 = map fst pairs1-       -- use env below, so that we reset cpe_rec_ids-       ; return (extendCorePrepEnvList env (bndrs `zip` bndrs2),-                 emptyFloats,-                 Just (Rec pairs1)) }-  where-    (bndrs, rhss) = unzip pairs--        -- Flatten all the floats, and the current-        -- group into a single giant Rec-    add_float (FloatLet (NonRec b r)) prs2 = (b,r) : prs2-    add_float (FloatLet (Rec prs1))   prs2 = prs1 ++ prs2-    add_float b                       _    = pprPanic "cpeBind" (ppr b)------------------cpePair :: TopLevelFlag -> RecFlag -> Demand -> Bool-        -> CorePrepEnv -> OutId -> CoreExpr-        -> UniqSM (Floats, CpeRhs)--- Used for all bindings--- The binder is already cloned, hence an OutId-cpePair top_lvl is_rec dmd is_unlifted env bndr rhs-  = assert (not (isJoinId bndr)) $ -- those should use cpeJoinPair-    do { (floats1, rhs1) <- cpeRhsE env rhs--       -- See if we are allowed to float this stuff out of the RHS-       ; (floats2, rhs2) <- float_from_rhs floats1 rhs1--       -- Make the arity match up-       ; (floats3, rhs3)-            <- if manifestArity rhs1 <= arity-               then return (floats2, cpeEtaExpand arity rhs2)-               else warnPprTrace True "CorePrep: silly extra arguments:" (ppr bndr) $-                               -- Note [Silly extra arguments]-                    (do { v <- newVar (idType bndr)-                        ; let float = mkFloat env topDmd False v rhs2-                        ; return ( addFloat floats2 float-                                 , cpeEtaExpand arity (Var v)) })--        -- Wrap floating ticks-       ; let (floats4, rhs4) = wrapTicks floats3 rhs3--       ; return (floats4, rhs4) }-  where-    arity = idArity bndr        -- We must match this arity--    ----------------------    float_from_rhs floats rhs-      | isEmptyFloats floats = return (emptyFloats, rhs)-      | isTopLevel top_lvl   = float_top    floats rhs-      | otherwise            = float_nested floats rhs--    ----------------------    float_nested floats rhs-      | wantFloatNested is_rec dmd is_unlifted floats rhs-                  = return (floats, rhs)-      | otherwise = dontFloat floats rhs--    ----------------------    float_top floats rhs-      | allLazyTop floats-      = return (floats, rhs)--      | Just floats <- canFloat floats rhs-      = return floats--      | otherwise-      = dontFloat floats rhs--dontFloat :: Floats -> CpeRhs -> UniqSM (Floats, CpeBody)--- Non-empty floats, but do not want to float from rhs--- So wrap the rhs in the floats--- But: rhs1 might have lambdas, and we can't---      put them inside a wrapBinds-dontFloat floats1 rhs-  = do { (floats2, body) <- rhsToBody rhs-        ; return (emptyFloats, wrapBinds floats1 $-                               wrapBinds floats2 body) }--{- Note [Silly extra arguments]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Suppose we had this-        f{arity=1} = \x\y. e-We *must* match the arity on the Id, so we have to generate-        f' = \x\y. e-        f  = \x. f' x--It's a bizarre case: why is the arity on the Id wrong?  Reason-(in the days of __inline_me__):-        f{arity=0} = __inline_me__ (let v = expensive in \xy. e)-When InlineMe notes go away this won't happen any more.  But-it seems good for CorePrep to be robust.--}------------------cpeJoinPair :: CorePrepEnv -> JoinId -> CoreExpr-            -> UniqSM (JoinId, CpeRhs)--- Used for all join bindings--- No eta-expansion: see Note [Do not eta-expand join points] in GHC.Core.Opt.Simplify.Utils-cpeJoinPair env bndr rhs-  = assert (isJoinId bndr) $-    do { let Just join_arity = isJoinId_maybe bndr-             (bndrs, body)   = collectNBinders join_arity rhs--       ; (env', bndrs') <- cpCloneBndrs env bndrs--       ; body' <- cpeBodyNF env' body -- Will let-bind the body if it starts-                                      -- with a lambda--       ; let rhs'  = mkCoreLams bndrs' body'-             bndr' = bndr `setIdUnfolding` evaldUnfolding-                          `setIdArity` count isId bndrs-                            -- See Note [Arity and join points]--       ; return (bndr', rhs') }--{--Note [Arity and join points]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Up to now, we've allowed a join point to have an arity greater than its join-arity (minus type arguments), since this is what's useful for eta expansion.-However, for code gen purposes, its arity must be exactly the number of value-arguments it will be called with, and it must have exactly that many value-lambdas. Hence if there are extra lambdas we must let-bind the body of the RHS:--  join j x y z = \w -> ... in ...-    =>-  join j x y z = (let f = \w -> ... in f) in ...--This is also what happens with Note [Silly extra arguments]. Note that it's okay-for us to mess with the arity because a join point is never exported.--}---- ------------------------------------------------------------------------------              CpeRhs: produces a result satisfying CpeRhs--- -----------------------------------------------------------------------------cpeRhsE :: CorePrepEnv -> CoreExpr -> UniqSM (Floats, CpeRhs)--- If---      e  ===>  (bs, e')--- then---      e = let bs in e'        (semantically, that is!)------ For example---      f (g x)   ===>   ([v = g x], f v)--cpeRhsE env (Type ty)-  = return (emptyFloats, Type (cpSubstTy env ty))-cpeRhsE env (Coercion co)-  = return (emptyFloats, Coercion (cpSubstCo env co))-cpeRhsE env expr@(Lit (LitNumber nt i))-   = case cp_convertNumLit (cpe_config env) nt i of-      Nothing -> return (emptyFloats, expr)-      Just e  -> cpeRhsE env e-cpeRhsE _env expr@(Lit {}) = return (emptyFloats, expr)-cpeRhsE env expr@(Var {})  = cpeApp env expr-cpeRhsE env expr@(App {})  = cpeApp env expr--cpeRhsE env (Let bind body)-  = do { (env', bind_floats, maybe_bind') <- cpeBind NotTopLevel env bind-       ; (body_floats, body') <- cpeRhsE env' body-       ; let expr' = case maybe_bind' of Just bind' -> Let bind' body'-                                         Nothing    -> body'-       ; return (bind_floats `appendFloats` body_floats, expr') }--cpeRhsE env (Tick tickish expr)-  -- Pull out ticks if they are allowed to be floated.-  | tickishFloatable tickish-  = do { (floats, body) <- cpeRhsE env expr-         -- See [Floating Ticks in CorePrep]-       ; return (unitFloat (FloatTick tickish) `appendFloats` floats, body) }-  | otherwise-  = do { body <- cpeBodyNF env expr-       ; return (emptyFloats, mkTick tickish' body) }-  where-    tickish' | Breakpoint ext n fvs <- tickish-             -- See also 'substTickish'-             = Breakpoint ext n (map (getIdFromTrivialExpr . lookupCorePrepEnv env) fvs)-             | otherwise-             = tickish--cpeRhsE env (Cast expr co)-   = do { (floats, expr') <- cpeRhsE env expr-        ; return (floats, Cast expr' (cpSubstCo env co)) }--cpeRhsE env expr@(Lam {})-   = do { let (bndrs,body) = collectBinders expr-        ; (env', bndrs') <- cpCloneBndrs env bndrs-        ; body' <- cpeBodyNF env' body-        ; return (emptyFloats, mkLams bndrs' body') }---- Eliminate empty case--- See Note [Unsafe coercions]-cpeRhsE env (Case scrut _ ty [])-  = do { (floats, scrut') <- cpeRhsE env scrut-       ; let ty'       = cpSubstTy env ty-             scrut_ty' = exprType scrut'-             co'       = mkUnivCo prov Representational scrut_ty' ty'-             prov      = CorePrepProv False-               -- False says that the kinds of two types may differ-               -- E.g. we might cast Int to Int#.  This is fine-               -- because the scrutinee is guaranteed to diverge--       ; return (floats, Cast scrut' co') }-   -- This can give rise to-   --   Warning: Unsafe coercion: between unboxed and boxed value-   -- but it's fine because 'scrut' diverges---- Eliminate unsafeEqualityProof--- See Note [Unsafe coercions]-cpeRhsE env (Case scrut bndr _ alts)-  | isUnsafeEqualityProof scrut-  , isDeadBinder bndr -- We can only discard the case if the case-binder-                      -- is dead.  It usually is, but see #18227-  , [Alt _ [co_var] rhs] <- alts-  , let Pair ty1 ty2 = coVarTypes co_var-        the_co = mkUnivCo prov Nominal (cpSubstTy env ty1) (cpSubstTy env ty2)-        prov   = CorePrepProv True  -- True <=> kind homogeneous-        env'   = extendCoVarEnv env co_var the_co-  = cpeRhsE env' rhs--cpeRhsE env (Case scrut bndr ty alts)-  = do { (floats, scrut') <- cpeBody env scrut-       ; (env', bndr2) <- cpCloneBndr env bndr-       ; let alts'-               | cp_catchNonexhaustiveCases $ cpe_config env-               , not (altsAreExhaustive alts)-               = addDefault alts (Just err)-               | otherwise = alts-               where err = mkImpossibleExpr ty "cpeRhsE: missing case alternative"-       ; alts'' <- mapM (sat_alt env') alts'--       ; return (floats, Case scrut' bndr2 ty alts'') }-  where-    sat_alt env (Alt con bs rhs)-       = do { (env2, bs') <- cpCloneBndrs env bs-            ; rhs' <- cpeBodyNF env2 rhs-            ; return (Alt con bs' rhs') }---- ------------------------------------------------------------------------------              CpeBody: produces a result satisfying CpeBody--- ------------------------------------------------------------------------------- | Convert a 'CoreExpr' so it satisfies 'CpeBody', without--- producing any floats (any generated floats are immediately--- let-bound using 'wrapBinds').  Generally you want this, esp.--- when you've reached a binding form (e.g., a lambda) and--- floating any further would be incorrect.-cpeBodyNF :: CorePrepEnv -> CoreExpr -> UniqSM CpeBody-cpeBodyNF env expr-  = do { (floats, body) <- cpeBody env expr-       ; return (wrapBinds floats body) }---- | Convert a 'CoreExpr' so it satisfies 'CpeBody'; also produce--- a list of 'Floats' which are being propagated upwards.  In--- fact, this function is used in only two cases: to--- implement 'cpeBodyNF' (which is what you usually want),--- and in the case when a let-binding is in a case scrutinee--here,--- we can always float out:------      case (let x = y in z) of ...---      ==> let x = y in case z of ...----cpeBody :: CorePrepEnv -> CoreExpr -> UniqSM (Floats, CpeBody)-cpeBody env expr-  = do { (floats1, rhs) <- cpeRhsE env expr-       ; (floats2, body) <- rhsToBody rhs-       ; return (floats1 `appendFloats` floats2, body) }-----------rhsToBody :: CpeRhs -> UniqSM (Floats, CpeBody)--- Remove top level lambdas by let-binding--rhsToBody (Tick t expr)-  | tickishScoped t == NoScope  -- only float out of non-scoped annotations-  = do { (floats, expr') <- rhsToBody expr-       ; return (floats, mkTick t expr') }--rhsToBody (Cast e co)-        -- You can get things like-        --      case e of { p -> coerce t (\s -> ...) }-  = do { (floats, e') <- rhsToBody e-       ; return (floats, Cast e' co) }--rhsToBody expr@(Lam {})   -- See Note [No eta reduction needed in rhsToBody]-  | all isTyVar bndrs           -- Type lambdas are ok-  = return (emptyFloats, expr)-  | otherwise                   -- Some value lambdas-  = do { let rhs = cpeEtaExpand (exprArity expr) expr-       ; fn <- newVar (exprType rhs)-       ; let float = FloatLet (NonRec fn rhs)-       ; return (unitFloat float, Var fn) }-  where-    (bndrs,_) = collectBinders expr--rhsToBody expr = return (emptyFloats, expr)---{- Note [No eta reduction needed in rhsToBody]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Historical note.  In the olden days we used to have a Prep-specific-eta-reduction step in rhsToBody:-  rhsToBody expr@(Lam {})-    | Just no_lam_result <- tryEtaReducePrep bndrs body-    = return (emptyFloats, no_lam_result)--The goal was to reduce-        case x of { p -> \xs. map f xs }-    ==> case x of { p -> map f }--to avoid allocating a lambda.  Of course, we'd allocate a PAP-instead, which is hardly better, but that's the way it was.--Now we simply don't bother with this. It doesn't seem to be a win,-and it's extra work.--}---- ------------------------------------------------------------------------------              CpeApp: produces a result satisfying CpeApp--- -----------------------------------------------------------------------------data ArgInfo = CpeApp  CoreArg-             | CpeCast Coercion-             | CpeTick CoreTickish--instance Outputable ArgInfo where-  ppr (CpeApp arg) = text "app" <+> ppr arg-  ppr (CpeCast co) = text "cast" <+> ppr co-  ppr (CpeTick tick) = text "tick" <+> ppr tick--{- Note [Ticks and mandatory eta expansion]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Something like-    `foo x = ({-# SCC foo #-} tagToEnum#) x :: Bool`-caused a compiler panic in #20938. Why did this happen?-The simplifier will eta-reduce the rhs giving us a partial-application of tagToEnum#. The tick is then pushed inside the-type argument. That is we get-    `(Tick<foo> tagToEnum#) @Bool`-CorePrep would go on to see a undersaturated tagToEnum# application-and eta expand the expression under the tick. Giving us:-    (Tick<scc> (\forall a. x -> tagToEnum# @a x) @Bool-Suddenly tagToEnum# is applied to a polymorphic type and the code generator-panics as it needs a concrete type to determine the representation.--The problem in my eyes was that the tick covers a partial application-of a primop. There is no clear semantic for such a construct as we can't-partially apply a primop since they do not have bindings.-We fix this by expanding the scope of such ticks slightly to cover the body-of the eta-expanded expression.--We do this by:-* Checking if an application is headed by a primOpish thing.-* If so we collect floatable ticks and usually but also profiling ticks-  along with regular arguments.-* When rebuilding the application we check if any profiling ticks appear-  before the primop is fully saturated.-* If the primop isn't fully satured we eta expand the primop application-  and scope the tick to scope over the body of the saturated expression.--Going back to #20938 this means starting with-    `(Tick<foo> tagToEnum#) @Bool`-we check if the function head is a primop (yes). This means we collect the-profiling tick like if it was floatable. Giving us-    (tagToEnum#, [CpeTick foo, CpeApp @Bool]).-cpe_app filters out the tick as a underscoped tick on the expression-`tagToEnum# @Bool`. During eta expansion we then put that tick back onto the-body of the eta-expansion lambdas. Giving us `\x -> Tick<foo> (tagToEnum# @Bool x)`.--}-cpeApp :: CorePrepEnv -> CoreExpr -> UniqSM (Floats, CpeRhs)--- May return a CpeRhs because of saturating primops-cpeApp top_env expr-  = do { let (terminal, args) = collect_args expr-      --  ; pprTraceM "cpeApp" $ (ppr expr)-       ; cpe_app top_env terminal args-       }--  where-    -- We have a nested data structure of the form-    -- e `App` a1 `App` a2 ... `App` an, convert it into-    -- (e, [CpeApp a1, CpeApp a2, ..., CpeApp an], depth)-    -- We use 'ArgInfo' because we may also need to-    -- record casts and ticks.  Depth counts the number-    -- of arguments that would consume strictness information-    -- (so, no type or coercion arguments.)-    collect_args :: CoreExpr -> (CoreExpr, [ArgInfo])-    collect_args e = go e []-      where-        go (App fun arg)      as-            = go fun (CpeApp arg : as)-        go (Cast fun co)      as-            = go fun (CpeCast co : as)-        go (Tick tickish fun) as-            -- Profiling ticks are slightly less strict so we expand their scope-            -- if they cover partial applications of things like primOps.-            -- See Note [Ticks and mandatory eta expansion]-            -- Here we look inside `fun` before we make the final decision about-            -- floating the tick which isn't optimal for perf. But this only makes-            -- a difference if we have a non-floatable tick which is somewhat rare.-            | Var vh <- head-            , Var head' <- lookupCorePrepEnv top_env vh-            , etaExpansionTick head' tickish-            = (head,as')-            where-              (head,as') = go fun (CpeTick tickish : as)--        -- Terminal could still be an app if it's wrapped by a tick.-        -- E.g. Tick<foo> (f x) can give us (f x) as terminal.-        go terminal as = (terminal, as)--    cpe_app :: CorePrepEnv-            -> CoreExpr -- The thing we are calling-            -> [ArgInfo]-            -> UniqSM (Floats, CpeRhs)-    cpe_app env (Var f) (CpeApp Type{} : CpeApp arg : args)-        | f `hasKey` lazyIdKey          -- Replace (lazy a) with a, and-            -- See Note [lazyId magic] in GHC.Types.Id.Make-       || f `hasKey` noinlineIdKey || f `hasKey` noinlineConstraintIdKey-            -- Replace (noinline a) with a-            -- See Note [noinlineId magic] in GHC.Types.Id.Make-       || f `hasKey` nospecIdKey        -- Replace (nospec a) with a-            -- See Note [nospecId magic] in GHC.Types.Id.Make--        -- Consider the code:-        ---        --      lazy (f x) y-        ---        -- We need to make sure that we need to recursively collect arguments on-        -- "f x", otherwise we'll float "f x" out (it's not a variable) and-        -- end up with this awful -ddump-prep:-        ---        --      case f x of f_x {-        --        __DEFAULT -> f_x y-        --      }-        ---        -- rather than the far superior "f x y".  Test case is par01.-        = let (terminal, args') = collect_args arg-          in cpe_app env terminal (args' ++ args)--    -- runRW# magic-    cpe_app env (Var f) (CpeApp _runtimeRep@Type{} : CpeApp _type@Type{} : CpeApp arg : rest)-        | f `hasKey` runRWKey-        -- N.B. While it may appear that n == 1 in the case of runRW#-        -- applications, keep in mind that we may have applications that return-        , has_value_arg (CpeApp arg : rest)-        -- See Note [runRW magic]-        -- Replace (runRW# f) by (f realWorld#), beta reducing if possible (this-        -- is why we return a CorePrepEnv as well)-        = case arg of-            Lam s body -> cpe_app (extendCorePrepEnv env s realWorldPrimId) body rest-            _          -> cpe_app env arg (CpeApp (Var realWorldPrimId) : rest)-             -- TODO: What about casts?-        where-          has_value_arg [] = False-          has_value_arg (CpeApp arg:_rest)-            | not (isTyCoArg arg) = True-          has_value_arg (_:rest) = has_value_arg rest--    cpe_app env (Var v) args-      = do { v1 <- fiddleCCall v-           ; let e2 = lookupCorePrepEnv env v1-                 hd = getIdFromTrivialExpr_maybe e2-                 -- Determine number of required arguments. See Note [Ticks and mandatory eta expansion]-                 min_arity = case hd of-                   Just v_hd -> if hasNoBinding v_hd then Just $! (idArity v_hd) else Nothing-                   Nothing -> Nothing-          --  ; pprTraceM "cpe_app:stricts:" (ppr v <+> ppr args $$ ppr stricts $$ ppr (idCbvMarks_maybe v))-           ; (app, floats, unsat_ticks) <- rebuild_app env args e2 emptyFloats stricts min_arity-           ; mb_saturate hd app floats unsat_ticks depth }-        where-          depth = val_args args-          stricts = case idDmdSig v of-                            DmdSig (DmdType _ demands)-                              | listLengthCmp demands depth /= GT -> demands-                                    -- length demands <= depth-                              | otherwise                         -> []-                -- If depth < length demands, then we have too few args to-                -- satisfy strictness  info so we have to  ignore all the-                -- strictness info, e.g. + (error "urk")-                -- Here, we can't evaluate the arg strictly, because this-                -- partial application might be seq'd--        -- We inlined into something that's not a var and has no args.-        -- Bounce it back up to cpeRhsE.-    cpe_app env fun [] = cpeRhsE env fun--    -- Here we get:-    -- N-variable fun, better let-bind it-    -- This case covers literals, apps, lams or let expressions applied to arguments.-    -- Basically things we want to ANF before applying to arguments.-    cpe_app env fun args-      = do { (fun_floats, fun') <- cpeArg env evalDmd fun-                          -- If evalDmd says that it's sure to be evaluated,-                          -- we'll end up case-binding it-           ; (app, floats,unsat_ticks) <- rebuild_app env args fun' fun_floats [] Nothing-           ; mb_saturate Nothing app floats unsat_ticks (val_args args) }--    -- Count the number of value arguments *and* coercions (since we don't eliminate the later in STG)-    val_args :: [ArgInfo] -> Int-    val_args args = go args 0-      where-        go [] !n = n-        go (info:infos) n =-          case info of-            CpeCast {} -> go infos n-            CpeTick tickish-              | tickishFloatable tickish                 -> go infos n-              -- If we can't guarantee a tick will be floated out of the application-              -- we can't guarantee the value args following it will be applied.-              | otherwise                             -> n-            CpeApp e                                  -> go infos n'-              where-                !n'-                  | isTypeArg e = n-                  | otherwise   = n+1--    -- Saturate if necessary-    mb_saturate head app floats unsat_ticks depth =-       case head of-         Just fn_id -> do { sat_app <- maybeSaturate fn_id app depth unsat_ticks-                          ; return (floats, sat_app) }-         _other     -> do { massert (null unsat_ticks)-                          ; return (floats, app) }--    -- Deconstruct and rebuild the application, floating any non-atomic-    -- arguments to the outside.  We collect the type of the expression,-    -- the head of the application, and the number of actual value arguments,-    -- all of which are used to possibly saturate this application if it-    -- has a constructor or primop at the head.-    rebuild_app-        :: CorePrepEnv-        -> [ArgInfo]                  -- The arguments (inner to outer)-        -> CpeApp                     -- The function-        -> Floats-        -> [Demand]-        -> Maybe Arity-        -> UniqSM (CpeApp-                  ,Floats-                  ,[CoreTickish] -- Underscoped ticks. See Note [Ticks and mandatory eta expansion]-                  )-    rebuild_app env args app floats ss req_depth =-      rebuild_app' env args app floats ss [] (fromMaybe 0 req_depth)--    rebuild_app'-        :: CorePrepEnv-        -> [ArgInfo] -- The arguments (inner to outer)-        -> CpeApp-        -> Floats-        -> [Demand]-        -> [CoreTickish]-        -> Int -- Number of arguments required to satisfy minimal tick scopes.-        -> UniqSM (CpeApp, Floats, [CoreTickish])-    rebuild_app' _ [] app floats ss rt_ticks !_req_depth-      = assertPpr (null ss) (ppr ss)-- make sure we used all the strictness info-        return (app, floats, rt_ticks)--    rebuild_app' env (a : as) fun' floats ss rt_ticks req_depth = case a of-      -- See Note [Ticks and mandatory eta expansion]-      _-        | not (null rt_ticks)-        , req_depth <= 0-        ->-            let tick_fun = foldr mkTick fun' rt_ticks-            in rebuild_app' env (a : as) tick_fun floats ss rt_ticks req_depth--      CpeApp (Type arg_ty)-        -> rebuild_app' env as (App fun' (Type arg_ty')) floats ss rt_ticks req_depth-        where-          arg_ty' = cpSubstTy env arg_ty--      CpeApp (Coercion co)-        -> rebuild_app' env as (App fun' (Coercion co')) floats (drop 1 ss) rt_ticks req_depth-        where-            co' = cpSubstCo env co--      CpeApp arg -> do-        let (ss1, ss_rest)  -- See Note [lazyId magic] in GHC.Types.Id.Make-               = case (ss, isLazyExpr arg) of-                   (_   : ss_rest, True)  -> (topDmd, ss_rest)-                   (ss1 : ss_rest, False) -> (ss1,    ss_rest)-                   ([],            _)     -> (topDmd, [])-        (fs, arg') <- cpeArg top_env ss1 arg-        rebuild_app' env as (App fun' arg') (fs `appendFloats` floats) ss_rest rt_ticks (req_depth-1)--      CpeCast co-        -> rebuild_app' env as (Cast fun' co') floats ss rt_ticks req_depth-        where-           co' = cpSubstCo env co-      -- See Note [Ticks and mandatory eta expansion]-      CpeTick tickish-        | tickishPlace tickish == PlaceRuntime-        , req_depth > 0-        -> assert (isProfTick tickish) $-           rebuild_app' env as fun' floats ss (tickish:rt_ticks) req_depth-        | otherwise-        -- See [Floating Ticks in CorePrep]-        -> rebuild_app' env as fun' (addFloat floats (FloatTick tickish)) ss rt_ticks req_depth--isLazyExpr :: CoreExpr -> Bool--- See Note [lazyId magic] in GHC.Types.Id.Make-isLazyExpr (Cast e _)              = isLazyExpr e-isLazyExpr (Tick _ e)              = isLazyExpr e-isLazyExpr (Var f `App` _ `App` _) = f `hasKey` lazyIdKey-isLazyExpr _                       = False--{- Note [runRW magic]-~~~~~~~~~~~~~~~~~~~~~-Some definitions, for instance @runST@, must have careful control over float out-of the bindings in their body. Consider this use of @runST@,--    f x = runST ( \ s -> let (a, s')  = newArray# 100 [] s-                             (_, s'') = fill_in_array_or_something a x s'-                         in freezeArray# a s'' )--If we inline @runST@, we'll get:--    f x = let (a, s')  = newArray# 100 [] realWorld#{-NB-}-              (_, s'') = fill_in_array_or_something a x s'-          in freezeArray# a s''--And now if we allow the @newArray#@ binding to float out to become a CAF,-we end up with a result that is totally and utterly wrong:--    f = let (a, s')  = newArray# 100 [] realWorld#{-NB-} -- YIKES!!!-        in \ x ->-            let (_, s'') = fill_in_array_or_something a x s'-            in freezeArray# a s''--All calls to @f@ will share a {\em single} array! Clearly this is nonsense and-must be prevented.--This is what @runRW#@ gives us: by being inlined extremely late in the-optimization (right before lowering to STG, in CorePrep), we can ensure that-no further floating will occur. This allows us to safely inline things like-@runST@, which are otherwise needlessly expensive (see #10678 and #5916).--'runRW' has a variety of quirks:-- * 'runRW' is known-key with a NOINLINE definition in-   GHC.Magic. This definition is used in cases where runRW is curried.-- * In addition to its normal Haskell definition in GHC.Magic, we give it-   a special late inlining here in CorePrep and GHC.StgToByteCode, avoiding-   the incorrect sharing due to float-out noted above.-- * It is levity-polymorphic:--    runRW# :: forall (r1 :: RuntimeRep). (o :: TYPE r)-           => (State# RealWorld -> (# State# RealWorld, o #))-           -> (# State# RealWorld, o #)-- * It has some special simplification logic to allow unboxing of results when-   runRW# appears in a strict context. See Note [Simplification of runRW#]-   below.-- * Since its body is inlined, we allow runRW#'s argument to contain jumps to-   join points. That is, the following is allowed:--    join j x = ...-    in runRW# @_ @_ (\s -> ... jump j 42 ...)--   The Core Linter knows about this. See Note [Linting of runRW#] in-   GHC.Core.Lint for details.--   The occurrence analyser and SetLevels also know about this, as described in-   Note [Simplification of runRW#].--Other relevant Notes:-- * Note [Simplification of runRW#] below, describing a transformation of runRW-   applications in strict contexts performed by the simplifier.- * Note [Linting of runRW#] in GHC.Core.Lint- * Note [runRW arg] below, describing a non-obvious case where the-   late-inlining could go wrong.--- Note [runRW arg]-~~~~~~~~~~~~~~~~~~~-Consider the Core program (from #11291),--   runRW# (case bot of {})--The late inlining logic in cpe_app would transform this into:--   (case bot of {}) realWorld#--Which would rise to a panic in CoreToStg.myCollectArgs, which expects only-variables in function position.--However, as runRW#'s strictness signature captures the fact that it will call-its argument this can't happen: the simplifier will transform the bottoming-application into simply (case bot of {}).--Note that this reasoning does *not* apply to non-bottoming continuations like:--    hello :: Bool -> Int-    hello n =-      runRW# (-          case n of-            True -> \s -> 23-            _    -> \s -> 10)--Why? The difference is that (case bot of {}) is considered by okCpeArg to be-trivial, consequently cpeArg (which the catch-all case of cpe_app calls on both-the function and the arguments) will forgo binding it to a variable. By-contrast, in the non-bottoming case of `hello` above  the function will be-deemed non-trivial and consequently will be case-bound.---Note [Simplification of runRW#]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Consider the program,--    case runRW# (\s -> I# 42#) of-      I# n# -> f n#--There is no reason why we should allocate an I# constructor given that we-immediately destructure it.--To avoid this the simplifier has a special transformation rule, specific to-runRW#, that pushes a strict context into runRW#'s continuation.  See the-`runRW#` guard in `GHC.Core.Opt.Simplify.rebuildCall`.  That is, it transforms--    K[ runRW# @r @ty cont ]-              ~>-    runRW# @r @ty (\s -> K[cont s])--This has a few interesting implications. Consider, for instance, this program:--    join j = ...-    in case runRW# @r @ty cont of-         result -> jump j result--Performing the transform described above would result in:--    join j x = ...-    in runRW# @r @ty (\s ->-         case cont of in-           result -> jump j result-       )--If runRW# were a "normal" function this call to join point j would not be-allowed in its continuation argument. However, since runRW# is inlined (as-described in Note [runRW magic] above), such join point occurrences are-completely fine. Both occurrence analysis (see the runRW guard in occAnalApp)-and Core Lint (see the App case of lintCoreExpr) have special treatment for-runRW# applications. See Note [Linting of runRW#] for details on the latter.--Moreover, it's helpful to ensure that runRW's continuation isn't floated out-For instance, if we have--    runRW# (\s -> do_something)--where do_something contains only top-level free variables, we may be tempted to-float the argument to the top-level. However, we must resist this urge as since-doing so would then require that runRW# produce an allocation and call, e.g.:--    let lvl = \s -> do_somethign-    in-    ....(runRW# lvl)....--whereas without floating the inlining of the definition of runRW would result-in straight-line code. Consequently, GHC.Core.Opt.SetLevels.lvlApp has special-treatment for runRW# applications, ensure the arguments are not floated as-MFEs.--Now that we float evaluation context into runRW#, we also have to give runRW# a-special higher-order CPR transformer lest we risk #19822. E.g.,--  case runRW# (\s -> doThings) of x -> Data.Text.Text x something something'-      ~>-  runRW# (\s -> case doThings s of x -> Data.Text.Text x something something')--The former had the CPR property, and so should the latter.--Other considered designs---------------------------One design that was rejected was to *require* that runRW#'s continuation be-headed by a lambda. However, this proved to be quite fragile. For instance,-SetLevels is very eager to float bottoming expressions. For instance given-something of the form,--    runRW# @r @ty (\s -> case expr of x -> undefined)--SetLevels will see that the body the lambda is bottoming and will consequently-float it to the top-level (assuming expr has no free coercion variables which-prevent this). We therefore end up with--    runRW# @r @ty (\s -> lvl s)--Which the simplifier will beta reduce, leaving us with--    runRW# @r @ty lvl--Breaking our desired invariant. Ultimately we decided to simply accept that-the continuation may not be a manifest lambda.----- ------------------------------------------------------------------------------      CpeArg: produces a result satisfying CpeArg--- -----------------------------------------------------------------------------Note [ANF-ising literal string arguments]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--Consider a program like,--    data Foo = Foo Addr#--    foo = Foo "turtle"#--When we go to ANFise this we might think that we want to float the string-literal like we do any other non-trivial argument. This would look like,--    foo = u\ [] case "turtle"# of s { __DEFAULT__ -> Foo s }--However, this 1) isn't necessary since strings are in a sense "trivial"; and 2)-wreaks havoc on the CAF annotations that we produce here since we the result-above is caffy since it is updateable. Ideally at some point in the future we-would like to just float the literal to the top level as suggested in #11312,--    s = "turtle"#-    foo = Foo s--However, until then we simply add a special case excluding literals from the-floating done by cpeArg.--}---- | Is an argument okay to CPE?-okCpeArg :: CoreExpr -> Bool--- Don't float literals. See Note [ANF-ising literal string arguments].-okCpeArg (Lit _) = False--- Do not eta expand a trivial argument-okCpeArg expr    = not (exprIsTrivial expr)---- This is where we arrange that a non-trivial argument is let-bound-cpeArg :: CorePrepEnv -> Demand-       -> CoreArg -> UniqSM (Floats, CpeArg)-cpeArg env dmd arg-  = do { (floats1, arg1) <- cpeRhsE env arg     -- arg1 can be a lambda-       ; let arg_ty      = exprType arg1-             is_unlifted = isUnliftedType arg_ty-             want_float  = wantFloatNested NonRecursive dmd is_unlifted-       ; (floats2, arg2) <- if want_float floats1 arg1-                            then return (floats1, arg1)-                            else dontFloat floats1 arg1-                -- Else case: arg1 might have lambdas, and we can't-                --            put them inside a wrapBinds--       ; if okCpeArg arg2-         then do { v <- newVar arg_ty-                 ; let arg3      = cpeEtaExpand (exprArity arg2) arg2-                       arg_float = mkFloat env dmd is_unlifted v arg3-                 ; return (addFloat floats2 arg_float, varToCoreExpr v) }-         else return (floats2, arg2)-       }--{--Note [Floating unlifted arguments]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Consider    C (let v* = expensive in v)--where the "*" indicates "will be demanded".  Usually v will have been-inlined by now, but let's suppose it hasn't (see #2756).  Then we-do *not* want to get--     let v* = expensive in C v--because that has different strictness.  Hence the use of 'allLazy'.-(NB: the let v* turns into a FloatCase, in mkLocalNonRec.)------------------------------------------------------------------------------------ Building the saturated syntax--- -----------------------------------------------------------------------------Note [Eta expansion of hasNoBinding things in CorePrep]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-maybeSaturate deals with eta expanding to saturate things that can't deal with-unsaturated applications (identified by 'hasNoBinding', currently-foreign calls, unboxed tuple/sum constructors, and representation-polymorphic-primitives such as 'coerce' and 'unsafeCoerce#').--Historical Note: Note that eta expansion in CorePrep used to be very fragile-due to the "prediction" of CAFfyness that we used to make during tidying.-We previously saturated primop-applications here as well but due to this fragility (see #16846) we now deal-with this another way, as described in Note [Primop wrappers] in GHC.Builtin.PrimOps.--}--maybeSaturate :: Id -> CpeApp -> Int -> [CoreTickish] -> UniqSM CpeRhs-maybeSaturate fn expr n_args unsat_ticks-  | hasNoBinding fn        -- There's no binding-  = return $ wrapLamBody (\body -> foldr mkTick body unsat_ticks) sat_expr--  | mark_arity > 0 -- A call-by-value function. See Note [CBV Function Ids]-  , not applied_marks-  = assertPpr-      ( not (isJoinId fn)) -- See Note [Do not eta-expand join points]-      ( ppr fn $$ text "expr:" <+> ppr expr $$ text "n_args:" <+> ppr n_args $$-          text "marks:" <+> ppr (idCbvMarks_maybe fn) $$-          text "join_arity" <+> ppr (isJoinId_maybe fn) $$-          text "fn_arity" <+> ppr fn_arity-       ) $-    -- pprTrace "maybeSat"-    --   ( ppr fn $$ text "expr:" <+> ppr expr $$ text "n_args:" <+> ppr n_args $$-    --       text "marks:" <+> ppr (idCbvMarks_maybe fn) $$-    --       text "join_arity" <+> ppr (isJoinId_maybe fn) $$-    --       text "fn_arity" <+> ppr fn_arity $$-    --       text "excess_arity" <+> ppr excess_arity $$-    --       text "mark_arity" <+> ppr mark_arity-    --    ) $-    return sat_expr--  | otherwise-  = assert (null unsat_ticks) $-    return expr-  where-    mark_arity    = idCbvMarkArity fn-    fn_arity      = idArity fn-    excess_arity  = (max fn_arity mark_arity) - n_args-    sat_expr      = cpeEtaExpand excess_arity expr-    applied_marks = n_args >= (length . dropWhile (not . isMarkedCbv) . reverse . expectJust "maybeSaturate" $ (idCbvMarks_maybe fn))-    -- For join points we never eta-expand (See Note [Do not eta-expand join points])-    -- so we assert all arguments that need to be passed cbv are visible so that the backend can evalaute them if required..-{--************************************************************************-*                                                                      *-                Simple GHC.Core operations-*                                                                      *-************************************************************************--}--{---- --------------------------------------------------------------------------------      Eta reduction--- -------------------------------------------------------------------------------Note [Eta expansion]-~~~~~~~~~~~~~~~~~~~~~-Eta expand to match the arity claimed by the binder Remember,-CorePrep must not change arity--Eta expansion might not have happened already, because it is done by-the simplifier only when there at least one lambda already.--NB1:we could refrain when the RHS is trivial (which can happen-    for exported things).  This would reduce the amount of code-    generated (a little) and make things a little worse for-    code compiled without -O.  The case in point is data constructor-    wrappers.--NB2: we have to be careful that the result of etaExpand doesn't-   invalidate any of the assumptions that CorePrep is attempting-   to establish.  One possible cause is eta expanding inside of-   an SCC note - we're now careful in etaExpand to make sure the-   SCC is pushed inside any new lambdas that are generated.--Note [Eta expansion and the CorePrep invariants]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-It turns out to be much much easier to do eta expansion-*after* the main CorePrep stuff.  But that places constraints-on the eta expander: given a CpeRhs, it must return a CpeRhs.--For example here is what we do not want:-                f = /\a -> g (h 3)      -- h has arity 2-After ANFing we get-                f = /\a -> let s = h 3 in g s-and now we do NOT want eta expansion to give-                f = /\a -> \ y -> (let s = h 3 in g s) y--Instead GHC.Core.Opt.Arity.etaExpand gives-                f = /\a -> \y -> let s = h 3 in g s y---}--cpeEtaExpand :: Arity -> CpeRhs -> CpeRhs-cpeEtaExpand arity expr-  | arity == 0 = expr-  | otherwise  = etaExpand arity expr--{--************************************************************************-*                                                                      *-                Floats-*                                                                      *-************************************************************************--Note [Pin demand info on floats]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We pin demand info on floated lets, so that we can see the one-shot thunks.--Note [Speculative evaluation]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Since call-by-value is much cheaper than call-by-need, we case-bind arguments-that are either--  1. Strictly evaluated anyway, according to the DmdSig of the callee, or-  2. ok-for-spec, according to 'exprOkForSpeculation'--While (1) is a no-brainer and always beneficial, (2) is a bit-more subtle, as the careful haddock for 'exprOkForSpeculation'-points out. Still, by case-binding the argument we don't need-to allocate a thunk for it, whose closure must be retained as-long as the callee might evaluate it. And if it is evaluated on-most code paths anyway, we get to turn the unknown eval in the-callee into a known call at the call site.--Very Nasty Wrinkle--We must be very careful not to speculate recursive calls!  Doing so-might well change termination behavior.--That comes up in practice for DFuns, which are considered ok-for-spec,-because they always immediately return a constructor.-See Note [NON-BOTTOM-DICTS invariant] in GHC.Core.--But not so if you speculate the recursive call, as #20836 shows:--  class Foo m => Foo m where-    runFoo :: m a -> m a-  newtype Trans m a = Trans { runTrans :: m a }-  instance Monad m => Foo (Trans m) where-    runFoo = id--(NB: class Foo m => Foo m` looks weird and needs -XUndecidableSuperClasses. The-example in #20836 is more compelling, but boils down to the same thing.)-This program compiles to the following DFun for the `Trans` instance:--  Rec {-  $fFooTrans-    = \ @m $dMonad -> C:Foo ($fFooTrans $dMonad) (\ @a -> id)-  end Rec }--Note that the DFun immediately terminates and produces a dictionary, just-like DFuns ought to, but it calls itself recursively to produce the `Foo m`-dictionary. But alas, if we treat `$fFooTrans` as always-terminating, so-that we can speculate its calls, and hence use call-by-value, we get:--  $fFooTrans-    = \ @m $dMonad -> case ($fFooTrans $dMonad) of sc ->-                      C:Foo sc (\ @a -> id)--and that's an infinite loop!-Note that this bad-ness only happens in `$fFooTrans`'s own RHS. In the-*body* of the letrec, it's absolutely fine to use call-by-value on-`foo ($fFooTrans d)`.--Our solution is this: we track in cpe_rec_ids the set of enclosing-recursively-bound Ids, the RHSs of which we are currently transforming and then-in 'exprOkForSpecEval' (a special entry point to 'exprOkForSpeculation',-basically) we'll say that any binder in this set is not ok-for-spec.--Note if we have a letrec group `Rec { f1 = rhs1; ...; fn = rhsn }`, and we-prep up `rhs1`, we have to include not only `f1`, but all binders of the group-`f1..fn` in this set, otherwise our fix is not robust wrt. mutual recursive-DFuns.--NB: If at some point we decide to have a termination analysis for general-functions (#8655, !1866), we need to take similar precautions for (guarded)-recursive functions:--  repeat x = x : repeat x--Same problem here: As written, repeat evaluates rapidly to WHNF. So `repeat x`-is a cheap call that we are willing to speculate, but *not* in repeat's RHS.-Fortunately, pce_rec_ids already has all the information we need in that case.--The problem is very similar to Note [Eta reduction in recursive RHSs].-Here as well as there it is *unsound* to change the termination properties-of the very function whose termination properties we are exploiting.--It is also similar to Note [Do not strictify a DFun's parameter dictionaries],-where marking recursive DFuns (of undecidable *instances*) strict in dictionary-*parameters* leads to quite the same change in termination as above.--}--data FloatingBind-  = FloatLet CoreBind    -- Rhs of bindings are CpeRhss-                         -- They are always of lifted type;-                         -- unlifted ones are done with FloatCase-- | FloatCase-      CpeBody         -- Always ok-for-speculation-      Id              -- Case binder-      AltCon [Var]    -- Single alternative-      Bool            -- Ok-for-speculation; False of a strict,-                      -- but lifted binding-- -- | See Note [Floating Ticks in CorePrep]- | FloatTick CoreTickish--data Floats = Floats OkToSpec (OrdList FloatingBind)--instance Outputable FloatingBind where-  ppr (FloatLet b) = ppr b-  ppr (FloatCase r b k bs ok) = text "case" <> braces (ppr ok) <+> ppr r-                                <+> text "of"<+> ppr b <> text "@"-                                <> case bs of-                                   [] -> ppr k-                                   _  -> parens (ppr k <+> ppr bs)-  ppr (FloatTick t) = ppr t--instance Outputable Floats where-  ppr (Floats flag fs) = text "Floats" <> brackets (ppr flag) <+>-                         braces (vcat (map ppr (fromOL fs)))--instance Outputable OkToSpec where-  ppr OkToSpec    = text "OkToSpec"-  ppr IfUnboxedOk = text "IfUnboxedOk"-  ppr NotOkToSpec = text "NotOkToSpec"---- Can we float these binds out of the rhs of a let?  We cache this decision--- to avoid having to recompute it in a non-linear way when there are--- deeply nested lets.-data OkToSpec-   = OkToSpec           -- Lazy bindings of lifted type-   | IfUnboxedOk        -- A mixture of lazy lifted bindings and n-                        -- ok-to-speculate unlifted bindings-   | NotOkToSpec        -- Some not-ok-to-speculate unlifted bindings--mkFloat :: CorePrepEnv -> Demand -> Bool -> Id -> CpeRhs -> FloatingBind-mkFloat env dmd is_unlifted bndr rhs-  | is_strict || ok_for_spec -- See Note [Speculative evaluation]-  , not is_hnf  = FloatCase rhs bndr DEFAULT [] ok_for_spec-    -- Don't make a case for a HNF binding, even if it's strict-    -- Otherwise we get  case (\x -> e) of ...!--  | is_unlifted = FloatCase rhs bndr DEFAULT [] True-      -- we used to assertPpr ok_for_spec (ppr rhs) here, but it is now disabled-      -- because exprOkForSpeculation isn't stable under ANF-ing. See for-      -- example #19489 where the following unlifted expression:-      ---      --    GHC.Prim.(#|_#) @LiftedRep @LiftedRep @[a_ax0] @[a_ax0]-      --                    (GHC.Types.: @a_ax0 a2_agq a3_agl)-      ---      -- is ok-for-spec but is ANF-ised into:-      ---      --    let sat = GHC.Types.: @a_ax0 a2_agq a3_agl-      --    in GHC.Prim.(#|_#) @LiftedRep @LiftedRep @[a_ax0] @[a_ax0] sat-      ---      -- which isn't ok-for-spec because of the let-expression.--  | is_hnf      = FloatLet (NonRec bndr                       rhs)-  | otherwise   = FloatLet (NonRec (setIdDemandInfo bndr dmd) rhs)-                   -- See Note [Pin demand info on floats]-  where-    is_hnf      = exprIsHNF rhs-    is_strict   = isStrUsedDmd dmd-    ok_for_spec = exprOkForSpecEval (not . is_rec_call) rhs-    is_rec_call = (`elemUnVarSet` cpe_rec_ids env)--emptyFloats :: Floats-emptyFloats = Floats OkToSpec nilOL--isEmptyFloats :: Floats -> Bool-isEmptyFloats (Floats _ bs) = isNilOL bs--wrapBinds :: Floats -> CpeBody -> CpeBody-wrapBinds (Floats _ binds) body-  = foldrOL mk_bind body binds-  where-    mk_bind (FloatCase rhs bndr con bs _) body = Case rhs bndr (exprType body) [Alt con bs body]-    mk_bind (FloatLet bind)               body = Let bind body-    mk_bind (FloatTick tickish)           body = mkTick tickish body--addFloat :: Floats -> FloatingBind -> Floats-addFloat (Floats ok_to_spec floats) new_float-  = Floats (combine ok_to_spec (check new_float)) (floats `snocOL` new_float)-  where-    check (FloatLet {})  = OkToSpec-    check (FloatCase _ _ _ _ ok_for_spec)-      | ok_for_spec = IfUnboxedOk-      | otherwise   = NotOkToSpec-    check FloatTick{}    = OkToSpec-        -- The ok-for-speculation flag says that it's safe to-        -- float this Case out of a let, and thereby do it more eagerly-        -- We need the top-level flag because it's never ok to float-        -- an unboxed binding to the top level--unitFloat :: FloatingBind -> Floats-unitFloat = addFloat emptyFloats--appendFloats :: Floats -> Floats -> Floats-appendFloats (Floats spec1 floats1) (Floats spec2 floats2)-  = Floats (combine spec1 spec2) (floats1 `appOL` floats2)--concatFloats :: [Floats] -> OrdList FloatingBind-concatFloats = foldr (\ (Floats _ bs1) bs2 -> appOL bs1 bs2) nilOL--combine :: OkToSpec -> OkToSpec -> OkToSpec-combine NotOkToSpec _ = NotOkToSpec-combine _ NotOkToSpec = NotOkToSpec-combine IfUnboxedOk _ = IfUnboxedOk-combine _ IfUnboxedOk = IfUnboxedOk-combine _ _           = OkToSpec--deFloatTop :: Floats -> [CoreBind]--- For top level only; we don't expect any FloatCases-deFloatTop (Floats _ floats)-  = foldrOL get [] floats-  where-    get (FloatLet b)               bs = get_bind b                 : bs-    get (FloatCase body var _ _ _) bs = get_bind (NonRec var body) : bs-    get b _ = pprPanic "corePrepPgm" (ppr b)--    -- See Note [Dead code in CorePrep]-    get_bind (NonRec x e) = NonRec x (occurAnalyseExpr e)-    get_bind (Rec xes)    = Rec [(x, occurAnalyseExpr e) | (x, e) <- xes]-------------------------------------------------------------------------------canFloat :: Floats -> CpeRhs -> Maybe (Floats, CpeRhs)-canFloat (Floats ok_to_spec fs) rhs-  | OkToSpec <- ok_to_spec           -- Worth trying-  , Just fs' <- go nilOL (fromOL fs)-  = Just (Floats OkToSpec fs', rhs)-  | otherwise-  = Nothing-  where-    go :: OrdList FloatingBind -> [FloatingBind]-       -> Maybe (OrdList FloatingBind)--    go (fbs_out) [] = Just fbs_out--    go fbs_out (fb@(FloatLet _) : fbs_in)-      = go (fbs_out `snocOL` fb) fbs_in--    go fbs_out (ft@FloatTick{} : fbs_in)-      = go (fbs_out `snocOL` ft) fbs_in--    go _ (FloatCase{} : _) = Nothing---wantFloatNested :: RecFlag -> Demand -> Bool -> Floats -> CpeRhs -> Bool-wantFloatNested is_rec dmd is_unlifted floats rhs-  =  isEmptyFloats floats-  || isStrUsedDmd dmd-  || is_unlifted-  || (allLazyNested is_rec floats && exprIsHNF rhs)-        -- Why the test for allLazyNested?-        --      v = f (x `divInt#` y)-        -- we don't want to float the case, even if f has arity 2,-        -- because floating the case would make it evaluated too early--allLazyTop :: Floats -> Bool-allLazyTop (Floats OkToSpec _) = True-allLazyTop _                   = False--allLazyNested :: RecFlag -> Floats -> Bool-allLazyNested _      (Floats OkToSpec    _) = True-allLazyNested _      (Floats NotOkToSpec _) = False-allLazyNested is_rec (Floats IfUnboxedOk _) = isNonRec is_rec--{--************************************************************************-*                                                                      *-                Cloning-*                                                                      *-************************************************************************--}---- ------------------------------------------------------------------------------                      The environment--- -----------------------------------------------------------------------------{- Note [Inlining in CorePrep]-~~~~~~~~~~~~~~~~~~~~~~~~~~~-There is a subtle but important invariant that must be upheld in the output-of CorePrep: there are no "trivial" updatable thunks.  Thus, this Core-is impermissible:--     let x :: ()-         x = y--(where y is a reference to a GLOBAL variable).  Thunks like this are silly:-they can always be profitably replaced by inlining x with y. Consequently,-the code generator/runtime does not bother implementing this properly-(specifically, there is no implementation of stg_ap_0_upd_info, which is the-stack frame that would be used to update this thunk.  The "0" means it has-zero free variables.)--In general, the inliner is good at eliminating these let-bindings.  However,-there is one case where these trivial updatable thunks can arise: when-we are optimizing away 'lazy' (see Note [lazyId magic], and also-'cpeRhsE'.)  Then, we could have started with:--     let x :: ()-         x = lazy @ () y--which is a perfectly fine, non-trivial thunk, but then CorePrep will-drop 'lazy', giving us 'x = y' which is trivial and impermissible.-The solution is CorePrep to have a miniature inlining pass which deals-with cases like this.  We can then drop the let-binding altogether.--Why does the removal of 'lazy' have to occur in CorePrep?-The gory details are in Note [lazyId magic] in GHC.Types.Id.Make, but the-main reason is that lazy must appear in unfoldings (optimizer-output) and it must prevent call-by-value for catch# (which-is implemented by CorePrep.)--An alternate strategy for solving this problem is to have the-inliner treat 'lazy e' as a trivial expression if 'e' is trivial.-We decided not to adopt this solution to keep the definition-of 'exprIsTrivial' simple.--There is ONE caveat however: for top-level bindings we have-to preserve the binding so that we float the (hacky) non-recursive-binding for data constructors; see Note [Data constructor workers].--Note [CorePrep inlines trivial CoreExpr not Id]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Why does cpe_env need to be an IdEnv CoreExpr, as opposed to an-IdEnv Id?  Naively, we might conjecture that trivial updatable thunks-as per Note [Inlining in CorePrep] always have the form-'lazy @ SomeType gbl_id'.  But this is not true: the following is-perfectly reasonable Core:--     let x :: ()-         x = lazy @ (forall a. a) y @ Bool--When we inline 'x' after eliminating 'lazy', we need to replace-occurrences of 'x' with 'y @ bool', not just 'y'.  Situations like-this can easily arise with higher-rank types; thus, cpe_env must-map to CoreExprs, not Ids.---}--data CorePrepConfig = CorePrepConfig-  { cp_catchNonexhaustiveCases :: !Bool-  -- ^ Whether to generate a default alternative with ``error`` in these-  -- cases. This is helpful when debugging demand analysis or type-  -- checker bugs which can sometimes manifest as segmentation faults.--  , cp_convertNumLit           :: !(LitNumType -> Integer -> Maybe CoreExpr)-  -- ^ Convert some numeric literals (Integer, Natural) into their final-  -- Core form.-  }--data CorePrepEnv-  = CPE { cpe_config          :: !CorePrepConfig-        -- ^ This flag is intended to aid in debugging strictness-        -- analysis bugs. These are particularly nasty to chase down as-        -- they may manifest as segmentation faults. When this flag is-        -- enabled we instead produce an 'error' expression to catch-        -- the case where a function we think should bottom-        -- unexpectedly returns.-        , cpe_env             :: IdEnv CoreExpr   -- Clone local Ids-        -- ^ This environment is used for three operations:-        ---        --      1. To support cloning of local Ids so that they are-        --      all unique (see item (6) of CorePrep overview).-        ---        --      2. To support beta-reduction of runRW, see-        --      Note [runRW magic] and Note [runRW arg].-        ---        --      3. To let us inline trivial RHSs of non top-level let-bindings,-        --      see Note [lazyId magic], Note [Inlining in CorePrep]-        --      and Note [CorePrep inlines trivial CoreExpr not Id] (#12076)--        , cpe_tyco_env :: Maybe CpeTyCoEnv -- See Note [CpeTyCoEnv]--        , cpe_rec_ids         :: UnVarSet -- Faster OutIdSet; See Note [Speculative evaluation]-    }--mkInitialCorePrepEnv :: CorePrepConfig -> CorePrepEnv-mkInitialCorePrepEnv cfg = CPE-      { cpe_config        = cfg-      , cpe_env           = emptyVarEnv-      , cpe_tyco_env      = Nothing-      , cpe_rec_ids       = emptyUnVarSet-      }--extendCorePrepEnv :: CorePrepEnv -> Id -> Id -> CorePrepEnv-extendCorePrepEnv cpe id id'-    = cpe { cpe_env = extendVarEnv (cpe_env cpe) id (Var id') }--extendCorePrepEnvExpr :: CorePrepEnv -> Id -> CoreExpr -> CorePrepEnv-extendCorePrepEnvExpr cpe id expr-    = cpe { cpe_env = extendVarEnv (cpe_env cpe) id expr }--extendCorePrepEnvList :: CorePrepEnv -> [(Id,Id)] -> CorePrepEnv-extendCorePrepEnvList cpe prs-    = cpe { cpe_env = extendVarEnvList (cpe_env cpe)-                        (map (\(id, id') -> (id, Var id')) prs) }--lookupCorePrepEnv :: CorePrepEnv -> Id -> CoreExpr-lookupCorePrepEnv cpe id-  = case lookupVarEnv (cpe_env cpe) id of-        Nothing  -> Var id-        Just exp -> exp--enterRecGroupRHSs :: CorePrepEnv -> [OutId] -> CorePrepEnv-enterRecGroupRHSs env grp-  = env { cpe_rec_ids = extendUnVarSetList grp (cpe_rec_ids env) }-----------------------------------------------------------------------------------           CpeTyCoEnv--- -----------------------------------------------------------------------------{- Note [CpeTyCoEnv]-~~~~~~~~~~~~~~~~~~~~-The cpe_tyco_env :: Maybe CpeTyCoEnv field carries a substitution-for type and coercion variables--* We need the coercion substitution to support the elimination of-  unsafeEqualityProof (see Note [Unsafe coercions])--* We need the type substitution in case one of those unsafe-  coercions occurs in the kind of tyvar binder (sigh)--We don't need an in-scope set because we don't clone any of these-binders at all, so no new capture can take place.--The cpe_tyco_env is almost always empty -- it only gets populated-when we get under an usafeEqualityProof.  Hence the Maybe CpeTyCoEnv,-which makes everything into a no-op in the common case.--}--data CpeTyCoEnv = TCE TvSubstEnv CvSubstEnv--emptyTCE :: CpeTyCoEnv-emptyTCE = TCE emptyTvSubstEnv emptyCvSubstEnv--extend_tce_cv :: CpeTyCoEnv -> CoVar -> Coercion -> CpeTyCoEnv-extend_tce_cv (TCE tv_env cv_env) cv co-  = TCE tv_env (extendVarEnv cv_env cv co)--extend_tce_tv :: CpeTyCoEnv -> TyVar -> Type -> CpeTyCoEnv-extend_tce_tv (TCE tv_env cv_env) tv ty-  = TCE (extendVarEnv tv_env tv ty) cv_env--lookup_tce_cv :: CpeTyCoEnv -> CoVar -> Coercion-lookup_tce_cv (TCE _ cv_env) cv-  = case lookupVarEnv cv_env cv of-        Just co -> co-        Nothing -> mkCoVarCo cv--lookup_tce_tv :: CpeTyCoEnv -> TyVar -> Type-lookup_tce_tv (TCE tv_env _) tv-  = case lookupVarEnv tv_env tv of-        Just ty -> ty-        Nothing -> mkTyVarTy tv--extendCoVarEnv :: CorePrepEnv -> CoVar -> Coercion -> CorePrepEnv-extendCoVarEnv cpe@(CPE { cpe_tyco_env = mb_tce }) cv co-  = cpe { cpe_tyco_env = Just (extend_tce_cv tce cv co) }-  where-    tce = mb_tce `orElse` emptyTCE---cpSubstTy :: CorePrepEnv -> Type -> Type-cpSubstTy (CPE { cpe_tyco_env = mb_env }) ty-  = case mb_env of-      Just env -> runIdentity (subst_ty env ty)-      Nothing  -> ty--cpSubstCo :: CorePrepEnv -> Coercion -> Coercion-cpSubstCo (CPE { cpe_tyco_env = mb_env }) co-  = case mb_env of-      Just tce -> runIdentity (subst_co tce co)-      Nothing  -> co--subst_tyco_mapper :: TyCoMapper CpeTyCoEnv Identity-subst_tyco_mapper = TyCoMapper-  { tcm_tyvar      = \env tv -> return (lookup_tce_tv env tv)-  , tcm_covar      = \env cv -> return (lookup_tce_cv env cv)-  , tcm_hole       = \_ hole -> pprPanic "subst_co_mapper:hole" (ppr hole)-  , tcm_tycobinder = \env tcv _vis k -> if isTyVar tcv-                                        then uncurry k (subst_tv_bndr env tcv)-                                        else uncurry k (subst_cv_bndr env tcv)-  , tcm_tycon      = \tc -> return tc }--subst_ty :: CpeTyCoEnv -> Type     -> Identity Type-subst_co :: CpeTyCoEnv -> Coercion -> Identity Coercion-(subst_ty, _, subst_co, _) = mapTyCoX subst_tyco_mapper--cpSubstTyVarBndr :: CorePrepEnv -> TyVar -> (CorePrepEnv, TyVar)-cpSubstTyVarBndr env@(CPE { cpe_tyco_env = mb_env }) tv-  = case mb_env of-      Nothing  -> (env, tv)-      Just tce -> (env { cpe_tyco_env = Just tce' }, tv')-               where-                  (tce', tv') = subst_tv_bndr tce tv--subst_tv_bndr :: CpeTyCoEnv -> TyVar -> (CpeTyCoEnv, TyVar)-subst_tv_bndr tce tv-  = (extend_tce_tv tce tv (mkTyVarTy tv'), tv')-  where-    tv'   = mkTyVar (tyVarName tv) kind'-    kind' = runIdentity $ subst_ty tce $ tyVarKind tv--cpSubstCoVarBndr :: CorePrepEnv -> CoVar -> (CorePrepEnv, CoVar)-cpSubstCoVarBndr env@(CPE { cpe_tyco_env = mb_env }) cv-  = case mb_env of-      Nothing  -> (env, cv)-      Just tce -> (env { cpe_tyco_env = Just tce' }, cv')-               where-                  (tce', cv') = subst_cv_bndr tce cv--subst_cv_bndr :: CpeTyCoEnv -> CoVar -> (CpeTyCoEnv, CoVar)-subst_cv_bndr tce cv-  = (extend_tce_cv tce cv (mkCoVarCo cv'), cv')-  where-    cv' = mkCoVar (varName cv) ty'-    ty' = runIdentity (subst_ty tce $ varType cv)----------------------------------------------------------------------------------- Cloning binders--- -----------------------------------------------------------------------------cpCloneBndrs :: CorePrepEnv -> [InVar] -> UniqSM (CorePrepEnv, [OutVar])-cpCloneBndrs env bs = mapAccumLM cpCloneBndr env bs--cpCloneBndr  :: CorePrepEnv -> InVar -> UniqSM (CorePrepEnv, OutVar)-cpCloneBndr env bndr-  | isTyVar bndr-  = return (cpSubstTyVarBndr env bndr)--  | isCoVar bndr-  = return (cpSubstCoVarBndr env bndr)--  | otherwise-  = do { bndr' <- clone_it bndr--       -- Drop (now-useless) rules/unfoldings-       -- See Note [Drop unfoldings and rules]-       -- and Note [Preserve evaluatedness] in GHC.Core.Tidy-       -- And force it.. otherwise the old unfolding is just retained.-       -- See #22071-       ; let !unfolding' = trimUnfolding (realIdUnfolding bndr)-                          -- Simplifier will set the Id's unfolding--             bndr'' = bndr' `setIdUnfolding`      unfolding'-                            `setIdSpecialisation` emptyRuleInfo--       ; return (extendCorePrepEnv env bndr bndr'', bndr'') }-  where-    clone_it bndr-      | isLocalId bndr-      = do { uniq <- getUniqueM-           ; let ty' = cpSubstTy env (idType bndr)-           ; return (setVarUnique (setIdType bndr ty') uniq) }--      | otherwise   -- Top level things, which we don't want-                    -- to clone, have become GlobalIds by now-      = return bndr--{- Note [Drop unfoldings and rules]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We want to drop the unfolding/rules on every Id:--  - We are now past interface-file generation, and in the-    codegen pipeline, so we really don't need full unfoldings/rules--  - The unfolding/rule may be keeping stuff alive that we'd like-    to discard.  See  Note [Dead code in CorePrep]--  - Getting rid of unnecessary unfoldings reduces heap usage--  - We are changing uniques, so if we didn't discard unfoldings/rules-    we'd have to substitute in them--HOWEVER, we want to preserve evaluated-ness;-see Note [Preserve evaluatedness] in GHC.Core.Tidy.--}----------------------------------------------------------------------------------- Cloning ccall Ids; each must have a unique name,--- to give the code generator a handle to hang it on--- -----------------------------------------------------------------------------fiddleCCall :: Id -> UniqSM Id-fiddleCCall id-  | isFCallId id = (id `setVarUnique`) <$> getUniqueM-  | otherwise    = return id----------------------------------------------------------------------------------- Generating new binders--- -----------------------------------------------------------------------------newVar :: Type -> UniqSM Id-newVar ty- = seqType ty `seq` mkSysLocalOrCoVarM (fsLit "sat") ManyTy ty------------------------------------------------------------------------------------ Floating ticks--- --------------------------------------------------------------------------------- Note [Floating Ticks in CorePrep]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- It might seem counter-intuitive to float ticks by default, given--- that we don't actually want to move them if we can help it. On the--- other hand, nothing gets very far in CorePrep anyway, and we want--- to preserve the order of let bindings and tick annotations in--- relation to each other. For example, if we just wrapped let floats--- when they pass through ticks, we might end up performing the--- following transformation:------   src<...> let foo = bar in baz---   ==>  let foo = src<...> bar in src<...> baz------ Because the let-binding would float through the tick, and then--- immediately materialize, achieving nothing but decreasing tick--- accuracy. The only special case is the following scenario:------   let foo = src<...> (let a = b in bar) in baz---   ==>  let foo = src<...> bar; a = src<...> b in baz------ Here we would not want the source tick to end up covering "baz" and--- therefore refrain from pushing ticks outside. Instead, we copy them--- into the floating binds (here "a") in cpePair. Note that where "b"--- or "bar" are (value) lambdas we have to push the annotations--- further inside in order to uphold our rules.------ All of this is implemented below in @wrapTicks@.---- | Like wrapFloats, but only wraps tick floats-wrapTicks :: Floats -> CoreExpr -> (Floats, CoreExpr)-wrapTicks (Floats flag floats0) expr =-    (Floats flag (toOL $ reverse floats1), foldr mkTick expr (reverse ticks1))-  where (floats1, ticks1) = foldlOL go ([], []) $ floats0-        -- Deeply nested constructors will produce long lists of-        -- redundant source note floats here. We need to eliminate-        -- those early, as relying on mkTick to spot it after the fact-        -- can yield O(n^3) complexity [#11095]-        go (floats, ticks) (FloatTick t)-          = assert (tickishPlace t == PlaceNonLam)-            (floats, if any (flip tickishContains t) ticks-                     then ticks else t:ticks)-        go (floats, ticks) f-          = (foldr wrap f (reverse ticks):floats, ticks)--        wrap t (FloatLet bind)           = FloatLet (wrapBind t bind)-        wrap t (FloatCase r b con bs ok) = FloatCase (mkTick t r) b con bs ok-        wrap _ other                     = pprPanic "wrapTicks: unexpected float!"-                                             (ppr other)+{-# LANGUAGE ViewPatterns #-}++{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}++{-+(c) The University of Glasgow, 1994-2006+++Core pass to saturate constructors and PrimOps+-}++module GHC.CoreToStg.Prep+   ( CorePrepConfig (..)+   , CorePrepPgmConfig (..)+   , corePrepPgm+   , corePrepExpr+   , mkConvertNumLiteral+   )+where++import GHC.Prelude++import GHC.Platform++import GHC.Driver.Flags++import GHC.Tc.Utils.Env+import GHC.Unit++import GHC.Builtin.Names+import GHC.Builtin.Types++import GHC.Core.Utils+import GHC.Core.Opt.Arity+import GHC.Core.Lint    ( EndPassConfig(..), endPassIO )+import GHC.Core+import GHC.Core.Subst+import GHC.Core.Make hiding( FloatBind(..) )   -- We use our own FloatBind here+import GHC.Core.Type+import GHC.Core.Coercion+import GHC.Core.TyCon+import GHC.Core.DataCon+import GHC.Core.Opt.OccurAnal++import GHC.Data.Maybe+import GHC.Data.OrdList+import GHC.Data.FastString+import GHC.Data.Graph.UnVar++import GHC.Utils.Error+import GHC.Utils.Misc+import GHC.Utils.Panic+import GHC.Utils.Outputable+import GHC.Utils.Monad  ( mapAccumLM )+import GHC.Utils.Logger++import GHC.Types.Demand+import GHC.Types.Var+import GHC.Types.Id+import GHC.Types.Id.Info+import GHC.Types.Id.Make ( realWorldPrimId )+import GHC.Types.Basic+import GHC.Types.Name   ( Name, NamedThing(..), nameSrcSpan, isInternalName )+import GHC.Types.SrcLoc ( SrcSpan(..), realSrcLocSpan, mkRealSrcLoc )+import GHC.Types.Literal+import GHC.Types.Tickish+import GHC.Types.TyThing+import GHC.Types.Unique.Supply++import Data.List        ( unfoldr )+import Control.Monad++{-+Note [CorePrep Overview]+~~~~~~~~~~~~~~~~~~~~~~~~++The goal of this pass is to prepare for code generation.++1.  Saturate constructor and primop applications.++2.  Convert to A-normal form; that is, function arguments+    are always variables.++    * Use case for strict arguments:+        f E ==> case E of x -> f x+        (where f is strict)++    * Use let for non-trivial lazy arguments+        f E ==> let x = E in f x+        (were f is lazy and x is non-trivial)++3.  Similarly, convert any unboxed lets into cases.+    [I'm experimenting with leaving 'ok-for-speculation'+     rhss in let-form right up to this point.]++4.  Ensure that *value* lambdas only occur as the RHS of a binding+    (The code generator can't deal with anything else.)+    Type lambdas are ok, however, because the code gen discards them.++5.  ANF-isation results in additional bindings that can obscure values.+    We float these out; see Note [Floating in CorePrep].++6.  Clone all local Ids.  See Note [Cloning in CorePrep]++7.  Give each dynamic CCall occurrence a fresh unique; this is+    rather like the cloning step above.++8.  Inject bindings for the "implicit" Ids:+        * Constructor wrappers+        * Constructor workers+    We want curried definitions for all of these in case they+    aren't inlined by some caller.++ 9. Convert bignum literals into their core representation.++10. Uphold tick consistency while doing this: We move ticks out of+    (non-type) applications where we can, and make sure that we+    annotate according to scoping rules when floating.++11. Collect cost centres (including cost centres in unfoldings) if we're in+    profiling mode. We have to do this here because we won't have unfoldings+    after this pass (see `trimUnfolding` and Note [Drop unfoldings and rules].++12. Eliminate some magic Ids, specifically+     runRW# (\s. e)  ==>  e[readWorldId/s]+             lazy e  ==>  e (see Note [lazyId magic] in GHC.Types.Id.Make)+         noinline e  ==>  e+           nospec e  ==>  e+     ToDo:  keepAlive# ...+    This is done in cpeApp++This is all done modulo type applications and abstractions, so that+when type erasure is done for conversion to STG, we don't end up with+any trivial or useless bindings.++Note [CorePrep invariants]+~~~~~~~~~~~~~~~~~~~~~~~~~~+Here is the syntax of the Core produced by CorePrep:++    Trivial expressions+       arg ::= lit |  var+              | arg ty  |  /\a. arg+              | truv co  |  /\c. arg  |  arg |> co++    Applications+       app ::= lit  |  var  |  app arg  |  app ty  | app co | app |> co++    Expressions+       body ::= app+              | let(rec) x = rhs in body     -- Boxed only+              | case app of pat -> body+              | /\a. body | /\c. body+              | body |> co++    Right hand sides (only place where value lambdas can occur)+       rhs ::= /\a.rhs  |  \x.rhs  |  body++We define a synonym for each of these non-terminals.  Functions+with the corresponding name produce a result in that syntax.++Note [Cloning in CorePrep]+~~~~~~~~~~~~~~~~~~~~~~~~~~+In CorePrep we+* Always clone non-CoVar Ids, so each has a unique Unique+* Sometimes clone CoVars and TyVars++We always clone non-CoVarIds, for three reasons++1. Things associated with labels in the final code must be truly unique in+   order to avoid labels being shadowed in the final output.++2. Even binders without info tables like function arguments or alternative+   bound binders must be unique at least in their type/unique combination.+   We only emit a single declaration for each binder when compiling to C+   so if binders are not unique we would either get duplicate declarations+   or misstyped variables. The later happend in #22402.++3. We heavily use unique-keyed maps in the backend which can go wrong when+   ids with the same unique are meant to represent the same variable.++Generally speaking we don't clone TyVars or CoVars. The code gen doesn't need+that (they are erased), and doing so would be tiresome because then we'd need+to substitute in types and coercions.  But sometimes need to: see+Note [Cloning CoVars and TyVars]++Note [Cloning CoVars and TyVars]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Normally we don't need to clone TyVars and CoVars, but there is one occasion+when we do (see #24463).  When we have+    case unsafeEqualityProof ... of UnsafeRefl g -> ...+we try to float it, using UnsafeEqualityCase.+Why?  See (U3) in Note [Implementing unsafeCoerce]++Alas, floating it widens the scope of `g`, and that led to catastrophe in+#24463, when two identically-named g's shadowed.++Solution: clone `g`; see `cpCloneCoVarBndr`.++BUT once we clone `g` we must apply the cloning substitution to all types+and coercions.  But that in turn means that, given a binder like+   /\ (a :: kind |> g). blah+we must substitute in a's kind, and hence need to substitute for `a`+itself in `blah`.++So our plan is:+  * Maintain a full Subst in `cpe_subst`++  * Clone a CoVar when we we meet an `isUnsafeEqualityCase`;+    otherwise TyVar/CoVar binders are never cloned.++  * So generally the TCvSubst is empty++  * Apply the substitution to type and coercion arguments in Core; but+    happily `substTy` has a no-op short-cut for an empty TCvSubst, so this+    is usually very cheap.++  * In `cpCloneBndr`, for a tyvar/covar binder, check for an empty substitution;+    in that case just do nothing+-}++type CpeArg  = CoreExpr    -- Non-terminal 'arg'+type CpeApp  = CoreExpr    -- Non-terminal 'app'+type CpeBody = CoreExpr    -- Non-terminal 'body'+type CpeRhs  = CoreExpr    -- Non-terminal 'rhs'++{-+************************************************************************+*                                                                      *+                Top level stuff+*                                                                      *+************************************************************************+-}++data CorePrepPgmConfig = CorePrepPgmConfig+  { cpPgm_endPassConfig     :: !EndPassConfig+  , cpPgm_generateDebugInfo :: !Bool+  }++corePrepPgm :: Logger+            -> CorePrepConfig+            -> CorePrepPgmConfig+            -> Module -> ModLocation -> CoreProgram -> [TyCon]+            -> IO CoreProgram+corePrepPgm logger cp_cfg pgm_cfg+            this_mod mod_loc binds data_tycons =+    withTiming logger+               (text "CorePrep"<+>brackets (ppr this_mod))+               (\a -> a `seqList` ()) $ do+    us <- mkSplitUniqSupply 's'+    let initialCorePrepEnv = mkInitialCorePrepEnv cp_cfg++    let+        implicit_binds = mkDataConWorkers+          (cpPgm_generateDebugInfo pgm_cfg)+          mod_loc data_tycons+            -- NB: we must feed mkImplicitBinds through corePrep too+            -- so that they are suitably cloned and eta-expanded++        binds_out = initUs_ us $ do+                      floats1 <- corePrepTopBinds initialCorePrepEnv binds+                      floats2 <- corePrepTopBinds initialCorePrepEnv implicit_binds+                      return (deFloatTop (floats1 `zipFloats` floats2))++    endPassIO logger (cpPgm_endPassConfig pgm_cfg)+              binds_out []+    return binds_out++corePrepExpr :: Logger -> CorePrepConfig -> CoreExpr -> IO CoreExpr+corePrepExpr logger config expr = do+    withTiming logger (text "CorePrep [expr]") (\e -> e `seq` ()) $ do+      us <- mkSplitUniqSupply 's'+      let initialCorePrepEnv = mkInitialCorePrepEnv config+      let new_expr = initUs_ us (cpeBodyNF initialCorePrepEnv expr)+      putDumpFileMaybe logger Opt_D_dump_prep "CorePrep" FormatCore (ppr new_expr)+      return new_expr++corePrepTopBinds :: CorePrepEnv -> [CoreBind] -> UniqSM Floats+-- Note [Floating out of top level bindings]+corePrepTopBinds initialCorePrepEnv binds+  = go initialCorePrepEnv binds+  where+    go _   []             = return emptyFloats+    go env (bind : binds) = do (env', floats, maybe_new_bind)+                                 <- cpeBind TopLevel env bind+                               massert (isNothing maybe_new_bind)+                                 -- Only join points get returned this way by+                                 -- cpeBind, and no join point may float to top+                               floatss <- go env' binds+                               return (floats `zipFloats` floatss)++mkDataConWorkers :: Bool -> ModLocation -> [TyCon] -> [CoreBind]+-- See Note [Data constructor workers]+-- c.f. Note [Injecting implicit bindings] in GHC.Iface.Tidy+mkDataConWorkers generate_debug_info mod_loc data_tycons+  = [ NonRec id (tick_it (getName data_con) (Var id))+                                -- The ice is thin here, but it works+    | tycon <- data_tycons,     -- CorePrep will eta-expand it+      data_con <- tyConDataCons tycon,+      let id = dataConWorkId data_con+    ]+ where+   -- If we want to generate debug info, we put a source note on the+   -- worker. This is useful, especially for heap profiling.+   tick_it name+     | not generate_debug_info               = id+     | RealSrcSpan span _ <- nameSrcSpan name = tick span+     | Just file <- ml_hs_file mod_loc       = tick (span1 file)+     | otherwise                             = tick (span1 "???")+     where tick span  = Tick $ SourceNote span $+             LexicalFastString $ mkFastString $ renderWithContext defaultSDocContext $ ppr name+           span1 file = realSrcLocSpan $ mkRealSrcLoc (mkFastString file) 1 1++{- Note [Floating in CorePrep]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+ANFisation risks producing a lot of nested lets that obscures values:+  let v = (:) (f 14) [] in e+  ==> { ANF in CorePrep }+  let v = let sat = f 14 in (:) sat [] in e+Here, `v` is not a value anymore, and we'd allocate a thunk closure for `v` that+allocates a thunk for `sat` and then allocates the cons cell.+Hence we carry around a bunch of floated bindings with us so that we again+expose the values:+  let v = let sat = f 14 in (:) sat [] in e+  ==> { Float sat }+  let sat = f 14 in+  let v = (:) sat [] in e+(We will not do this transformation if `v` does not become a value afterwards;+see Note [wantFloatLocal].)+If `v` is bound at the top-level, we might even float `sat` to top-level;+see Note [Floating out of top level bindings].+For nested let bindings, we have to keep in mind Note [Core letrec invariant]+and may exploit strict contexts; see Note [wantFloatLocal].++There are 3 main categories of floats, encoded in the `FloatingBind` type:++  * `Float`: A floated binding, as `sat` above.+    These come in different flavours as described by their `FloatInfo` and+    `BindInfo`, which captures how far the binding can be floated and whether or+    not we want to case-bind. See Note [BindInfo and FloatInfo].+  * `UnsafeEqualityCase`: Used for floating around unsafeEqualityProof bindings;+    see (U3) of Note [Implementing unsafeCoerce].+    It's exactly a `Float` that is `CaseBound` and `LazyContextFloatable`+    (see `mkNonRecFloat`), but one that has a non-DEFAULT Case alternative to+    bind the unsafe coercion field of the Refl constructor.+  * `FloatTick`: A floated `Tick`. See Note [Floating Ticks in CorePrep].++Note [Floating out of top level bindings]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+NB: we do need to float out of top-level bindings+Consider        x = length [True,False]+We want to get+                s1 = False : []+                s2 = True  : s1+                x  = length s2++We return a *list* of bindings, because we may start with+        x* = f (g y)+where x is demanded, in which case we want to finish with+        a = g y+        x* = f a+And then x will actually end up case-bound++Note [Join points and floating]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Join points can float out of other join points but not out of value bindings:++  let z =+    let  w = ... in -- can float+    join k = ... in -- can't float+    ... jump k ...+  join j x1 ... xn =+    let  y = ... in -- can float (but don't want to)+    join h = ... in -- can float (but not much point)+    ... jump h ...+  in ...++Here, the jump to h remains valid if h is floated outward, but the jump to k+does not.++We don't float *out* of join points. It would only be safe to float out of+nullary join points (or ones where the arguments are all either type arguments+or dead binders). Nullary join points aren't ever recursive, so they're always+effectively one-shot functions, which we don't float out of. We *could* float+join points from nullary join points, but there's no clear benefit at this+stage.++Note [Data constructor workers]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Create any necessary "implicit" bindings for data con workers.  We+create the rather strange (non-recursive!) binding++        $wC = \x y -> $wC x y++i.e. a curried constructor that allocates.  This means that we can+treat the worker for a constructor like any other function in the rest+of the compiler.  The point here is that CoreToStg will generate a+StgConApp for the RHS, rather than a call to the worker (which would+give a loop).  As Lennart says: the ice is thin here, but it works.++Hmm.  Should we create bindings for dictionary constructors?  They are+always fully applied, and the bindings are just there to support+partial applications. But it's easier to let them through.+++Note [Dead code in CorePrep]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Imagine that we got an input program like this (see #4962):++  f :: Show b => Int -> (Int, b -> Maybe Int -> Int)+  f x = (g True (Just x) + g () (Just x), g)+    where+      g :: Show a => a -> Maybe Int -> Int+      g _ Nothing = x+      g y (Just z) = if z > 100 then g y (Just (z + length (show y))) else g y unknown++After specialisation and SpecConstr, we would get something like this:++  f :: Show b => Int -> (Int, b -> Maybe Int -> Int)+  f x = (g$Bool_True_Just x + g$Unit_Unit_Just x, g)+    where+      {-# RULES g $dBool = g$Bool+                g $dUnit = g$Unit #-}+      g = ...+      {-# RULES forall x. g$Bool True (Just x) = g$Bool_True_Just x #-}+      g$Bool = ...+      {-# RULES forall x. g$Unit () (Just x) = g$Unit_Unit_Just x #-}+      g$Unit = ...+      g$Bool_True_Just = ...+      g$Unit_Unit_Just = ...++Note that the g$Bool and g$Unit functions are actually dead code: they+are only kept alive by the occurrence analyser because they are+referred to by the rules of g, which is being kept alive by the fact+that it is used (unspecialised) in the returned pair.++However, at the CorePrep stage there is no way that the rules for g+will ever fire, and it really seems like a shame to produce an output+program that goes to the trouble of allocating a closure for the+unreachable g$Bool and g$Unit functions.++The way we fix this is to:+ * In cloneBndr, drop all unfoldings/rules++ * In deFloatTop, run a simple dead code analyser on each top-level+   RHS to drop the dead local bindings.++The reason we don't just OccAnal the whole output of CorePrep is that+the tidier ensures that all top-level binders are GlobalIds, so they+don't show up in the free variables any longer. So if you run the+occurrence analyser on the output of CoreTidy (or later) you e.g. turn+this program:++  Rec {+  f = ... f ...+  }++Into this one:++  f = ... f ...++(Since f is not considered to be free in its own RHS.)+++Note [keepAlive# magic]+~~~~~~~~~~~~~~~~~~~~~~~+When interacting with foreign code, it is often necessary for the user to+extend the lifetime of a heap object beyond the lifetime that would be apparent+from the on-heap references alone. For instance, a program like:++  foreign import safe "hello" hello :: ByteArray# -> IO ()++  callForeign :: IO ()+  callForeign = IO $ \s0 ->+    case newByteArray# n# s0 of (# s1, barr #) ->+      unIO hello barr s1++As-written this program is susceptible to memory-unsafety since there are+no references to `barr` visible to the garbage collector. Consequently, if a+garbage collection happens during the execution of the C function `hello`, it+may be that the array is freed while in use by the foreign function.++To address this, we introduced a new primop, keepAlive#, which "scopes over"+the computation needing the kept-alive value:++  keepAlive# :: forall (ra :: RuntimeRep) (rb :: RuntimeRep) (a :: TYPE a) (b :: TYPE b).+                a -> State# RealWorld -> (State# RealWorld -> b) -> b++When entered, an application (keepAlive# x s k) will apply `k` to the state+token, evaluating it to WHNF. However, during the course of this evaluation+will *guarantee* that `x` is considered to be alive.++There are a few things to note here:++ - we are RuntimeRep-polymorphic in the value to be kept-alive. This is+   necessary since we will often (but not always) be keeping alive something+   unlifted (like a ByteArray#)++ - we are RuntimeRep-polymorphic in the result value since the result may take+   many forms (e.g. a boxed value, a raw state token, or a (# State s, result #).++We implement this operation by desugaring to touch# during CorePrep (see+GHC.CoreToStg.Prep.cpeApp). Specifically,++  keepAlive# x s0 k++is transformed to:++  case k s0 of r ->+  case touch# x realWorld# of s1 ->+    r++Operationally, `keepAlive# x s k` is equivalent to pushing a stack frame with a+pointer to `x` and entering `k s0`. This compilation strategy is safe+because we do no optimization on STG that would drop or re-order the+continuation containing the `touch#`. However, if we were to become more+aggressive in our STG pipeline then we would need to revisit this.++Beyond this CorePrep transformation, there is very little special about+keepAlive#. However, we did explore (and eventually gave up on)+an optimisation which would allow unboxing of constructed product results,+which we describe below.+++Lost optimisation: CPR unboxing+--------------------------------+One unfortunate property of this approach is that the simplifier is unable to+unbox the result of a keepAlive# expression. For instance, consider the program:++  case keepAlive# arr s0 (+         \s1 -> case peekInt arr s1 of+                  (# s2, r #) -> I# r+  ) of+    I# x -> ...++This is a surprisingly common pattern, previously used, e.g., in+GHC.IO.Buffer.readWord8Buf. While exploring ideas, we briefly played around+with optimising this away by pushing strict contexts (like the+`case [] of I# x -> ...` above) into keepAlive#'s continuation. While this can+recover unboxing, it can also unfortunately in general change the asymptotic+memory (namely stack) behavior of the program. For instance, consider++  writeN =+    ...+      case keepAlive# x s0 (\s1 -> something s1) of+        (# s2, x #) ->+          writeN ...++As it is tail-recursive, this program will run in constant space. However, if+we push outer case into the continuation we get:++  writeN =++      case keepAlive# x s0 (\s1 ->+        case something s1 of+          (# s2, x #) ->+            writeN ...+      ) of+        ...++Which ends up building a stack which is linear in the recursion depth. For this+reason, we ended up giving up on this optimisation.+++Historical note: touch# and its inadequacy+------------------------------------------+Prior to the introduction of `keepAlive#` we instead addressed the need for+lifetime extension with the `touch#` primop:++    touch# :: a -> State# s -> State# s++This operation would ensure that the `a` value passed as the first argument was+considered "alive" at the time the primop application is entered.++For instance, the user might modify `callForeign` as:++  callForeign :: IO ()+  callForeign s0 = IO $ \s0 ->+    case newByteArray# n# s0 of (# s1, barr #) ->+    case unIO hello barr s1 of (# s2, () #) ->+    case touch# barr s2 of s3 ->+      (# s3, () #)++However, in #14346 we discovered that this primop is insufficient in the+presence of simplification. For instance, consider a program like:++  callForeign :: IO ()+  callForeign s0 = IO $ \s0 ->+    case newByteArray# n# s0 of (# s1, barr #) ->+    case unIO (forever $ hello barr) s1 of (# s2, () #) ->+    case touch# barr s2 of s3 ->+      (# s3, () #)++In this case the Simplifier may realize that (forever $ hello barr)+will never return and consequently that the `touch#` that follows is dead code.+As such, it will be dropped, resulting in memory unsoundness.+This unsoundness lead to the introduction of keepAlive#.++++Other related tickets:++ - #15544+ - #17760+ - #14375+ - #15260+ - #18061++************************************************************************+*                                                                      *+                The main code+*                                                                      *+************************************************************************+-}++cpeBind :: TopLevelFlag -> CorePrepEnv -> CoreBind+        -> UniqSM (CorePrepEnv,+                   Floats,         -- Floating value bindings+                   Maybe CoreBind) -- Just bind' <=> returned new bind; no float+                                   -- Nothing <=> added bind' to floats instead+cpeBind top_lvl env (NonRec bndr rhs)+  | not (isJoinId bndr)+  = do { (env1, bndr1) <- cpCloneBndr env bndr+       ; let dmd         = idDemandInfo bndr+             is_unlifted = isUnliftedType (idType bndr)+       ; (floats, rhs1) <- cpePair top_lvl NonRecursive+                                   dmd is_unlifted+                                   env bndr1 rhs+       -- See Note [Inlining in CorePrep]+       ; let triv_rhs = exprIsTrivial rhs1+             env2    | triv_rhs  = extendCorePrepEnvExpr env1 bndr rhs1+                     | otherwise = env1+             floats1 | triv_rhs, isInternalName (idName bndr)+                     = floats+                     | otherwise+                     = snocFloat floats new_float++             new_float = mkNonRecFloat env dmd is_unlifted bndr1 rhs1++       ; return (env2, floats1, Nothing) }++  | otherwise -- A join point; see Note [Join points and floating]+  = assert (not (isTopLevel top_lvl)) $ -- can't have top-level join point+    do { (_, bndr1) <- cpCloneBndr env bndr+       ; (bndr2, rhs1) <- cpeJoinPair env bndr1 rhs+       ; return (extendCorePrepEnv env bndr bndr2,+                 emptyFloats,+                 Just (NonRec bndr2 rhs1)) }++cpeBind top_lvl env (Rec pairs)+  | not (isJoinId (head bndrs))+  = do { (env, bndrs1) <- cpCloneBndrs env bndrs+       ; let env' = enterRecGroupRHSs env bndrs1+       ; stuff <- zipWithM (cpePair top_lvl Recursive topDmd False env')+                           bndrs1 rhss++       ; let (zipManyFloats -> floats, rhss1) = unzip stuff+             -- Glom all floats into the Rec, *except* FloatStrings; see+             -- see Note [ANF-ising literal string arguments], Wrinkle (FS1)+             is_lit (Float (NonRec _ rhs) CaseBound TopLvlFloatable) = exprIsTickedString rhs+             is_lit _                                                = False+             (string_floats, top) = partitionOL is_lit (fs_binds floats)+                 -- Strings will *always* be in `top_floats` (we made sure of+                 -- that in `snocOL`), so that's the only field we need to+                 -- partition.+             floats'   = floats { fs_binds = top }+             all_pairs = foldrOL add_float (bndrs1 `zip` rhss1) (getFloats floats')+       -- use env below, so that we reset cpe_rec_ids+       ; return (extendCorePrepEnvList env (bndrs `zip` bndrs1),+                 snocFloat (emptyFloats { fs_binds = string_floats })+                           (Float (Rec all_pairs) LetBound TopLvlFloatable),+                 Nothing) }++  | otherwise -- See Note [Join points and floating]+  = do { (env, bndrs1) <- cpCloneBndrs env bndrs+       ; let env' = enterRecGroupRHSs env bndrs1+       ; pairs1 <- zipWithM (cpeJoinPair env') bndrs1 rhss++       ; let bndrs2 = map fst pairs1+       -- use env below, so that we reset cpe_rec_ids+       ; return (extendCorePrepEnvList env (bndrs `zip` bndrs2),+                 emptyFloats,+                 Just (Rec pairs1)) }+  where+    (bndrs, rhss) = unzip pairs++    -- Flatten all the floats, and the current+    -- group into a single giant Rec+    add_float (Float bind bound _) prs2+      | bound /= CaseBound+      || all (definitelyLiftedType . idType) (bindersOf bind)+           -- The latter check is hit in -O0 (i.e., flavours quick, devel2)+           -- for dictionary args which haven't been floated out yet, #24102.+           -- They are preferably CaseBound, but since they are lifted we may+           -- just as well put them in the Rec, in contrast to lifted bindings.+      = case bind of+          NonRec x e -> (x,e) : prs2+          Rec prs1 -> prs1 ++ prs2+    add_float f _ = pprPanic "cpeBind" (ppr f)+++---------------+cpePair :: TopLevelFlag -> RecFlag -> Demand -> Bool+        -> CorePrepEnv -> OutId -> CoreExpr+        -> UniqSM (Floats, CpeRhs)+-- Used for all bindings+-- The binder is already cloned, hence an OutId+cpePair top_lvl is_rec dmd is_unlifted env bndr rhs+  = assert (not (isJoinId bndr)) $ -- those should use cpeJoinPair+    do { (floats1, rhs1) <- cpeRhsE env rhs++       -- See if we are allowed to float this stuff out of the RHS+       ; let dec = want_float_from_rhs floats1 rhs1+       ; (floats2, rhs2) <- executeFloatDecision dec floats1 rhs1++       -- Make the arity match up+       ; (floats3, rhs3)+            <- if manifestArity rhs1 <= arity+               then return (floats2, cpeEtaExpand arity rhs2)+               else warnPprTrace True "CorePrep: silly extra arguments:" (ppr bndr) $+                               -- Note [Silly extra arguments]+                    (do { v <- newVar (idType bndr)+                        ; let float = mkNonRecFloat env topDmd False v rhs2+                        ; return ( snocFloat floats2 float+                                 , cpeEtaExpand arity (Var v)) })++        -- Wrap floating ticks+       ; let (floats4, rhs4) = wrapTicks floats3 rhs3++       ; return (floats4, rhs4) }+  where+    arity = idArity bndr        -- We must match this arity++    want_float_from_rhs floats rhs+      | isTopLevel top_lvl = wantFloatTop floats+      | otherwise          = wantFloatLocal is_rec dmd is_unlifted floats rhs++{- Note [Silly extra arguments]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Suppose we had this+        f{arity=1} = \x\y. e+We *must* match the arity on the Id, so we have to generate+        f' = \x\y. e+        f  = \x. f' x++It's a bizarre case: why is the arity on the Id wrong?  Reason+(in the days of __inline_me__):+        f{arity=0} = __inline_me__ (let v = expensive in \xy. e)+When InlineMe notes go away this won't happen any more.  But+it seems good for CorePrep to be robust.+-}++---------------+cpeJoinPair :: CorePrepEnv -> JoinId -> CoreExpr+            -> UniqSM (JoinId, CpeRhs)+-- Used for all join bindings+-- No eta-expansion: see Note [Do not eta-expand join points] in GHC.Core.Opt.Simplify.Utils+cpeJoinPair env bndr rhs+  = assert (isJoinId bndr) $+    do { let JoinPoint join_arity = idJoinPointHood bndr+             (bndrs, body)        = collectNBinders join_arity rhs++       ; (env', bndrs') <- cpCloneBndrs env bndrs++       ; body' <- cpeBodyNF env' body -- Will let-bind the body if it starts+                                      -- with a lambda++       ; let rhs'  = mkCoreLams bndrs' body'+             bndr' = bndr `setIdUnfolding` evaldUnfolding+                          `setIdArity` count isId bndrs+                            -- See Note [Arity and join points]++       ; return (bndr', rhs') }++{-+Note [Arity and join points]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Up to now, we've allowed a join point to have an arity greater than its join+arity (minus type arguments), since this is what's useful for eta expansion.+However, for code gen purposes, its arity must be exactly the number of value+arguments it will be called with, and it must have exactly that many value+lambdas. Hence if there are extra lambdas we must let-bind the body of the RHS:++  join j x y z = \w -> ... in ...+    =>+  join j x y z = (let f = \w -> ... in f) in ...++This is also what happens with Note [Silly extra arguments]. Note that it's okay+for us to mess with the arity because a join point is never exported.+-}++-- ---------------------------------------------------------------------------+--              CpeRhs: produces a result satisfying CpeRhs+-- ---------------------------------------------------------------------------++cpeRhsE :: CorePrepEnv -> CoreExpr -> UniqSM (Floats, CpeRhs)+-- If+--      e  ===>  (bs, e')+-- then+--      e = let bs in e'        (semantically, that is!)+--+-- For example+--      f (g x)   ===>   ([v = g x], f v)++cpeRhsE env (Type ty)+  = return (emptyFloats, Type (cpSubstTy env ty))+cpeRhsE env (Coercion co)+  = return (emptyFloats, Coercion (cpSubstCo env co))+cpeRhsE env expr@(Lit (LitNumber nt i))+   = case cp_convertNumLit (cpe_config env) nt i of+      Nothing -> return (emptyFloats, expr)+      Just e  -> cpeRhsE env e+cpeRhsE _env expr@(Lit {}) = return (emptyFloats, expr)+cpeRhsE env expr@(Var {})  = cpeApp env expr+cpeRhsE env expr@(App {})  = cpeApp env expr++cpeRhsE env (Let bind body)+  = do { (env', bind_floats, maybe_bind') <- cpeBind NotTopLevel env bind+       ; (body_floats, body') <- cpeRhsE env' body+       ; let expr' = case maybe_bind' of Just bind' -> Let bind' body'+                                         Nothing    -> body'+       ; return (bind_floats `appFloats` body_floats, expr') }++cpeRhsE env (Tick tickish expr)+  -- Pull out ticks if they are allowed to be floated.+  | tickishFloatable tickish+  = do { (floats, body) <- cpeRhsE env expr+         -- See [Floating Ticks in CorePrep]+       ; return (FloatTick tickish `consFloat` floats, body) }+  | otherwise+  = do { body <- cpeBodyNF env expr+       ; return (emptyFloats, mkTick tickish' body) }+  where+    tickish' | Breakpoint ext n fvs modl <- tickish+             -- See also 'substTickish'+             = Breakpoint ext n (map (getIdFromTrivialExpr . lookupCorePrepEnv env) fvs) modl+             | otherwise+             = tickish++cpeRhsE env (Cast expr co)+   = do { (floats, expr') <- cpeRhsE env expr+        ; return (floats, Cast expr' (cpSubstCo env co)) }++cpeRhsE env expr@(Lam {})+   = do { let (bndrs,body) = collectBinders expr+        ; (env', bndrs') <- cpCloneBndrs env bndrs+        ; body' <- cpeBodyNF env' body+        ; return (emptyFloats, mkLams bndrs' body') }++cpeRhsE env (Case scrut bndr _ alts@[Alt con [covar] _])+  -- See (U3) in Note [Implementing unsafeCoerce]+  -- We need make the Case float, otherwise we get+  --   let x = case ... of UnsafeRefl co ->+  --           let y = expr in+  --           K y+  --   in f x+  -- instead of+  --   case ... of UnsafeRefl co ->+  --   let y = expr in+  --   let x = K y+  --   in f x+  -- Note that `x` is a value here. This is visible in the GHCi debugger tests+  -- (such as `print003`).+  | Just rhs <- isUnsafeEqualityCase scrut bndr alts+  = do { (floats_scrut, scrut) <- cpeBody env scrut++       ; (env, bndr')  <- cpCloneBndr env bndr+       ; (env, covar') <- cpCloneCoVarBndr env covar+                          -- Important: here we clone the CoVar+                          -- See Note [Cloning CoVars and TyVars]++         -- Up until here this should do exactly the same as the regular code+         -- path of `cpeRhsE Case{}`.+       ; (floats_rhs, rhs) <- cpeBody env rhs+         -- ... but we want to float `floats_rhs` as in (U3) so that rhs' might+         -- become a value+       ; let case_float = UnsafeEqualityCase scrut bndr' con [covar']+         -- NB: It is OK to "evaluate" the proof eagerly.+         --     Usually there's the danger that we float the unsafeCoerce out of+         --     a branching Case alt. Not so here, because the regular code path+         --     for `cpeRhsE Case{}` will not float out of alts.+             floats = snocFloat floats_scrut case_float `appFloats` floats_rhs+       ; return (floats, rhs) }++cpeRhsE env (Case scrut bndr ty alts)+  = do { (floats, scrut') <- cpeBody env scrut+       ; (env', bndr2) <- cpCloneBndr env bndr+       ; let alts'+               | cp_catchNonexhaustiveCases $ cpe_config env+               , not (altsAreExhaustive alts)+               = addDefault alts (Just err)+               | otherwise = alts+               where err = mkImpossibleExpr ty "cpeRhsE: missing case alternative"+       ; alts'' <- mapM (sat_alt env') alts'++       ; return (floats, Case scrut' bndr2 (cpSubstTy env ty) alts'') }+  where+    sat_alt env (Alt con bs rhs)+       = do { (env2, bs') <- cpCloneBndrs env bs+            ; rhs' <- cpeBodyNF env2 rhs+            ; return (Alt con bs' rhs') }++-- ---------------------------------------------------------------------------+--              CpeBody: produces a result satisfying CpeBody+-- ---------------------------------------------------------------------------++-- | Convert a 'CoreExpr' so it satisfies 'CpeBody', without+-- producing any floats (any generated floats are immediately+-- let-bound using 'wrapBinds').  Generally you want this, esp.+-- when you've reached a binding form (e.g., a lambda) and+-- floating any further would be incorrect.+cpeBodyNF :: CorePrepEnv -> CoreExpr -> UniqSM CpeBody+cpeBodyNF env expr+  = do { (floats, body) <- cpeBody env expr+       ; return (wrapBinds floats body) }++-- | Convert a 'CoreExpr' so it satisfies 'CpeBody'; also produce+-- a list of 'Floats' which are being propagated upwards.  In+-- fact, this function is used in only two cases: to+-- implement 'cpeBodyNF' (which is what you usually want),+-- and in the case when a let-binding is in a case scrutinee--here,+-- we can always float out:+--+--      case (let x = y in z) of ...+--      ==> let x = y in case z of ...+--+cpeBody :: CorePrepEnv -> CoreExpr -> UniqSM (Floats, CpeBody)+cpeBody env expr+  = do { (floats1, rhs) <- cpeRhsE env expr+       ; (floats2, body) <- rhsToBody rhs+       ; return (floats1 `appFloats` floats2, body) }++--------+rhsToBody :: CpeRhs -> UniqSM (Floats, CpeBody)+-- Remove top level lambdas by let-binding++rhsToBody (Tick t expr)+  | tickishScoped t == NoScope  -- only float out of non-scoped annotations+  = do { (floats, expr') <- rhsToBody expr+       ; return (floats, mkTick t expr') }++rhsToBody (Cast e co)+        -- You can get things like+        --      case e of { p -> coerce t (\s -> ...) }+  = do { (floats, e') <- rhsToBody e+       ; return (floats, Cast e' co) }++rhsToBody expr@(Lam {})   -- See Note [No eta reduction needed in rhsToBody]+  | all isTyVar bndrs           -- Type lambdas are ok+  = return (emptyFloats, expr)+  | otherwise                   -- Some value lambdas+  = do { let rhs = cpeEtaExpand (exprArity expr) expr+       ; fn <- newVar (exprType rhs)+       ; let float = Float (NonRec fn rhs) LetBound TopLvlFloatable+       ; return (unitFloat float, Var fn) }+  where+    (bndrs,_) = collectBinders expr++rhsToBody expr = return (emptyFloats, expr)+++{- Note [No eta reduction needed in rhsToBody]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Historical note.  In the olden days we used to have a Prep-specific+eta-reduction step in rhsToBody:+  rhsToBody expr@(Lam {})+    | Just no_lam_result <- tryEtaReducePrep bndrs body+    = return (emptyFloats, no_lam_result)++The goal was to reduce+        case x of { p -> \xs. map f xs }+    ==> case x of { p -> map f }++to avoid allocating a lambda.  Of course, we'd allocate a PAP+instead, which is hardly better, but that's the way it was.++Now we simply don't bother with this. It doesn't seem to be a win,+and it's extra work.+-}++-- ---------------------------------------------------------------------------+--              CpeApp: produces a result satisfying CpeApp+-- ---------------------------------------------------------------------------++data ArgInfo = CpeApp  CoreArg+             | CpeCast Coercion+             | CpeTick CoreTickish++instance Outputable ArgInfo where+  ppr (CpeApp arg) = text "app" <+> ppr arg+  ppr (CpeCast co) = text "cast" <+> ppr co+  ppr (CpeTick tick) = text "tick" <+> ppr tick++{- Note [Ticks and mandatory eta expansion]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Something like+    `foo x = ({-# SCC foo #-} tagToEnum#) x :: Bool`+caused a compiler panic in #20938. Why did this happen?+The simplifier will eta-reduce the rhs giving us a partial+application of tagToEnum#. The tick is then pushed inside the+type argument. That is we get+    `(Tick<foo> tagToEnum#) @Bool`+CorePrep would go on to see a undersaturated tagToEnum# application+and eta expand the expression under the tick. Giving us:+    (Tick<scc> (\forall a. x -> tagToEnum# @a x) @Bool+Suddenly tagToEnum# is applied to a polymorphic type and the code generator+panics as it needs a concrete type to determine the representation.++The problem in my eyes was that the tick covers a partial application+of a primop. There is no clear semantic for such a construct as we can't+partially apply a primop since they do not have bindings.+We fix this by expanding the scope of such ticks slightly to cover the body+of the eta-expanded expression.++We do this by:+* Checking if an application is headed by a primOpish thing.+* If so we collect floatable ticks and usually but also profiling ticks+  along with regular arguments.+* When rebuilding the application we check if any profiling ticks appear+  before the primop is fully saturated.+* If the primop isn't fully satured we eta expand the primop application+  and scope the tick to scope over the body of the saturated expression.++Going back to #20938 this means starting with+    `(Tick<foo> tagToEnum#) @Bool`+we check if the function head is a primop (yes). This means we collect the+profiling tick like if it was floatable. Giving us+    (tagToEnum#, [CpeTick foo, CpeApp @Bool]).+cpe_app filters out the tick as a underscoped tick on the expression+`tagToEnum# @Bool`. During eta expansion we then put that tick back onto the+body of the eta-expansion lambdas. Giving us `\x -> Tick<foo> (tagToEnum# @Bool x)`.+-}+cpeApp :: CorePrepEnv -> CoreExpr -> UniqSM (Floats, CpeRhs)+-- May return a CpeRhs because of saturating primops+cpeApp top_env expr+  = do { let (terminal, args) = collect_args expr+      --  ; pprTraceM "cpeApp" $ (ppr expr)+       ; cpe_app top_env terminal args+       }++  where+    -- We have a nested data structure of the form+    -- e `App` a1 `App` a2 ... `App` an, convert it into+    -- (e, [CpeApp a1, CpeApp a2, ..., CpeApp an], depth)+    -- We use 'ArgInfo' because we may also need to+    -- record casts and ticks.  Depth counts the number+    -- of arguments that would consume strictness information+    -- (so, no type or coercion arguments.)+    collect_args :: CoreExpr -> (CoreExpr, [ArgInfo])+    collect_args e = go e []+      where+        go (App fun arg)      as+            = go fun (CpeApp arg : as)+        go (Cast fun co)      as+            = go fun (CpeCast co : as)+        go (Tick tickish fun) as+            -- Profiling ticks are slightly less strict so we expand their scope+            -- if they cover partial applications of things like primOps.+            -- See Note [Ticks and mandatory eta expansion]+            -- Here we look inside `fun` before we make the final decision about+            -- floating the tick which isn't optimal for perf. But this only makes+            -- a difference if we have a non-floatable tick which is somewhat rare.+            | Var vh <- head+            , Var head' <- lookupCorePrepEnv top_env vh+            , etaExpansionTick head' tickish+            = (head,as')+            where+              (head,as') = go fun (CpeTick tickish : as)++        -- Terminal could still be an app if it's wrapped by a tick.+        -- E.g. Tick<foo> (f x) can give us (f x) as terminal.+        go terminal as = (terminal, as)++    cpe_app :: CorePrepEnv+            -> CoreExpr -- The thing we are calling+            -> [ArgInfo]+            -> UniqSM (Floats, CpeRhs)+    cpe_app env (Var f) (CpeApp Type{} : CpeApp arg : args)+        | f `hasKey` lazyIdKey          -- Replace (lazy a) with a, and+            -- See Note [lazyId magic] in GHC.Types.Id.Make+       || f `hasKey` noinlineIdKey || f `hasKey` noinlineConstraintIdKey+            -- Replace (noinline a) with a+            -- See Note [noinlineId magic] in GHC.Types.Id.Make+       || f `hasKey` nospecIdKey        -- Replace (nospec a) with a+            -- See Note [nospecId magic] in GHC.Types.Id.Make++        -- Consider the code:+        --+        --      lazy (f x) y+        --+        -- We need to make sure that we need to recursively collect arguments on+        -- "f x", otherwise we'll float "f x" out (it's not a variable) and+        -- end up with this awful -ddump-prep:+        --+        --      case f x of f_x {+        --        __DEFAULT -> f_x y+        --      }+        --+        -- rather than the far superior "f x y".  Test case is par01.+        = let (terminal, args') = collect_args arg+          in cpe_app env terminal (args' ++ args)++    -- runRW# magic+    cpe_app env (Var f) (CpeApp _runtimeRep@Type{} : CpeApp _type@Type{} : CpeApp arg : rest)+        | f `hasKey` runRWKey+        -- N.B. While it may appear that n == 1 in the case of runRW#+        -- applications, keep in mind that we may have applications that return+        , has_value_arg (CpeApp arg : rest)+        -- See Note [runRW magic]+        -- Replace (runRW# f) by (f realWorld#), beta reducing if possible (this+        -- is why we return a CorePrepEnv as well)+        = case arg of+            Lam s body -> cpe_app (extendCorePrepEnv env s realWorldPrimId) body rest+            _          -> cpe_app env arg (CpeApp (Var realWorldPrimId) : rest)+             -- TODO: What about casts?+        where+          has_value_arg [] = False+          has_value_arg (CpeApp arg:_rest)+            | not (isTyCoArg arg) = True+          has_value_arg (_:rest) = has_value_arg rest++    cpe_app env (Var v) args+      = do { v1 <- fiddleCCall v+           ; let e2 = lookupCorePrepEnv env v1+                 hd = getIdFromTrivialExpr_maybe e2+                 -- Determine number of required arguments. See Note [Ticks and mandatory eta expansion]+                 min_arity = case hd of+                   Just v_hd -> if hasNoBinding v_hd then Just $! (idArity v_hd) else Nothing+                   Nothing -> Nothing+          --  ; pprTraceM "cpe_app:stricts:" (ppr v <+> ppr args $$ ppr stricts $$ ppr (idCbvMarks_maybe v))+           ; (app, floats, unsat_ticks) <- rebuild_app env args e2 emptyFloats stricts min_arity+           ; mb_saturate hd app floats unsat_ticks depth }+        where+          depth = val_args args+          stricts = case idDmdSig v of+                            DmdSig (DmdType _ demands)+                              | listLengthCmp demands depth /= GT -> demands+                                    -- length demands <= depth+                              | otherwise                         -> []+                -- If depth < length demands, then we have too few args to+                -- satisfy strictness  info so we have to  ignore all the+                -- strictness info, e.g. + (error "urk")+                -- Here, we can't evaluate the arg strictly, because this+                -- partial application might be seq'd++        -- We inlined into something that's not a var and has no args.+        -- Bounce it back up to cpeRhsE.+    cpe_app env fun [] = cpeRhsE env fun++    -- Here we get:+    -- N-variable fun, better let-bind it+    -- This case covers literals, apps, lams or let expressions applied to arguments.+    -- Basically things we want to ANF before applying to arguments.+    cpe_app env fun args+      = do { (fun_floats, fun') <- cpeArg env evalDmd fun+                          -- If evalDmd says that it's sure to be evaluated,+                          -- we'll end up case-binding it+           ; (app, floats,unsat_ticks) <- rebuild_app env args fun' fun_floats [] Nothing+           ; mb_saturate Nothing app floats unsat_ticks (val_args args) }++    -- Count the number of value arguments *and* coercions (since we don't eliminate the later in STG)+    val_args :: [ArgInfo] -> Int+    val_args args = go args 0+      where+        go [] !n = n+        go (info:infos) n =+          case info of+            CpeCast {} -> go infos n+            CpeTick tickish+              | tickishFloatable tickish                 -> go infos n+              -- If we can't guarantee a tick will be floated out of the application+              -- we can't guarantee the value args following it will be applied.+              | otherwise                             -> n+            CpeApp e                                  -> go infos n'+              where+                !n'+                  | isTypeArg e = n+                  | otherwise   = n+1++    -- Saturate if necessary+    mb_saturate head app floats unsat_ticks depth =+       case head of+         Just fn_id -> do { sat_app <- maybeSaturate fn_id app depth unsat_ticks+                          ; return (floats, sat_app) }+         _other     -> do { massert (null unsat_ticks)+                          ; return (floats, app) }++    -- Deconstruct and rebuild the application, floating any non-atomic+    -- arguments to the outside.  We collect the type of the expression,+    -- the head of the application, and the number of actual value arguments,+    -- all of which are used to possibly saturate this application if it+    -- has a constructor or primop at the head.+    rebuild_app+        :: CorePrepEnv+        -> [ArgInfo]                  -- The arguments (inner to outer)+        -> CpeApp                     -- The function+        -> Floats                     -- INVARIANT: These floats don't bind anything that is in the CpeApp!+                                      -- Just stuff floated out from the head of the application.+        -> [Demand]+        -> Maybe Arity+        -> UniqSM (CpeApp+                  ,Floats+                  ,[CoreTickish] -- Underscoped ticks. See Note [Ticks and mandatory eta expansion]+                  )+    rebuild_app env args app floats ss req_depth =+      rebuild_app' env args app floats ss [] (fromMaybe 0 req_depth)++    rebuild_app'+        :: CorePrepEnv+        -> [ArgInfo] -- The arguments (inner to outer)+        -> CpeApp+        -> Floats+        -> [Demand]+        -> [CoreTickish]+        -> Int -- Number of arguments required to satisfy minimal tick scopes.+        -> UniqSM (CpeApp, Floats, [CoreTickish])+    rebuild_app' _ [] app floats ss rt_ticks !_req_depth+      = assertPpr (null ss) (ppr ss)-- make sure we used all the strictness info+        return (app, floats, rt_ticks)++    rebuild_app' env (a : as) fun' floats ss rt_ticks req_depth = case a of+      -- See Note [Ticks and mandatory eta expansion]+      _+        | not (null rt_ticks)+        , req_depth <= 0+        ->+            let tick_fun = foldr mkTick fun' rt_ticks+            in rebuild_app' env (a : as) tick_fun floats ss rt_ticks req_depth++      CpeApp (Type arg_ty)+        -> rebuild_app' env as (App fun' (Type arg_ty')) floats ss rt_ticks req_depth+        where+           arg_ty' = cpSubstTy env arg_ty++      CpeApp (Coercion co)+        -> rebuild_app' env as (App fun' (Coercion co')) floats (drop 1 ss) rt_ticks req_depth+        where+           co' = cpSubstCo env co++      CpeApp arg -> do+        let (ss1, ss_rest)  -- See Note [lazyId magic] in GHC.Types.Id.Make+               = case (ss, isLazyExpr arg) of+                   (_   : ss_rest, True)  -> (topDmd, ss_rest)+                   (ss1 : ss_rest, False) -> (ss1,    ss_rest)+                   ([],            _)     -> (topDmd, [])+        (fs, arg') <- cpeArg top_env ss1 arg+        rebuild_app' env as (App fun' arg') (fs `zipFloats` floats) ss_rest rt_ticks (req_depth-1)++      CpeCast co+        -> rebuild_app' env as (Cast fun' co') floats ss rt_ticks req_depth+        where+           co' = cpSubstCo env co++      -- See Note [Ticks and mandatory eta expansion]+      CpeTick tickish+        | tickishPlace tickish == PlaceRuntime+        , req_depth > 0+        -> assert (isProfTick tickish) $+           rebuild_app' env as fun' floats ss (tickish:rt_ticks) req_depth+        | otherwise+        -- See [Floating Ticks in CorePrep]+        -> rebuild_app' env as fun' (snocFloat floats (FloatTick tickish)) ss rt_ticks req_depth++isLazyExpr :: CoreExpr -> Bool+-- See Note [lazyId magic] in GHC.Types.Id.Make+isLazyExpr (Cast e _)              = isLazyExpr e+isLazyExpr (Tick _ e)              = isLazyExpr e+isLazyExpr (Var f `App` _ `App` _) = f `hasKey` lazyIdKey+isLazyExpr _                       = False++{- Note [runRW magic]+~~~~~~~~~~~~~~~~~~~~~+Some definitions, for instance @runST@, must have careful control over float out+of the bindings in their body. Consider this use of @runST@,++    f x = runST ( \ s -> let (a, s')  = newArray# 100 [] s+                             (_, s'') = fill_in_array_or_something a x s'+                         in freezeArray# a s'' )++If we inline @runST@, we'll get:++    f x = let (a, s')  = newArray# 100 [] realWorld#{-NB-}+              (_, s'') = fill_in_array_or_something a x s'+          in freezeArray# a s''++And now if we allow the @newArray#@ binding to float out to become a CAF,+we end up with a result that is totally and utterly wrong:++    f = let (a, s')  = newArray# 100 [] realWorld#{-NB-} -- YIKES!!!+        in \ x ->+            let (_, s'') = fill_in_array_or_something a x s'+            in freezeArray# a s''++All calls to @f@ will share a {\em single} array! Clearly this is nonsense and+must be prevented.++This is what @runRW#@ gives us: by being inlined extremely late in the+optimization (right before lowering to STG, in CorePrep), we can ensure that+no further floating will occur. This allows us to safely inline things like+@runST@, which are otherwise needlessly expensive (see #10678 and #5916).++'runRW' has a variety of quirks:++ * 'runRW' is known-key with a NOINLINE definition in+   GHC.Magic. This definition is used in cases where runRW is curried.++ * In addition to its normal Haskell definition in GHC.Magic, we give it+   a special late inlining here in CorePrep and GHC.StgToByteCode, avoiding+   the incorrect sharing due to float-out noted above.++ * It is levity-polymorphic:++    runRW# :: forall (r1 :: RuntimeRep). (o :: TYPE r)+           => (State# RealWorld -> (# State# RealWorld, o #))+           -> (# State# RealWorld, o #)++ * It has some special simplification logic to allow unboxing of results when+   runRW# appears in a strict context. See Note [Simplification of runRW#]+   below.++ * Since its body is inlined, we allow runRW#'s argument to contain jumps to+   join points. That is, the following is allowed:++    join j x = ...+    in runRW# @_ @_ (\s -> ... jump j 42 ...)++   The Core Linter knows about this. See Note [Linting of runRW#] in+   GHC.Core.Lint for details.++   The occurrence analyser and SetLevels also know about this, as described in+   Note [Simplification of runRW#].++Other relevant Notes:++ * Note [Simplification of runRW#] below, describing a transformation of runRW+   applications in strict contexts performed by the simplifier.+ * Note [Linting of runRW#] in GHC.Core.Lint+ * Note [runRW arg] below, describing a non-obvious case where the+   late-inlining could go wrong.++Note [runRW arg]+~~~~~~~~~~~~~~~~~~~+Consider the Core program (from #11291),++   runRW# (case bot of {})++The late inlining logic in cpe_app would transform this into:++   (case bot of {}) realWorld#++Which would rise to a panic in CoreToStg.myCollectArgs, which expects only+variables in function position.++However, as runRW#'s strictness signature captures the fact that it will call+its argument this can't happen: the simplifier will transform the bottoming+application into simply (case bot of {}).++Note that this reasoning does *not* apply to non-bottoming continuations like:++    hello :: Bool -> Int+    hello n =+      runRW# (+          case n of+            True -> \s -> 23+            _    -> \s -> 10)++Why? The difference is that (case bot of {}) is considered by okCpeArg to be+trivial, consequently cpeArg (which the catch-all case of cpe_app calls on both+the function and the arguments) will forgo binding it to a variable. By+contrast, in the non-bottoming case of `hello` above  the function will be+deemed non-trivial and consequently will be case-bound.++Note [Simplification of runRW#]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider the program,++    case runRW# (\s -> I# 42#) of+      I# n# -> f n#++There is no reason why we should allocate an I# constructor given that we+immediately destructure it.++To avoid this the simplifier has a special transformation rule, specific to+runRW#, that pushes a strict context into runRW#'s continuation.  See the+`runRW#` guard in `GHC.Core.Opt.Simplify.rebuildCall`.  That is, it transforms++    K[ runRW# @r @ty cont ]+              ~>+    runRW# @r @ty (\s -> K[cont s])++This has a few interesting implications. Consider, for instance, this program:++    join j = ...+    in case runRW# @r @ty cont of+         result -> jump j result++Performing the transform described above would result in:++    join j x = ...+    in runRW# @r @ty (\s ->+         case cont of in+           result -> jump j result+       )++If runRW# were a "normal" function this call to join point j would not be+allowed in its continuation argument. However, since runRW# is inlined (as+described in Note [runRW magic] above), such join point occurrences are+completely fine. Both occurrence analysis (see the runRW guard in occAnalApp)+and Core Lint (see the App case of lintCoreExpr) have special treatment for+runRW# applications. See Note [Linting of runRW#] for details on the latter.++Moreover, it's helpful to ensure that runRW's continuation isn't floated out+For instance, if we have++    runRW# (\s -> do_something)++where do_something contains only top-level free variables, we may be tempted to+float the argument to the top-level. However, we must resist this urge as since+doing so would then require that runRW# produce an allocation and call, e.g.:++    let lvl = \s -> do_somethign+    in+    ....(runRW# lvl)....++whereas without floating the inlining of the definition of runRW would result+in straight-line code. Consequently, GHC.Core.Opt.SetLevels.lvlApp has special+treatment for runRW# applications, ensure the arguments are not floated as+MFEs.++Now that we float evaluation context into runRW#, we also have to give runRW# a+special higher-order CPR transformer lest we risk #19822. E.g.,++  case runRW# (\s -> doThings) of x -> Data.Text.Text x something something'+      ~>+  runRW# (\s -> case doThings s of x -> Data.Text.Text x something something')++The former had the CPR property, and so should the latter.++Other considered designs+------------------------++One design that was rejected was to *require* that runRW#'s continuation be+headed by a lambda. However, this proved to be quite fragile. For instance,+SetLevels is very eager to float bottoming expressions. For instance given+something of the form,++    runRW# @r @ty (\s -> case expr of x -> undefined)++SetLevels will see that the body the lambda is bottoming and will consequently+float it to the top-level (assuming expr has no free coercion variables which+prevent this). We therefore end up with++    runRW# @r @ty (\s -> lvl s)++Which the simplifier will beta reduce, leaving us with++    runRW# @r @ty lvl++Breaking our desired invariant. Ultimately we decided to simply accept that+the continuation may not be a manifest lambda.+++-- ---------------------------------------------------------------------------+--      CpeArg: produces a result satisfying CpeArg+-- ---------------------------------------------------------------------------++Note [ANF-ising literal string arguments]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider a Core program like,++    data Foo = Foo Addr#+    foo = Foo "turtle"#++String literals are non-trivial, see 'GHC.Types.Literal.litIsTrivial', hence+they are non-atomic in STG.+With -O1, FloatOut is likely to have floated most of these strings to top-level,+not least to give CSE a chance to deduplicate strings early (before the+linker, that is).+(Notable exceptions seem to be applications of 'unpackAppendCString#'.)+But with -O0, there is no FloatOut, so CorePrep must do the ANFisation to++    s = "turtle"#+    foo = Foo s++(String literals are the only kind of binding allowed at top-level and hence+their `FloatInfo` is `TopLvlFloatable`.)++This appears to lead to bad code if the arg is under a lambda, because CorePrep+doesn't float out of RHSs, e.g., (T23270)++    foo x = ... patError "turtle"# ...+==> foo x = ... case "turtle"# of s { __DEFAULT -> petError s } ...++This looks bad because it evals an HNF on every call.+But actually, it doesn't, because "turtle"# is already an HNF. Here is the Cmm:++  [section ""cstring" . cB4_str" {+       cB4_str:+           I8[] "turtle"+   }+  ...+  _sAG::I64 = cB4_str;+  R2 = _sAG::I64;+  Sp = Sp + 8;+  call Control.Exception.Base.patError_info(R2) args: 8, res: 0, upd: 8;++Wrinkles:++(FS1) We detect string literals in `cpeBind Rec{}` and float them out anyway;+      otherwise we'd try to bind a string literal in a letrec, violating+      Note [Core letrec invariant]. Since we know that literals don't have+      free variables, we float further.+      Arguably, we could just as well relax the letrec invariant for+      string literals, or anthing that is a value (lifted or not).+      This is tracked in #24036.+-}++-- This is where we arrange that a non-trivial argument is let-bound+cpeArg :: CorePrepEnv -> Demand+       -> CoreArg -> UniqSM (Floats, CpeArg)+cpeArg env dmd arg+  = do { (floats1, arg1) <- cpeRhsE env arg     -- arg1 can be a lambda+       ; let arg_ty      = exprType arg1+             is_unlifted = isUnliftedType arg_ty+             dec         = wantFloatLocal NonRecursive dmd is_unlifted floats1 arg1+       ; (floats2, arg2) <- executeFloatDecision dec floats1 arg1+                -- Else case: arg1 might have lambdas, and we can't+                --            put them inside a wrapBinds++       -- Now ANF-ise any non-trivial argument+       -- NB: "non-trivial" includes string literals;+       -- see Note [ANF-ising literal string arguments]+       ; if exprIsTrivial arg2+         then return (floats2, arg2)+         else do { v <- newVar arg_ty+                 -- See Note [Eta expansion of arguments in CorePrep]+                 ; let arity = cpeArgArity env dec arg2+                       arg3  = cpeEtaExpand arity arg2+                       arg_float = mkNonRecFloat env dmd is_unlifted v arg3+                 ; return (snocFloat floats2 arg_float, varToCoreExpr v) }+       }++cpeArgArity :: CorePrepEnv -> FloatDecision -> CoreArg -> Arity+-- ^ See Note [Eta expansion of arguments in CorePrep]+-- Returning 0 means "no eta-expansion"; see cpeEtaExpand+cpeArgArity env float_decision arg+  | FloatNone <- float_decision+  = 0    -- Crucial short-cut+         -- See wrinkle (EA2) in Note [Eta expansion of arguments in CorePrep]++  | Just ao <- cp_arityOpts (cpe_config env) -- Just <=> -O1 or -O2+  , not (has_join_in_tail_context arg)+            -- See Wrinkle (EA1) of Note [Eta expansion of arguments in CorePrep]+  = case exprEtaExpandArity ao arg of+      Nothing -> 0+      Just at -> arityTypeArity at++  | otherwise+  = exprArity arg -- this is cheap enough for -O0++has_join_in_tail_context :: CoreExpr -> Bool+-- ^ Identify the cases where we'd generate invalid `CpeApp`s as described in+-- Wrinkle (EA1) of Note [Eta expansion of arguments in CorePrep]+has_join_in_tail_context (Let bs e)            = isJoinBind bs || has_join_in_tail_context e+has_join_in_tail_context (Lam b e) | isTyVar b = has_join_in_tail_context e+has_join_in_tail_context (Cast e _)            = has_join_in_tail_context e+has_join_in_tail_context (Tick _ e)            = has_join_in_tail_context e+has_join_in_tail_context (Case _ _ _ alts)     = any has_join_in_tail_context (rhssOfAlts alts)+has_join_in_tail_context _                     = False++maybeSaturate :: Id -> CpeApp -> Int -> [CoreTickish] -> UniqSM CpeRhs+maybeSaturate fn expr n_args unsat_ticks+  | hasNoBinding fn        -- There's no binding+    -- See Note [Eta expansion of hasNoBinding things in CorePrep]+  = return $ wrapLamBody (\body -> foldr mkTick body unsat_ticks) sat_expr++  | mark_arity > 0 -- A call-by-value function. See Note [CBV Function Ids]+  , not applied_marks+  = assertPpr+      ( not (isJoinId fn)) -- See Note [Do not eta-expand join points]+      ( ppr fn $$ text "expr:" <+> ppr expr $$ text "n_args:" <+> ppr n_args $$+          text "marks:" <+> ppr (idCbvMarks_maybe fn) $$+          text "join_arity" <+> ppr (idJoinPointHood fn) $$+          text "fn_arity" <+> ppr fn_arity+       ) $+    -- pprTrace "maybeSat"+    --   ( ppr fn $$ text "expr:" <+> ppr expr $$ text "n_args:" <+> ppr n_args $$+    --       text "marks:" <+> ppr (idCbvMarks_maybe fn) $$+    --       text "join_arity" <+> ppr (isJoinId_maybe fn) $$+    --       text "fn_arity" <+> ppr fn_arity $$+    --       text "excess_arity" <+> ppr excess_arity $$+    --       text "mark_arity" <+> ppr mark_arity+    --    ) $+    return sat_expr++  | otherwise+  = assert (null unsat_ticks) $+    return expr+  where+    mark_arity    = idCbvMarkArity fn+    fn_arity      = idArity fn+    excess_arity  = (max fn_arity mark_arity) - n_args+    sat_expr      = cpeEtaExpand excess_arity expr+    applied_marks = n_args >= (length . dropWhile (not . isMarkedCbv) .+                               reverse . expectJust "maybeSaturate" $ (idCbvMarks_maybe fn))+    -- For join points we never eta-expand (See Note [Do not eta-expand join points])+    -- so we assert all arguments that need to be passed cbv are visible so that the+    -- backend can evalaute them if required..++{- Note [Eta expansion]+~~~~~~~~~~~~~~~~~~~~~~~+Eta expand to match the arity claimed by the binder Remember,+CorePrep must not change arity++Eta expansion might not have happened already, because it is done by+the simplifier only when there at least one lambda already.++NB1:we could refrain when the RHS is trivial (which can happen+    for exported things).  This would reduce the amount of code+    generated (a little) and make things a little worse for+    code compiled without -O.  The case in point is data constructor+    wrappers.++NB2: we have to be careful that the result of etaExpand doesn't+   invalidate any of the assumptions that CorePrep is attempting+   to establish.  One possible cause is eta expanding inside of+   an SCC note - we're now careful in etaExpand to make sure the+   SCC is pushed inside any new lambdas that are generated.++Note [Eta expansion of hasNoBinding things in CorePrep]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+maybeSaturate deals with eta expanding to saturate things that can't deal+with unsaturated applications (identified by 'hasNoBinding', currently+foreign calls, unboxed tuple/sum constructors, and representation-polymorphic+primitives such as 'coerce' and 'unsafeCoerce#').++Historical Note: Note that eta expansion in CorePrep used to be very fragile+due to the "prediction" of CAFfyness that we used to make during tidying.  We+previously saturated primop applications here as well but due to this+fragility (see #16846) we now deal with this another way, as described in+Note [Primop wrappers] in GHC.Builtin.PrimOps.++Note [Eta expansion and the CorePrep invariants]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+It turns out to be much much easier to do eta expansion+*after* the main CorePrep stuff.  But that places constraints+on the eta expander: given a CpeRhs, it must return a CpeRhs.++For example here is what we do not want:+                f = /\a -> g (h 3)      -- h has arity 2+After ANFing we get+                f = /\a -> let s = h 3 in g s+and now we do NOT want eta expansion to give+                f = /\a -> \ y -> (let s = h 3 in g s) y++Instead GHC.Core.Opt.Arity.etaExpand gives+                f = /\a -> \y -> let s = h 3 in g s y++Note [Eta expansion of arguments in CorePrep]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Suppose `g = \x y. blah` and consider the expression `f (g x)`; we ANFise to++  let t = g x+  in f t++We really don't want that `t` to be a thunk! That just wastes runtime, updating+a thunk with a PAP etc. The code generator could in principle allocate a PAP,+but in fact it does not know how to do that -- it's easier just to eta-expand:++  let t = \y. g x y+  in f t++To what arity should we eta-expand the argument? `cpeArg` uses two strategies,+governed by the presence of `-fdo-clever-arg-eta-expansion` (implied by -O):++  1. Cheap, with -O0: just use `exprArity`.+  2. More clever but expensive, with -O1 -O2: use `exprEtaExpandArity`,+     same function the Simplifier uses to eta expand RHSs and lambda bodies.++The only reason for using (1) rather than (2) is to keep compile times down.+Using (2) in -O0 bumped up compiler allocations by 2-3% in tests T4801 and+T5321*. However, Plan (2) catches cases that (1) misses.+For example (#23083, assuming -fno-pedantic-bottoms):++  let t = case z of __DEFAULT -> g x+  in f t++to++  let t = \y -> case z of __DEFAULT -> g x y+  in f t++Note that there is a missed opportunity in eta expanding `t` earlier, in the+Simplifier: It would allow us to inline `g`, potentially enabling further+simplification. But then we could have inlined `g` into the PAP to begin with,+and that is discussed in #23150; hence we needn't worry about that in CorePrep.++There is a nasty Wrinkle:++(EA1) When eta expanding an argument headed by a join point, we might get+      "crap", as Note [Eta expansion for join points] in GHC.Core.Opt.Arity puts+      it.+      Consider++        f (join j x = rhs in ...(j 1)...(j 2)...)++      where the argument has arity 1. We might be tempted to eta expand, to++        f (\y -> (join j x = rhs in ...(j 1)...(j 2)...) y)++      Why hasn't the App to `y` been pushed into the join point? That's exactly+      the crap of Note [Eta expansion for join points], so we have to put up+      with it here.+      In our case, (join j x = rhs in ...(j 1)...(j 2)...) is not a valid+      `CpeApp` (see Note [CorePrep invariants]) and we'd get a crash in the App+      case of `coreToStgExpr`.+      Hence we simply check for the cases where an intervening join point+      binding in the tail context of the argument would lead to the introduction+      of such crap via `has_join_in_tail_context`, in which case we abstain from+      eta expansion.++      This scenario occurs rarely; hence it's OK to generate sub-optimal code.+      The alternative would be to fix Note [Eta expansion for join points], but+      that's quite challenging due to unfoldings of (recursive) join points.++(EA2) In cpeArgArity, if float_decision = FloatNone) the `arg` will look like+           let <binds> in rhs+      where <binds> is non-empty and can't be floated out of a lazy context (see+      `wantFloatLocal`). So we can't eta-expand it anyway, so we can return 0+      forthwith.  Without this short-cut we will call exprEtaExpandArity on the+      `arg`, and <binds> might be enormous. exprEtaExpandArity be very expensive+      on this: it uses arityType, and may look at <binds>.++      On the other hand, if float_decision = FloatAll, there will be no+      let-bindings around 'arg'; they will have floated out.  So+      exprEtaExpandArity is cheap.++      This can make a huge difference on deeply nested expressions like+         f (f (f (f (f  ...))))+      #24471 is a good example, where Prep took 25% of compile time!+-}++cpeEtaExpand :: Arity -> CpeRhs -> CpeRhs+cpeEtaExpand arity expr+  | arity == 0 = expr+  | otherwise  = etaExpand arity expr++{-+************************************************************************+*                                                                      *+                Floats+*                                                                      *+************************************************************************++Note [Pin demand info on floats]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+We pin demand info on floated lets, so that we can see the one-shot thunks.++Note [Speculative evaluation]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Since call-by-value is much cheaper than call-by-need, we case-bind arguments+that are either++  1. Strictly evaluated anyway, according to the DmdSig of the callee, or+  2. ok-for-spec, according to 'exprOkForSpeculation'.+     This includes DFuns `$fEqList a`, for example.+     (Could identify more in the future; see reference to !1866 below.)++While (1) is a no-brainer and always beneficial, (2) is a bit+more subtle, as the careful haddock for 'exprOkForSpeculation'+points out. Still, by case-binding the argument we don't need+to allocate a thunk for it, whose closure must be retained as+long as the callee might evaluate it. And if it is evaluated on+most code paths anyway, we get to turn the unknown eval in the+callee into a known call at the call site.++Very Nasty Wrinkle++We must be very careful not to speculate recursive calls!  Doing so+might well change termination behavior.++That comes up in practice for DFuns, which are considered ok-for-spec,+because they always immediately return a constructor.+See Note [NON-BOTTOM-DICTS invariant] in GHC.Core.++But not so if you speculate the recursive call, as #20836 shows:++  class Foo m => Foo m where+    runFoo :: m a -> m a+  newtype Trans m a = Trans { runTrans :: m a }+  instance Monad m => Foo (Trans m) where+    runFoo = id++(NB: class Foo m => Foo m` looks weird and needs -XUndecidableSuperClasses. The+example in #20836 is more compelling, but boils down to the same thing.)+This program compiles to the following DFun for the `Trans` instance:++  Rec {+  $fFooTrans+    = \ @m $dMonad -> C:Foo ($fFooTrans $dMonad) (\ @a -> id)+  end Rec }++Note that the DFun immediately terminates and produces a dictionary, just+like DFuns ought to, but it calls itself recursively to produce the `Foo m`+dictionary. But alas, if we treat `$fFooTrans` as always-terminating, so+that we can speculate its calls, and hence use call-by-value, we get:++  $fFooTrans+    = \ @m $dMonad -> case ($fFooTrans $dMonad) of sc ->+                      C:Foo sc (\ @a -> id)++and that's an infinite loop!+Note that this bad-ness only happens in `$fFooTrans`'s own RHS. In the+*body* of the letrec, it's absolutely fine to use call-by-value on+`foo ($fFooTrans d)`.++Our solution is this: we track in cpe_rec_ids the set of enclosing+recursively-bound Ids, the RHSs of which we are currently transforming and then+in 'exprOkForSpecEval' (a special entry point to 'exprOkForSpeculation',+basically) we'll say that any binder in this set is not ok-for-spec.++Note if we have a letrec group `Rec { f1 = rhs1; ...; fn = rhsn }`, and we+prep up `rhs1`, we have to include not only `f1`, but all binders of the group+`f1..fn` in this set, otherwise our fix is not robust wrt. mutual recursive+DFuns.++NB: If at some point we decide to have a termination analysis for general+functions (#8655, !1866), we need to take similar precautions for (guarded)+recursive functions:++  repeat x = x : repeat x++Same problem here: As written, repeat evaluates rapidly to WHNF. So `repeat x`+is a cheap call that we are willing to speculate, but *not* in repeat's RHS.+Fortunately, pce_rec_ids already has all the information we need in that case.++The problem is very similar to Note [Eta reduction in recursive RHSs].+Here as well as there it is *unsound* to change the termination properties+of the very function whose termination properties we are exploiting.++It is also similar to Note [Do not strictify a DFun's parameter dictionaries],+where marking recursive DFuns (of undecidable *instances*) strict in dictionary+*parameters* leads to quite the same change in termination as above.++Note [BindInfo and FloatInfo]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+The `BindInfo` of a `Float` describes whether it will be case-bound or+let-bound:++  * `LetBound`: A let binding `let x = rhs in ...`, can be Rec or NonRec.+  * `CaseBound`: A case binding `case rhs of x -> { __DEFAULT -> .. }`.+                 (So always NonRec.)+                 Some case-bound things (string literals, lifted bindings)+                 can float to top-level (but not all), hence it is similar+                 to, but not the same as `StrictContextFloatable :: FloatInfo`+                 described below.++This info is used in `wrapBinds` to pick the corresponding binding form.++We want to case-bind iff the binding is (non-recursive, and) either++  * ok-for-spec-eval (and perhaps lifted, see Note [Speculative evaluation]), or+  * unlifted, or+  * strictly used++The `FloatInfo` of a `Float` describes how far it can float without+(a) violating Core invariants and (b) changing semantics.++  * Any binding is at least `StrictContextFloatable`, meaning we may float it+    out of a strict context such as `f <>` where `f` is strict.++  * A binding is `LazyContextFloatable` if we may float it out of a lazy context+    such as `let x = <> in Just x`.+    Counterexample: A strict or unlifted binding that isn't ok-for-spec-eval+                    such as `case divInt# x y of r -> { __DEFAULT -> I# r }`.+                    Here, we may not foat out the strict `r = divInt# x y`.++  * A binding is `TopLvlFloatable` if it is `LazyContextFloatable` and also can+    be bound at the top level.+    Counterexample: A strict or unlifted binding (ok-for-spec-eval or not)+                    such as `case x +# y of r -> { __DEFAULT -> I# r }`.++This meaning of "at least" is encoded in `floatsAtLeastAsFarAs`.+Note that today, `LetBound` implies `TopLvlFloatable`, so we could make do with+the the following enum (check `mkNonRecFloat` for whether this is up to date):++   LetBoundTopLvlFloatable          (lifted or boxed values)+  CaseBoundTopLvlFloatable          (strings, ok-for-spec-eval and lifted)+  CaseBoundLazyContextFloatable     (ok-for-spec-eval and unlifted)+  CaseBoundStrictContextFloatable   (not ok-for-spec-eval and unlifted)++Although there is redundancy in the current encoding, SG thinks it is cleaner+conceptually.++See also Note [Floats and FloatDecision] for how we maintain whole groups of+floats and how far they go.++Note [Floats and FloatDecision]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+We have a special datatype `Floats` for modelling a telescope of `FloatingBind`+and caching its "maximum" `FloatInfo`, according to `floatsAtLeastAsFarAs`+(see Note [BindInfo and FloatInfo] for the ordering).+There are several operations for creating and combining `Floats` that maintain+scoping and the cached `FloatInfo`.++When deciding whether we want to float out a `Floats` out of a binding context+such as `let x = <> in e` (let), `f <>` (app), or `x = <>; ...` (top-level),+we consult the cached `FloatInfo` of the `Floats`:++  * If we want to float to the top-level (`x = <>; ...`), we check whether+    we may float-at-least-as-far-as `TopLvlFloatable`, in which case we+    respond with `FloatAll :: FloatDecision`; otherwise we say `FloatNone`.+  * If we want to float locally (let or app), then the floating decision is+    described in Note [wantFloatLocal].++`executeFloatDecision` is then used to act on the particular `FloatDecision`.+-}++-- See Note [BindInfo and FloatInfo]+data BindInfo+  = CaseBound -- ^ A strict binding+  | LetBound  -- ^ A lazy or value binding+  deriving Eq++-- See Note [BindInfo and FloatInfo]+data FloatInfo+  = TopLvlFloatable+  -- ^ Anything that can be bound at top-level, such as arbitrary lifted+  -- bindings or anything that responds True to `exprIsHNF`, such as literals or+  -- saturated DataCon apps where unlifted or strict args are values.++  | LazyContextFloatable+  -- ^ Anything that can be floated out of a lazy context.+  -- In addition to any 'TopLvlFloatable' things, this includes (unlifted)+  -- bindings that are ok-for-spec that we intend to case-bind.++  | StrictContextFloatable+  -- ^ Anything that can be floated out of a strict evaluation context.+  -- That is possible for all bindings; this is the Top element of 'FloatInfo'.++  deriving Eq++instance Outputable BindInfo where+  ppr CaseBound = text "Case"+  ppr LetBound  = text "Let"++instance Outputable FloatInfo where+  ppr TopLvlFloatable = text "top-lvl"+  ppr LazyContextFloatable = text "lzy-ctx"+  ppr StrictContextFloatable = text "str-ctx"++-- See Note [Floating in CorePrep]+-- and Note [BindInfo and FloatInfo]+data FloatingBind+  = Float !CoreBind !BindInfo !FloatInfo    -- Never a join-point binding+  | UnsafeEqualityCase !CoreExpr !CoreBndr !AltCon ![CoreBndr]+  | FloatTick CoreTickish++-- See Note [Floats and FloatDecision]+data Floats+  = Floats+  { fs_info  :: !FloatInfo+  , fs_binds :: !(OrdList FloatingBind)+  }++instance Outputable FloatingBind where+  ppr (Float b bi fi) = ppr bi <+> ppr fi <+> ppr b+  ppr (FloatTick t) = ppr t+  ppr (UnsafeEqualityCase scrut b k bs) = text "case" <+> ppr scrut+                                <+> text "of"<+> ppr b <> text "@"+                                <> case bs of+                                   [] -> ppr k+                                   _  -> parens (ppr k <+> ppr bs)++instance Outputable Floats where+  ppr (Floats info binds) = text "Floats" <> brackets (ppr info) <> braces (ppr binds)++lubFloatInfo :: FloatInfo -> FloatInfo -> FloatInfo+lubFloatInfo StrictContextFloatable _                      = StrictContextFloatable+lubFloatInfo _                      StrictContextFloatable = StrictContextFloatable+lubFloatInfo LazyContextFloatable   _                      = LazyContextFloatable+lubFloatInfo _                      LazyContextFloatable   = LazyContextFloatable+lubFloatInfo TopLvlFloatable        TopLvlFloatable        = TopLvlFloatable++floatsAtLeastAsFarAs :: FloatInfo -> FloatInfo -> Bool+-- See Note [Floats and FloatDecision]+floatsAtLeastAsFarAs l r = l `lubFloatInfo` r == r++emptyFloats :: Floats+emptyFloats = Floats TopLvlFloatable nilOL++isEmptyFloats :: Floats -> Bool+isEmptyFloats (Floats _ b) = isNilOL b++getFloats :: Floats -> OrdList FloatingBind+getFloats = fs_binds++unitFloat :: FloatingBind -> Floats+unitFloat = snocFloat emptyFloats++floatInfo :: FloatingBind -> FloatInfo+floatInfo (Float _ _ info)     = info+floatInfo UnsafeEqualityCase{} = LazyContextFloatable -- See Note [Floating in CorePrep]+floatInfo FloatTick{}          = TopLvlFloatable      -- We filter these out in cpePair,+                                                      -- see Note [Floating Ticks in CorePrep]++-- | Append a `FloatingBind` `b` to a `Floats` telescope `bs` that may reference any+-- binding of the 'Floats'.+snocFloat :: Floats -> FloatingBind -> Floats+snocFloat floats fb =+  Floats { fs_info  = lubFloatInfo (fs_info floats) (floatInfo fb)+         , fs_binds = fs_binds floats `snocOL` fb }++-- | Cons a `FloatingBind` `b` to a `Floats` telescope `bs` which scopes over+-- `b`.+consFloat :: FloatingBind -> Floats -> Floats+consFloat fb floats =+  Floats { fs_info  = lubFloatInfo (fs_info floats) (floatInfo fb)+         , fs_binds = fb `consOL`  fs_binds floats }++-- | Append two telescopes, nesting the right inside the left.+appFloats :: Floats -> Floats -> Floats+appFloats outer inner =+  Floats { fs_info  = lubFloatInfo (fs_info outer) (fs_info inner)+         , fs_binds = fs_binds outer `appOL` fs_binds inner }++-- | Zip up two `Floats`, none of which scope over the other+zipFloats :: Floats -> Floats -> Floats+-- We may certainly just nest one telescope in the other, so appFloats is a+-- valid implementation strategy.+zipFloats = appFloats++-- | `zipFloats` a bunch of independent telescopes.+zipManyFloats :: [Floats] -> Floats+zipManyFloats = foldr zipFloats emptyFloats++mkNonRecFloat :: CorePrepEnv -> Demand -> Bool -> Id -> CpeRhs -> FloatingBind+mkNonRecFloat env dmd is_unlifted bndr rhs+  = -- pprTrace "mkNonRecFloat" (ppr bndr <+> ppr (bound,info)+    --                             <+> ppr is_lifted <+> ppr is_strict+    --                             <+> ppr ok_for_spec+    --                           $$ ppr rhs) $+    Float (NonRec bndr' rhs) bound info+  where+    bndr' = setIdDemandInfo bndr dmd -- See Note [Pin demand info on floats]+    (bound,info)+      | is_lifted, is_hnf        = (LetBound, TopLvlFloatable)+          -- is_lifted: We currently don't allow unlifted values at the+          --            top-level or inside letrecs+          --            (but SG thinks that in principle, we should)+      | is_data_con bndr         = (LetBound, TopLvlFloatable)+          -- We need this special case for unlifted DataCon workers/wrappers+          -- until #17521 is fixed+      | exprIsTickedString rhs   = (CaseBound, TopLvlFloatable)+          -- String literals are unboxed (so must be case-bound) and float to+          -- the top-level+      | is_unlifted, ok_for_spec = (CaseBound, LazyContextFloatable)+      | is_lifted,   ok_for_spec = (CaseBound, TopLvlFloatable)+          -- See Note [Speculative evaluation]+          -- Ok-for-spec-eval things will be case-bound, lifted or not.+          -- But when it's lifted we are ok with floating it to top-level+          -- (where it is actually bound lazily).+      | is_unlifted || is_strict = (CaseBound, StrictContextFloatable)+          -- These will never be floated out of a lazy RHS context+      | otherwise                = assertPpr is_lifted (ppr rhs) $+                                   (LetBound, TopLvlFloatable)+          -- And these float freely but can't be speculated, hence LetBound++    is_lifted   = not is_unlifted+    is_hnf      = exprIsHNF rhs+    is_strict   = isStrUsedDmd dmd+    ok_for_spec = exprOkForSpecEval (not . is_rec_call) rhs+    is_rec_call = (`elemUnVarSet` cpe_rec_ids env)+    is_data_con = isJust . isDataConId_maybe++-- | Wrap floats around an expression+wrapBinds :: Floats -> CpeBody -> CpeBody+wrapBinds floats body+  = -- pprTraceWith "wrapBinds" (\res -> ppr floats $$ ppr body $$ ppr res) $+    foldrOL mk_bind body (getFloats floats)+  where+    -- See Note [BindInfo and FloatInfo] on whether we pick Case or Let here+    mk_bind f@(Float bind CaseBound _) body+      | NonRec bndr rhs <- bind+      = mkDefaultCase rhs bndr body+      | otherwise+      = pprPanic "wrapBinds" (ppr f)+    mk_bind (Float bind _ _) body+      = Let bind body+    mk_bind (UnsafeEqualityCase scrut b con bs) body+      = mkSingleAltCase scrut b con bs body+    mk_bind (FloatTick tickish) body+      = mkTick tickish body++-- | Put floats at top-level+deFloatTop :: Floats -> [CoreBind]+-- Precondition: No Strict or LazyContextFloatable 'FloatInfo', no ticks!+deFloatTop floats+  = foldrOL get [] (getFloats floats)+  where+    get (Float b _ TopLvlFloatable) bs+      = get_bind b : bs+    get b _  = pprPanic "corePrepPgm" (ppr b)++    -- See Note [Dead code in CorePrep]+    get_bind (NonRec x e) = NonRec x (occurAnalyseExpr e)+    get_bind (Rec xes)    = Rec [(x, occurAnalyseExpr e) | (x, e) <- xes]++---------------------------------------------------------------------------++{- Note [wantFloatLocal]+~~~~~~~~~~~~~~~~~~~~~~~~+Consider+  let x = let y = e1 in e2+  in e+Similarly for `(\x. e) (let y = e1 in e2)`.+Do we want to float out `y` out of `x`?+(This is discussed in detail in the paper+"Let-floating: moving bindings to give faster programs".)++`wantFloatLocal` is concerned with answering this question.+It considers the Demand on `x`, whether or not `e2` is unlifted and the+`FloatInfo` of the `y` binding (e.g., it might itself be unlifted, a value,+strict, or ok-for-spec).++We float out if ...+  1. ... the binding context is strict anyway, so either `x` is used strictly+     or has unlifted type.+     Doing so is trivially sound and won`t increase allocations, so we+     return `FloatAll`.+     This might happen while ANF-ising `f (g (h 13))` where `f`,`g` are strict:+       f (g (h 13))+       ==> { ANF }+       case (case h 13 of r -> g r) of r2 -> f r2+       ==> { Float }+       case h 13 of r -> case g r of r2 -> f r2+     The latter is easier to read and grows less stack.+  2. ... `e2` becomes a value in doing so, in which case we won't need to+     allocate a thunk for `x`/the arg that closes over the FVs of `e1`.+     In general, this is only sound if `y=e1` is `LazyContextFloatable`.+     (See Note [BindInfo and FloatInfo].)+     Nothing is won if `x` doesn't become a value+     (i.e., `let x = let sat = f 14 in g sat in e`),+     so we return `FloatNone` if there is any float that is+     `StrictContextFloatable`, and return `FloatAll` otherwise.++To elaborate on (2), consider the case when the floated binding is+`e1 = divInt# a b`, e.g., not `LazyContextFloatable`:+  let x = I# (a `divInt#` b)+  in e+this ANFises to+  let x = case a `divInt#` b of r { __DEFAULT -> I# r }+  in e+If `x` is used lazily, we may not float `r` further out.+A float binding `x +# y` is OK, though, and so every ok-for-spec-eval+binding is `LazyContextFloatable`.++Wrinkles:++ (W1) When the outer binding is a letrec, i.e.,+        letrec x = case a +# b of r { __DEFAULT -> f y r }+               y = [x]+        in e+      we don't want to float `LazyContextFloatable` bindings such as `r` either+      and require `TopLvlFloatable` instead.+      The reason is that we don't track FV of FloatBindings, so we would need+      to park them in the letrec,+        letrec r = a +# b -- NB: r`s RHS might scope over x and y+               x = f y r+               y = [x]+        in e+      and now we have violated Note [Core letrec invariant].+      So we preempt this case in `wantFloatLocal`, responding `FloatNone` unless+      all floats are `TopLvlFloatable`.+-}++data FloatDecision+  = FloatNone+  | FloatAll++executeFloatDecision :: FloatDecision -> Floats -> CpeRhs -> UniqSM (Floats, CpeRhs)+executeFloatDecision dec floats rhs+  = case dec of+      FloatAll                 -> return (floats, rhs)+      FloatNone+        | isEmptyFloats floats -> return (emptyFloats, rhs)+        | otherwise            -> do { (floats', body) <- rhsToBody rhs+                                     ; return (emptyFloats, wrapBinds floats $+                                                            wrapBinds floats' body) }+            -- FloatNone case: `rhs` might have lambdas, and we can't+            -- put them inside a wrapBinds, which expects a `CpeBody`.++wantFloatTop :: Floats -> FloatDecision+wantFloatTop fs+  | fs_info fs `floatsAtLeastAsFarAs` TopLvlFloatable = FloatAll+  | otherwise                                         = FloatNone++wantFloatLocal :: RecFlag -> Demand -> Bool -> Floats -> CpeRhs -> FloatDecision+-- See Note [wantFloatLocal]+wantFloatLocal is_rec rhs_dmd rhs_is_unlifted floats rhs+  |  isEmptyFloats floats -- Well yeah...+  || isStrUsedDmd rhs_dmd -- Case (1) of Note [wantFloatLocal]+  || rhs_is_unlifted      -- dito+  || (fs_info floats `floatsAtLeastAsFarAs` max_float_info && exprIsHNF rhs)+                          -- Case (2) of Note [wantFloatLocal]+  = FloatAll++  | otherwise+  = FloatNone+  where+    max_float_info | isRec is_rec = TopLvlFloatable+                   | otherwise    = LazyContextFloatable+                    -- See Note [wantFloatLocal], Wrinkle (W1)+                    -- for 'is_rec'++{-+************************************************************************+*                                                                      *+                Cloning+*                                                                      *+************************************************************************+-}++-- ---------------------------------------------------------------------------+--                      The environment+-- ---------------------------------------------------------------------------++{- Note [Inlining in CorePrep]+~~~~~~~~~~~~~~~~~~~~~~~~~~~+There is a subtle but important invariant that must be upheld in the output+of CorePrep: there are no "trivial" updatable thunks.  Thus, this Core+is impermissible:++     let x :: ()+         x = y++(where y is a reference to a GLOBAL variable).  Thunks like this are silly:+they can always be profitably replaced by inlining x with y. Consequently,+the code generator/runtime does not bother implementing this properly+(specifically, there is no implementation of stg_ap_0_upd_info, which is the+stack frame that would be used to update this thunk.  The "0" means it has+zero free variables.)++In general, the inliner is good at eliminating these let-bindings.  However,+there is one case where these trivial updatable thunks can arise: when+we are optimizing away 'lazy' (see Note [lazyId magic], and also+'cpeRhsE'.)  Then, we could have started with:++     let x :: ()+         x = lazy @ () y++which is a perfectly fine, non-trivial thunk, but then CorePrep will+drop 'lazy', giving us 'x = y' which is trivial and impermissible.+The solution is CorePrep to have a miniature inlining pass which deals+with cases like this.  We can then drop the let-binding altogether.++Why does the removal of 'lazy' have to occur in CorePrep?+The gory details are in Note [lazyId magic] in GHC.Types.Id.Make, but the+main reason is that lazy must appear in unfoldings (optimizer+output) and it must prevent call-by-value for catch# (which+is implemented by CorePrep.)++An alternate strategy for solving this problem is to have the+inliner treat 'lazy e' as a trivial expression if 'e' is trivial.+We decided not to adopt this solution to keep the definition+of 'exprIsTrivial' simple.++There is ONE caveat however: for top-level bindings we have+to preserve the binding so that we float the (hacky) non-recursive+binding for data constructors; see Note [Data constructor workers].++Note [CorePrep inlines trivial CoreExpr not Id]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+TODO+Why does cpe_env need to be an IdEnv CoreExpr, as opposed to an+IdEnv Id?  Naively, we might conjecture that trivial updatable thunks+as per Note [Inlining in CorePrep] always have the form+'lazy @ SomeType gbl_id'.  But this is not true: the following is+perfectly reasonable Core:++     let x :: ()+         x = lazy @ (forall a. a) y @ Bool++When we inline 'x' after eliminating 'lazy', we need to replace+occurrences of 'x' with 'y @ bool', not just 'y'.  Situations like+this can easily arise with higher-rank types; thus, cpe_env must+map to CoreExprs, not Ids.++-}++data CorePrepConfig = CorePrepConfig+  { cp_catchNonexhaustiveCases :: !Bool+  -- ^ Whether to generate a default alternative with ``error`` in these+  -- cases. This is helpful when debugging demand analysis or type+  -- checker bugs which can sometimes manifest as segmentation faults.++  , cp_convertNumLit           :: !(LitNumType -> Integer -> Maybe CoreExpr)+  -- ^ Convert some numeric literals (Integer, Natural) into their final+  -- Core form.++  , cp_arityOpts               :: !(Maybe ArityOpts)+  -- ^ Configuration for arity analysis ('exprEtaExpandArity').+  -- See Note [Eta expansion of arguments in CorePrep]+  -- When 'Nothing' (e.g., -O0, -O1), use the cheaper 'exprArity' instead+  }++data CorePrepEnv+  = CPE { cpe_config          :: !CorePrepConfig+        -- ^ This flag is intended to aid in debugging strictness+        -- analysis bugs. These are particularly nasty to chase down as+        -- they may manifest as segmentation faults. When this flag is+        -- enabled we instead produce an 'error' expression to catch+        -- the case where a function we think should bottom+        -- unexpectedly returns.++        , cpe_subst :: Subst+        -- ^ The IdEnv part of the substitution is used for three operations:+        --+        --      1. To support cloning of local Ids so that they are+        --      all unique (see Note [Cloning in CorePrep])+        --+        --      2. To support beta-reduction of runRW, see+        --      Note [runRW magic] and Note [runRW arg].+        --+        --      3. To let us inline trivial RHSs of non top-level let-bindings,+        --      see Note [lazyId magic], Note [Inlining in CorePrep]+        --      and Note [CorePrep inlines trivial CoreExpr not Id] (#12076)+        --+        -- The TyCoVar part of the substitution is used only for+        --     Note [Cloning CoVars and TyVars]++        , cpe_rec_ids         :: UnVarSet -- Faster OutIdSet; See Note [Speculative evaluation]+    }++mkInitialCorePrepEnv :: CorePrepConfig -> CorePrepEnv+mkInitialCorePrepEnv cfg = CPE+      { cpe_config        = cfg+      , cpe_subst         = emptySubst+      , cpe_rec_ids       = emptyUnVarSet+      }++extendCorePrepEnv :: CorePrepEnv -> Id -> Id -> CorePrepEnv+extendCorePrepEnv cpe@(CPE { cpe_subst = subst }) id id'+    = cpe { cpe_subst = subst2 }+    where+      subst1 = extendSubstInScope subst id'+      subst2 = extendIdSubst subst1 id (Var id')++extendCorePrepEnvList :: CorePrepEnv -> [(Id,Id)] -> CorePrepEnv+extendCorePrepEnvList cpe@(CPE { cpe_subst = subst }) prs+    = cpe { cpe_subst = subst2 }+    where+      subst1 = extendSubstInScopeList subst (map snd prs)+      subst2 = extendIdSubstList subst1 [(id, Var id') | (id,id') <- prs]++extendCorePrepEnvExpr :: CorePrepEnv -> Id -> CoreExpr -> CorePrepEnv+extendCorePrepEnvExpr cpe id expr+    = cpe { cpe_subst = extendIdSubst (cpe_subst cpe) id expr }++lookupCorePrepEnv :: CorePrepEnv -> Id -> CoreExpr+lookupCorePrepEnv cpe id+  = case lookupIdSubst_maybe (cpe_subst cpe) id of+       Just e -> e+       Nothing -> Var id+    -- Do not use GHC.Core.Subs.lookupIdSubst because that is a no-op on GblIds;+    -- and Tidy has made top-level externally-visible Ids into GblIds++enterRecGroupRHSs :: CorePrepEnv -> [OutId] -> CorePrepEnv+enterRecGroupRHSs env grp+  = env { cpe_rec_ids = extendUnVarSetList grp (cpe_rec_ids env) }++cpSubstTy :: CorePrepEnv -> Type -> Type+cpSubstTy (CPE { cpe_subst = subst }) ty = substTy subst ty+          -- substTy has a short-cut if the TCvSubst is empty++cpSubstCo :: CorePrepEnv -> Coercion -> Coercion+cpSubstCo (CPE { cpe_subst = subst }) co = substCo subst co+          -- substCo has a short-cut if the TCvSubst is empty++------------------------------------------------------------------------------+-- Cloning binders+-- ---------------------------------------------------------------------------++cpCloneBndrs :: CorePrepEnv -> [InVar] -> UniqSM (CorePrepEnv, [OutVar])+cpCloneBndrs env bs = mapAccumLM cpCloneBndr env bs++cpCloneCoVarBndr :: CorePrepEnv -> InVar -> UniqSM (CorePrepEnv, OutVar)+-- Clone the CoVar+-- See Note [Cloning CoVars and TyVars]+cpCloneCoVarBndr env@(CPE { cpe_subst = subst }) covar+  = assertPpr (isCoVar covar) (ppr covar) $+    do { uniq <- getUniqueM+       ; let covar1 = setVarUnique covar uniq+             covar2 = updateVarType (substTy subst) covar1+             subst1 = extendTCvSubstWithClone subst covar covar2+       ; return (env { cpe_subst = subst1 }, covar2) }++cpCloneBndr  :: CorePrepEnv -> InVar -> UniqSM (CorePrepEnv, OutVar)+-- See Note [Cloning in CorePrep]+cpCloneBndr env@(CPE { cpe_subst = subst }) bndr+  | isTyCoVar bndr  -- See Note [Cloning CoVars and TyVars]+  = if isEmptyTCvSubst subst    -- The common case+    then return (env { cpe_subst = extendSubstInScope subst bndr }, bndr)+    else -- No need to clone the Unique; but we must apply the substitution+         let bndr1  = updateVarType (substTy subst) bndr+             subst1 = extendTCvSubstWithClone subst bndr bndr1+         in return (env { cpe_subst = subst1 }, bndr1)++  | otherwise  -- A non-CoVar Id+  = do { bndr1 <- clone_it bndr+       ; let bndr2 = updateIdTypeAndMult (substTy subst) bndr1++       -- Drop (now-useless) rules/unfoldings+       -- See Note [Drop unfoldings and rules]+       -- and Note [Preserve evaluatedness] in GHC.Core.Tidy+       -- And force it.. otherwise the old unfolding is just retained.+       -- See #22071+       ; let !unfolding' = trimUnfolding (realIdUnfolding bndr)+                          -- Simplifier will set the Id's unfolding++             bndr3 = bndr2 `setIdUnfolding`      unfolding'+                           `setIdSpecialisation` emptyRuleInfo++       ; return (extendCorePrepEnv env bndr bndr3, bndr3) }+  where+    clone_it bndr+      | isLocalId bndr+      = do { uniq <- getUniqueM+           ; return (setVarUnique bndr uniq) }++      | otherwise   -- Top level things, which we don't want+                    -- to clone, have become GlobalIds by now+      = return bndr++{- Note [Drop unfoldings and rules]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+We want to drop the unfolding/rules on every Id:++  - We are now past interface-file generation, and in the+    codegen pipeline, so we really don't need full unfoldings/rules++  - The unfolding/rule may be keeping stuff alive that we'd like+    to discard.  See  Note [Dead code in CorePrep]++  - Getting rid of unnecessary unfoldings reduces heap usage++  - We are changing uniques, so if we didn't discard unfoldings/rules+    we'd have to substitute in them++HOWEVER, we want to preserve evaluated-ness;+see Note [Preserve evaluatedness] in GHC.Core.Tidy.+-}++------------------------------------------------------------------------------+-- Cloning ccall Ids; each must have a unique name,+-- to give the code generator a handle to hang it on+-- ---------------------------------------------------------------------------++fiddleCCall :: Id -> UniqSM Id+fiddleCCall id+  | isFCallId id = (id `setVarUnique`) <$> getUniqueM+  | otherwise    = return id++------------------------------------------------------------------------------+-- Generating new binders+-- ---------------------------------------------------------------------------++newVar :: Type -> UniqSM Id+newVar ty+ = seqType ty `seq` mkSysLocalOrCoVarM (fsLit "sat") ManyTy ty+++------------------------------------------------------------------------------+-- Floating ticks+-- ---------------------------------------------------------------------------+--+-- Note [Floating Ticks in CorePrep]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- It might seem counter-intuitive to float ticks by default, given+-- that we don't actually want to move them if we can help it. On the+-- other hand, nothing gets very far in CorePrep anyway, and we want+-- to preserve the order of let bindings and tick annotations in+-- relation to each other. For example, if we just wrapped let floats+-- when they pass through ticks, we might end up performing the+-- following transformation:+--+--   src<...> let foo = bar in baz+--   ==>  let foo = src<...> bar in src<...> baz+--+-- Because the let-binding would float through the tick, and then+-- immediately materialize, achieving nothing but decreasing tick+-- accuracy. The only special case is the following scenario:+--+--   let foo = src<...> (let a = b in bar) in baz+--   ==>  let foo = src<...> bar; a = src<...> b in baz+--+-- Here we would not want the source tick to end up covering "baz" and+-- therefore refrain from pushing ticks outside. Instead, we copy them+-- into the floating binds (here "a") in cpePair. Note that where "b"+-- or "bar" are (value) lambdas we have to push the annotations+-- further inside in order to uphold our rules.+--+-- All of this is implemented below in @wrapTicks@.++-- | Like wrapFloats, but only wraps tick floats+wrapTicks :: Floats -> CoreExpr -> (Floats, CoreExpr)+wrapTicks floats expr+  | (floats1, ticks1) <- fold_fun go floats+  = (floats1, foldrOL mkTick expr ticks1)+  where fold_fun f floats =+           let (binds, ticks) = foldlOL f (nilOL,nilOL) (fs_binds floats)+           in (floats { fs_binds = binds }, ticks)+        -- Deeply nested constructors will produce long lists of+        -- redundant source note floats here. We need to eliminate+        -- those early, as relying on mkTick to spot it after the fact+        -- can yield O(n^3) complexity [#11095]+        go (flt_binds, ticks) (FloatTick t)+          = assert (tickishPlace t == PlaceNonLam)+            (flt_binds, if any (flip tickishContains t) ticks+                        then ticks else ticks `snocOL` t)+        go (flt_binds, ticks) f@UnsafeEqualityCase{}+          -- unsafe equality case will be erased; don't wrap anything!+          = (flt_binds `snocOL` f, ticks)+        go (flt_binds, ticks) f@Float{}+          = (flt_binds `snocOL` foldrOL wrap f ticks, ticks)++        wrap t (Float bind bound info) = Float (wrapBind t bind) bound info+        wrap _ f                 = pprPanic "Unexpected FloatingBind" (ppr f)         wrapBind t (NonRec binder rhs) = NonRec binder (mkTick t rhs)         wrapBind t (Rec pairs)         = Rec (mapSnd (mkTick t) pairs) 
compiler/GHC/Data/Bitmap.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE BangPatterns #-}- -- -- (c) The University of Glasgow 2003-2006 --
compiler/GHC/Data/Graph/Collapse.hs view
@@ -25,7 +25,7 @@ import GHC.Cmm.Dataflow.Label import GHC.Data.Graph.Inductive.Graph import GHC.Types.Unique.Supply-import GHC.Utils.Panic+import GHC.Utils.Panic hiding (assert)   {-|@@ -131,7 +131,7 @@ -- to a single supernode, then materialize (``inflate'') the reducible -- equivalent graph from that supernode.  The `Supernode` class -- defines only the methods needed to collapse; rematerialization is--- the responsiblity of the client.+-- the responsibility of the client. -- -- During the Hecht-Ullman algorithm, every supernode has a unique -- entry point, which is given by `superLabel`.  But this invariant is
compiler/GHC/Data/Graph/Inductive/PatriciaTree.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE BangPatterns, ScopedTypeVariables #-}-{-# LANGUAGE DeriveGeneric #-}  -- |An efficient implementation of 'Data.Graph.Inductive.Graph.Graph' -- using big-endian patricia tree (i.e. "Data.IntMap").
compiler/GHC/Driver/Config/CmmToAsm.hs view
@@ -21,7 +21,8 @@    , ncgAsmContext            = initSDocContext dflags PprCode    , ncgProcAlignment         = cmmProcAlignment dflags    , ncgExternalDynamicRefs   = gopt Opt_ExternalDynamicRefs dflags-   , ncgPIC                   = positionIndependent dflags+   -- no PIC on wasm32 for now+   , ncgPIC                   = positionIndependent dflags && not (platformArch (targetPlatform dflags) == ArchWasm32)    , ncgInlineThresholdMemcpy = fromIntegral $ maxInlineMemcpyInsns dflags    , ncgInlineThresholdMemset = fromIntegral $ maxInlineMemsetInsns dflags    , ncgSplitSections         = gopt Opt_SplitSections dflags
compiler/GHC/Driver/Config/CmmToLlvm.hs view
@@ -23,6 +23,7 @@     , llvmCgContext              = initSDocContext dflags PprCode     , llvmCgFillUndefWithGarbage = gopt Opt_LlvmFillUndefWithGarbage dflags     , llvmCgSplitSection         = gopt Opt_SplitSections dflags+    , llvmCgAvxEnabled           = isAvxEnabled dflags     , llvmCgBmiVersion           = case platformArch (targetPlatform dflags) of                                       ArchX86_64 -> bmiVersion dflags                                       ArchX86    -> bmiVersion dflags
compiler/GHC/Driver/Config/Core/Opt/LiberateCase.hs view
@@ -6,7 +6,7 @@  import GHC.Core.Opt.LiberateCase ( LibCaseOpts(..) ) --- | Initialize configuration for the liberate case Core optomization+-- | Initialize configuration for the liberate case Core optimization -- pass. initLiberateCaseOpts :: DynFlags -> LibCaseOpts initLiberateCaseOpts dflags = LibCaseOpts
compiler/GHC/Driver/Config/Core/Opt/Simplify.hs view
@@ -80,7 +80,6 @@ initGentleSimplMode dflags = (initSimplMode dflags InitialPhase "Gentle")   { -- Don't do case-of-case transformations.     -- This makes full laziness work better-    -- See Note [Case-of-case and full laziness]     sm_case_case = False   } @@ -90,37 +89,3 @@     (True, True) -> FloatEnabled     (True, False)-> FloatNestedOnly     (False, _)   -> FloatDisabled---{- Note [Case-of-case and full laziness]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Case-of-case can hide opportunities for let-floating (full laziness).-For example-   rec { f = \y. case (expensive x) of (a,b) -> blah }-We might hope to float the (expensive x) out of the \y-loop.-But if we inline `expensive` we might get-   \y. case (case x of I# x' -> body) of (a,b) -> blah-Now if we do case-of-case we get-   \y. case x if I# x2 ->-       case body of (a,b) -> blah--Sadly, at this point `body` mentions `x2`, so we can't float it out of the-\y-loop.--Solution: don't do case-of-case in the "gentle" simplification phase that-precedes the first float-out transformation.  Implementation:--  * `sm_case_case` field in SimplMode--  * Consult `sm_case_case` (via `seCaseCase`) before doing case-of-case-    in GHC.Core.Opt.Simplify.Iteration.rebuildCall.--Wrinkles--* This applies equally to the case-of-runRW# transformation:-    case (runRW# (\s. body)) of (a,b) -> blah-    --->-    runRW# (\s. case body of (a,b) -> blah)-  Again, don't do this when `sm_case_case` is off.  See #25055 for-  a motivating example.--}
compiler/GHC/Driver/Config/CoreToStg/Prep.hs view
@@ -9,6 +9,7 @@ import GHC.Driver.Env import GHC.Driver.Session import GHC.Driver.Config.Core.Lint+import GHC.Driver.Config.Core.Opt.Arity import GHC.Tc.Utils.Env import GHC.Types.Var import GHC.Utils.Outputable ( alwaysQualify )@@ -17,14 +18,18 @@  initCorePrepConfig :: HscEnv -> IO CorePrepConfig initCorePrepConfig hsc_env = do+   let dflags = hsc_dflags hsc_env    convertNumLit <- do-     let platform = targetPlatform $ hsc_dflags hsc_env+     let platform = targetPlatform dflags          home_unit = hsc_home_unit hsc_env          lookup_global = lookupGlobal hsc_env      mkConvertNumLiteral platform home_unit lookup_global    return $ CorePrepConfig-      { cp_catchNonexhaustiveCases = gopt Opt_CatchNonexhaustiveCases $ hsc_dflags hsc_env+      { cp_catchNonexhaustiveCases = gopt Opt_CatchNonexhaustiveCases dflags       , cp_convertNumLit = convertNumLit+      , cp_arityOpts = if gopt Opt_DoCleverArgEtaExpansion dflags+                       then Just (initArityOpts dflags)+                       else Nothing       }  initCorePrepPgmConfig :: DynFlags -> [Var] -> CorePrepPgmConfig
compiler/GHC/Driver/Config/HsToCore.hs view
@@ -12,7 +12,7 @@   { bang_opt_strict_data   = xopt LangExt.StrictData dflags   , bang_opt_unbox_disable = gopt Opt_OmitInterfacePragmas dflags       -- Don't unbox if we aren't optimising; rather arbitrarily,-      -- we use -fomit-iface-pragmas as the indication+      -- we use -fomit-interface-pragmas as the indication   , bang_opt_unbox_strict  = gopt Opt_UnboxStrictFields dflags   , bang_opt_unbox_small   = gopt Opt_UnboxSmallStrictFields dflags   }
compiler/GHC/Driver/Config/Linker.hs view
@@ -1,13 +1,93 @@ module GHC.Driver.Config.Linker   ( initFrameworkOpts-  ) where+  , initLinkerConfig+  )+where +import GHC.Prelude+import GHC.Platform import GHC.Linker.Config  import GHC.Driver.DynFlags+import GHC.Driver.Session +import Data.List (isPrefixOf)+ initFrameworkOpts :: DynFlags -> FrameworkOpts initFrameworkOpts dflags = FrameworkOpts   { foFrameworkPaths    = frameworkPaths    dflags   , foCmdlineFrameworks = cmdlineFrameworks dflags   }++-- | Initialize linker configuration from DynFlags+initLinkerConfig :: DynFlags -> LinkerConfig+initLinkerConfig dflags =+  let+    -- see Note [Solaris linker]+    ld_filter = case platformOS (targetPlatform dflags) of+                  OSSolaris2 -> sunos_ld_filter+                  _          -> id+    sunos_ld_filter :: String -> String+    sunos_ld_filter = unlines . sunos_ld_filter' . lines+    sunos_ld_filter' x = if (undefined_found x && ld_warning_found x)+                          then (ld_prefix x) ++ (ld_postfix x)+                          else x+    breakStartsWith x y = break (isPrefixOf x) y+    ld_prefix = fst . breakStartsWith "Undefined"+    undefined_found = not . null . snd . breakStartsWith "Undefined"+    ld_warn_break = breakStartsWith "ld: warning: symbol referencing errors"+    ld_postfix = tail . snd . ld_warn_break+    ld_warning_found = not . null . snd . ld_warn_break++    -- program and arguments+    --+    -- `-optl` args come at the end, so that later `-l` options+    -- given there manually can fill in symbols needed by+    -- Haskell libraries coming in via `args`.+    (p,pre_args) = pgm_l dflags+    post_args    = map Option (getOpts dflags opt_l)++  in LinkerConfig+    { linkerProgram     = p+    , linkerOptionsPre  = pre_args+    , linkerOptionsPost = post_args+    , linkerTempDir     = tmpDir dflags+    , linkerFilter      = ld_filter+    }++{- Note [Solaris linker]+   ~~~~~~~~~~~~~~~~~~~~~+  SunOS/Solaris ld emits harmless warning messages about unresolved+  symbols in case of compiling into shared library when we do not+  link against all the required libs. That is the case of GHC which+  does not link against RTS library explicitly in order to be able to+  choose the library later based on binary application linking+  parameters. The warnings look like:++Undefined                       first referenced+  symbol                             in file+stg_ap_n_fast                       ./T2386_Lib.o+stg_upd_frame_info                  ./T2386_Lib.o+templatezmhaskell_LanguageziHaskellziTHziLib_litE_closure ./T2386_Lib.o+templatezmhaskell_LanguageziHaskellziTHziLib_appE_closure ./T2386_Lib.o+templatezmhaskell_LanguageziHaskellziTHziLib_conE_closure ./T2386_Lib.o+templatezmhaskell_LanguageziHaskellziTHziSyntax_mkNameGzud_closure ./T2386_Lib.o+newCAF                              ./T2386_Lib.o+stg_bh_upd_frame_info               ./T2386_Lib.o+stg_ap_ppp_fast                     ./T2386_Lib.o+templatezmhaskell_LanguageziHaskellziTHziLib_stringL_closure ./T2386_Lib.o+stg_ap_p_fast                       ./T2386_Lib.o+stg_ap_pp_fast                      ./T2386_Lib.o+ld: warning: symbol referencing errors++  this is actually coming from T2386 testcase. The emitting of those+  warnings is also a reason why so many TH testcases fail on Solaris.++  Following filter code is SunOS/Solaris linker specific and should+  filter out only linker warnings. Please note that the logic is a+  little bit more complex due to the simple reason that we need to preserve+  any other linker emitted messages. If there are any. Simply speaking+  if we see "Undefined" and later "ld: warning:..." then we omit all+  text between (including) the marks. Otherwise we copy the whole output.+-}+
compiler/GHC/Driver/Config/StgToCmm.hs view
@@ -41,6 +41,7 @@   , stgToCmmFastPAPCalls  = gopt Opt_FastPAPCalls          dflags   , stgToCmmSCCProfiling  = sccProfilingEnabled            dflags   , stgToCmmEagerBlackHole = gopt Opt_EagerBlackHoling     dflags+  , stgToCmmOrigThunkInfo = gopt Opt_OrigThunkInfo         dflags   , stgToCmmInfoTableMap  = gopt Opt_InfoTableMap          dflags   , stgToCmmInfoTableMapWithFallback = gopt Opt_InfoTableMapWithFallback dflags   , stgToCmmInfoTableMapWithStack = gopt Opt_InfoTableMapWithStack dflags@@ -52,7 +53,8 @@   , stgToCmmDoBoundsCheck = gopt Opt_DoBoundsChecking      dflags   , stgToCmmDoTagCheck    = gopt Opt_DoTagInferenceChecks  dflags   -- backend flags-  , stgToCmmAllowBigArith             = not ncg || platformArch platform == ArchWasm32+  , stgToCmmAllowBigArith             = not ncg || platformArch platform == ArchWasm32 || platformArch platform == ArchX86+  , stgToCmmAllowBigQuot              = not ncg || platformArch platform == ArchWasm32   , stgToCmmAllowQuotRemInstr         = ncg  && (x86ish || ppc)   , stgToCmmAllowQuotRem2             = (ncg && (x86ish || ppc)) || llvm   , stgToCmmAllowExtendedAddSubInstrs = (ncg && (x86ish || ppc)) || llvm
compiler/GHC/Driver/Config/StgToJS.hs view
@@ -1,11 +1,15 @@ module GHC.Driver.Config.StgToJS   ( initStgToJSConfig+  , initJSLinkConfig   ) where  import GHC.StgToJS.Types+import GHC.StgToJS.Linker.Types  import GHC.Driver.DynFlags+import GHC.Driver.Config.Linker+ import GHC.Platform.Ways import GHC.Utils.Outputable @@ -30,4 +34,19 @@   , csRuntimeAssert   = False   -- settings   , csContext         = initSDocContext dflags defaultDumpStyle+  , csLinkerConfig    = initLinkerConfig dflags   }++-- | Default linker configuration+initJSLinkConfig :: DynFlags -> JSLinkConfig+initJSLinkConfig dflags = JSLinkConfig+  { lcNoJSExecutables = False+  , lcNoHsMain        = False+  , lcNoRts           = False+  , lcNoStats         = False+  , lcCombineAll      = True+  , lcForeignRefs     = True+  , lcForceEmccRts    = False+  , lcLinkCsources    = not (gopt Opt_DisableJsCsources dflags)+  }+
compiler/GHC/Driver/Config/Tidy.hs view
@@ -40,6 +40,7 @@     , opt_expose_rules      = not (gopt Opt_OmitInterfacePragmas dflags)     , opt_trim_ids          = gopt Opt_OmitInterfacePragmas dflags     , opt_static_ptr_opts   = static_ptr_opts+    , opt_keep_auto_rules   = gopt Opt_KeepAutoRules dflags     }  initStaticPtrOpts :: HscEnv -> IO StaticPtrOpts
compiler/GHC/Driver/GenerateCgIPEStub.hs view
@@ -10,8 +10,7 @@ import GHC.Cmm.CLabel (CLabel, mkAsmTempLabel) import GHC.Cmm.Dataflow (O) import GHC.Cmm.Dataflow.Block (blockSplit, blockToList)-import GHC.Cmm.Dataflow.Collections-import GHC.Cmm.Dataflow.Label (Label)+import GHC.Cmm.Dataflow.Label import GHC.Cmm.Info.Build (emptySRT) import GHC.Cmm.Pipeline (cmmPipeline) import GHC.Data.Stream (Stream, liftIO)
compiler/GHC/Driver/Main.hs view
@@ -1,14 +1,14 @@-{-# LANGUAGE BangPatterns #-} {-# LANGUAGE LambdaCase #-}  {-# LANGUAGE NondecreasingIndentation #-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE TypeApplications #-} {-# LANGUAGE MultiWayIf #-}  {-# OPTIONS_GHC -fprof-auto-top #-} +-- Remove this after cmmToRawCmmHook removal+{-# OPTIONS_GHC -Wno-deprecations #-}+ ------------------------------------------------------------------------------- -- -- | Main API for compiling plain Haskell source code.@@ -110,7 +110,6 @@ import GHC.Prelude  import GHC.Platform-import GHC.Platform.Ways  import GHC.Driver.Plugins import GHC.Driver.Session@@ -176,7 +175,6 @@ import GHC.Core import GHC.Core.Lint.Interactive ( interactiveInScope ) import GHC.Core.Tidy           ( tidyExpr )-import GHC.Core.Type           ( Type, Kind ) import GHC.Core.Utils          ( exprType ) import GHC.Core.ConLike import GHC.Core.Opt.Pipeline@@ -186,7 +184,8 @@ import GHC.Core.FamInstEnv import GHC.Core.Rules import GHC.Core.Stats-import GHC.Core.LateCC (addLateCostCentresPgm)+import GHC.Core.LateCC+import GHC.Core.LateCC.Types   import GHC.CoreToStg.Prep@@ -198,6 +197,7 @@  import GHC.Tc.Module import GHC.Tc.Utils.Monad+import GHC.Tc.Utils.TcType import GHC.Tc.Zonk.Env ( ZonkFlexi (DefaultFlexi) )  import GHC.Stg.Syntax@@ -253,12 +253,12 @@  import GHC.Utils.Fingerprint ( Fingerprint ) import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Error import GHC.Utils.Outputable import GHC.Utils.Misc import GHC.Utils.Logger import GHC.Utils.TmpFs+import GHC.Utils.Touch  import qualified GHC.LanguageExtensions as LangExt @@ -269,7 +269,6 @@ import GHC.Data.Stream (Stream) import GHC.Data.Maybe -import qualified GHC.SysTools import GHC.SysTools (initSysTools) import GHC.SysTools.BaseDir (findTopDir) @@ -346,41 +345,11 @@   mySettings <- initSysTools top_dir   dflags <- initDynFlags (defaultDynFlags mySettings)   hsc_env <- newHscEnv top_dir dflags-  checkBrokenTablesNextToCode (hsc_logger hsc_env) dflags   setUnsafeGlobalDynFlags dflags    -- c.f. DynFlags.parseDynamicFlagsFull, which    -- creates DynFlags and sets the UnsafeGlobalDynFlags   return hsc_env --- | The binutils linker on ARM emits unnecessary R_ARM_COPY relocations which--- breaks tables-next-to-code in dynamically linked modules. This--- check should be more selective but there is currently no released--- version where this bug is fixed.--- See https://sourceware.org/bugzilla/show_bug.cgi?id=16177 and--- https://gitlab.haskell.org/ghc/ghc/issues/4210#note_78333-checkBrokenTablesNextToCode :: Logger -> DynFlags -> IO ()-checkBrokenTablesNextToCode logger dflags = do-  let invalidLdErr = "Tables-next-to-code not supported on ARM \-                     \when using binutils ld (please see: \-                     \https://sourceware.org/bugzilla/show_bug.cgi?id=16177)"-  broken <- checkBrokenTablesNextToCode' logger dflags-  when broken (panic invalidLdErr)--checkBrokenTablesNextToCode' :: Logger -> DynFlags -> IO Bool-checkBrokenTablesNextToCode' logger dflags-  | not (isARM arch)               = return False-  | ways dflags `hasNotWay` WayDyn = return False-  | not tablesNextToCode           = return False-  | otherwise                      = do-    linkerInfo <- liftIO $ GHC.SysTools.getLinkerInfo logger dflags-    case linkerInfo of-      GnuLD _  -> return True-      _        -> return False-  where platform = targetPlatform dflags-        arch = platformArch platform-        tablesNextToCode = platformTablesNextToCode platform-- -- -----------------------------------------------------------------------------  getDiagnostics :: Hsc (Messages GhcMessage)@@ -1294,7 +1263,7 @@           -- .hie files.           let hie_file = ml_hie_file mod_location           whenM (doesFileExist hie_file) $-            GHC.SysTools.touch logger dflags "Touching hie file" hie_file+            GHC.Utils.Touch.touch hie_file     else         -- See Note [Strictness in ModIface]         forceModIface iface@@ -1813,44 +1782,93 @@                -> IO (FilePath, Maybe FilePath, [(ForeignSrcLang, FilePath)], Maybe StgCgInfos, Maybe CmmCgInfos )                 -- ^ @Just f@ <=> _stub.c is f hscGenHardCode hsc_env cgguts location output_filename = do-        let CgGuts{ -- This is the last use of the ModGuts in a compilation.-                    -- From now on, we just use the bits we need.-                    cg_module   = this_mod,+        let CgGuts{ cg_module   = this_mod,                     cg_binds    = core_binds,-                    cg_ccs      = local_ccs,-                    cg_tycons   = tycons,-                    cg_foreign  = foreign_stubs0,-                    cg_foreign_files = foreign_files,-                    cg_dep_pkgs = dependencies,-                    cg_hpc_info = hpc_info,-                    cg_spt_entries = spt_entries+                    cg_ccs      = local_ccs                     } = cgguts             dflags = hsc_dflags hsc_env             logger = hsc_logger hsc_env-            hooks  = hsc_hooks hsc_env-            tmpfs  = hsc_tmpfs hsc_env-            llvm_config = hsc_llvm_config hsc_env-            profile = targetProfile dflags-            data_tycons = filter isDataTyCon tycons-            -- cg_tycons includes newtypes, for the benefit of External Core,-            -- but we don't generate any code for newtypes -        --------------------        -- Insert late cost centres if enabled.-        -- If `-fprof-late-inline` is enabled we can skip this, as it will have added-        -- a superset of cost centres we would add here already. -        (late_cc_binds, late_local_ccs) <--              if gopt Opt_ProfLateCcs dflags && not (gopt Opt_ProfLateInlineCcs dflags)-                  then  {-# SCC lateCC #-} do-                    (binds,late_ccs) <- addLateCostCentresPgm dflags logger this_mod core_binds-                    return ( binds, (S.toList late_ccs `mappend` local_ccs ))+        -------------------+        -- Insert late cost centres based on the provided flags.+        --+        -- If -fprof-late-inline is enabled, we will skip adding CCs on any+        -- top-level bindings here (via shortcut in `addLateCostCenters`),+        -- since it will have already added a superset of the CCs we would add+        -- here.+        let+          late_cc_config :: LateCCConfig+          late_cc_config =+            LateCCConfig+              { lateCCConfig_whichBinds =+                  if gopt Opt_ProfLateInlineCcs dflags then+                    LateCCNone+                  else if gopt Opt_ProfLateCcs dflags then+                    LateCCAllBinds+                  else if gopt Opt_ProfLateOverloadedCcs dflags then+                    LateCCOverloadedBinds                   else-                    return (core_binds, local_ccs)+                    LateCCNone+              , lateCCConfig_overloadedCalls =+                  gopt Opt_ProfLateoverloadedCallsCCs dflags+              , lateCCConfig_env =+                  LateCCEnv+                    { lateCCEnv_module = this_mod+                    , lateCCEnv_file = fsLit <$> ml_hs_file location+                    , lateCCEnv_countEntries= gopt Opt_ProfCountEntries dflags+                    , lateCCEnv_collectCCs = True+                    }+              } +        (late_cc_binds, late_cc_state) <-+          addLateCostCenters logger late_cc_config core_binds +        when (dopt Opt_D_dump_late_cc dflags || dopt Opt_D_verbose_core2core dflags) $+          putDumpFileMaybe logger Opt_D_dump_late_cc "LateCC" FormatCore (vcat (map ppr late_cc_binds))          -------------------+        -- Run late plugins+        -- This is the last use of the ModGuts in a compilation.+        -- From now on, we just use the bits we need.+        ( CgGuts+            { cg_tycons        = tycons,+              cg_foreign       = foreign_stubs0,+              cg_foreign_files = foreign_files,+              cg_dep_pkgs      = dependencies,+              cg_hpc_info      = hpc_info,+              cg_spt_entries   = spt_entries,+              cg_binds         = late_binds,+              cg_ccs           = late_local_ccs+            }+          , _+          ) <-+          {-# SCC latePlugins #-}+          withTiming+            logger+            (text "LatePlugins"<+>brackets (ppr this_mod))+            (const ()) $+            withPlugins (hsc_plugins hsc_env)+              (($ hsc_env) . latePlugin)+                ( cgguts+                    { cg_binds = late_cc_binds+                    , cg_ccs = S.toList (lateCCState_ccs late_cc_state) ++ local_ccs+                    }+                , lateCCState_ccState late_cc_state+                )++        let+          hooks  = hsc_hooks hsc_env+          tmpfs  = hsc_tmpfs hsc_env+          llvm_config = hsc_llvm_config hsc_env+          profile = targetProfile dflags+          data_tycons = filter isDataTyCon tycons+          -- cg_tycons includes newtypes, for the benefit of External Core,+          -- but we don't generate any code for newtypes++++        -------------------         -- PREPARE FOR CODE GENERATION         -- Do saturation and convert to A-normal form         (prepd_binds) <- {-# SCC "CorePrep" #-} do@@ -1859,7 +1877,7 @@             (hsc_logger hsc_env)             cp_cfg             (initCorePrepPgmConfig (hsc_dflags hsc_env) (interactiveInScope $ hsc_IC hsc_env))-            this_mod location late_cc_binds data_tycons+            this_mod location late_binds data_tycons          -----------------  Convert to STG ------------------         (stg_binds_with_deps, denv, (caf_ccs, caf_cc_stacks), stg_cg_infos)@@ -2647,7 +2665,7 @@    case interp of     -- always generate JS code for the JS interpreter (no bytecode!)-    Interp (ExternalInterp (ExtJS i)) _ _ ->+    Interp (ExternalInterp (ExtJS i)) _ ->       jsCodeGen hsc_env srcspan i this_mod stg_binds_with_deps binding_id      _ -> do
compiler/GHC/Driver/Make.hs view
@@ -1,18 +1,7 @@-{-# LANGUAGE BangPatterns #-}-{-# LANGUAGE DeriveTraversable #-}-{-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE NondecreasingIndentation #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE StandaloneDeriving #-} -{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-}-{-# LANGUAGE MultiParamTypeClasses #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE RankNTypes #-} {-# LANGUAGE DerivingStrategies #-}-{-# LANGUAGE GeneralisedNewtypeDeriving #-}-{-# LANGUAGE TupleSections #-} {-# LANGUAGE ApplicativeDo #-} {-# LANGUAGE MultiWayIf #-} {-# LANGUAGE RecordWildCards #-}@@ -93,7 +82,6 @@ import GHC.Utils.Exception ( throwIO, SomeAsyncException ) import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Misc import GHC.Utils.Error import GHC.Utils.Logger@@ -311,16 +299,16 @@  -- Note [Missing home modules] -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- Sometimes we don't want GHC to process modules that weren't specified as--- explicit targets. For example, cabal may want to enable this warning--- when building a library, so that GHC warns the user about modules listed--- neither in `exposed-modules` nor in `other-modules`.+-- Sometimes user doesn't want GHC to pick up modules, not explicitly listed+-- in a command line. For example, cabal may want to enable this warning+-- when building a library, so that GHC warns user about modules, not listed+-- neither in `exposed-modules`, nor in `other-modules`. ----- Here "home module" means a module that doesn't come from another package.+-- Here "home module" means a module, that doesn't come from an other package. -- -- For example, if GHC is invoked with modules "A" and "B" as targets, -- but "A" imports some other module "C", then GHC will issue a warning--- about module "C" not being listed in the command line.+-- about module "C" not being listed in a command line. -- -- The warning in enabled by `-Wmissing-home-modules`. See #13129 warnMissingHomeModules ::  DynFlags -> [Target] -> ModuleGraph -> DriverMessages@@ -331,6 +319,8 @@   where     diag_opts = initDiagOpts dflags +    is_known_module mod = any (is_my_target mod) targets+     -- We need to be careful to handle the case where (possibly     -- path-qualified) filenames (aka 'TargetFile') rather than module     -- names are being passed on the GHC command-line.@@ -339,31 +329,27 @@     -- `ghc --make -isrc-exe Main` are supposed to be equivalent.     -- Note also that we can't always infer the associated module name     -- directly from the filename argument.  See #13727.-    is_known_module mod =-      is_module_target mod-      ||-      maybe False is_file_target (ml_hs_file (ms_location mod))--    is_module_target mod = (moduleName (ms_mod mod), ms_unitid mod) `Set.member` mod_targets--    is_file_target file = Set.member (withoutExt file) file_targets--    file_targets = Set.fromList (mapMaybe file_target targets)--    file_target Target {targetId} =-      case targetId of-        TargetModule _ -> Nothing-        TargetFile file _ ->-          Just (withoutExt (augmentByWorkingDirectory dflags file))--    mod_targets = Set.fromList (mod_target <$> targets)+    is_my_target mod target =+      let tuid = targetUnitId target+      in case targetId target of+          TargetModule name+            -> moduleName (ms_mod mod) == name+                && tuid == ms_unitid mod+          TargetFile target_file _+            | Just mod_file <- ml_hs_file (ms_location mod)+            ->+             augmentByWorkingDirectory dflags target_file == mod_file || -    mod_target Target {targetUnitId, targetId} =-      case targetId of-        TargetModule name -> (name, targetUnitId)-        TargetFile file _ -> (mkModuleName (withoutExt file), targetUnitId)+             --  Don't warn on B.hs-boot if B.hs is specified (#16551)+             addBootSuffix target_file == mod_file || -    withoutExt = fst . splitExtension+             --  We can get a file target even if a module name was+             --  originally specified in a command line because it can+             --  be converted in guessTarget (by appending .hs/.lhs).+             --  So let's convert it back and compare with module name+             mkModuleName (fst $ splitExtension target_file)+              == moduleName (ms_mod mod)+          _ -> False      missing = map (moduleName . ms_mod) $       filter (not . is_known_module) $@@ -744,7 +730,7 @@     checkHowMuch how_much $ do      -- mg2_with_srcimps drops the hi-boot nodes, returning a-    -- graph with cycles. It is just used for warning about unecessary source imports.+    -- graph with cycles. It is just used for warning about unnecessary source imports.     let mg2_with_srcimps :: [SCC ModuleGraphNode]         mg2_with_srcimps = topSortModuleGraph True mod_graph Nothing @@ -1576,9 +1562,8 @@                 -- which case there can be repeats downsweep hsc_env old_summaries excl_mods allow_dup_roots    = do-       rootSummaries <- mapM getRootSummary roots-       let (root_errs, rootSummariesOk) = partitionEithers rootSummaries -- #17549-           root_map = mkRootMap rootSummariesOk+       (root_errs, rootSummariesOk) <- partitionWithM getRootSummary roots -- #17549+       let root_map = mkRootMap rootSummariesOk        checkDuplicates root_map        (deps, map0) <- loopSummaries rootSummariesOk (M.empty, root_map)        let closure_errs = checkHomeUnitsClosed (hsc_unit_env hsc_env)@@ -2426,7 +2411,7 @@     show_path :: [ModuleGraphNode] -> SDoc     show_path []  = panic "show_path"     show_path [m] = ppr_node m <+> text "imports itself"-    show_path (m1:m2:ms) = vcat ( nest 6 (ppr_node m1)+    show_path (m1:m2:ms) = vcat ( nest 14 (ppr_node m1)                                 : nest 6 (text "imports" <+> ppr_node m2)                                 : go ms )        where
compiler/GHC/Driver/MakeSem.hs view
@@ -343,7 +343,7 @@ tryAcquire _ _ _ = retry  -- | When there are free tokens and no pending jobs,--- spawn a thread to release a token from the semamphore.+-- spawn a thread to release a token from the semaphore. -- -- See 'releaseThread'. tryRelease :: Jobserver
compiler/GHC/Driver/Pipeline.hs view
@@ -1,14 +1,7 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE BangPatterns #-}--{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE NondecreasingIndentation #-}-{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE LambdaCase #-}-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE NondecreasingIndentation #-} {-# LANGUAGE ViewPatterns #-}-{-# LANGUAGE TypeApplications #-}  ----------------------------------------------------------------------------- --@@ -83,7 +76,6 @@ import GHC.Linker.Types  import GHC.StgToJS.Linker.Linker-import GHC.StgToJS.Linker.Types (defaultJSLinkConfig)  import GHC.Utils.Outputable import GHC.Utils.Error@@ -124,7 +116,6 @@ import Control.Monad import qualified Control.Monad.Catch as MC (handle) import Data.Maybe-import Data.Either      ( partitionEithers ) import qualified Data.Set as Set  import Data.Time        ( getCurrentTime )@@ -448,7 +439,7 @@         -- Don't showPass in Batch mode; doLink will do that for us.         case ghcLink dflags of           LinkBinary-            | backendUseJSLinker (backend dflags) -> linkJSBinary logger fc dflags unit_env obj_files pkg_deps+            | backendUseJSLinker (backend dflags) -> linkJSBinary logger tmpfs fc dflags unit_env obj_files pkg_deps             | otherwise -> linkBinary logger tmpfs dflags unit_env obj_files pkg_deps           LinkStaticLib -> linkStaticLib logger dflags unit_env obj_files pkg_deps           LinkDynLib    -> linkDynLibCheck logger tmpfs dflags unit_env obj_files pkg_deps@@ -465,14 +456,13 @@         return Succeeded  -linkJSBinary :: Logger -> FinderCache -> DynFlags -> UnitEnv -> [FilePath] -> [UnitId] -> IO ()-linkJSBinary logger fc dflags unit_env obj_files pkg_deps = do+linkJSBinary :: Logger -> TmpFs -> FinderCache -> DynFlags -> UnitEnv -> [FilePath] -> [UnitId] -> IO ()+linkJSBinary logger tmpfs fc dflags unit_env obj_files pkg_deps = do   -- we use the default configuration for now. In the future we may expose   -- settings to the user via DynFlags.-  let lc_cfg   = defaultJSLinkConfig+  let lc_cfg   = initJSLinkConfig dflags   let cfg      = initStgToJSConfig dflags-  let extra_js = mempty-  jsLinkBinary fc lc_cfg cfg extra_js logger dflags unit_env obj_files pkg_deps+  jsLinkBinary fc lc_cfg cfg logger tmpfs dflags unit_env obj_files pkg_deps  linkingNeeded :: Logger -> DynFlags -> UnitEnv -> Bool -> [Linkable] -> [UnitId] -> IO RecompileRequired linkingNeeded logger dflags unit_env staticLink linkables pkg_deps = do@@ -489,8 +479,7 @@     Right t -> do         -- first check object files and extra_ld_inputs         let extra_ld_inputs = [ f | FileOption _ f <- ldInputs dflags ]-        e_extra_times <- mapM (tryIO . getModificationUTCTime) extra_ld_inputs-        let (errs,extra_times) = partitionEithers e_extra_times+        (errs,extra_times) <- partitionWithM (tryIO . getModificationUTCTime) extra_ld_inputs         let obj_times =  map linkableTime linkables ++ extra_times         if not (null errs) || any (t <) obj_times             then return $ needsRecompileBecause ObjectsChanged@@ -514,9 +503,7 @@          pkg_libfiles <- mapM (uncurry (findHSLib platform (ways dflags))) pkg_hslibs         if any isNothing pkg_libfiles then return $ needsRecompileBecause LibraryChanged else do-        e_lib_times <- mapM (tryIO . getModificationUTCTime)-                          (catMaybes pkg_libfiles)-        let (lib_errs,lib_times) = partitionEithers e_lib_times+        (lib_errs,lib_times) <- partitionWithM (tryIO . getModificationUTCTime) (catMaybes pkg_libfiles)         if not (null lib_errs) || any (t <) lib_times            then return $ needsRecompileBecause LibraryChanged            else do@@ -593,7 +580,7 @@     NoLink        -> return ()     LinkBinary       | backendUseJSLinker (backend dflags)-                  -> linkJSBinary logger fc dflags unit_env o_files []+                  -> linkJSBinary logger tmpfs fc dflags unit_env o_files []       | otherwise -> linkBinary logger tmpfs dflags unit_env o_files []     LinkStaticLib -> linkStaticLib      logger       dflags unit_env o_files []     LinkDynLib    -> linkDynLibCheck    logger tmpfs dflags unit_env o_files []@@ -628,9 +615,6 @@               LangObjcxx -> viaCPipeline Cobjcxx               LangAsm    -> \pe hsc_env ml fp -> asPipeline True pe hsc_env ml fp               LangJs     -> \pe hsc_env ml fp -> Just <$> foreignJsPipeline pe hsc_env ml fp-#if __GLASGOW_HASKELL__ < 811-              RawObject  -> panic "compileForeign: should be unreachable"-#endif             pipe_env = mkPipeEnv NoStop stub_c Nothing (Temporary TFL_GhcSession)         res <- runPipeline (hsc_hooks hsc_env) (pipeline pipe_env hsc_env Nothing stub_c)         case res of@@ -795,7 +779,15 @@   if backendGeneratesCode (backend (hsc_dflags hsc_env)) then     do       res <- hscGenBackendPipeline pipe_env hsc_env mod_sum result-      when (gopt Opt_BuildDynamicToo (hsc_dflags hsc_env)) $ do+      -- Only run dynamic-too if the backend generates object files+      -- See Note [Writing interface files]+      -- If we are writing a simple interface (not . backendWritesFiles), then+      -- hscMaybeWriteIface in the regular pipeline will write both the hi and+      -- dyn_hi files. This way we can avoid running the pipeline twice and+      -- generating a duplicate linkable.+      -- We must not run the backend a second time with `dynamicNow` enable because+      -- all the work has already been done in the first pipeline.+      when (gopt Opt_BuildDynamicToo (hsc_dflags hsc_env) && backendWritesFiles (backend (hsc_dflags hsc_env)) ) $ do           let dflags' = setDynamicNow (hsc_dflags hsc_env) -- set "dynamicNow"           () <$ hscGenBackendPipeline pipe_env (hscSetFlags dflags' hsc_env) mod_sum result       return res@@ -836,6 +828,12 @@     StopAs -> return Nothing     _ -> Just <$> use (T_As use_cpp pipe_env hsc_env location input_fn) +lasPipeline :: P m => Bool -> PipeEnv -> HscEnv -> Maybe ModLocation -> FilePath -> m (Maybe ObjFile)+lasPipeline use_cpp pipe_env hsc_env location input_fn =+  case stop_phase pipe_env of+    StopAs -> return Nothing+    _ -> Just <$> use (T_LlvmAs use_cpp pipe_env hsc_env location input_fn)+ viaCPipeline :: P m => Phase -> PipeEnv -> HscEnv -> Maybe ModLocation -> FilePath -> m (Maybe FilePath) viaCPipeline c_phase pipe_env hsc_env location input_fn = do   out_fn <- use (T_Cc c_phase pipe_env hsc_env location input_fn)@@ -859,7 +857,7 @@     if gopt Opt_NoLlvmMangler (hsc_dflags hsc_env)       then return llc_fn       else use (T_LlvmMangle pipe_env hsc_env llc_fn)-  asPipeline False pipe_env hsc_env location mangled_fn+  lasPipeline False pipe_env hsc_env location mangled_fn  cmmCppPipeline :: P m => PipeEnv -> HscEnv -> FilePath -> m (Maybe FilePath) cmmCppPipeline pipe_env hsc_env input_fn = do
compiler/GHC/Driver/Pipeline/Execute.hs view
@@ -46,7 +46,6 @@ import GHC.CmmToLlvm.Mangler import GHC.SysTools import GHC.SysTools.Cpp-import GHC.Utils.Panic.Plain import System.Directory import System.FilePath import GHC.Utils.Misc@@ -72,6 +71,7 @@ import GHC.Linker.ExtraObj import GHC.Linker.Dynamic import GHC.Utils.Panic+import GHC.Utils.Touch import GHC.Unit.Module.Env import GHC.Driver.Env.KnotVars import GHC.Driver.Config.Finder@@ -121,7 +121,7 @@         (hsc_dflags hsc_env)         (hsc_unit_env hsc_env)         (CppOpts-          { cppUseCc       = True+          { useHsCpp       = False           , cppLinePragmas = True           })         input_fn output_fn@@ -146,6 +146,8 @@   runLlvmOptPhase pipe_env hsc_env input_fn runPhase (T_LlvmLlc pipe_env hsc_env input_fn) =   runLlvmLlcPhase pipe_env hsc_env input_fn+runPhase (T_LlvmAs cpp pipe_env hsc_env location input_fn) = do+  runLlvmAsPhase cpp pipe_env hsc_env location input_fn runPhase (T_LlvmMangle pipe_env hsc_env input_fn) =   runLlvmManglePhase pipe_env hsc_env input_fn runPhase (T_MergeForeign pipe_env hsc_env input_fn fos) =@@ -283,17 +285,12 @@     return output_fn  -runAsPhase :: Bool -> PipeEnv -> HscEnv -> Maybe ModLocation -> FilePath -> IO FilePath-runAsPhase with_cpp pipe_env hsc_env location input_fn = do+-- Run either 'clang' or 'gcc' phases+runGenericAsPhase :: (Logger -> DynFlags -> [Option] -> IO ()) -> [Option] -> Bool -> PipeEnv -> HscEnv -> Maybe ModLocation -> FilePath -> IO FilePath+runGenericAsPhase run_as extra_opts with_cpp pipe_env hsc_env location input_fn = do         let dflags     = hsc_dflags   hsc_env         let logger     = hsc_logger   hsc_env-        let unit_env   = hsc_unit_env hsc_env-        let platform   = ue_platform unit_env -        -- LLVM from version 3.0 onwards doesn't support the OS X system-        -- assembler, so we use clang as the assembler instead. (#5636)-        let as_prog = applyAssemblerProg $ backendAssemblerProg (backend dflags)-         let cmdline_include_paths = includePaths dflags         let pic_c_flags = picCCOpts dflags @@ -310,9 +307,8 @@                                 includePathsQuoteImplicit cmdline_include_paths]         let runAssembler inputFilename outputFilename               = withAtomicRename outputFilename $ \temp_outputFilename ->-                    as_prog+                    run_as                        logger dflags-                       platform                        (local_includes ++ global_includes                        -- See Note [-fPIC for assembler]                        ++ map GHC.SysTools.Option pic_c_flags@@ -334,14 +330,25 @@                           , GHC.SysTools.FileOption "" inputFilename                           , GHC.SysTools.Option "-o"                           , GHC.SysTools.FileOption "" temp_outputFilename-                          ])+                          ] ++ extra_opts)          debugTraceMsg logger 4 (text "Running the assembler")         runAssembler input_fn output_fn          return output_fn +-- Invoke `clang` to assemble a .S file produced by LLvm toolchain+runLlvmAsPhase :: Bool -> PipeEnv -> HscEnv -> Maybe ModLocation -> FilePath -> IO FilePath+runLlvmAsPhase =+  runGenericAsPhase runLlvmAs [ GHC.SysTools.Option "-Wno-unused-command-line-argument" ] +-- Invoke 'gcc' to assemble a .S file+runAsPhase :: Bool -> PipeEnv -> HscEnv -> Maybe ModLocation -> FilePath -> IO FilePath+runAsPhase =+  runGenericAsPhase runAs []+++ -- Note [JS Backend .o file procedure] -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --@@ -370,14 +377,10 @@  -- | Run the JS Backend postHsc phase. runJsPhase :: PipeEnv -> HscEnv -> Maybe ModLocation -> FilePath -> IO FilePath-runJsPhase _pipe_env hsc_env _location input_fn = do-  let dflags     = hsc_dflags   hsc_env-  let logger     = hsc_logger   hsc_env-+runJsPhase _pipe_env _hsc_env _location input_fn = do   -- The object file is already generated. We only touch it to ensure the   -- timestamp is refreshed, see Note [JS Backend .o file procedure].-  touchObjectFile logger dflags input_fn-+  touchObjectFile input_fn   return input_fn  -- | Deal with foreign JS files (embed them into .o files)@@ -392,22 +395,6 @@   embedJsFile logger dflags tmpfs unit_env input_fn output_fn   return output_fn --applyAssemblerProg-    :: DefunctionalizedAssemblerProg-    -> Logger -> DynFlags -> Platform -> [Option] -> IO ()-applyAssemblerProg StandardAssemblerProg logger dflags _platform =-    runAs logger dflags-applyAssemblerProg JSAssemblerProg logger dflags _platform =-    runEmscripten logger dflags-applyAssemblerProg DarwinClangAssemblerProg logger dflags platform =-    if platformOS platform == OSDarwin then-        runClang logger dflags-    else-        runAs logger dflags--- runCcPhase :: Phase -> PipeEnv -> HscEnv -> Maybe ModLocation -> FilePath -> IO FilePath runCcPhase cc_phase pipe_env hsc_env location input_fn = do   let dflags    = hsc_dflags hsc_env@@ -435,19 +422,6 @@          includePathsQuoteImplicit cmdline_include_paths)   let include_paths = include_paths_quote ++ include_paths_global -  -- pass -D or -optP to preprocessor when compiling foreign C files-  -- (#16737). Doing it in this way is simpler and also enable the C-  -- compiler to perform preprocessing and parsing in a single pass,-  -- but it may introduce inconsistency if a different pgm_P is specified.-  let opts = getOpts dflags opt_P-      aug_imports = augmentImports dflags opts--      more_preprocessor_opts = concat-        [ ["-Xpreprocessor", i]-        | not hcc-        , i <- aug_imports-        ]-   let gcc_extra_viac_flags = extraGccViaCFlags dflags   let pic_c_flags = picCCOpts dflags @@ -536,7 +510,6 @@                  ++ [ "-include", ghcVersionH ]                  ++ framework_paths                  ++ include_paths-                 ++ more_preprocessor_opts                  ++ pkg_extra_cc_opts                  )) @@ -575,7 +548,7 @@                     -- In the case of hs-boot files, generate a dummy .o-boot                    -- stamp file for the benefit of Make-                   HsBootFile -> touchObjectFile logger dflags o_file+                   HsBootFile -> touchObjectFile o_file                    HsSrcFile -> panic "HscUpdate not relevant for HscSrcFile"                   -- MP: I wonder if there are any lurking bugs here because we@@ -640,7 +613,7 @@        -- GHC.HsToCore.Ticks.isGoodTickSrcSpan where we check that the filename in        -- a SrcLoc is the same as the source filename, the two will        -- look bogusly different. See test:-       -- libraries/hpc/tests/function/subdir/tough2.hs+       -- testsuite/tests/hpc/function/subdir/tough2.hs        escape ('\\':cs) = '\\':'\\': escape cs        escape ('\"':cs) = '\\':'\"': escape cs        escape ('\'':cs) = '\\':'\'': escape cs@@ -679,7 +652,7 @@            (hsc_dflags hsc_env)            (hsc_unit_env hsc_env)            (CppOpts-              { cppUseCc       = False+              { useHsCpp       = True               , cppLinePragmas = True               })            input_fn output_fn@@ -968,11 +941,8 @@             -> DynFlags             -> [(String, String)]  -- ^ pairs of (opt, llc) arguments llvmOptions llvm_config dflags =-       [("-enable-tbaa -tbaa",  "-enable-tbaa") | gopt Opt_LlvmTBAA dflags ]-    ++ [("-relocation-model=" ++ rmodel+       [("-relocation-model=" ++ rmodel         ,"-relocation-model=" ++ rmodel) | not (null rmodel)]-    ++ [("-stack-alignment=" ++ (show align)-        ,"-stack-alignment=" ++ (show align)) | align > 0 ]      -- Additional llc flags     ++ [("", "-mcpu=" ++ mcpu)   | not (null mcpu)@@ -992,18 +962,9 @@         platform = targetPlatform dflags         arch = platformArch platform -        align :: Int-        align = case platformArch platform of-                  ArchX86_64 | isAvxEnabled dflags -> 32-                  _                                -> 0-         attrs :: String         attrs = intercalate "," $ mattr-              ++ ["+sse4.2"  | isSse4_2Enabled dflags   ]-              ++ ["+popcnt"  | isSse4_2Enabled dflags   ]-                   -- LLVM gates POPCNT instructions behind the popcnt flag,-                   -- while the GHC NCG (as well as GCC, Clang) gates it-                   -- behind SSE4.2 instead.+              ++ ["+sse42"   | isSse4_2Enabled dflags   ]               ++ ["+sse2"    | isSse2Enabled platform   ]               ++ ["+sse"     | isSseEnabled platform    ]               ++ ["+avx512f" | isAvx512fEnabled dflags  ]@@ -1181,10 +1142,10 @@   -touchObjectFile :: Logger -> DynFlags -> FilePath -> IO ()-touchObjectFile logger dflags path = do+touchObjectFile :: FilePath -> IO ()+touchObjectFile path = do   createDirectoryIfMissing True $ takeDirectory path-  GHC.SysTools.touch logger dflags "Touching object file" path+  GHC.Utils.Touch.touch path  -- Note [-fPIC for assembler] -- ~~~~~~~~~~~~~~~~~~~~~~~~~~
compiler/GHC/Hs/Syn/Type.hs view
@@ -42,13 +42,13 @@ hsLPatType (L _ p) = hsPatType p  hsPatType :: Pat GhcTc -> Type-hsPatType (ParPat _ _ pat _)            = hsLPatType pat+hsPatType (ParPat _ pat)                = hsLPatType pat hsPatType (WildPat ty)                  = ty hsPatType (VarPat _ lvar)               = idType (unLoc lvar) hsPatType (BangPat _ pat)               = hsLPatType pat hsPatType (LazyPat _ pat)               = hsLPatType pat hsPatType (LitPat _ lit)                = hsLitType lit-hsPatType (AsPat _ var _ _)             = idType (unLoc var)+hsPatType (AsPat _ var _)               = idType (unLoc var) hsPatType (ViewPat ty _ _)              = ty hsPatType (ListPat ty _)                = mkListTy ty hsPatType (TuplePat tys _ bx)           = mkTupleTy1 bx tys@@ -63,6 +63,8 @@ hsPatType (SigPat ty _ _)               = ty hsPatType (NPat ty _ _ _)               = ty hsPatType (NPlusKPat ty _ _ _ _ _)      = ty+hsPatType (EmbTyPat ty _)               = typeKind ty+hsPatType (InvisPat ty _)               = typeKind ty hsPatType (XPat ext) =   case ext of     CoPat _ _ ty       -> ty@@ -104,13 +106,12 @@ hsExprType (HsIPVar v _) = dataConCantHappen v hsExprType (HsOverLit _ lit) = overLitType lit hsExprType (HsLit _ lit) = hsLitType lit-hsExprType (HsLam     _ (MG { mg_ext = match_group })) = matchGroupTcType match_group-hsExprType (HsLamCase _ _ (MG { mg_ext = match_group })) = matchGroupTcType match_group+hsExprType (HsLam _ _ (MG { mg_ext = match_group })) = matchGroupTcType match_group hsExprType (HsApp _ f _) = funResultTy $ lhsExprType f-hsExprType (HsAppType x f _ _) = piResultTy (lhsExprType f) x+hsExprType (HsAppType x f _) = piResultTy (lhsExprType f) x hsExprType (OpApp v _ _ _) = dataConCantHappen v hsExprType (NegApp _ _ se) = syntaxExprType se-hsExprType (HsPar _ _ e _) = lhsExprType e+hsExprType (HsPar _ e) = lhsExprType e hsExprType (SectionL v _ _) = dataConCantHappen v hsExprType (SectionR v _ _) = dataConCantHappen v hsExprType (ExplicitTuple _ args box) = mkTupleTy box $ map hsTupArgType args@@ -118,7 +119,7 @@ hsExprType (HsCase _ _ (MG { mg_ext = match_group })) = mg_res_ty match_group hsExprType (HsIf _ _ t _) = lhsExprType t hsExprType (HsMultiIf ty _) = ty-hsExprType (HsLet _ _ _ _ body) = lhsExprType body+hsExprType (HsLet _ _ body) = lhsExprType body hsExprType (HsDo ty _ _) = ty hsExprType (ExplicitList ty _) = mkListTy ty hsExprType (RecordCon con_expr _ _) = hsExprType con_expr@@ -142,8 +143,9 @@ hsExprType (HsProc _ _ lcmd_top) = lhsCmdTopType lcmd_top hsExprType (HsStatic (_, ty) _s) = ty hsExprType (HsPragE _ _ e) = lhsExprType e+hsExprType (HsEmbTy x _) = dataConCantHappen x hsExprType (XExpr (WrapExpr (HsWrap wrap e))) = hsWrapperType wrap $ hsExprType e-hsExprType (XExpr (ExpansionExpr (HsExpanded _ tc_e))) = hsExprType tc_e+hsExprType (XExpr (ExpandedThingTc _ e))  = hsExprType e hsExprType (XExpr (ConLikeTc con _ _)) = conLikeType con hsExprType (XExpr (HsTick _ e)) = lhsExprType e hsExprType (XExpr (HsBinTick _ _ e)) = lhsExprType e
compiler/GHC/HsToCore.hs view
@@ -41,6 +41,7 @@ import GHC.HsToCore.Docs  import GHC.Tc.Types+import GHC.Tc.Types.Origin ( Position(..) ) import GHC.Tc.Utils.Monad  ( finalSafeMode, fixSafeInstances, initIfaceLoad ) import GHC.Tc.Module ( runTcInteractive ) @@ -77,6 +78,7 @@  import GHC.Types.Id import GHC.Types.Id.Info+import GHC.Types.Id.Make ( mkRepPolyIdConcreteTyVars ) import GHC.Types.ForeignStubs import GHC.Types.Avail import GHC.Types.Basic@@ -795,5 +797,9 @@               arity = 1 -             id   = mkExportedVanillaId unsafeCoercePrimName ty `setIdInfo` info+             concs = mkRepPolyIdConcreteTyVars+                     [((mkTyVarTy openAlphaTyVar, Argument 1 Top), runtimeRep1TyVar)]+                     unsafeCoercePrimName++             id   = mkExportedLocalId (RepPolyId concs) unsafeCoercePrimName ty `setIdInfo` info        ; return (id, old_expr) }
compiler/GHC/HsToCore/Arrows.hs view
@@ -295,7 +295,7 @@     let env_stk_expr = mkCorePairExpr (mkBigCoreVarTup env_ids) mkCoreUnitExpr     fail_expr <- mkFailExpr (ArrowMatchCtxt ProcExpr) env_stk_ty     var <- selectSimpleMatchVarL ManyTy pat-    match_code <- matchSimply (Var var) (ArrowMatchCtxt ProcExpr) pat env_stk_expr fail_expr+    match_code <- matchSimply (Var var) (ArrowMatchCtxt ProcExpr) ManyTy pat env_stk_expr fail_expr     let pat_ty = hsLPatType pat     let proc_code = do_premap meth_ids pat_ty env_stk_ty cmd_ty                     (Lam var match_code)@@ -415,14 +415,7 @@             free_vars `unionDVarSet`               (exprFreeIdsDSet core_arg `uniqDSetIntersectUniqSet` local_vars)) -dsCmd ids local_vars stack_ty res_ty-        (HsCmdLam _ (MG { mg_alts-          = (L _ [L _ (Match { m_pats  = pats-                             , m_grhss = GRHSs _ [L _ (GRHS _ [] body)] _ })]) }))-        env_ids-  = dsCmdLam ids local_vars stack_ty res_ty pats body env_ids--dsCmd ids local_vars stack_ty res_ty (HsCmdPar _ _ cmd _) env_ids+dsCmd ids local_vars stack_ty res_ty (HsCmdPar _ cmd) env_ids   = dsLCmd ids local_vars stack_ty res_ty cmd env_ids  -- D, xs |- e :: Bool@@ -535,11 +528,18 @@  -} dsCmd ids local_vars stack_ty res_ty-      (HsCmdLamCase _ lc_variant match@MG { mg_ext = MatchGroupTc {mg_arg_tys = arg_tys} } )+        (HsCmdLam _ LamSingle (MG { mg_alts+          = (L _ [L _ (Match { m_pats  = pats+                             , m_grhss = GRHSs _ [L _ (GRHS _ [] body)] _ })]) }))+        env_ids+  = dsCmdLam ids local_vars stack_ty res_ty pats body env_ids++dsCmd ids local_vars stack_ty res_ty+      (HsCmdLam _ lam_variant match@MG { mg_ext = MatchGroupTc {mg_arg_tys = arg_tys} } )       env_ids = do     arg_ids <- newSysLocalsDs arg_tys -    let match_ctxt = ArrowLamCaseAlt lc_variant+    let match_ctxt = ArrowLamAlt lam_variant         pat_vars = mkVarSet arg_ids         local_vars' = pat_vars `unionVarSet` local_vars         (pat_tys, stack_ty') = splitTypeAt (length arg_tys) stack_ty@@ -591,7 +591,7 @@ -- --              ---> premap (\ ((xs),stk) -> let binds in ((ys),stk)) c -dsCmd ids local_vars stack_ty res_ty (HsCmdLet _ _ lbinds@binds _ body) env_ids = do+dsCmd ids local_vars stack_ty res_ty (HsCmdLet _ lbinds@binds body) env_ids = do     let         defined_vars = mkVarSet (collectLocalBinders CollWithDictBinders binds)         local_vars' = defined_vars `unionVarSet` local_vars@@ -646,8 +646,6 @@     dsHsWrapper wrap $ \core_wrap ->       return (core_wrap core_cmd, env_ids') -dsCmd _ _ _ _ c@(HsCmdLam {}) _ = pprPanic "dsCmd" (ppr c)- -- D; ys |-a c : stk --> t      (ys <= xs) -- --------------------- -- D; xs |-a c : stk --> t      ---> premap (\ ((xs),stk) -> ((ys),stk)) c@@ -738,10 +736,11 @@         core_expr = buildEnvStack env_ids' stack_id'         in_ty = envStackType env_ids stack_ty         in_ty' = envStackType env_ids' stack_ty'+        lam_cxt = ArrowMatchCtxt (ArrowLamAlt LamSingle) -    fail_expr <- mkFailExpr (ArrowMatchCtxt KappaExpr) in_ty'+    fail_expr <- mkFailExpr lam_cxt in_ty'     -- match the patterns against the parameters-    match_code <- matchSimplys (map Var param_ids) (ArrowMatchCtxt KappaExpr) pats core_expr+    match_code <- matchSimplys (map Var param_ids) lam_cxt pats core_expr                     fail_expr     -- match the parameters against the top of the old stack     (stack_id, param_code) <- matchVarStack param_ids stack_id' match_code@@ -785,9 +784,9 @@   let       left_id  = mkConLikeTc (RealDataCon left_con)       right_id = mkConLikeTc (RealDataCon right_con)-      left_expr  ty1 ty2 e = noLocA $ HsApp noComments+      left_expr  ty1 ty2 e = noLocA $ HsApp noExtField                          (noLocA $ mkHsWrap (mkWpTyApps [ty1, ty2]) left_id ) e-      right_expr ty1 ty2 e = noLocA $ HsApp noComments+      right_expr ty1 ty2 e = noLocA $ HsApp noExtField                          (noLocA $ mkHsWrap (mkWpTyApps [ty1, ty2]) right_id) e        -- Prefix each tuple with a distinct series of Left's and Right's,@@ -809,9 +808,9 @@     -- i.e. Void. The choices then effectively become `arr absurd`,     -- implemented as `arr \case {}`.     Nothing -> ([], void_ty,) . do_arr ids void_ty res_ty <$>-      dsExpr (HsLamCase EpAnnNotUsed LamCase+      dsExpr (HsLam noAnn LamCase         (MG { mg_alts = noLocA []-            , mg_ext = MatchGroupTc [Scaled ManyTy void_ty] res_ty (Generated SkipPmc)+            , mg_ext = MatchGroupTc [Scaled ManyTy void_ty] res_ty (Generated OtherExpansion SkipPmc)             }))        -- Replace the commands in the case with these tagged tuples,@@ -964,7 +963,7 @@     fail_expr <- mkFailExpr (StmtCtxt (HsDoStmt (DoExpr Nothing))) out_ty     pat_id    <- selectSimpleMatchVarL ManyTy pat     match_code-      <- matchSimply (Var pat_id) (StmtCtxt (HsDoStmt (DoExpr Nothing))) pat body_expr fail_expr+      <- matchSimply (Var pat_id) (StmtCtxt (HsDoStmt (DoExpr Nothing))) ManyTy pat body_expr fail_expr     pair_id   <- newSysLocalDs ManyTy after_c_ty     let         proj_expr = Lam pair_id (coreCasePair pair_id pat_id env_id match_code)@@ -1191,7 +1190,7 @@ -- Match a list of expressions against a list of patterns, left-to-right.  matchSimplys :: [CoreExpr]              -- Scrutinees-             -> HsMatchContext GhcTc    -- Match kind+             -> HsMatchContextRn        -- Match kind              -> [LPat GhcTc]            -- Patterns they should match              -> CoreExpr                -- Return this if they all match              -> CoreExpr                -- Return this if they don't@@ -1199,7 +1198,7 @@ matchSimplys [] _ctxt [] result_expr _fail_expr = return result_expr matchSimplys (exp:exps) ctxt (pat:pats) result_expr fail_expr = do     match_code <- matchSimplys exps ctxt pats result_expr fail_expr-    matchSimply exp ctxt pat match_code fail_expr+    matchSimply exp ctxt ManyTy pat match_code fail_expr matchSimplys _ _ _ _ _ = panic "matchSimplys"  -- List of leaf expressions, with set of variables bound in each
compiler/GHC/HsToCore/Binds.hs view
@@ -81,7 +81,6 @@ import GHC.Utils.Monad import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain  import Control.Monad @@ -117,10 +116,54 @@     top_level_err bindsType (L loc bind)       = putSrcSpanDs (locA loc) $         diagnosticDs (DsTopLevelBindsNotAllowed bindsType bind)+{-+Note [Return non-recursive bindings in dependency order]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+For recursive bindings, the desugarer has no choice: it returns a single big+Rec{...} group. +But for /non-recursive/ bindings, the desugarer guarantees to desugar them to+a sequence of non-recurive Core bindings, in dependency order. +Why is this important?  Partly it saves a bit of work in the first run of the+occurrence analyser. But more importantly, for linear types, non-recursive lets+can be linear whereas recursive-let can't. Since we check the output of the+desugarer for linearity (see also Note [Linting linearity]), desugaring+non-recursive lets to recursive lets would break linearity checks. An+alternative is to refine the typing rule for recursive lets so that we don't+have to care (see in particular #23218 and #18694), but the outcome of this line+of work is still unclear. In the meantime, being a little precise in the+desugarer is cheap. (paragraph written on 2023-06-09)++In dsLHSBinds (and dependencies), a single binding can be desugared to multiple+bindings. For instance because the source binding has the {-# SPECIALIZE #-}+pragma. In:++f _ = …+ where+  {-# SPECIALIZE g :: F Int -> F Int #-}+  g :: C a => F a -> F a+  g _ = …++The g binding desugars to++let {+  $sg = … } in++  g+  [RULES: "SPEC g" g @Int $dC = $sg]+  g = …++In order to avoid generating a letrec that will immediately be reordered, we+make sure to return the binding in dependency order [$sg, g].++-}+ -- | Desugar all other kind of bindings, Ids of strict binds are returned to -- later be forced in the binding group body, see Note [Desugar Strict binds]+--+-- Invariant: the desugared bindings are returned in dependency order,+-- see Note [Return non-recursive bindings in dependency order] dsLHsBinds :: LHsBinds GhcTc -> DsM ([Id], [(Id,CoreExpr)]) dsLHsBinds binds   = do { ds_bs <- mapBagM dsLHsBind binds@@ -134,6 +177,9 @@                             putSrcSpanDs (locA loc) $ dsHsBind dflags bind  -- | Desugar a single binding (or group of recursive binds).+--+-- Invariant: the desugared bindings are returned in dependency order,+-- see Note [Return non-recursive bindings in dependency order] dsHsBind :: DynFlags          -> HsBind GhcTc          -> DsM ([Id], [(Id,CoreExpr)])@@ -191,7 +237,7 @@         ; body_expr <- dsGuarded grhss ty rhss_nablas         ; let body' = mkOptTickBox rhs_tick body_expr               pat'  = decideBangHood dflags pat-        ; (force_var,sel_binds) <- mkSelectorBinds var_ticks pat body'+        ; (force_var,sel_binds) <- mkSelectorBinds var_ticks pat PatBindRhs body'           -- We silently ignore inline pragmas; no makeCorePair           -- Not so cool, but really doesn't matter         ; let force_var' = if isBangedLPat pat'@@ -205,16 +251,15 @@                         , abs_exports = exports                         , abs_ev_binds = ev_binds                         , abs_binds = binds, abs_sig = has_sig }))-  = do { ds_binds <- addTyCs FromSource (listToBag dicts) $+  = dsTcEvBinds_s ev_binds $ \ds_ev_binds -> do+    { ds_binds <- addTyCs FromSource (listToBag dicts) $                      dsLHsBinds binds              -- addTyCs: push type constraints deeper              --            for inner pattern match check              -- See Check, Note [Long-distance information] -       ; dsTcEvBinds_s ev_binds $ \ds_ev_binds -> do--       -- dsAbsBinds does the hard work-       { dsAbsBinds dflags tyvars dicts exports ds_ev_binds ds_binds has_sig } }+    -- dsAbsBinds does the hard work+    ; dsAbsBinds dflags tyvars dicts exports ds_ev_binds ds_binds (isSingletonBag binds) has_sig }  dsHsBind _ (PatSynBind{}) = panic "dsHsBind: PatSynBind" @@ -223,11 +268,12 @@            -> [TyVar] -> [EvVar] -> [ABExport]            -> [CoreBind]                -- Desugared evidence bindings            -> ([Id], [(Id,CoreExpr)])   -- Desugared value bindings+           -> Bool                      -- Single source binding            -> Bool                      -- Single binding with signature            -> DsM ([Id], [(Id,CoreExpr)])  dsAbsBinds dflags tyvars dicts exports-           ds_ev_binds (force_vars, bind_prs) has_sig+           ds_ev_binds (force_vars, bind_prs) is_singleton has_sig      -- A very important common case: one exported variable     -- Non-recursive bindings come through this way@@ -263,14 +309,20 @@                                        (isDefaultMethod prags)                                        (dictArity dicts) rhs -       ; return (force_vars', main_bind : fromOL spec_binds) } }+       ; return (force_vars', fromOL spec_binds ++ [main_bind]) } }      -- Another common case: no tyvars, no dicts     -- In this case we can have a much simpler desugaring     --    lcl_id{inl-prag} = rhs  -- Auxiliary binds     --    gbl_id = lcl_id |> co   -- Main binds+    --+    -- See Note [The no-tyvar no-dict case]   | null tyvars, null dicts-  = do { let mk_main :: ABExport -> DsM (Id, CoreExpr)+  = do { let wrap_first_bind f ((main, main_rhs):other_binds) =+               ((main, f main_rhs):other_binds)+             wrap_first_bind _ [] = panic "dsAbsBinds received an empty binding list"++             mk_main :: ABExport -> DsM (Id, CoreExpr)              mk_main (ABE { abe_poly = gbl_id, abe_mono = lcl_id                           , abe_wrap = wrap })                      -- No SpecPrags (no dicts)@@ -278,15 +330,19 @@                = do { dsHsWrapper wrap $ \core_wrap -> do                     { return ( gbl_id `setInlinePragma` defaultInlinePragma                              , core_wrap (Var lcl_id)) } }-        ; main_prs <- mapM mk_main exports-       ; return (force_vars, flattenBinds ds_ev_binds-                              ++ mk_aux_binds bind_prs ++ main_prs ) }+       ; let bind_prs' = map mk_aux_bind bind_prs+             -- When there's a single source binding, we wrap the evidence binding in a+             -- separate let-rec (DSB1) inside the first desugared binding (DSB2).+             -- See Note [The no-tyvar no-dict case].+             final_prs | is_singleton = wrap_first_bind (mkCoreLets ds_ev_binds) bind_prs'+                       | otherwise = flattenBinds ds_ev_binds ++ bind_prs'+       ; return (force_vars, final_prs ++ main_prs ) }      -- The general case     -- See Note [Desugaring AbsBinds]   | otherwise-  = do { let aux_binds = Rec (mk_aux_binds bind_prs)+  = do { let aux_binds = Rec (map mk_aux_bind bind_prs)                 -- Monomorphic recursion possible, hence Rec               new_force_vars = get_new_force_vars force_vars@@ -322,7 +378,7 @@                            -- Kill the INLINE pragma because it applies to                            -- the user written (local) function.  The global                            -- Id is just the selector.  Hmm.-                     ; return ((global', rhs) : fromOL spec_binds) } }+                     ; return (fromOL spec_binds ++ [(global', rhs)]) } }         ; export_binds_s <- mapM mk_bind (exports ++ extra_exports) @@ -330,11 +386,11 @@                 , (poly_tup_id, poly_tup_rhs) :                    concat export_binds_s) }   where-    mk_aux_binds :: [(Id,CoreExpr)] -> [(Id,CoreExpr)]-    mk_aux_binds bind_prs = [ makeCorePair dflags lcl_w_inline False 0 rhs-                            | (lcl_id, rhs) <- bind_prs-                            , let lcl_w_inline = lookupVarEnv inline_env lcl_id-                                                 `orElse` lcl_id ]+    mk_aux_bind :: (Id,CoreExpr) -> (Id,CoreExpr)+    mk_aux_bind (lcl_id, rhs) = let lcl_w_inline = lookupVarEnv inline_env lcl_id+                                                   `orElse` lcl_id+                                 in+                                 makeCorePair dflags lcl_w_inline False 0 rhs      inline_env :: IdEnv Id -- Maps a monomorphic local Id to one with                            -- the inline pragma from the source@@ -473,48 +529,71 @@ The top-level AbsBinds for $cround has no tyvars or dicts (because the instance does not).  But the method is locally overloaded! -Note [Abstracting over tyvars only]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-When abstracting over type variable only (not dictionaries), we don't really need to-built a tuple and select from it, as we do in the general case. Instead we can take+Note [The no-tyvar no-dict case]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Suppose we are desugaring+    AbsBinds { tyvars   = []+             , dicts    = []+             , exports  = [ ABE f fm, ABE g gm ]+             , binds    = B+             , ev_binds = EB }+That is: no type variables or dictionary abstractions.  Here, `f` and `fm` are+the polymorphic and monomorphic versions of `f`; in this special case they will+both have the same type. -        AbsBinds [a,b] [ ([a,b], fg, fl, _),-                         ([b],   gg, gl, _) ]-                { fl = e1-                  gl = e2-                   h = e3 }+Specialising Note [Desugaring AbsBinds] for this case gives the desugaring -and desugar it to+    tup = letrec EB' in letrec B' in (fm,gm)+    f = case tup of { (fm,gm) -> fm }+    g = case tup of { (fm,gm) -> fm } -        fg = /\ab. let B in e1-        gg = /\b. let a = () in let B in S(e2)-        h  = /\ab. let B in e3+where B' is the result of desugaring B. This desugaring is a little silly: we+don't need the intermediate tuple (contrast with the general case where fm and f+have different types). So instead, in this case, we desugar to -where B is the *non-recursive* binding-        fl = fg a b-        gl = gg b-        h  = h a b    -- See (b); note shadowing!+    EB'; B'; f=fm; g=gm -Notice (a) g has a different number of type variables to f, so we must-             use the mkArbitraryType thing to fill in the gaps.-             We use a type-let to do that.+This is done in the `null tyvars, null dicts` case of `dsAbsBinds`. -         (b) The local variable h isn't in the exports, and rather than-             clone a fresh copy we simply replace h by (h a b), where-             the two h's have different types!  Shadowing happens here,-             which looks confusing but works fine.+But there is a wrinkle (DSB1).  If the original binding group was+/non-recursive/, we want to return a bunch of non-recursive bindings in+dependency order: see Note [Return non-recursive bindings in dependency order]. -         (c) The result is *still* quadratic-sized if there are a lot of-             small bindings.  So if there are more than some small-             number (10), we filter the binding set B by the free-             variables of the particular RHS.  Tiresome.+But there is no guarantee that EB', the desugared evidence bindings, will be+non-recursive.  Happily, in the non-recursive case, B will have just a single+binding (f = rhs), so we can wrap EB' around its RHS, thus: +   fm = letrec EB' in rhs; f = fm++There is a sub-wrinkle (DSB2).  If B is a /pattern/ bindings, it will desugar to+a "main" binding followed by a bunch of selectors. The main binding always+comes first, so we can pick it out and wrap EB' around its RHS.  For example++    AbsBinds { tyvars   = []+             , dicts    = []+             , exports  = [ ABE p pm, ABE q qm ]+             , binds    = PatBind (pm, Just qm) rhs+             , ev_binds = EB }++can desguar to++   pt = let EB' in+        case rhs of+          (pm,Just qm) -> (pm,qm)+   pm = case pt of (pm,qm) -> pm+   qm = case pt of (pm,qm) -> qm++   p = pm+   q = qm++The first three bindings come from desugaring the PatBind, and subsequently+wrapping the RHS of the main binding in EB'.+ Why got to this trouble?  It's a common case, and it removes the quadratic-sized tuple desugaring.  Less clutter, hopefully faster compilation, especially in a case where there are a *lot* of bindings. - Note [Eta-expanding INLINE things] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Consider@@ -622,6 +701,65 @@  See https://gitlab.haskell.org/ghc/ghc/wikis/strict-pragma for a more detailed explanation of the desugaring of strict bindings.++Wrinkle 1: forcing linear variables++Consider++  let %1 !x = rhs in <body>+==>+  let x = rhs in x `seq` <body>++In the desugared version x is used in both arguments of seq. This isn't+recognised a linear. So we can't strictly speaking use seq. Instead, the code is+really desugared as++  let x = rhs in case x of x { _ -> <body> }++The shadowing with the case-binder is crucial. The linear linter (see+Note [Linting linearity] in GHC.Core.Lint) understands this as linear. This is+what the seqVar function does.++To be more precise, suppose x has multiplicity p, the fully annotated seqVar (in+Core, p is really stored inside x) is++  case x of %p x { _ -> <body> }++In linear Core, case u of %p y { _ -> v } consumes u with multiplicity p, and+makes y available with multiplicity p in v. Which is exactly what we want.++Wrinkle 2: linear patterns++Consider the following linear binding (linear lets are always non-recursive):++  let+     %1 f : g = rhs+  in <body>++The general case would desugar it to++  let t = let tm = rhs+              fm = case tm of fm:_ -> fm+              gm = case tm of _:gm -> gm+           in+           (tm, fm, gm)++  in let f = case t a of (_,fm,_) -> fm+  in let g = case t a of (_,_,gm) -> gm+  in let tm = case t a of (tm,_,_) -> tm+  in tm `seq` <body>++But all the case expression drop variables, which is prohibited by+linearity. But because this is a non-recursive let (in particular we're+desugaring a single binding), we can (and do) desugar the binding as a simple+case-expression instead:++  case rhs of {+    (f:g) -> <body>+  }++This is handled by the special case: a non-recursive PatBind in+GHC.HsToCore.Expr.ds_val_bind.  Note [Strict binds checks] ~~~~~~~~~~~~~~~~~~~~~~~~~~
compiler/GHC/HsToCore/Breakpoints.hs view
@@ -19,6 +19,13 @@ import Data.List (intersperse) import Data.Array +-- | Initialize memory for breakpoint data that is shared between the bytecode+-- generator and the interpreter.+--+-- Since GHCi and the RTS need to interact with breakpoint data and the bytecode+-- generator needs to encode this information for each expression, the data is+-- allocated remotely in GHCi's address space and passed to the codegen as+-- foreign pointers. mkModBreaks :: Interp -> Module -> SizedSeq Tick -> IO ModBreaks mkModBreaks interp mod extendedMixEntries   = do
compiler/GHC/HsToCore/Docs.hs view
@@ -1,12 +1,7 @@ -- | Extract docs from the renamer output so they can be serialized. {-# LANGUAGE LambdaCase #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE TypeApplications #-}-{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE ViewPatterns #-}-{-# LANGUAGE BangPatterns #-}  module GHC.HsToCore.Docs where @@ -68,16 +63,17 @@                , tcg_imports = import_avails                , tcg_insts = insts                , tcg_fam_insts = fam_insts-               , tcg_doc_hdr = mb_doc_hdr+               , tcg_hdr_info = mb_hdr_info                , tcg_th_docs = th_docs_var                , tcg_type_env = ty_env                } = do     th_docs <- liftIO $ readIORef th_docs_var-    let doc_hdr = (unLoc <$> mb_doc_hdr)+    let doc_hdr = unLoc <$> fst mb_hdr_info         ExtractedTHDocs th_hdr th_decl_docs th_arg_docs th_inst_docs = extractTHDocs th_docs         mod_docs          =  Docs          { docs_mod_hdr = th_hdr <|> doc_hdr+         , docs_exports = exports_docs          -- Left biased union (see #21220)          , docs_decls = plusUniqMap_C (\a _ -> a)                           ((:[]) <$> th_decl_docs `plusUniqMap` th_inst_docs)@@ -105,6 +101,7 @@                              , isDefaultMethodOcc occ                              ] +    exports_docs = maybe emptyUniqMap mkExportsDocs mb_rn_exports     (doc_map, arg_map) = mkMaps def_meths_env local_insts decls_with_docs     decls_with_docs = topDecls rn_decls     local_insts = filter (nameIsLocalOrFrom semantic_mdl)@@ -114,6 +111,25 @@     named_chunks = getNamedChunks (isJust mb_rn_exports) rn_decls extractDocs _ _ = pure Nothing +mkExportsDocs :: [(LIE GhcRn, Avails)] -> UniqMap Name (HsDoc GhcRn)+mkExportsDocs = foldMap f+  where+    f :: (LIE GhcRn, Avails) -> UniqMap Name (HsDoc GhcRn)+    f (L _ ie, avails)+      | Just (L _ doc) <- ieExportDoc ie =+        listToUniqMap [ (availName nm, doc) | nm <- avails ]+    f _ = emptyUniqMap++    ieExportDoc :: IE GhcRn -> Maybe (ExportDoc GhcRn)+    ieExportDoc (IEVar _ _ doc) = doc+    ieExportDoc (IEThingAbs _ _ doc) = doc+    ieExportDoc (IEThingAll _ _ doc) = doc+    ieExportDoc (IEThingWith _ _ _ _ doc) = doc+    ieExportDoc (IEModuleContents _ _) = Nothing+    ieExportDoc (IEGroup _ _ _) = Nothing+    ieExportDoc (IEDoc _ _) = Nothing+    ieExportDoc (IEDocNamed _ _) = Nothing+ -- | If we have an explicit export list, we extract the documentation structure -- from that. -- Otherwise we use the renamed exports and declarations.@@ -255,7 +271,7 @@              -> ( [(Name, [HsDoc GhcRn])]                 , [(Name, IntMap (HsDoc GhcRn))]                 )-    mappings (L (SrcSpanAnn _ (RealSrcSpan l _)) decl, doc) =+    mappings (L (EpAnn (EpaSpan (RealSrcSpan l _)) _ _) decl, doc) =            (dm, am)       where         args = declTypeDocs decl@@ -269,7 +285,7 @@         ns = names l decl         dm = [(n, d) | (n, d) <- zip ns (repeat doc) ++ zip subNs subDocs, not $ all (isEmptyDocString . hsDocString) d]         am = [(n, args) | n <- ns] ++ zip subNs subArgs-    mappings (L (SrcSpanAnn _ (UnhelpfulSpan _)) _, _) = ([], [])+    mappings (L (EpAnn _ _ _) _, _) = ([], [])      instanceMap :: Map RealSrcSpan Name     instanceMap = M.fromList [(l, n) | n <- instances, RealSrcSpan l _ <- [getSrcSpan n] ]@@ -418,8 +434,8 @@  gadtConArgDocs :: HsConDeclGADTDetails GhcRn -> HsType GhcRn -> IntMap (HsDoc GhcRn) gadtConArgDocs con_args res_ty = case con_args of-  PrefixConGADT args -> con_arg_docs 0 $ map (unLoc . hsScaledThing) args ++ [res_ty]-  RecConGADT _ _     -> con_arg_docs 1 [res_ty]+  PrefixConGADT _ args -> con_arg_docs 0 $ map (unLoc . hsScaledThing) args ++ [res_ty]+  RecConGADT _ _       -> con_arg_docs 1 [res_ty]  con_arg_docs :: Int -> [HsType GhcRn] -> IntMap (HsDoc GhcRn) con_arg_docs n = IM.fromList . catMaybes . zipWith f [n..]
compiler/GHC/HsToCore/Expr.hs view
@@ -3,6 +3,7 @@ {-# LANGUAGE ViewPatterns #-}  {-# OPTIONS_GHC -Wno-incomplete-uni-patterns   #-}+{-# LANGUAGE LambdaCase #-}  {- (c) The University of Glasgow 2006@@ -31,7 +32,7 @@ import GHC.HsToCore.Pmc import GHC.HsToCore.Errors.Types import GHC.Types.SourceText-import GHC.Types.Name+import GHC.Types.Name hiding (varName) import GHC.Core.FamInstEnv( topNormaliseType ) import GHC.HsToCore.Quote import GHC.HsToCore.Ticks (stripTicksTopHsExpr)@@ -51,6 +52,7 @@ import GHC.Driver.Session import GHC.Types.CostCentre import GHC.Types.Id+import GHC.Types.Id.Info import GHC.Types.Id.Make import GHC.Unit.Module import GHC.Core.ConLike@@ -64,9 +66,9 @@ import GHC.Data.Bag import GHC.Utils.Outputable as Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Core.PatSyn import Control.Monad+import GHC.Types.Error  {- ************************************************************************@@ -86,7 +88,8 @@ -- caller sets location dsValBinds :: HsValBinds GhcTc -> CoreExpr -> DsM CoreExpr dsValBinds (XValBindsLR (NValBinds binds _)) body-  = foldrM ds_val_bind body binds+  = do { dflags <- getDynFlags+       ; foldrM (ds_val_bind dflags) body binds } dsValBinds (ValBinds {})       _    = panic "dsValBinds ValBindsIn"  -------------------------@@ -105,12 +108,12 @@  ------------------------- -- caller sets location-ds_val_bind :: (RecFlag, LHsBinds GhcTc) -> CoreExpr -> DsM CoreExpr+ds_val_bind :: DynFlags -> (RecFlag, LHsBinds GhcTc) -> CoreExpr -> DsM CoreExpr -- Special case for bindings which bind unlifted variables -- We need to do a case right away, rather than building -- a tuple and doing selections. -- Silently ignore INLINE and SPECIALISE pragmas...-ds_val_bind (NonRecursive, hsbinds) body+ds_val_bind _ (NonRecursive, hsbinds) body   | [L loc bind] <- bagToList hsbinds         -- Non-recursive, non-overloaded bindings only come in ones         -- ToDo: in some bizarre case it's conceivable that there@@ -144,13 +147,39 @@     is_polymorphic _ = False  -ds_val_bind (is_rec, binds) _body+ds_val_bind _ (is_rec, binds) _body   | anyBag (isUnliftedHsBind . unLoc) binds  -- see Note [Strict binds checks] in GHC.HsToCore.Binds   = assert (isRec is_rec )     errDsCoreExpr $ DsRecBindsNotAllowedForUnliftedTys (bagToList binds) +-- Special case: a non-recursive PatBind. No dancing about with lets and seqs,+-- we make a case immediately. Very important for linear types: let !pat can be+-- linear, but selectors as used in the general case aren't. So the general case+-- would transform a linear definition into a non-linear one. See Wrinkle 2+-- Note [Desugar Strict binds] in GHC.HsToCore.Binds.+ds_val_bind dflags (NonRecursive, hsbinds) body+  | [L _loc (PatBind { pat_lhs = pat, pat_rhs = grhss, pat_mult = mult_ann+                     , pat_ext = (ty, (rhs_tick, _var_ticks))})] <- bagToList hsbinds+        -- Non-recursive, non-overloaded bindings only come in ones+  , pat' <- decideBangHood dflags pat+  , isBangedLPat pat'+  = do { rhss_nablas <- pmcGRHSs PatBindGuards grhss+        ; rhs_expr <- dsGuarded grhss ty rhss_nablas+        ; let rhs' = mkOptTickBox rhs_tick rhs_expr+        ; let body_ty = exprType body+        ; let mult = getTcMultAnn mult_ann+        ; error_expr <- mkErrorAppDs pAT_ERROR_ID body_ty (ppr pat')+        ; matchSimply rhs' PatBindRhs mult pat' body error_expr }+    -- This is the one place where matchSimply is given a non-ManyTy+    -- multiplicity argument.+    --+    -- In this form, there isn't a natural place for the var_ticks. In+    -- mkSelectorBinds, the ticks are around the selector function but there+    -- aren't any selection functions as we make a single pattern-match. Is this a+    -- problem?+ -- Ordinary case for bindings; none should be unlifted-ds_val_bind (is_rec, binds) body+ds_val_bind _ (is_rec, binds) body   = do  { massert (isRec is_rec || isSingletonBag binds)                -- we should never produce a non-recursive list of multiple binds @@ -160,18 +189,23 @@           -- NB: bindings have a fixed RuntimeRep, so it's OK to call isUnliftedType           case prs of             [] -> return body-            _  -> return (Let (Rec prs) body') }-        -- Use a Rec regardless of is_rec.-        -- Why? Because it allows the binds to be all-        -- mixed up, which is what happens in one rare case-        -- Namely, for an AbsBind with no tyvars and no dicts,-        --         but which does have dictionary bindings.-        -- See notes with GHC.Tc.Solver.inferLoop [NO TYVARS]-        -- It turned out that wrapping a Rec here was the easiest solution-        ---        -- NB The previous case dealt with unlifted bindings, so we-        --    only have to deal with lifted ones now; so Rec is ok+            _  -> return (mkLets (mk_binds is_rec prs) body') }+            -- We can make a non-recursive let because we make sure to return+            -- the bindings in dependency order in dsLHsBinds,+            -- see Note [Return non-recursive bindings in dependency order] in+            -- GHC.HsToCore.Binds +-- | Helper function. You can use the result of 'mk_binds' with 'mkLets' for+-- instance.+--+--   * @'mk_binds' 'Recursive' binds@ makes a single mutually-recursive+--     bindings with all the rhs/lhs pairs in @binds@+--   * @'mk_binds' 'NonRecursive' binds@ makes one non-recursive binding+--     for each rhs/lhs pairs in @binds@+mk_binds :: RecFlag -> [(b, (Expr b))] -> [Bind b]+mk_binds Recursive binds = [Rec binds]+mk_binds NonRecursive binds = map (uncurry NonRec) binds+ ------------------ dsUnliftedBind :: HsBind GhcTc -> CoreExpr -> DsM CoreExpr dsUnliftedBind (XHsBindsLR (AbsBinds { abs_tvs = [], abs_ev_vars = []@@ -203,11 +237,8 @@         -- ==> case rhs of C x# y# -> body     do { match_nablas <- pmcGRHSs PatBindGuards grhss        ; rhs          <- dsGuarded grhss ty match_nablas-       ; let upat = unLoc pat-             eqn = EqnInfo { eqn_pats = [upat],-                             eqn_orig = FromSource,-                             eqn_rhs = cantFailMatchResult body }-       ; var    <- selectMatchVar ManyTy upat+       ; let eqn = EqnMatch { eqn_pat = pat, eqn_rest = EqnDone (cantFailMatchResult body) }+       ; var    <- selectMatchVar ManyTy (unLoc pat)                     -- `var` will end up in a let binder, so the multiplicity                     -- doesn't matter.        ; result <- matchEquations PatBindRhs [var] [eqn] (exprType body)@@ -230,11 +261,42 @@ -- | Desugar a typechecked expression. dsExpr :: HsExpr GhcTc -> DsM CoreExpr dsExpr (HsVar    _ (L _ id))           = dsHsVar id-dsExpr (HsRecSel _ (FieldOcc id _))    = dsHsVar id++{- Record selectors are warned about if they are not+present in all of the parent data type's constructor,+or always in case of pattern synonym record selectors+(regulated by a flag). However, this only produces+a warning if it's not a part of a record selector+application. For example:++        data T = T1 | T2 {s :: Bool}+        f x = s x -- the warning from this case will be supressed++See the `HsApp` case for where it is filtered out+-}+dsExpr (HsRecSel _ (FieldOcc id _))+  = do { let name = getName id+             RecSelId {sel_cons = (_, cons_wo_field)}+                  = idDetails id+       ; cons_trimmed <- trim_cons cons_wo_field+       ; unless (null cons_wo_field) $ diagnosticDs+             $ DsIncompleteRecordSelector name cons_trimmed (cons_trimmed /= cons_wo_field)+                 -- This only produces a warning if it's not a part of a+                 -- record selector application (e.g. `s a` where `s` is a selector)+                 -- See the `HsApp` case for where it is filtered out+       ; dsHsVar id }+  where+    trim_cons :: [ConLike] -> DsM [ConLike]+    trim_cons cons_wo_field = do+      dflags <- getDynFlags+      let maxConstructors = maxUncoveredPatterns dflags+      return $ take maxConstructors cons_wo_field++ dsExpr (HsUnboundVar (HER ref _ _) _)  = dsEvTerm =<< readMutVar ref         -- See Note [Holes] in GHC.Tc.Types.Constraint -dsExpr (HsPar _ _ e _)        = dsLExpr e+dsExpr (HsPar _ e)            = dsLExpr e dsExpr (ExprWithTySig _ e _)  = dsLExpr e  dsExpr (HsIPVar x _)          = dataConCantHappen x@@ -252,7 +314,10 @@  dsExpr e@(XExpr ext_expr_tc)   = case ext_expr_tc of-      ExpansionExpr (HsExpanded _ b) -> dsExpr b+      ExpandedThingTc o e+        | OrigStmt (L loc _) <- o+        -> putSrcSpanDsA loc $ dsExpr e+        | otherwise -> dsExpr e       WrapExpr {}                    -> dsHsWrapped e       ConLikeTc con tvs tys          -> dsConLike con tvs tys       -- Hpc Support@@ -290,17 +355,33 @@   = do { expr' <- dsLExpr expr        ; dsSyntaxExpr neg_expr [expr'] } -dsExpr (HsLam _ a_Match)-  = uncurry mkCoreLams <$> matchWrapper LambdaExpr Nothing a_Match--dsExpr (HsLamCase _ lc_variant matches)-  = uncurry mkCoreLams <$> matchWrapper (LamCaseAlt lc_variant) Nothing matches+dsExpr (HsLam _ variant a_Match)+  = uncurry mkCoreLams <$> matchWrapper (LamAlt variant) Nothing a_Match  dsExpr e@(HsApp _ fun arg)-  = do { fun' <- dsLExpr fun+         -- We want to have a special case that uses the PMC information to filter+         -- out some of the incomplete record selectors warnings and not trigger+         -- the warning emitted during the desugaring of dsExpr(HsRecSel)+         -- See Note [Detecting incomplete record selectors] in GHC.HsToCore.Pmc+  = do { (msgs, fun') <- captureMessagesDs $ dsLExpr fun+             -- Make sure to filter out the generic incomplete record selector warning+             -- if it's a raw record selector        ; arg' <- dsLExpr arg+       ; case getIdFromTrivialExpr_maybe fun' of+           Just fun_id | isRecordSelector fun_id+             -> do { let msgs' = filterMessages is_incomplete_rec_sel_msg msgs+                   ; addMessagesDs msgs'+                   ; pmcRecSel fun_id arg' }+           _ -> addMessagesDs msgs+       ; warnUnusedBindValue fun arg (exprType arg')        ; return $ mkCoreAppDs (text "HsApp" <+> ppr e) fun' arg' }+  where+    is_incomplete_rec_sel_msg :: MsgEnvelope DsMessage -> Bool+    is_incomplete_rec_sel_msg (MsgEnvelope {errMsgDiagnostic = DsIncompleteRecordSelector{}})+                                = False+    is_incomplete_rec_sel_msg _ = True + dsExpr e@(HsAppType {}) = dsHsWrapped e  {-@@ -365,6 +446,8 @@ dsExpr (HsPragE _ prag expr) =   ds_prag_expr prag expr +dsExpr (HsEmbTy x _) = dataConCantHappen x+ dsExpr (HsCase ctxt discrim matches)   = do { core_discrim <- dsLExpr discrim        ; ([discrim_var], matching_code) <- matchWrapper ctxt (Just [discrim]) matches@@ -372,7 +455,7 @@  -- Pepe: The binds are in scope in the body but NOT in the binding group --       This is to avoid silliness in breakpoints-dsExpr (HsLet _ _ binds _ body) = do+dsExpr (HsLet _ binds body) = do     body' <- dsLExpr body     dsLocalBinds binds body' @@ -749,10 +832,10 @@         later_pats   = rec_tup_pats         rets         = map noLocA rec_rets         mfix_app     = nlHsSyntaxApps mfix_op [mfix_arg]-        match_group  = MatchGroupTc [unrestricted tup_ty] body_ty (Generated SkipPmc)-        mfix_arg     = noLocA $ HsLam noExtField+        match_group  = MatchGroupTc [unrestricted tup_ty] body_ty (Generated OtherExpansion SkipPmc)+        mfix_arg     = noLocA $ HsLam noAnn LamSingle                            (MG { mg_alts = noLocA [mkSimpleMatch-                                                    LambdaExpr+                                                    (LamAlt LamSingle)                                                     [mfix_pat] body]                                , mg_ext = match_group                                })@@ -865,6 +948,28 @@ -}  -- Warn about certain types of values discarded in monadic bindings (#3263)+warnUnusedBindValue :: LHsExpr GhcTc -> LHsExpr GhcTc -> Type -> DsM ()+warnUnusedBindValue fun arg@(L loc _) arg_ty+  | Just (l, f) <- fish_var fun+  , f `hasKey` thenMClassOpKey    -- it is a (>>)+  = when (isGeneratedSrcSpan l) $ -- it is compiler generated (>>)+         putSrcSpanDs (locA loc) $ warnDiscardedDoBindings arg arg_ty+  where+    -- Retrieve the location info and the head of the application+    -- It is important that we /do not/ look through HsApp to avoid+    -- generating duplicate warnings+    -- See Part 2. of Note [Expanding HsDo with XXExprGhcRn]+    fish_var :: LHsExpr GhcTc -> Maybe (SrcSpan , Id)+    fish_var (L l (HsVar _ id)) = return (locA l, unLoc id)+    fish_var (L _ (HsAppType _ e _)) = fish_var e+    fish_var (L l (XExpr (WrapExpr (HsWrap _ e)))) = do (l, e') <- fish_var (L l e)+                                                        return (l, e')+    fish_var (L l (XExpr (ExpandedThingTc _ e))) = fish_var (L l e)+    fish_var _ = Nothing++warnUnusedBindValue _ _ _  = return ()++-- Warn about certain types of values discarded in monadic bindings (#3263) warnDiscardedDoBindings :: LHsExpr GhcTc -> Type -> DsM () warnDiscardedDoBindings rhs rhs_ty   | Just (m_ty, elt_ty) <- tcSplitAppTy_maybe rhs_ty@@ -904,11 +1009,11 @@ dsHsWrapped orig_hs_expr   = go idHsWrapper orig_hs_expr   where-    go wrap (HsPar _ _ (L _ hs_e) _)+    go wrap (HsPar _ (L _ hs_e))        = go wrap hs_e     go wrap1 (XExpr (WrapExpr (HsWrap wrap2 hs_e)))        = go (wrap1 <.> wrap2) hs_e-    go wrap (HsAppType ty (L _ hs_e) _ _)+    go wrap (HsAppType ty (L _ hs_e) _)        = go (wrap <.> WpTyApp ty) hs_e      go wrap (HsVar _ (L _ var))
compiler/GHC/HsToCore/Foreign/C.hs view
@@ -56,7 +56,6 @@  import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Encoding  import Data.Maybe
compiler/GHC/HsToCore/Foreign/Call.hs view
@@ -45,7 +45,6 @@ import GHC.Driver.DynFlags import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain  import Data.Maybe 
compiler/GHC/HsToCore/Foreign/Decl.hs view
@@ -20,6 +20,7 @@  import GHC.HsToCore.Foreign.C import GHC.HsToCore.Foreign.JavaScript+import GHC.HsToCore.Foreign.Wasm import GHC.HsToCore.Foreign.Utils import GHC.HsToCore.Monad @@ -86,16 +87,16 @@    do_decl (ForeignImport { fd_name = id, fd_i_ext = co, fd_fi = spec }) = do       traceIf (text "fi start" <+> ppr id)       let id' = unLoc id-      (bs, h, c) <- dsFImport id' co spec+      (bs, h, c, ids) <- dsFImport id' co spec       traceIf (text "fi end" <+> ppr id)-      return (h, c, [], bs)+      return (h, c, ids, bs)     do_decl (ForeignExport { fd_name = L _ id                           , fd_e_ext = co                           , fd_fe = CExport _                               (L _ (CExportStatic _ ext_nm cconv)) }) = do-      (h, c, _, _) <- dsFExport id co ext_nm cconv False-      return (h, c, [id], [])+      (h, c, _, _, ids, bs) <- dsFExport id co ext_nm cconv False+      return (h, c, ids, bs)  {- ************************************************************************@@ -126,12 +127,20 @@ dsFImport :: Id           -> Coercion           -> ForeignImport (GhcPass p)-          -> DsM ([Binding], CHeader, CStub)+          -> DsM ([Binding], CHeader, CStub, [Id]) dsFImport id co (CImport _ cconv safety mHeader spec) = do   platform <- getPlatform-  case platformArch platform of-    ArchJavaScript -> dsJsImport id co spec (unLoc cconv) (unLoc safety) mHeader-    _              -> dsCImport  id co spec (unLoc cconv) (unLoc safety) mHeader+  let cconv' = unLoc cconv+      safety' = unLoc safety+  case (platformArch platform, cconv') of+    (ArchJavaScript, _) -> do+      (bs, h, c) <- dsJsImport id co spec cconv' safety' mHeader+      pure (bs, h, c, [])+    (ArchWasm32, JavaScriptCallConv) ->+      dsWasmJSImport id co spec safety'+    _ -> do+      (bs, h, c) <- dsCImport id co spec cconv' safety' mHeader+      pure (bs, h, c, [])  {- ************************************************************************@@ -165,12 +174,20 @@                  , CStub        -- contents of Module_stub.c                  , String       -- string describing type to pass to createAdj.                  , Int          -- size of args to stub function+                 , [Id]         -- function closures to be registered as GC roots+                 , [Binding]    -- additional bindings used by desugared foreign export                  ) dsFExport fn_id co ext_name cconv is_dyn = do   platform <- getPlatform-  case platformArch platform of-    ArchJavaScript -> dsJsFExport fn_id co ext_name cconv is_dyn-    _              -> dsCFExport  fn_id co ext_name cconv is_dyn+  case (platformArch platform, cconv) of+    (ArchJavaScript, _) -> do+      (h, c, ts, args) <- dsJsFExport fn_id co ext_name cconv is_dyn+      pure (h, c, ts, args, [fn_id], [])+    (ArchWasm32, JavaScriptCallConv) ->+      dsWasmJSExport fn_id co ext_name+    _ -> do+      (h, c, ts, args) <- dsCFExport fn_id co ext_name cconv is_dyn+      pure (h, c, ts, args, [fn_id], [])   foreignExportsInitialiser :: Platform -> Module -> [Id] -> CStub@@ -202,4 +219,3 @@      closure_ptr :: Id -> SDoc     closure_ptr fn = text "(StgPtr) &" <> ppr fn <> text "_closure"-
compiler/GHC/HsToCore/Foreign/JavaScript.hs view
@@ -58,7 +58,6 @@ import GHC.Builtin.Names  import GHC.Data.FastString-import GHC.Data.Pair import GHC.Data.Maybe  import GHC.Utils.Outputable@@ -83,7 +82,7 @@  dsJsFExport fn_id co ext_name cconv isDyn = do     let-       ty                              = pSnd $ coercionKind co+       ty                              = coercionRKind co        (_tvs,sans_foralls)             = tcSplitForAllTyVars ty        (fe_arg_tys', orig_res_ty)      = tcSplitFunTys sans_foralls        -- We must use tcSplits here, because we want to see@@ -158,14 +157,17 @@   idTag i = let (tag, u) = unpkUnique (getUnique i)             in  CHeader (char tag <> word64 u) +  normal_args = map (\(nm,_ty,_,_) -> nm) arg_info+  all_args+    | isNothing maybe_target = text "stableptr_offset" : normal_args+    | otherwise              = normal_args+   fun_args     | null arg_info = empty -- text "void"-    | otherwise         = hsep $ punctuate comma-                               $ map (\(nm,_ty,_,_) -> nm) arg_info+    | otherwise     = hsep $ punctuate comma all_args    fun_proto-      = text "async" <+>-        text "function" <+>+      = text "function" <+>         (if isNothing maybe_target          then text "h$" <> ftext c_nm          else ftext c_nm) <>@@ -189,7 +191,7 @@   -- the target which will form the root of what we ask rts_evalIO to run   the_cfun      = case maybe_target of-          Nothing    -> text "h$deRefStablePtr(the_stableptr)"+          Nothing    -> text "h$deRefStablePtr(stableptr_offset)"           Just hs_fn -> idClosureText hs_fn    -- the expression we give to rts_eval@@ -211,8 +213,7 @@                $$ vcat                  [ lbrace                  ,   text "return"-                     <+> text "await"-                     <+> text "h$rts_eval"+                     <+> text "h$rts_eval_sync"                      <> parens ((if is_IO_res_ty                                  then expr_to_run                                  else text "h$rts_toIO" <> parens expr_to_run)@@ -242,7 +243,7 @@   -> Maybe Header   -> DsM ([Binding], CHeader, CStub) dsJsImport id co (CLabel cid) cconv _ _ = do-   let ty = pFst $ coercionKind co+   let ty = coercionLKind co        fod = case tyConAppTyCon_maybe (dropForAlls ty) of              Just tycon               | tyConUnique tycon == funPtrTyConKey ->@@ -272,7 +273,7 @@                  -> DsM ([Binding], CHeader, CStub) dsJsFExportDynamic id co0 cconv = do     let-      ty                            = pFst (coercionKind co0)+      ty                            = coercionLKind co0       (tvs,sans_foralls)            = tcSplitForAllTyVars ty       ([Scaled arg_mult arg_ty], fn_res_ty)  = tcSplitFunTys sans_foralls       (io_tc, res_ty)               = expectJust "dsJsFExportDynamic: IO type expected"@@ -342,7 +343,7 @@         -> DsM ([(Id, Expr TyVar)], CHeader, CStub) dsJsCall fn_id co (CCall (CCallSpec target cconv safety)) _mDeclHeader = do     let-        ty                   = pFst $ coercionKind co+        ty                   = coercionLKind co         (tv_bndrs, rho)      = tcSplitForAllTyVarBinders ty         (arg_tys, io_res_ty) = tcSplitFunTys rho @@ -471,10 +472,6 @@     Just arg3_tycon                = maybe_arg3_tycon  -boxJsResult :: Type-            -> DsM (Type, CoreExpr -> CoreExpr)-boxJsResult result_ty-  | isRuntimeRepKindedTy result_ty = panic "boxJsResult: runtime rep ty" -- fixme -- Takes the result of the user-level ccall: --      either (IO t), --      or maybe just t for an side-effect-free call@@ -485,7 +482,7 @@ -- where t' is the unwrapped form of t.  If t is simply (), then -- the result type will be --      State# RealWorld -> (# State# RealWorld #)-+boxJsResult :: Type -> DsM (Type, CoreExpr -> CoreExpr) boxJsResult result_ty   | Just (io_tycon, io_res_ty) <- tcSplitIOType_maybe result_ty         -- isIOType_maybe handles the case where the type is a@@ -585,7 +582,6 @@ -- E.g. foreign import foo :: Int -> IO T -- Then resultWrapper deals with marshalling the 'T' part jsResultWrapper result_ty-  | isRuntimeRepKindedTy result_ty = return (Nothing, id) -- fixme this seems like a hack   -- Base case 1a: unboxed tuples   | Just (tc, args) <- splitTyConApp_maybe result_ty   , isUnboxedTupleTyCon tc {- && False -} = do
compiler/GHC/HsToCore/Foreign/Utils.hs view
@@ -27,7 +27,6 @@  import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain  type Binding = (Id, CoreExpr) -- No rec/nonrec structure;                               -- the occurrence analyser will sort it all out@@ -58,7 +57,7 @@ primTyDescChar !platform ty  | ty `eqType` unitTy = 'v'  | otherwise- = case typePrimRep1 (getPrimTyOf ty) of+ = case typePrimRepU (getPrimTyOf ty) of      IntRep      -> signed_word      WordRep     -> unsigned_word      Int8Rep     -> 'B'
+ compiler/GHC/HsToCore/Foreign/Wasm.hs view
@@ -0,0 +1,724 @@+{-# LANGUAGE OverloadedStrings #-}+{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}++module GHC.HsToCore.Foreign.Wasm+  ( dsWasmJSImport,+    dsWasmJSExport,+  )+where++import Data.List+  ( intercalate,+    stripPrefix,+  )+import Data.Maybe+import GHC.Builtin.Names+import GHC.Builtin.Types+import GHC.Builtin.Types.Prim+import GHC.Core+import GHC.Core.Coercion+import GHC.Core.DataCon+import GHC.Core.Make+import GHC.Core.Multiplicity+import GHC.Core.TyCon+import GHC.Core.Type+import GHC.Core.Utils+import GHC.Data.FastString+import GHC.Hs+import GHC.HsToCore.Foreign.Call+import GHC.HsToCore.Foreign.Utils+import GHC.HsToCore.Monad+import GHC.HsToCore.Types+import GHC.Iface.Env+import GHC.Prelude+import GHC.Tc.Utils.Env+import GHC.Tc.Utils.Monad+import GHC.Tc.Utils.TcType+import GHC.Types.ForeignCall+import GHC.Types.ForeignStubs+import GHC.Types.Id+import GHC.Types.Name+import GHC.Types.SourceText+import GHC.Types.SrcLoc+import GHC.Types.Var+import GHC.Unit+import GHC.Utils.Outputable+import GHC.Utils.Panic+import Language.Haskell.Syntax.Basic++dsWasmJSImport ::+  Id ->+  Coercion ->+  CImportSpec ->+  Safety ->+  DsM ([Binding], CHeader, CStub, [Id])+dsWasmJSImport id co (CFunction (StaticTarget _ js_src mUnitId _)) safety+  | js_src == "wrapper" = dsWasmJSDynamicExport id co mUnitId+  | otherwise = do+      (bs, h, c) <- dsWasmJSStaticImport id co (unpackFS js_src) mUnitId safety+      pure (bs, h, c, [])+dsWasmJSImport _ _ _ _ = panic "dsWasmJSImport: unreachable"++{-++Note [Desugaring JSFFI dynamic export]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++A JSFFI dynamic export wraps a Haskell function as a JavaScript+callback:++foreign import javascript "wrapper"+  mk_wrapper :: HsFuncType -> IO JSVal++We desugar it to three bindings under the hood:++1. The worker function++mk_wrapper_worker :: StablePtr HsFuncType -> HsFuncType+mk_wrapper_worker sp = unsafeDupablePerformIO (deRefStablePtr sp)++No need to bother with eta-expansion here. Also, the worker function+is marked as a JSFFI static export.++2. The adjustor function++foreign import javascript unsafe "(...args) => __exports.mk_wrapper_worker($1, ...args)"+  mk_wrapper_adjustor :: StablePtr HsFuncType -> IO JSVal++It generates a JavaScript callback that captures the stable pointer.+When the callback is invoked later, it calls our worker function and+passes the stable pointer as well as the rest of the arguments.++3. The wrapper function++mk_wrapper :: HsFuncType -> IO JSVal+mk_wrapper = mkJSCallback mk_wrapper_adjustor++This is the user-facing mk_wrapper binding. It allocates a stable+pointer for the Haskell function closure, then calls the adjustor+function to fetch the JSVal that represents the JavaScript callback.+The JSVal as returned by the adjustor is not returned directly; it has+a StablePtr# field which is NULL by default, but for JSFFI dynamic+exports, it's set to the Haskell function's stable pointer. This way,+when we call freeJSVal, the Haskell function can be freed as well.++-}++dsWasmJSDynamicExport ::+  Id -> Coercion -> Maybe Unit -> DsM ([Binding], CHeader, CStub, [Id])+dsWasmJSDynamicExport fn_id co mUnitId = do+  sp_tycon <- dsLookupTyCon stablePtrTyConName+  let ty = coercionLKind co+      (tv_bndrs, fun_ty) = tcSplitForAllTyVarBinders ty+      ([Scaled ManyTy arg_ty], io_jsval_ty) = tcSplitFunTys fun_ty+      sp_ty = mkTyConApp sp_tycon [arg_ty]+      (real_arg_tys, _) = tcSplitFunTys arg_ty+  sp_id <- newSysLocalDs ManyTy sp_ty+  work_uniq <- newUnique+  work_export_name <- uniqueCFunName+  deRefStablePtr_id <- lookupGhcInternalVarId "GHC.Internal.Stable" "deRefStablePtr"+  unsafeDupablePerformIO_id <-+    lookupGhcInternalVarId+      "GHC.Internal.IO.Unsafe"+      "unsafeDupablePerformIO"+  let work_id =+        mkExportedVanillaId+          ( mkExternalName+              work_uniq+              (nameModule $ getName fn_id)+              (mkVarOcc $ "jsffi_" ++ occNameString (getOccName fn_id) ++ "_work")+              generatedSrcSpan+          )+          work_ty+      work_rhs =+        mkCoreLams ([tv | Bndr tv _ <- tv_bndrs] ++ [sp_id])+          $ mkApps+            (Var unsafeDupablePerformIO_id)+            [Type arg_ty, mkApps (Var deRefStablePtr_id) [Type arg_ty, Var sp_id]]+      work_ty = exprType work_rhs+  (work_h, work_c, _, _, work_ids, work_bs) <-+    dsWasmJSExport+      work_id+      (mkRepReflCo work_ty)+      work_export_name+  adjustor_uniq <- newUnique+  let adjustor_id =+        mkExportedVanillaId+          ( mkExternalName+              adjustor_uniq+              (nameModule $ getName fn_id)+              ( mkVarOcc+                  $ "jsffi_"+                  ++ occNameString (getOccName fn_id)+                  ++ "_adjustor"+              )+              generatedSrcSpan+          )+          adjustor_ty+      adjustor_ty = mkForAllTys tv_bndrs $ mkVisFunTysMany [sp_ty] io_jsval_ty+      adjustor_js_src =+        "("+          ++ intercalate "," ["a" ++ show i | i <- [1 .. length real_arg_tys]]+          ++ ") => __exports."+          ++ unpackFS work_export_name+          ++ "($1"+          ++ mconcat [",a" ++ show i | i <- [1 .. length real_arg_tys]]+          ++ ")"+  (adjustor_bs, adjustor_h, adjustor_c) <-+    dsWasmJSStaticImport+      adjustor_id+      (mkRepReflCo adjustor_ty)+      adjustor_js_src+      mUnitId+      PlayRisky+  mkJSCallback_id <- lookupGhcInternalVarId "GHC.Internal.Wasm.Prim.Exports" "mkJSCallback"+  let wrap_rhs =+        mkCoreLams [tv | Bndr tv _ <- tv_bndrs]+          $ mkApps+            (Var mkJSCallback_id)+            [ Type arg_ty,+              mkApps+                (Var adjustor_id)+                [Type $ mkTyVarTy tv | Bndr tv _ <- tv_bndrs]+            ]+  pure+    ( [(fn_id, Cast wrap_rhs co), (work_id, work_rhs)] ++ work_bs ++ adjustor_bs,+      work_h `mappend` adjustor_h,+      work_c `mappend` adjustor_c,+      work_ids+    )++{-++Note [Desugaring JSFFI import]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++The simplest case is JSFFI sync import, those marked as unsafe. It is+implemented on top of C FFI unsafe import.++Unlike C FFI which generates a worker/wrapper pair that unboxes the+arguments and boxes the result in Haskell, we only desugar to a single+Haskell binding that case-binds the arguments to ensure they're+evaluated, then passes the boxed arguments directly to C and receive+the boxed result from C as well.++This is of course less efficient than how C FFI does it, and unboxed+FFI types aren't supported, but it's the easiest way to implement it,+especially since leaving all the boxing/unboxing business to C unifies+the implementation of JSFFI imports and exports.++Now, each sync import calls a generated C function with a unique+symbol. The C function uses rts_get* to unbox the arguments, call into+JavaScript, then boxes the result with rts_mk* and returns it to+Haskell. But wait, how on earth is C able to call into JavaScript+here!? The secret is using a wasm import:++__attribute__((import_module("ghc_wasm_jsffi"), import_name("my_js_func")))+HsJSVal worker_func(HsInt a1, HsJSVal a2);++Wasm imports live in the same namespace as other wasm functions, so+our C wrapper function can call into this imported worker function,+which will literally be the user written JavaScript function with+binders $1, $2, etc.++So far so good, but how does the source code snippet go from Haskell+source files to the JavaScript module which provides the+ghc_wasm_jsffi imports to be used by the wasm module at runtime? The+secret is embedding the source code snippets in a wasm custom section+named ghc_wasm_jsffi:++.section .custom_section.ghc_wasm_jsffi,"",@+.asciz my_js_func+.asciz ($1, $2)+.asciz js_code_containing($1, $2)++At link time, for all object files touched by wasm-ld, all+ghc_wasm_jsffi sections are concatenated into a single ghc_wasm_jsffi+section in the output wasm module. And then, a simple "post-linker"+program can parse the payload of that section and emit a JavaScript+module. Note that above is assembly source file, but we're only+generating a C stub, so we need to smuggle the assembly code into C+via __asm__.++JSFFI async import is implemented on top of JSFFI sync import. We+still desugar it to a single Haskell binding that calls C, with some+subtle differences:++- The C result type is always a boxed JSVal that represents the+  JavaScript Promise, instead of the actual Haskell result type.+- In the custom section payload, we emit "async ($1, $2)" instead of+  "($1, $2)". As you can see, it is the arrow function binder, and the+  post-linker will respect the async binder and allow await in the+  function body.+- The C import is also marked as safe. This is required since the+  JavaScript code may re-enter Haskell. If re-entrance only happens in+  future event loop tasks, it's fine to mark the C import as unsafe+  since the current Haskell execution context has already been freed+  at that point, but there's no such guarantee, so better safe than+  sorry here.++Now we have the Promise JSVal, we apply stg_blockPromise to it to get+a thunk with the desired return type. When the thunk is forced, it+will block the forcing thread and wait for the Promise to resolve or+reject. See Note [stg_blockPromise] for detailed explanation of how it+works.++-}++dsWasmJSStaticImport ::+  Id ->+  Coercion ->+  String ->+  Maybe Unit ->+  Safety ->+  DsM ([Binding], CHeader, CStub)+dsWasmJSStaticImport fn_id co js_src' mUnitId safety = do+  cfun_name <- uniqueCFunName+  let ty = coercionLKind co+      (tvs, fun_ty) = tcSplitForAllInvisTyVars ty+      (arg_tys, orig_res_ty) = tcSplitFunTys fun_ty+      (res_ty, is_io) = case tcSplitIOType_maybe orig_res_ty of+        Just (_, res_ty) -> (res_ty, True)+        Nothing -> (orig_res_ty, False)+      js_src+        -- Just desugar it to a JSFFI import with source text "$1($2,+        -- ...)", with the same type signature and safety annotation.+        | js_src' == "dynamic" =+            "$1("+              ++ intercalate "," ["$" ++ show i | i <- [2 .. length arg_tys]]+              ++ ")"+        | otherwise =+            js_src'+  case safety of+    PlayRisky -> do+      rhs <-+        importBindingRHS+          mUnitId+          PlayRisky+          cfun_name+          tvs+          arg_tys+          orig_res_ty+          id+      pure+        ( [(fn_id, Cast rhs co)],+          CHeader commonCDecls,+          importCStub+            PlayRisky+            cfun_name+            (map scaledThing arg_tys)+            res_ty+            js_src+        )+    _ -> do+      io_tycon <- dsLookupTyCon ioTyConName+      jsval_ty <- mkTyConTy <$> lookupGhcInternalTyCon "GHC.Internal.Wasm.Prim.Types" "JSVal"+      bindIO_id <- dsLookupGlobalId bindIOName+      returnIO_id <- dsLookupGlobalId returnIOName+      promise_id <- newSysLocalDs ManyTy jsval_ty+      blockPromise_id <- lookupGhcInternalVarId "GHC.Internal.Wasm.Prim.Imports" "stg_blockPromise"+      msgPromise_id <-+        lookupGhcInternalVarId "GHC.Internal.Wasm.Prim.Imports" $ "stg_messagePromise" ++ ffiType res_ty+      unsafeDupablePerformIO_id <-+        lookupGhcInternalVarId+          "GHC.Internal.IO.Unsafe"+          "unsafeDupablePerformIO"+      rhs <-+        importBindingRHS+          mUnitId+          PlaySafe+          cfun_name+          tvs+          arg_tys+          (mkTyConApp io_tycon [jsval_ty])+          $ ( if is_io+                then id+                else \m_res ->+                  mkApps (Var unsafeDupablePerformIO_id) [Type res_ty, m_res]+            )+          -- (m_promise :: IO JSVal) >>= (\promise -> return (stg_blockPromise promise msgPromise))+          -- stg_blockPromise returns the thunk+          . ( \m_promise ->+                mkApps+                  (Var bindIO_id)+                  [ Type jsval_ty,+                    Type res_ty,+                    m_promise,+                    Lam promise_id+                      $ mkApps+                        (Var returnIO_id)+                        [ Type res_ty,+                          mkApps+                            (Var blockPromise_id)+                            [Type res_ty, Var promise_id, Var msgPromise_id]+                        ]+                  ]+            )+      pure+        ( [(fn_id, Cast rhs co)],+          CHeader commonCDecls,+          importCStub+            PlaySafe+            cfun_name+            (map scaledThing arg_tys)+            jsval_ty+            js_src+        )++uniqueCFunName :: DsM FastString+uniqueCFunName = do+  cfun_num <- ds_next_wrapper_num <$> getGblEnv+  mkWrapperName cfun_num "ghc_wasm_jsffi" ""++importBindingRHS ::+  Maybe Unit ->+  Safety ->+  FastString ->+  [TyVar] ->+  [Scaled Type] ->+  Type ->+  (CoreExpr -> CoreExpr) ->+  DsM CoreExpr+importBindingRHS mUnitId safety cfun_name tvs arg_tys orig_res_ty res_trans =+  do+    ccall_uniq <- newUnique+    args_unevaled <- newSysLocalsDs arg_tys+    args_evaled <- newSysLocalsDs arg_tys+    -- ccall_action_ty: type of the_call, State# RealWorld -> (# State# RealWorld, a #)+    -- res_wrapper: turn the_call to (IO a) or a+    (ccall_action_ty, res_wrapper) <- case tcSplitIOType_maybe orig_res_ty of+      Just (io_tycon, res_ty) -> do+        s0_id <- newSysLocalDs ManyTy realWorldStatePrimTy+        s1_id <- newSysLocalDs ManyTy realWorldStatePrimTy+        let io_data_con = tyConSingleDataCon io_tycon+            toIOCon = dataConWorkId io_data_con+            (ccall_res_ty, wrap)+              | res_ty `eqType` unitTy =+                  ( mkTupleTy Unboxed [realWorldStatePrimTy],+                    \the_call ->+                      mkApps+                        (Var toIOCon)+                        [ Type res_ty,+                          Lam s0_id+                            $ mkWildCase+                              (App the_call (Var s0_id))+                              (unrestricted ccall_res_ty)+                              (mkTupleTy Unboxed [realWorldStatePrimTy, unitTy])+                              [ Alt+                                  (DataAlt (tupleDataCon Unboxed 1))+                                  [s1_id]+                                  (mkCoreUnboxedTuple [Var s1_id, unitExpr])+                              ]+                        ]+                  )+              | otherwise =+                  ( mkTupleTy Unboxed [realWorldStatePrimTy, res_ty],+                    \the_call -> mkApps (Var toIOCon) [Type res_ty, the_call]+                  )+        pure (realWorldStatePrimTy `mkVisFunTyMany` ccall_res_ty, wrap)+      Nothing -> do+        unsafeDupablePerformIO_id <-+          lookupGhcInternalVarId+            "GHC.Internal.IO.Unsafe"+            "unsafeDupablePerformIO"+        io_data_con <- dsLookupDataCon ioDataConName+        let ccall_res_ty =+              mkTupleTy Unboxed [realWorldStatePrimTy, orig_res_ty]+            toIOCon = dataConWorkId io_data_con+            wrap the_call =+              mkApps+                (Var unsafeDupablePerformIO_id)+                [ Type orig_res_ty,+                  mkApps (Var toIOCon) [Type orig_res_ty, the_call]+                ]+        pure (realWorldStatePrimTy `mkVisFunTyMany` ccall_res_ty, wrap)+    let cfun_fcall =+          CCall+            ( CCallSpec+                (StaticTarget NoSourceText cfun_name mUnitId True)+                CCallConv+                safety+            )+        call_app =+          mkFCall ccall_uniq cfun_fcall (map Var args_evaled) ccall_action_ty+        rhs =+          mkCoreLams (tvs ++ args_unevaled)+            $ foldr+              (\(arg_u, arg_e) acc -> mkDefaultCase (Var arg_u) arg_e acc)+              -- res_trans transforms the result. When desugaring+              -- JSFFI sync imports, the result is just (IO a) or a,+              -- and res_trans is id; for async cases, the result is+              -- always (IO JSVal), and res_trans will wrap it in a+              -- thunk that has the original return type. This way, we+              -- can reuse most of the RHS generation logic for both+              -- sync/async imports.+              (res_trans $ res_wrapper call_app)+              (zip args_unevaled args_evaled)+    pure rhs++importCStub :: Safety -> FastString -> [Type] -> Type -> String -> CStub+importCStub safety cfun_name arg_tys res_ty js_src = CStub c_doc [] []+  where+    import_name = fromJust $ stripPrefix "ghczuwasmzujsffi" (unpackFS cfun_name)+    import_asm =+      text "__asm__"+        <> parens+          ( vcat+              [ text (show l)+                | l <-+                    [ ".section .custom_section.ghc_wasm_jsffi,\"\",@\n",+                      ".asciz \"" ++ import_name ++ "\"\n",+                      ".asciz \""+                        ++ ( case safety of+                               PlayRisky -> "("+                               _ -> "async ("+                           )+                        ++ intercalate "," ["$" ++ show i | i <- [1 .. length arg_tys]]+                        ++ ")\"\n",+                      ".asciz " ++ show js_src ++ "\n"+                    ]+              ]+          )+        <> semi+    import_attr =+      text "__attribute__"+        <> parens+          ( parens+              ( hsep+                  ( punctuate+                      comma+                      [ text k <> parens (doubleQuotes (text v))+                        | (k, v) <-+                            [("import_module", "ghc_wasm_jsffi"), ("import_name", import_name)]+                      ]+                  )+              )+          )+    import_proto =+      import_res_ty <+> text import_name <> parens import_args <> semi+    import_res_ty+      | res_ty `eqType` unitTy = text "void"+      | otherwise = text ("Hs" ++ ffiType res_ty)+    import_arg_list =+      [ text ("Hs" ++ ffiType arg_ty) <+> char 'a' <> int i+        | (i, arg_ty) <- zip [1 ..] arg_tys+      ]+    import_args = case import_arg_list of+      [] -> text "void"+      _ -> hsep $ punctuate comma import_arg_list+    cfun_proto = cfun_res_ty <+> ppr cfun_name <> parens cfun_args+    cfun_ret+      | res_ty `eqType` unitTy = cfun_call_import <> semi+      | otherwise = text "return" <+> cfun_call_import <> semi+    cfun_make_arg arg_ty arg_val =+      text ("rts_get" ++ ffiType arg_ty) <> parens arg_val+    cfun_make_ret ret_val+      | res_ty `eqType` unitTy = ret_val+      | otherwise =+          text ("rts_mk" ++ ffiType res_ty)+            -- We can cheat a little bit here since there's only+            -- MainCapability in the single-threaded RTS anyway, so no+            -- need to call rts_unsafeGetMyCapability().+            <> parens (hsep (punctuate comma [text "&MainCapability", ret_val]))+    cfun_call_import =+      cfun_make_ret+        $ text import_name+        <> parens+          ( hsep+              ( punctuate+                  comma+                  [ cfun_make_arg arg_ty (char 'a' <> int n)+                    | (arg_ty, n) <- zip arg_tys [1 ..]+                  ]+              )+          )+    cfun_res_ty+      | res_ty `eqType` unitTy = text "void"+      | otherwise = text "HaskellObj"+    cfun_arg_list =+      [text "HaskellObj" <+> char 'a' <> int n | n <- [1 .. length arg_tys]]+    cfun_args = case cfun_arg_list of+      [] -> text "void"+      _ -> hsep $ punctuate comma cfun_arg_list+    c_doc =+      commonCDecls+        $+$ import_asm+        $+$ import_attr+        $+$ import_proto+        $+$ cfun_proto+        $+$ braces cfun_ret++{-++Note [Desugaring JSFFI static export]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++A JSFFI static export wraps a top-level Haskell binding as a wasm+module export that can be called in JavaScript as an async function:++foreign export javascript "plus"+  (+) :: Int -> Int -> Int++Just like generating C stub for a JSFFI import, we need to generate C+stub for a JSFFI export as well:++__attribute__((export_name("plus")))+HsJSVal plus(HsInt a1, HsInt a2) { ... }++At link time, you need to pass -optl-Wl,--export=plus,--export=... to+specify your entrypoint function symbols as roots of wasm-ld link-time+garbage collection. As for the auto-generated exports when desugaring+the JSFFI dynamic exports, they will be transitively included as well+due to the export_name attribute.++For each JSFFI static export, we create an internal worker function+which takes the same arguments as the exported Haskell binding, but+always returns (IO JSVal). Its RHS simply applies the arguments to the+original binding, then applies a runIO/runNonIO top handler function+to the result. The top handler creates a JavaScript Promise that+stands for Haskell evaluation result, schedules Haskell computation to+happen, and the Promise will eventually be resolved with the result or+rejected with an exception. That Promise is what we return in the C+stub function. See Note [Async JSFFI scheduler] for detailed+explanation.++There's nothing else to explain about the C stub function body; just+like C FFI exports, it calls rts_mk* to box the arguments, rts_apply+to apply them to the worker function, evaluates the result, then+unboxes the resulting Promise using rts_getJSVal and returns it.++Now, in JavaScript, once the wasm instance is initialized, you can+directly call these exports and await them, as if they're real+JavaScript async functions.++-}++dsWasmJSExport ::+  Id ->+  Coercion ->+  CLabelString ->+  DsM (CHeader, CStub, String, Int, [Id], [Binding])+dsWasmJSExport fn_id co ext_name = do+  work_uniq <- newUnique+  let ty = coercionRKind co+      (tvs, fun_ty) = tcSplitForAllInvisTyVars ty+      (arg_tys, orig_res_ty) = tcSplitFunTys fun_ty+      (res_ty, is_io) = case tcSplitIOType_maybe orig_res_ty of+        Just (_, res_ty) -> (res_ty, True)+        Nothing -> (orig_res_ty, False)+      (_, res_ty_args) = splitTyConApp res_ty+      res_ty_str = ffiType res_ty+  args <- newSysLocalsDs arg_tys+  promiseRes_id <-+    lookupGhcInternalVarId "GHC.Internal.Wasm.Prim.Exports" $ "js_promiseResolve" ++ res_ty_str+  runIO_id <- lookupGhcInternalVarId "GHC.Internal.Wasm.Prim.Exports" "runIO"+  runNonIO_id <- lookupGhcInternalVarId "GHC.Internal.Wasm.Prim.Exports" "runNonIO"+  let work_id =+        mkExportedVanillaId+          ( mkExternalName+              work_uniq+              (nameModule $ getName fn_id)+              (mkVarOcc $ "jsffi_" ++ occNameString (getOccName fn_id))+              generatedSrcSpan+          )+          (exprType work_rhs)+      work_rhs =+        mkCoreLams (tvs ++ args)+          $ mkApps+            (Var $ if is_io then runIO_id else runNonIO_id)+            [ Type res_ty,+              mkApps (Var promiseRes_id) $ map Type res_ty_args,+              mkApps (Cast (Var fn_id) co)+                $ map (Type . mkTyVarTy) tvs+                ++ map Var args+            ]+      work_closure = ppr work_id <> text "_closure"+      work_closure_decl = text "extern StgClosure" <+> work_closure <> semi+      cstub_attr =+        text "__attribute__"+          <> parens+            (parens $ text "export_name" <> parens (doubleQuotes $ ftext ext_name))+      cstub_arg_list =+        [ text ("Hs" ++ ffiType (scaledThing arg_ty)) <+> char 'a' <> int i+          | (i, arg_ty) <- zip [1 ..] arg_tys+        ]+      cstub_args = case cstub_arg_list of+        [] -> text "void"+        _ -> hsep $ punctuate comma cstub_arg_list+      cstub_proto = text "HsJSVal" <+> ftext ext_name <> parens cstub_args+      cstub_body =+        vcat+          [ lbrace,+            text "Capability *cap = rts_lock();",+            text "HaskellObj ret;",+            -- rts_evalLazyIO is fine, the top handler always returns+            -- an evaluated result+            text "rts_evalLazyIO"+              <> parens+                ( hsep+                    $ punctuate+                      comma+                      [ text "&cap",+                        foldl'+                          ( \acc (i, arg_ty) ->+                              text "rts_apply"+                                <> parens+                                  ( hsep+                                      $ punctuate+                                        comma+                                        [ text "cap",+                                          acc,+                                          text ("rts_mk" ++ ffiType (scaledThing arg_ty))+                                            <> parens+                                              (hsep $ punctuate comma [text "cap", char 'a' <> int i])+                                        ]+                                  )+                          )+                          (char '&' <> work_closure)+                          $ zip [1 ..] arg_tys,+                        text "&ret"+                      ]+                )+              <> semi,+            text "rts_checkSchedStatus"+              <> parens (doubleQuotes (ftext ext_name) <> comma <> text "cap")+              <> semi,+            text "rts_unlock(cap);",+            text "return rts_getJSVal(ret);",+            rbrace+          ]+      cstub =+        commonCDecls+          $+$ work_closure_decl+          $+$ cstub_attr+          $+$ cstub_proto+          $+$ cstub_body+  pure+    ( CHeader commonCDecls,+      CStub cstub [] [],+      "",+      -1,+      [work_id],+      [(work_id, work_rhs)]+    )++lookupGhcInternalVarId :: FastString -> String -> DsM Id+lookupGhcInternalVarId m v = do+  n <- lookupOrig (mkGhcInternalModule m) (mkVarOcc v)+  dsLookupGlobalId n++lookupGhcInternalTyCon :: FastString -> String -> DsM TyCon+lookupGhcInternalTyCon m t = do+  n <- lookupOrig (mkGhcInternalModule m) (mkTcOcc t)+  dsLookupTyCon n++ffiType :: Type -> String+ffiType = occNameString . getOccName . fst . splitTyConApp++commonCDecls :: SDoc+commonCDecls =+  vcat+    [ text "typedef __externref_t HsJSVal;",+      text "HsJSVal rts_getJSVal(HaskellObj);",+      text "HaskellObj rts_mkJSVal(Capability*, HsJSVal);"+    ]
compiler/GHC/HsToCore/GuardedRHSs.hs view
@@ -28,7 +28,6 @@ import GHC.Types.SrcLoc import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Core.Multiplicity import Control.Monad ( zipWithM ) import Data.List.NonEmpty ( NonEmpty, toList )@@ -55,7 +54,7 @@  -- In contrast, @dsGRHSs@ produces a @MatchResult CoreExpr@. -dsGRHSs :: HsMatchContext GhcTc+dsGRHSs :: HsMatchContextRn         -> GRHSs GhcTc (LHsExpr GhcTc) -- ^ Guarded RHSs         -> Type                        -- ^ Type of RHS         -> NonEmpty Nablas             -- ^ Refined pattern match checking@@ -76,7 +75,7 @@                              -- NB: nested dsLet inside matchResult        ; return match_result2 } -dsGRHS :: HsMatchContext GhcTc -> Type -> Nablas -> LGRHS GhcTc (LHsExpr GhcTc)+dsGRHS :: HsMatchContextRn -> Type -> Nablas -> LGRHS GhcTc (LHsExpr GhcTc)        -> DsM (MatchResult CoreExpr) dsGRHS hs_ctx rhs_ty rhs_nablas (L _ (GRHS _ guards rhs))   = matchGuards (map unLoc guards) hs_ctx rhs_nablas rhs rhs_ty@@ -90,7 +89,7 @@ -}  matchGuards :: [GuardStmt GhcTc]     -- Guard-            -> HsMatchContext GhcTc  -- Context+            -> HsMatchContextRn      -- Context             -> Nablas                -- The RHS's covered set for PmCheck             -> LHsExpr GhcTc         -- RHS             -> Type                  -- Type of RHS of guard
compiler/GHC/HsToCore/ListComp.hs view
@@ -33,7 +33,6 @@ import GHC.Types.SrcLoc import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Tc.Utils.TcType import GHC.Data.List.SetOps( getNth ) @@ -285,7 +284,7 @@         letrec_body = App (Var h) core_list1      rest_expr <- deListComp quals core_fail-    core_match <- matchSimply (Var u2) (StmtCtxt (HsDoStmt ListComp)) pat rest_expr core_fail+    core_match <- matchSimply (Var u2) (StmtCtxt (HsDoStmt ListComp)) ManyTy pat rest_expr core_fail      let         rhs = Lam u1 $@@ -373,7 +372,7 @@     core_rest <- dfListComp c_id b quals      -- build the pattern match-    core_expr <- matchSimply (Var x) (StmtCtxt (HsDoStmt ListComp))+    core_expr <- matchSimply (Var x) (StmtCtxt (HsDoStmt ListComp)) ManyTy                 pat core_rest (Var b)      -- now build the outermost foldr, and return
compiler/GHC/HsToCore/Match.hs view
@@ -29,14 +29,20 @@  import {-#SOURCE#-} GHC.HsToCore.Expr (dsExpr) -import GHC.Types.Basic ( Origin(..), isGenerated, requiresPMC )+import GHC.Types.Basic ( Origin(..), requiresPMC )+ import GHC.Types.SourceText+    ( FractionalLit,+      IntegralLit(il_value),+      negateFractionalLit,+      integralFractionalLit ) import GHC.Driver.DynFlags import GHC.Hs import GHC.Hs.Syn.Type import GHC.Tc.Types.Evidence import GHC.Tc.Utils.Monad import GHC.HsToCore.Pmc+import GHC.HsToCore.Pmc.Utils import GHC.HsToCore.Pmc.Types ( Nablas ) import GHC.HsToCore.Monad import GHC.HsToCore.Binds@@ -68,7 +74,6 @@ import GHC.Types.Name import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Data.FastString import GHC.Types.Unique import GHC.Types.Unique.DFM@@ -193,13 +198,9 @@  match [] ty eqns   = assertPpr (not (null eqns)) (ppr ty) $-    return (foldr1 combineMatchResults match_results)-  where-    match_results = [ assert (null (eqn_pats eqn)) $-                      eqn_rhs eqn-                    | eqn <- eqns ]+    combineEqnRhss (NEL.fromList eqns) -match (v:vs) ty eqns    -- Eqns *can* be empty+match (v:vs) ty eqns    -- Eqns can be empty, but each equation is nonempty   = assertPpr (all (isInternalName . idName) vars) (ppr vars) $     do  { dflags <- getDynFlags         ; let platform = targetPlatform dflags@@ -222,12 +223,11 @@     dropGroup :: Functor f => f (PatGroup,EquationInfo) -> f EquationInfo     dropGroup = fmap snd -    match_groups :: [NonEmpty (PatGroup,EquationInfo)] -> DsM (NonEmpty (MatchResult CoreExpr))-    -- Result list of [MatchResult CoreExpr] is always non-empty+    match_groups :: [NonEmpty (PatGroup,EquationInfoNE)] -> DsM (NonEmpty (MatchResult CoreExpr))     match_groups [] = matchEmpty v ty     match_groups (g:gs) = mapM match_group $ g :| gs -    match_group :: NonEmpty (PatGroup,EquationInfo) -> DsM (MatchResult CoreExpr)+    match_group :: NonEmpty (PatGroup,EquationInfoNE) -> DsM (MatchResult CoreExpr)     match_group eqns@((group,_) :| _)         = case group of             PgCon {}  -> matchConFamily  vars ty (ne $ subGroupUniq [(c,e) | (PgCon c, e) <- eqns'])@@ -267,20 +267,20 @@     mk_seq fail = return $ mkWildCase (Var var) (idScaledType var) res_ty                                       [Alt DEFAULT [] fail] -matchVariables :: NonEmpty MatchId -> Type -> NonEmpty EquationInfo -> DsM (MatchResult CoreExpr)+matchVariables :: NonEmpty MatchId -> Type -> NonEmpty EquationInfoNE -> DsM (MatchResult CoreExpr) -- Real true variables, just like in matchVar, SLPJ p 94 -- No binding to do: they'll all be wildcards by now (done in tidy) matchVariables (_ :| vars) ty eqns = match vars ty $ NEL.toList $ shiftEqns eqns -matchBangs :: NonEmpty MatchId -> Type -> NonEmpty EquationInfo -> DsM (MatchResult CoreExpr)+matchBangs :: NonEmpty MatchId -> Type -> NonEmpty EquationInfoNE -> DsM (MatchResult CoreExpr) matchBangs (var :| vars) ty eqns   = do  { match_result <- match (var:vars) ty $ NEL.toList $             decomposeFirstPat getBangPat <$> eqns         ; return (mkEvalMatchResult var ty match_result) } -matchCoercion :: NonEmpty MatchId -> Type -> NonEmpty EquationInfo -> DsM (MatchResult CoreExpr)+matchCoercion :: NonEmpty MatchId -> Type -> NonEmpty EquationInfoNE -> DsM (MatchResult CoreExpr) -- Apply the coercion to the match variable and then match that-matchCoercion (var :| vars) ty (eqns@(eqn1 :| _))+matchCoercion (var :| vars) ty eqns@(eqn1 :| _)   = do  { let XPat (CoPat co pat _) = firstPat eqn1         ; let pat_ty' = hsPatType pat         ; var' <- newUniqueId var (idMult var) pat_ty'@@ -290,9 +290,9 @@         { let bind = NonRec var' (core_wrap (Var var))         ; return (mkCoLetMatchResult bind match_result) } } -matchView :: NonEmpty MatchId -> Type -> NonEmpty EquationInfo -> DsM (MatchResult CoreExpr)+matchView :: NonEmpty MatchId -> Type -> NonEmpty EquationInfoNE -> DsM (MatchResult CoreExpr) -- Apply the view function to the match variable and then match that-matchView (var :| vars) ty (eqns@(eqn1 :| _))+matchView (var :| vars) ty eqns@(eqn1 :| _)   = do  { -- we could pass in the expr from the PgView,          -- but this needs to extract the pat anyway          -- to figure out the type of the fresh variable@@ -309,10 +309,9 @@                     match_result) }  -- decompose the first pattern and leave the rest alone-decomposeFirstPat :: (Pat GhcTc -> Pat GhcTc) -> EquationInfo -> EquationInfo-decomposeFirstPat extractpat (eqn@(EqnInfo { eqn_pats = pat : pats }))-        = eqn { eqn_pats = extractpat pat : pats}-decomposeFirstPat _ _ = panic "decomposeFirstPat"+decomposeFirstPat :: (Pat GhcTc -> Pat GhcTc) -> EquationInfoNE -> EquationInfoNE+decomposeFirstPat extract eqn@(EqnMatch { eqn_pat = pat }) = eqn{eqn_pat = fmap extract pat}+decomposeFirstPat _ (EqnDone {}) = panic "decomposeFirstPat"  getCoPat, getBangPat, getViewPat :: Pat GhcTc -> Pat GhcTc getCoPat (XPat (CoPat _ pat _)) = pat@@ -405,15 +404,14 @@         -- POST CONDITION: head pattern in the EqnInfo is         --      one of these for which patGroup is defined. -tidyEqnInfo _ (EqnInfo { eqn_pats = [] })-  = panic "tidyEqnInfo"+tidyEqnInfo _ eqn@(EqnDone {}) = return (idDsWrapper, eqn) -tidyEqnInfo v eqn@(EqnInfo { eqn_pats = pat : pats, eqn_orig = orig })-  = do { (wrap, pat') <- tidy1 v orig pat-       ; return (wrap, eqn { eqn_pats = pat' : pats }) }+tidyEqnInfo v eqn@(EqnMatch { eqn_pat = (L loc pat) }) = do+  (wrap, pat') <- tidy1 v (not . isGoodSrcSpan . locA $ loc) pat+  return (wrap, eqn{eqn_pat = L loc pat' })  tidy1 :: Id                  -- The Id being scrutinised-      -> Origin              -- Was this a pattern the user wrote?+      -> Bool                -- `True` if the pattern was generated, `False` if it was user-written       -> Pat GhcTc           -- The pattern against which it is to be matched       -> DsM (DsWrapper,     -- Extra bindings to do before the match               Pat GhcTc)     -- Equivalent pattern@@ -424,10 +422,10 @@ -- It eliminates many pattern forms (as-patterns, variable patterns, -- list patterns, etc) and returns any created bindings in the wrapper. -tidy1 v o (ParPat _ _ pat _)  = tidy1 v o (unLoc pat)-tidy1 v o (SigPat _ pat _)    = tidy1 v o (unLoc pat)+tidy1 v g (ParPat _ pat)      = tidy1 v g (unLoc pat)+tidy1 v g (SigPat _ pat _)    = tidy1 v g (unLoc pat) tidy1 _ _ (WildPat ty)        = return (idDsWrapper, WildPat ty)-tidy1 v o (BangPat _ (L l p)) = tidy_bang_pat v o l p+tidy1 v g (BangPat _ (L l p)) = tidy_bang_pat v g l p          -- case v of { x -> mr[] }         -- = case v of { _ -> let x=v in mr[] }@@ -436,8 +434,8 @@          -- case v of { x@p -> mr[] }         -- = case v of { p -> let x=v in mr[] }-tidy1 v o (AsPat _ (L _ var) _ pat)-  = do  { (wrap, pat') <- tidy1 v o (unLoc pat)+tidy1 v g (AsPat _ (L _ var) pat)+  = do  { (wrap, pat') <- tidy1 v g (unLoc pat)         ; return (wrapBind var v . wrap, pat') }  {- now, here we handle lazy patterns:@@ -455,13 +453,13 @@     -- This is a convenient place to check for unlifted types under a lazy pattern.     -- Doing this check during type-checking is unsatisfactory because we may     -- not fully know the zonked types yet. We sure do here.-  = do  { let unlifted_bndrs = filter (isUnliftedType . idType) (collectPatBinders CollNoDictBinders pat)+  = putSrcSpanDs (getLocA pat) $+    do  { let unlifted_bndrs = filter (isUnliftedType . idType) (collectPatBinders CollNoDictBinders pat)             -- NB: the binders can't be representation-polymorphic, so we're OK to call isUnliftedType         ; unless (null unlifted_bndrs) $-          putSrcSpanDs (getLocA pat) $           diagnosticDs (DsLazyPatCantBindVarsOfUnliftedType unlifted_bndrs) -        ; (_,sel_prs) <- mkSelectorBinds [] pat (Var v)+        ; (_,sel_prs) <- mkSelectorBinds [] pat LazyPatCtx (Var v)         ; let sel_binds =  [NonRec b rhs | (b,rhs) <- sel_prs]         ; return (mkCoreLets sel_binds, WildPat (idType v)) } @@ -489,22 +487,22 @@                  -- See Note [Unboxed tuple RuntimeRep vars] in TyCon  -- LitPats: we *might* be able to replace these w/ a simpler form-tidy1 _ o (LitPat _ lit)-  = do { unless (isGenerated o) $+tidy1 _ g (LitPat _ lit)+  = do { unless g $            warnAboutOverflowedLit lit        ; return (idDsWrapper, tidyLitPat lit) }  -- NPats: we *might* be able to replace these w/ a simpler form-tidy1 _ o (NPat ty (L _ lit@OverLit { ol_val = v }) mb_neg eq)-  = do { unless (isGenerated o) $+tidy1 _ g (NPat ty (L _ lit@OverLit { ol_val = v }) mb_neg eq)+  = do { unless g $            let lit' | Just _ <- mb_neg = lit{ ol_val = negateOverLitVal v }                     | otherwise = lit            in warnAboutOverflowedOverLit lit'        ; return (idDsWrapper, tidyNPat lit mb_neg eq ty) }  -- NPlusKPat: we may want to warn about the literals-tidy1 _ o n@(NPlusKPat _ _ (L _ lit1) lit2 _ _)-  = do { unless (isGenerated o) $ do+tidy1 _ g n@(NPlusKPat _ _ (L _ lit1) lit2 _ _)+  = do { unless g $ do            warnAboutOverflowedOverLit lit1            warnAboutOverflowedOverLit lit2        ; return (idDsWrapper, n) }@@ -514,28 +512,28 @@   = return (idDsWrapper, non_interesting_pat)  ---------------------tidy_bang_pat :: Id -> Origin -> SrcSpanAnnA -> Pat GhcTc+tidy_bang_pat :: Id -> Bool -> SrcSpanAnnA -> Pat GhcTc               -> DsM (DsWrapper, Pat GhcTc)  -- Discard par/sig under a bang-tidy_bang_pat v o _ (ParPat _ _ (L l p) _) = tidy_bang_pat v o l p-tidy_bang_pat v o _ (SigPat _ (L l p) _) = tidy_bang_pat v o l p+tidy_bang_pat v g _ (ParPat _ (L l p))   = tidy_bang_pat v g l p+tidy_bang_pat v g _ (SigPat _ (L l p) _) = tidy_bang_pat v g l p  -- Push the bang-pattern inwards, in the hope that -- it may disappear next time-tidy_bang_pat v o l (AsPat x v' at p)-  = tidy1 v o (AsPat x v' at (L l (BangPat noExtField p)))-tidy_bang_pat v o l (XPat (CoPat w p t))-  = tidy1 v o (XPat $ CoPat w (BangPat noExtField (L l p)) t)+tidy_bang_pat v g l (AsPat x v' p)+  = tidy1 v g (AsPat x v' (L l (BangPat noExtField p)))+tidy_bang_pat v g l (XPat (CoPat w p t))+  = tidy1 v g (XPat $ CoPat w (BangPat noExtField (L l p)) t)  -- Discard bang around strict pattern-tidy_bang_pat v o _ p@(LitPat {})    = tidy1 v o p-tidy_bang_pat v o _ p@(ListPat {})   = tidy1 v o p-tidy_bang_pat v o _ p@(TuplePat {})  = tidy1 v o p-tidy_bang_pat v o _ p@(SumPat {})    = tidy1 v o p+tidy_bang_pat v g _ p@(LitPat {})    = tidy1 v g p+tidy_bang_pat v g _ p@(ListPat {})   = tidy1 v g p+tidy_bang_pat v g _ p@(TuplePat {})  = tidy1 v g p+tidy_bang_pat v g _ p@(SumPat {})    = tidy1 v g p  -- Data/newtype constructors-tidy_bang_pat v o l p@(ConPat { pat_con = L _ (RealDataCon dc)+tidy_bang_pat v g l p@(ConPat { pat_con = L _ (RealDataCon dc)                               , pat_args = args                               , pat_con_ext = ConPatTc                                 { cpt_arg_tys = arg_tys@@ -544,8 +542,8 @@   -- Newtypes: push bang inwards (#9844)   =     if isNewTyCon (dataConTyCon dc)-      then tidy1 v o (p { pat_args = push_bang_into_newtype_arg l (scaledThing ty) args })-      else tidy1 v o p  -- Data types: discard the bang+      then tidy1 v g (p { pat_args = push_bang_into_newtype_arg l (scaledThing ty) args })+      else tidy1 v g p  -- Data types: discard the bang     where       (ty:_) = dataConInstArgTys dc arg_tys @@ -737,7 +735,7 @@ --                         p2 q2 -> ...  matchWrapper-  :: HsMatchContext GhcTc              -- ^ For shadowing warning messages+  :: HsMatchContextRn                  -- ^ For shadowing warning messages   -> Maybe [LHsExpr GhcTc]             -- ^ Scrutinee(s)                                        -- see Note [matchWrapper scrutinees]   -> MatchGroup GhcTc (LHsExpr GhcTc)  -- ^ Matches being desugared@@ -772,7 +770,6 @@                            })   = do  { dflags <- getDynFlags         ; locn   <- getSrcSpanDs-         ; new_vars    <- case matches of                            []    -> newSysLocalsDs arg_tys                            (m:_) ->@@ -784,12 +781,19 @@         -- Pattern match check warnings for /this match-group/.         -- @rhss_nablas@ is a flat list of covered Nablas for each RHS.         -- Each Match will split off one Nablas for its RHSs from this.+        ; tracePm "matchWrapper"+          (vcat [ ppr ctxt+                , text "scrs" <+> ppr scrs+                , text "matches group" <+> ppr matches+                , text "matchPmChecked" <+> ppr (isMatchContextPmChecked dflags origin ctxt)])         ; matches_nablas <-             if isMatchContextPmChecked dflags origin ctxt+               -- See Note [Expanding HsDo with XXExprGhcRn] Part 1. Wrinkle 1 for+               -- pmc for pattern synonyms              -- See Note [Long-distance information] in GHC.HsToCore.Pmc             then addHsScrutTmCs (concat scrs) new_vars $-                 pmcMatches (DsMatchContext ctxt locn) new_vars matches+                 pmcMatches origin (DsMatchContext ctxt locn) new_vars matches              -- When we're not doing PM checks on the match group,             -- we still need to propagate long-distance information.@@ -808,16 +812,14 @@     mk_eqn_info :: LMatch GhcTc (LHsExpr GhcTc) -> (Nablas, NonEmpty Nablas) -> DsM EquationInfo     mk_eqn_info (L _ (Match { m_pats = pats, m_grhss = grhss })) (pat_nablas, rhss_nablas)       = do { dflags <- getDynFlags-           ; let upats = map (unLoc . decideBangHood dflags) pats+           ; let upats = map (decideBangHood dflags) pats            -- pat_nablas is the covered set *after* matching the pattern, but            -- before any of the GRHSs. We extend the environment with pat_nablas            -- (via updPmNablas) so that the where-clause of 'grhss' can profit            -- from that knowledge (#18533)            ; match_result <- updPmNablas pat_nablas $                              dsGRHSs ctxt grhss rhs_ty rhss_nablas-           ; return EqnInfo { eqn_pats = upats-                            , eqn_orig = FromSource-                            , eqn_rhs  = match_result } }+           ; return $ mkEqnInfo upats match_result }      discard_warnings_if_skip_pmc orig =       if requiresPMC orig@@ -881,7 +883,7 @@ on the user-written case statement). -} -matchEquations  :: HsMatchContext GhcTc+matchEquations  :: HsMatchContextRn                 -> [MatchId] -> [EquationInfo] -> Type                 -> DsM CoreExpr matchEquations ctxt vars eqns_info rhs_ty@@ -895,7 +897,8 @@ -- situation where we want to match a single expression against a single -- pattern. It returns an expression. matchSimply :: CoreExpr                 -- ^ Scrutinee-            -> HsMatchContext GhcTc     -- ^ Match kind+            -> HsMatchContextRn         -- ^ Match kind+            -> Mult                     -- ^ Scaling factor of the case expression             -> LPat GhcTc               -- ^ Pattern it should match             -> CoreExpr                 -- ^ Return this if it matches             -> CoreExpr                 -- ^ Return this if it doesn't@@ -909,15 +912,15 @@ --     match is awkward --   * And we still export 'matchSinglePatVar', so not much is gained if we --     don't also implement it in terms of 'matchWrapper'-matchSimply scrut hs_ctx pat result_expr fail_expr = do+matchSimply scrut hs_ctx mult pat result_expr fail_expr = do     let       match_result = cantFailMatchResult result_expr       rhs_ty       = exprType fail_expr         -- Use exprType of fail_expr, because won't refine in the case of failure!-    match_result' <- matchSinglePat scrut hs_ctx pat rhs_ty match_result+    match_result' <- matchSinglePat scrut hs_ctx pat mult rhs_ty match_result     extractMatchResult match_result' fail_expr -matchSinglePat :: CoreExpr -> HsMatchContext GhcTc -> LPat GhcTc+matchSinglePat :: CoreExpr -> HsMatchContextRn -> LPat GhcTc -> Mult                -> Type -> MatchResult CoreExpr -> DsM (MatchResult CoreExpr) -- matchSinglePat ensures that the scrutinee is a variable -- and then calls matchSinglePatVar@@ -926,24 +929,19 @@ -- Used for things like [ e | pat <- stuff ], where -- incomplete patterns are just fine -matchSinglePat (Var var) ctx pat ty match_result+matchSinglePat (Var var) ctx pat _ ty match_result   | not (isExternalName (idName var))   = matchSinglePatVar var Nothing ctx pat ty match_result -matchSinglePat scrut hs_ctx pat ty match_result-  = do { var           <- selectSimpleMatchVarL ManyTy pat-                            -- matchSinglePat is only used in matchSimply, which-                            -- is used in list comprehension, arrow notation,-                            -- and to create field selectors. All of which only-                            -- bind unrestricted variables, hence the 'Many'-                            -- above.+matchSinglePat scrut hs_ctx pat mult ty match_result+  = do { var           <- selectSimpleMatchVarL mult pat        ; match_result' <- matchSinglePatVar var (Just scrut) hs_ctx pat ty match_result        ; return $ bindNonRec var scrut <$> match_result'        }  matchSinglePatVar :: Id   -- See Note [Match Ids]                   -> Maybe CoreExpr -- ^ The scrutinee the match id is bound to-                  -> HsMatchContext GhcTc -> LPat GhcTc+                  -> HsMatchContextRn -> LPat GhcTc                   -> Type -> MatchResult CoreExpr -> DsM (MatchResult CoreExpr) matchSinglePatVar var mb_scrut ctx pat ty match_result   = assertPpr (isInternalName (idName var)) (ppr var) $@@ -958,10 +956,9 @@               pmcPatBind (DsMatchContext ctx locn) var (unLoc pat)          else getLdiNablas -       ; let eqn_info = EqnInfo { eqn_pats = [unLoc (decideBangHood dflags pat)]-                                , eqn_orig = FromSource-                                , eqn_rhs  =-               updPmNablasMatchResult ldi_nablas match_result }+       ; let eqn_info = EqnMatch { eqn_pat = decideBangHood dflags pat+                                 , eqn_rest =+          EqnDone $ updPmNablasMatchResult ldi_nablas match_result }                -- See Note [Long-distance information in do notation]                -- in GHC.HsToCore.Expr. @@ -999,6 +996,13 @@                         -- the LHsExpr is the expression e            Type         -- the Type is the type of p (equivalently, the result type of e) +instance Show PatGroup where+  show PgAny = "PgAny"+  show (PgCon _) = "PgCon"+  show (PgLit _) = "PgLit"+  show (PgView _ _) = "PgView"+  show _ = "PgOther"+ {- Note [Don't use Literal for PgN] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Previously we had, as PatGroup constructors@@ -1019,7 +1023,7 @@ for overloaded strings. -} -groupEquations :: Platform -> [EquationInfo] -> [NonEmpty (PatGroup, EquationInfo)]+groupEquations :: Platform -> [EquationInfoNE] -> [NonEmpty (PatGroup, EquationInfoNE)] -- If the result is of form [g1, g2, g3], -- (a) all the (pg,eq) pairs in g1 have the same pg -- (b) none of the gi are empty@@ -1139,14 +1143,16 @@     exp :: HsExpr GhcTc -> HsExpr GhcTc -> Bool     -- real comparison is on HsExpr's     -- strip parens-    exp (HsPar _ _ (L _ e) _) e' = exp e e'-    exp e (HsPar _ _ (L _ e') _) = exp e e'+    exp (HsPar _ (L _ e)) e' = exp e e'+    exp e (HsPar _ (L _ e')) = exp e e'     -- because the expressions do not necessarily have the same type,     -- we have to compare the wrappers     exp (XExpr (WrapExpr (HsWrap h e))) (XExpr (WrapExpr (HsWrap  h' e'))) =       wrap h h' && exp e e'-    exp (XExpr (ExpansionExpr (HsExpanded _ b))) (XExpr (ExpansionExpr (HsExpanded _ b'))) =-      exp b b'+    exp (XExpr (ExpandedThingTc o x)) (XExpr (ExpandedThingTc o' x'))+      | isHsThingRnExpr o+      , isHsThingRnExpr o'+      = exp x x'     exp (HsVar _ i) (HsVar _ i') =  i == i'     exp (XExpr (ConLikeTc c _ _)) (XExpr (ConLikeTc c' _ _)) = c == c'     -- the instance for IPName derives using the id, so this works if the@@ -1163,8 +1169,8 @@     exp (HsApp _ e1 e2) (HsApp _ e1' e2') = lexp e1 e1' && lexp e2 e2'     -- the fixities have been straightened out by now, so it's safe     -- to ignore them?-    exp (OpApp _ l o ri) (OpApp _ l' o' ri') =-        lexp l l' && lexp o o' && lexp ri ri'+    exp (OpApp _ l g ri) (OpApp _ l' o' ri') =+        lexp l l' && lexp g o' && lexp ri ri'     exp (NegApp _ e n) (NegApp _ e' n') = lexp e e' && syn_exp n n'     exp (SectionL _ e1 e2) (SectionL _ e1' e2') =         lexp e1 e1' && lexp e2 e2'@@ -1265,6 +1271,7 @@    _ -> pprPanic "patGroup NPlusKPat" (ppr oval) patGroup _ (ViewPat _ expr p)           = PgView expr (hsPatType (unLoc p)) patGroup platform (LitPat _ lit)        = PgLit (hsLitKey platform lit)+patGroup _ EmbTyPat{} = PgAny patGroup platform (XPat ext) = case ext of   CoPat _ p _      -> PgCo (hsPatType p) -- Type of innelexp pattern   ExpansionPat _ p -> patGroup platform p
compiler/GHC/HsToCore/Match.hs-boot view
@@ -5,7 +5,8 @@ import GHC.Tc.Utils.TcType  ( Type ) import GHC.HsToCore.Monad ( DsM, EquationInfo, MatchResult ) import GHC.Core ( CoreExpr )-import GHC.Hs   ( LPat, HsMatchContext, MatchGroup, LHsExpr )+import GHC.Hs   ( LPat, MatchGroup, LHsExpr, Mult )+import GHC.Hs.Expr ( HsMatchContextRn ) import GHC.Hs.Extension ( GhcTc )  match   :: [Id]@@ -14,14 +15,15 @@         -> DsM (MatchResult CoreExpr)  matchWrapper-        :: HsMatchContext GhcTc+        :: HsMatchContextRn         -> Maybe [LHsExpr GhcTc]         -> MatchGroup GhcTc (LHsExpr GhcTc)         -> DsM ([Id], CoreExpr)  matchSimply         :: CoreExpr-        -> HsMatchContext GhcTc+        -> HsMatchContextRn+        -> Mult         -> LPat GhcTc         -> CoreExpr         -> CoreExpr@@ -30,7 +32,7 @@ matchSinglePatVar         :: Id         -> Maybe CoreExpr-        -> HsMatchContext GhcTc+        -> HsMatchContextRn         -> LPat GhcTc         -> Type         -> MatchResult CoreExpr
compiler/GHC/HsToCore/Match/Constructor.hs view
@@ -2,6 +2,7 @@ {-# LANGUAGE TypeFamilies #-}  {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}+{-# OPTIONS_GHC -Wno-unrecognised-warning-flags -Wno-x-data-list-nonempty-unzip #-}  {- (c) The University of Glasgow 2006@@ -20,7 +21,6 @@ import GHC.Hs import GHC.HsToCore.Binds import GHC.Core.ConLike-import GHC.Types.Basic import GHC.Tc.Utils.TcType import GHC.Core.Multiplicity import GHC.HsToCore.Monad@@ -34,7 +34,6 @@ import GHC.Types.SrcLoc import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import Control.Monad(liftM) import Data.List.NonEmpty (NonEmpty(..)) import qualified Data.List.NonEmpty as NE@@ -94,7 +93,7 @@  matchConFamily :: NonEmpty Id                -> Type-               -> NonEmpty (NonEmpty EquationInfo)+               -> NonEmpty (NonEmpty EquationInfoNE)                -> DsM (MatchResult CoreExpr) -- Each group of eqns is for a single constructor matchConFamily (var :| vars) ty groups@@ -113,7 +112,7 @@  matchPatSyn :: NonEmpty Id             -> Type-            -> NonEmpty EquationInfo+            -> NonEmpty EquationInfoNE             -> DsM (MatchResult CoreExpr) matchPatSyn (var :| vars) ty eqns   = do let mult = idMult var@@ -129,7 +128,7 @@ matchOneConLike :: [Id]                 -> Type                 -> Mult-                -> NonEmpty EquationInfo+                -> NonEmpty EquationInfoNE                 -> DsM (CaseAlt ConLike) matchOneConLike vars ty mult (eqn1 :| eqns)   -- All eqns for a single constructor   = do  { let inst_tys = assert (all tcIsTcTyVar ex_tvs) $@@ -143,7 +142,7 @@         -- and returns the types of the *value* args, which is what we want                match_group :: [Id]-                          -> NonEmpty (ConArgPats, EquationInfo)+                          -> NonEmpty (ConArgPats, EquationInfoNE)                           -> DsM (MatchResult CoreExpr)               -- All members of the group have compatible ConArgPats               match_group arg_vars arg_eqn_prs@@ -153,24 +152,21 @@                      ; return $ foldr1 (.) wraps <$> match_result                      } -              shift (_, eqn@(EqnInfo-                             { eqn_pats = ConPat-                               { pat_args = args-                               , pat_con_ext = ConPatTc-                                 { cpt_tvs = tvs-                                 , cpt_dicts = ds-                                 , cpt_binds = bind-                                 }-                               } : pats-                             }))+              shift (_, EqnMatch {+                      eqn_pat = L _ (ConPat+                                    { pat_args = args+                                    , pat_con_ext = ConPatTc+                                      { cpt_tvs = tvs+                                      , cpt_dicts = ds+                                      , cpt_binds = bind }})+                    , eqn_rest = rest })                 = do dsTcEvBinds bind $ \ds_bind ->                        return ( wrapBinds (tvs `zip` tvs1)                               . wrapBinds (ds  `zip` dicts1)                               . mkCoreLets ds_bind-                              , eqn { eqn_orig = Generated SkipPmc-                                    , eqn_pats = conArgPats val_arg_tys args ++ pats }+                              , prependPats (conArgPats val_arg_tys args) rest                               )-              shift (_, (EqnInfo { eqn_pats = ps })) = pprPanic "matchOneCon/shift" (ppr ps)+              shift (_, eqn) = pprPanic "matchOneCon/shift" (ppr eqn)         ; let scaled_arg_tys = map (scaleScaled mult) val_arg_tys             -- The 'val_arg_tys' are taken from the data type definition, they             -- do not take into account the context multiplicity, therefore we@@ -184,7 +180,7 @@                 -- suggestions for the new variables          -- Divide into sub-groups; see Note [Record patterns]-        ; let groups :: NonEmpty (NonEmpty (ConArgPats, EquationInfo))+        ; let groups :: NonEmpty (NonEmpty (ConArgPats, EquationInfoNE))               groups = NE.groupBy1 compatible_pats                      $ fmap (\eqn -> (pat_args (firstPat eqn), eqn)) (eqn1 :| eqns) @@ -256,14 +252,14 @@                           -- Used only to fill in the types of WildPats, which                           -- are probably never looked at anyway            -> ConArgPats-           -> [Pat GhcTc]-conArgPats _arg_tys (PrefixCon _ ps) = map unLoc ps-conArgPats _arg_tys (InfixCon p1 p2) = [unLoc p1, unLoc p2]+           -> [LPat GhcTc]+conArgPats _arg_tys (PrefixCon _ ps) = ps+conArgPats _arg_tys (InfixCon p1 p2) = [p1, p2] conArgPats  arg_tys (RecCon (HsRecFields { rec_flds = rpats }))-  | null rpats = map WildPat (map scaledThing arg_tys)+  | null rpats = map (noLocA . WildPat . scaledThing) arg_tys         -- Important special case for C {}, which can be used for a         -- datacon that isn't declared to have fields at all-  | otherwise  = map (unLoc . hfbRHS . unLoc) rpats+  | otherwise  = map (hfbRHS . unLoc) rpats  {- Note [Record patterns]
compiler/GHC/HsToCore/Match/Literal.hs view
@@ -63,7 +63,6 @@ import GHC.Utils.Outputable as Outputable import GHC.Utils.Misc import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Unique (sameUnique)  import GHC.Data.FastString@@ -438,7 +437,7 @@ -- ^ See if the expression is an 'Integral' literal. getLHsIntegralLit (L _ e) = go e   where-    go (HsPar _ _ e _)        = getLHsIntegralLit e+    go (HsPar _ e)            = getLHsIntegralLit e     go (HsOverLit _ over_lit) = getIntegralLit over_lit     go (HsLit _ lit)          = getSimpleIntegralLit lit @@ -482,7 +481,7 @@  -- | Extract the Char if the expression is a Char literal. getLHsCharLit :: LHsExpr GhcTc -> Maybe Char-getLHsCharLit (L _ (HsPar _ _ e _))        = getLHsCharLit e+getLHsCharLit (L _ (HsPar _ e))            = getLHsCharLit e getLHsCharLit (L _ (HsLit _ (HsChar _ c))) = Just c getLHsCharLit (L _ (XExpr (HsTick _ e)))         = getLHsCharLit e getLHsCharLit (L _ (XExpr (HsBinTick _ _ e)))    = getLHsCharLit e@@ -607,7 +606,7 @@  matchLiterals :: NonEmpty Id               -> Type -- ^ Type of the whole case expression-              -> NonEmpty (NonEmpty EquationInfo) -- ^ All PgLits+              -> NonEmpty (NonEmpty EquationInfoNE) -- ^ All PgLits               -> DsM (MatchResult CoreExpr)  matchLiterals (var :| vars) ty sub_groups@@ -625,11 +624,11 @@             return (mkCoPrimCaseMatchResult var ty $ NEL.toList alts)         }   where-    match_group :: NonEmpty EquationInfo -> DsM (Literal, MatchResult CoreExpr)-    match_group eqns@(firstEqn :| _)+    match_group :: NonEmpty EquationInfoNE -> DsM (Literal, MatchResult CoreExpr)+    match_group eqns         = do { dflags <- getDynFlags              ; let platform = targetPlatform dflags-             ; let LitPat _ hs_lit = firstPat firstEqn+             ; let EqnMatch { eqn_pat = L _ (LitPat _ hs_lit) } = NEL.head eqns              ; match_result <- match vars ty (NEL.toList $ shiftEqns eqns)              ; return (hsLitKey platform hs_lit, match_result) } @@ -682,7 +681,7 @@ ************************************************************************ -} -matchNPats :: NonEmpty Id -> Type -> NonEmpty EquationInfo -> DsM (MatchResult CoreExpr)+matchNPats :: NonEmpty Id -> Type -> NonEmpty EquationInfoNE -> DsM (MatchResult CoreExpr) matchNPats (var :| vars) ty (eqn1 :| eqns)    -- All for the same literal   = do  { let NPat _ (L _ lit) mb_neg eq_chk = firstPat eqn1         ; lit_expr <- dsOverLit lit@@ -711,7 +710,7 @@ \end{verbatim} -} -matchNPlusKPats :: NonEmpty Id -> Type -> NonEmpty EquationInfo -> DsM (MatchResult CoreExpr)+matchNPlusKPats :: NonEmpty Id -> Type -> NonEmpty EquationInfoNE -> DsM (MatchResult CoreExpr) -- All NPlusKPats, for the *same* literal k matchNPlusKPats (var :| vars) ty (eqn1 :| eqns)   = do  { let NPlusKPat _ (L _ n1) (L _ lit1) lit2 ge minus@@ -727,7 +726,7 @@                    fmap (foldr1 (.) wraps)                      $                    match_result) }   where-    shift n1 eqn@(EqnInfo { eqn_pats = NPlusKPat _ (L _ n) _ _ _ _ : pats })-        = (wrapBind n n1, eqn { eqn_pats = pats })+    shift n1 (EqnMatch { eqn_pat = L _ (NPlusKPat _ (L _ n) _ _ _ _), eqn_rest = rest })+        = (wrapBind n n1, rest)         -- The wrapBind is a no-op for the first equation     shift _ e = pprPanic "matchNPlusKPats/shift" (ppr e)
compiler/GHC/HsToCore/Monad.hs view
@@ -45,10 +45,12 @@         -- Warnings and errors         DsWarning, diagnosticDs, errDsCoreExpr,         failWithDs, failDs, discardWarningsDs,+        addMessagesDs, captureMessagesDs,          -- Data types         DsMatchContext(..),-        EquationInfo(..), MatchResult (..), runMatchResult, DsWrapper, idDsWrapper,+        EquationInfo(..), EquationInfoNE, prependPats, mkEqnInfo, eqnMatchResult,+        MatchResult (..), runMatchResult, DsWrapper, idDsWrapper,          -- Trace injection         pprRuntimeTrace@@ -91,7 +93,6 @@ import GHC.Unit.Module.ModGuts  import GHC.Types.Name.Reader-import GHC.Types.Basic ( Origin ) import GHC.Types.SourceFile import GHC.Types.Id import GHC.Types.Var (EvId)@@ -124,34 +125,49 @@ -}  data DsMatchContext-  = DsMatchContext (HsMatchContext GhcTc) SrcSpan+  = DsMatchContext HsMatchContextRn SrcSpan   deriving ()  instance Outputable DsMatchContext where   ppr (DsMatchContext hs_match ss) = ppr ss <+> pprMatchContext hs_match  data EquationInfo-  = EqnInfo { eqn_pats :: [Pat GhcTc]-              -- ^ The patterns for an equation-              ---              -- NB: We have /already/ applied 'decideBangHood' to-              -- these patterns.  See Note [decideBangHood] in "GHC.HsToCore.Utils"+  = EqnMatch  { eqn_pat :: LPat GhcTc+                -- ^ The first pattern of the equation+                --+                -- NB: The location info is used to determine whether the+                -- pattern is generated or not.+                -- This helps us avoid warnings on patterns that GHC elaborated.+                --+                -- NB: We have /already/ applied 'decideBangHood' to this+                -- pattern. See Note [decideBangHood] in "GHC.HsToCore.Utils" -            , eqn_orig :: Origin-              -- ^ Was this equation present in the user source?-              ---              -- This helps us avoid warnings on patterns that GHC elaborated.-              ---              -- For instance, the pattern @-1 :: Word@ gets desugared into-              -- @W# -1## :: Word@, but we shouldn't warn about an overflowed-              -- literal for /both/ of these cases.+              , eqn_rest :: EquationInfo }+                -- ^ The rest of the equation after its first pattern -            , eqn_rhs  :: MatchResult CoreExpr-              -- ^ What to do after match-            }+  | EqnDone+  -- The empty tail of an equation having no more patterns+            (MatchResult CoreExpr)+            -- ^ What to do after match +type EquationInfoNE = EquationInfo+-- An EquationInfo which has at least one pattern++prependPats :: [LPat GhcTc] -> EquationInfo -> EquationInfo+prependPats [] eqn = eqn+prependPats (pat:pats) eqn = EqnMatch { eqn_pat = pat, eqn_rest = prependPats pats eqn }++mkEqnInfo :: [LPat GhcTc] -> MatchResult CoreExpr -> EquationInfo+mkEqnInfo pats = prependPats pats . EqnDone++eqnMatchResult :: EquationInfo -> MatchResult CoreExpr+eqnMatchResult (EqnDone rhs) = rhs+eqnMatchResult (EqnMatch { eqn_rest = eq }) = eqnMatchResult eq+ instance Outputable EquationInfo where-    ppr (EqnInfo pats _ _) = ppr pats+    ppr = ppr . allEqnPats where+      allEqnPats (EqnDone {}) = []+      allEqnPats (EqnMatch { eqn_pat = pat, eqn_rest = eq }) = unLoc pat : allEqnPats eq  type DsWrapper = CoreExpr -> CoreExpr idDsWrapper :: DsWrapper@@ -429,7 +445,7 @@ putSrcSpanDs (RealSrcSpan real_span _) thing_inside   = updLclEnv (\ env -> env {dsl_loc = real_span}) thing_inside -putSrcSpanDsA :: SrcSpanAnn' ann -> DsM a -> DsM a+putSrcSpanDsA :: EpAnn ann -> DsM a -> DsM a putSrcSpanDsA loc = putSrcSpanDs (locA loc)  -- | Emit a diagnostic for the current source location. In case the diagnostic is a warning,@@ -443,6 +459,12 @@        ; let msg = mkMsgEnvelope diag_opts loc (ds_name_ppr_ctx env) dsMessage        ; updMutVar (ds_msgs env) (\ msgs -> msg `addMessage` msgs) } +addMessagesDs :: Messages DsMessage -> DsM ()+addMessagesDs msgs1+  = do { msg_var <- ds_msgs <$> getGblEnv+       ; msgs0 <- liftIO $ readIORef msg_var+       ; liftIO $ writeIORef msg_var (msgs0 `unionMessages` msgs1) }+ -- | Issue an error, but return the expression for (), so that we can continue -- reporting errors. errDsCoreExpr :: DsMessage -> DsM CoreExpr@@ -457,6 +479,13 @@  failDs :: DsM a failDs = failM++captureMessagesDs :: DsM a -> DsM (Messages DsMessage, a)+captureMessagesDs thing_inside+  = do { msg_var <- liftIO $ newIORef emptyMessages+       ; res <- updGblEnv (\gbl -> gbl {ds_msgs = msg_var}) thing_inside+       ; msgs <- liftIO $ readIORef msg_var+       ; return (msgs, res) }  mkNamePprCtxDs :: DsM NamePprCtx mkNamePprCtxDs = ds_name_ppr_ctx <$> getGblEnv
compiler/GHC/HsToCore/Pmc.hs view
@@ -35,11 +35,12 @@ --     'ldiMatch'. See Section 4.1 of the paper. module GHC.HsToCore.Pmc (         -- Checking and printing-        pmcPatBind, pmcMatches, pmcGRHSs,+        pmcPatBind, pmcMatches, pmcGRHSs, pmcRecSel,         isMatchContextPmChecked, isMatchContextPmChecked_SinglePat,          -- See Note [Long-distance information]-        addTyCs, addCoreScrutTmCs, addHsScrutTmCs, getLdiNablas+        addTyCs, addCoreScrutTmCs, addHsScrutTmCs, getLdiNablas,+        getNFirstUncovered     ) where  import GHC.Prelude@@ -50,8 +51,8 @@ import GHC.HsToCore.Pmc.Desugar import GHC.HsToCore.Pmc.Check import GHC.HsToCore.Pmc.Solver-import GHC.Types.Basic (Origin(..))-import GHC.Core (CoreExpr)+import GHC.Types.Basic (Origin(..), isDoExpansionGenerated)+import GHC.Core import GHC.Driver.DynFlags import GHC.Hs import GHC.Types.Id@@ -59,21 +60,20 @@ import GHC.Utils.Misc import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Types.Var (EvVar)+import GHC.Types.Var (EvVar, Var (..))+import GHC.Types.Id.Info import GHC.Tc.Utils.TcType (evVarPred)-import GHC.Tc.Utils.Monad (updTopFlags) import {-# SOURCE #-} GHC.HsToCore.Expr (dsLExpr) import GHC.HsToCore.Monad import GHC.Data.Bag-import GHC.Data.IOEnv (unsafeInterleaveM) import GHC.Data.OrdList-import GHC.Utils.Monad (mapMaybeM) -import Control.Monad (when, forM_)+import Control.Monad (when, unless, forM_) import qualified Data.Semigroup as Semi import Data.List.NonEmpty ( NonEmpty(..) ) import qualified Data.List.NonEmpty as NE import Data.Coerce+import GHC.Tc.Utils.Monad  -- -- * Exported entry points to the checker@@ -118,6 +118,7 @@         then id         else discardWarningsDs     want_pmc PatBindRhs = True+    want_pmc LazyPatCtx = True     want_pmc (StmtCtxt stmt_ctxt) =       case stmt_ctxt of         PatGuard {} -> False@@ -127,7 +128,7 @@ -- | Exhaustive for guard matches, is used for guards in pattern bindings and -- in @MultiIf@ expressions. Returns the 'Nablas' covered by the RHSs. pmcGRHSs-  :: HsMatchContext GhcTc         -- ^ Match context, for warning messages+  :: HsMatchContextRn             -- ^ Match context, for warning messages   -> GRHSs GhcTc (LHsExpr GhcTc)  -- ^ The GRHSs to check   -> DsM (NonEmpty Nablas)        -- ^ Covered 'Nablas' for each RHS, for long                                   --   distance info@@ -161,20 +162,21 @@ -- checks an @-XEmptyCase@ with only a single match variable. -- See Note [Checking EmptyCase]. pmcMatches-  :: DsMatchContext                  -- ^ Match context, for warnings messages+  :: Origin+  -> DsMatchContext                  -- ^ Match context, for warnings messages   -> [Id]                            -- ^ Match variables, i.e. x and y above   -> [LMatch GhcTc (LHsExpr GhcTc)]  -- ^ List of matches   -> DsM [(Nablas, NonEmpty Nablas)] -- ^ One covered 'Nablas' per Match and                                      --   GRHS, for long distance info.-pmcMatches ctxt vars matches = {-# SCC "pmcMatches" #-} do+pmcMatches origin ctxt vars matches = {-# SCC "pmcMatches" #-} do   -- We have to force @missing@ before printing out the trace message,   -- otherwise we get interleaved output from the solver. This function   -- should be strict in @missing@ anyway!   !missing <- getLdiNablas   tracePm "pmcMatches {" $-          hang (vcat [ppr ctxt, ppr vars, text "Matches:"])+          hang (vcat [ppr origin, ppr ctxt, ppr vars, text "Matches:"])                2-               (vcat (map ppr matches) $$ ppr missing)+               ((ppr matches) $$ (text "missing:" <+> ppr missing))   case NE.nonEmpty matches of     Nothing -> do       -- This must be an -XEmptyCase. See Note [Checking EmptyCase]@@ -190,8 +192,92 @@       result  <- {-# SCC "checkMatchGroup" #-}                  unCA (checkMatchGroup matches) missing       tracePm "}: " (ppr (cr_uncov result))-      {-# SCC "formatReportWarnings" #-} formatReportWarnings ReportMatchGroup ctxt vars result+      unless (isDoExpansionGenerated origin) -- Do expansion generated code shouldn't emit overlapping warnings+        ({-# SCC "formatReportWarnings" #-}+        formatReportWarnings ReportMatchGroup ctxt vars result)       return (NE.toList (ldiMatchGroup (cr_ret result)))++{-+Note [Detecting incomplete record selectors]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+A record selector occurrence is incomplete iff. it could fail due to+being applied to a data type constructor not present for this record field.++e.g.+  data T = T1 | T2 {x :: Int}+  d = x someComputation -- `d` may fail++There are 4 parts to detecting and warning about+incomplete record selectors to consider:++  - Computing which constructors a general application of a record field will succeed on,+    and which ones it will fail on. This is stored in the `sel_cons` field of+    `IdDetails` datatype, which is a part of an `Id` and calculated when renaming a+    record selector in `mkOneRecordSelector`++  - Emitting a warning whenever a `HasField` constraint is solved.+    This is checked in `matchHasField` and emitted only for when+    the constraint is resolved with an implicit instance rather than a+    custom one (since otherwise the warning will be emitted in+      the custom implementation anyways)++    e.g.+      g :: HasField "x" t Int => t -> Int+      g = getField @"x"++      f :: T -> Int+      f = g -- warning will be emitted here++  - Emitting a warning for a general occurrence of the record selector+    This is done during the renaming of a `HsRecSel` expression in `dsExpr`+    and simply pulls the information about incompleteness from the `Id`++    e.g.+      l :: T -> Int+      l a = x a -- warning will be emitted here++  - Emitting a warning for a record selector `sel` applied to a variable `y`.+    In that case we want to use the long-distance information from the+    pattern match checker to rule out impossible constructors+    (See Note [Long-distance information]). We first add constraints to+    the long-distance `Nablas` that `y` cannot be one of the constructors that+    contain `sel` (function `checkRecSel` in GHC.HsToCore.Pmc.Check). If the+    `Nablas` are still inhabited, we emit a warning with the inhabiting constructors+    as examples of where `sel` may fail.++    e.g.+      z :: T -> Int+      z T1 = 0+      z a = x a -- warning will not be emitted here since `a` can only be `T2`+-}++pmcRecSel :: Id       -- ^ Id of the selector+          -> CoreExpr -- ^ Core expression of the argument to the selector+          -> DsM ()+pmcRecSel sel_id arg+  | RecSelId{ sel_cons = (cons_w_field, _ : _) } <- idDetails sel_id = do+      !missing <- getLdiNablas++      tracePm "pmcRecSel {" (ppr sel_id)+      CheckResult{ cr_ret = PmRecSel{ pr_arg_var = arg_id }, cr_uncov = uncov_nablas }+        <- unCA (checkRecSel (PmRecSel () arg cons_w_field)) missing+      tracePm "}: " $ ppr uncov_nablas++      inhabited <- isInhabited uncov_nablas+      when inhabited $ warn_incomplete arg_id uncov_nablas+        where+          sel_name = varName sel_id+          warn_incomplete arg_id uncov_nablas = do+            dflags <- getDynFlags+            let maxConstructors = maxUncoveredPatterns dflags+            unc_examples <- getNFirstUncovered MinimalCover [arg_id] (maxConstructors + 1) uncov_nablas+            let cons = [con | unc_example <- unc_examples+                      , Just (PACA (PmAltConLike con) _ _) <- [lookupSolution unc_example arg_id]]+                not_full_examples = length cons == (maxConstructors + 1)+                cons' = take maxConstructors cons+            diagnosticDs $ DsIncompleteRecordSelector sel_name cons' not_full_examples++pmcRecSel _ _ = return ()  {- Note [pmcPatBind doesn't warn on pattern guards] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compiler/GHC/HsToCore/Pmc/Check.hs view
@@ -19,7 +19,7 @@ -- "GHC.HsToCore.Pmc.Solver". module GHC.HsToCore.Pmc.Check (         CheckAction(..),-        checkMatchGroup, checkGRHSs, checkPatBind, checkEmptyCase+        checkMatchGroup, checkGRHSs, checkPatBind, checkEmptyCase, checkRecSel     ) where  import GHC.Prelude@@ -33,11 +33,15 @@ import GHC.Utils.Outputable import GHC.Tc.Utils.TcType (evVarPred) import GHC.Data.OrdList+import GHC.Data.Bag  import qualified Data.Semigroup as Semi import Data.List.NonEmpty ( NonEmpty(..) ) import qualified Data.List.NonEmpty as NE import Data.Coerce+import GHC.Types.Var+import GHC.Core+import GHC.Core.Utils  -- | Coverage checking action. Can be composed 'leftToRight' or 'topToBottom'. newtype CheckAction a = CA { unCA :: Nablas -> DsM (CheckResult a) }@@ -184,6 +188,20 @@  checkPatBind :: (PmPatBind Pre) -> CheckAction (PmPatBind Post) checkPatBind = coerce checkGRHS++checkRecSel :: PmRecSel () -> CheckAction (PmRecSel Id)+-- See Note [Detecting incomplete record selectors] in GHC.HsToCore.Pmc+checkRecSel pr@(PmRecSel { pr_arg = arg, pr_cons = cons }) = CA $ \inc -> do+  arg_id <- case arg of+           Var arg_id -> return arg_id+           _ -> mkPmId $ exprType arg++  let con_cts = map (PhiNotConCt arg_id . PmAltConLike) cons+      arg_ct  = PhiCoreCt arg_id arg+      phi_cts = listToBag (arg_ct : con_cts)+  unc <- addPhiCtsNablas inc phi_cts+  pure CheckResult { cr_ret = pr{ pr_arg_var = arg_id }, cr_uncov = unc, cr_approx = mempty }+  {- Note [Checking EmptyCase] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compiler/GHC/HsToCore/Pmc/Desugar.hs view
@@ -110,7 +110,7 @@ desugarPat x pat = case pat of   WildPat  _ty -> pure []   VarPat _ y   -> pure (mkPmLetVar (unLoc y) x)-  ParPat _ _ p _ -> desugarLPat x p+  ParPat _ p   -> desugarLPat x p   LazyPat _ _  -> pure [] -- like a wildcard   BangPat _ p@(L l p') ->     -- Add the bang in front of the list, because it will happen before any@@ -120,9 +120,11 @@    -- (x@pat)   ==>   Desugar pat with x as match var and handle impedance   --                 mismatch with incoming match var-  AsPat _ (L _ y) _ p -> (mkPmLetVar y x ++) <$> desugarLPat y p+  AsPat _ (L _ y) p -> (mkPmLetVar y x ++) <$> desugarLPat y p    SigPat _ p _ty -> desugarLPat x p+  EmbTyPat _ _ -> pure []+  InvisPat _ _ -> pure []    XPat ext -> case ext of 
compiler/GHC/HsToCore/Pmc/Solver.hs view
@@ -43,7 +43,6 @@ import GHC.Utils.Misc import GHC.Utils.Monad (allM) import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Data.Bag  import GHC.Types.CompleteMatch@@ -92,7 +91,6 @@ import Control.Monad.Trans.Class (lift) import Control.Monad.Trans.State.Strict import Data.Coerce-import Data.Either   (partitionEithers) import Data.Foldable (foldlM, minimumBy, toList) import Data.Monoid   (Any(..)) import Data.List     (sortBy, find)@@ -609,7 +607,7 @@   inhabitationTest initFuel (nabla_ty_st nabla) nabla''  partitionPhiCts :: PhiCts -> ([PredType], [PhiCt])-partitionPhiCts = partitionEithers . map to_either . toList+partitionPhiCts = partitionWith to_either . toList   where     to_either (PhiTyCt pred_ty) = Left pred_ty     to_either ct                = Right ct
compiler/GHC/HsToCore/Pmc/Utils.hs view
@@ -61,16 +61,17 @@   , Opt_WarnIncompleteUniPatterns   , Opt_WarnIncompletePatternsRecUpd   , Opt_WarnOverlappingPatterns+  , Opt_WarnIncompleteRecordSelectors   ]  -- | Check whether the redundancy checker should run (redundancy only)-overlapping :: DynFlags -> HsMatchContext id -> Bool+overlapping :: DynFlags -> HsMatchContext fn -> Bool -- See Note [Inaccessible warnings for record updates] overlapping _      RecUpd = False overlapping dflags _      = wopt Opt_WarnOverlappingPatterns dflags  -- | Check whether the exhaustiveness checker should run (exhaustiveness only)-exhaustive :: DynFlags -> HsMatchContext id -> Bool+exhaustive :: DynFlags -> HsMatchContext fn -> Bool exhaustive  dflags = maybe False (`wopt` dflags) . exhaustiveWarningFlag  -- | Check whether unnecessary bangs should be warned about@@ -80,16 +81,17 @@ -- | Denotes whether an exhaustiveness check is supported, and if so, -- via which 'WarningFlag' it's controlled. -- Returns 'Nothing' if check is not supported.-exhaustiveWarningFlag :: HsMatchContext id -> Maybe WarningFlag+exhaustiveWarningFlag :: HsMatchContext fn -> Maybe WarningFlag exhaustiveWarningFlag FunRhs{}           = Just Opt_WarnIncompletePatterns exhaustiveWarningFlag CaseAlt            = Just Opt_WarnIncompletePatterns-exhaustiveWarningFlag LamCaseAlt{}       = Just Opt_WarnIncompletePatterns exhaustiveWarningFlag IfAlt              = Just Opt_WarnIncompletePatterns-exhaustiveWarningFlag LambdaExpr         = Just Opt_WarnIncompleteUniPatterns+exhaustiveWarningFlag (LamAlt LamSingle) = Just Opt_WarnIncompleteUniPatterns+exhaustiveWarningFlag (LamAlt _case)     = Just Opt_WarnIncompletePatterns exhaustiveWarningFlag PatBindRhs         = Just Opt_WarnIncompleteUniPatterns exhaustiveWarningFlag PatBindGuards      = Just Opt_WarnIncompletePatterns exhaustiveWarningFlag (ArrowMatchCtxt c) = arrowMatchContextExhaustiveWarningFlag c exhaustiveWarningFlag RecUpd             = Just Opt_WarnIncompletePatternsRecUpd+exhaustiveWarningFlag LazyPatCtx         = Just Opt_WarnIncompleteUniPatterns exhaustiveWarningFlag ThPatSplice        = Nothing exhaustiveWarningFlag PatSyn             = Nothing exhaustiveWarningFlag ThPatQuote         = Nothing@@ -99,22 +101,22 @@  arrowMatchContextExhaustiveWarningFlag :: HsArrowMatchContext -> Maybe WarningFlag arrowMatchContextExhaustiveWarningFlag = \ case-  ProcExpr          -> Just Opt_WarnIncompleteUniPatterns-  ArrowCaseAlt      -> Just Opt_WarnIncompletePatterns-  ArrowLamCaseAlt _ -> Just Opt_WarnIncompletePatterns-  KappaExpr         -> Just Opt_WarnIncompleteUniPatterns+  ProcExpr              -> Just Opt_WarnIncompleteUniPatterns+  ArrowCaseAlt          -> Just Opt_WarnIncompletePatterns+  ArrowLamAlt LamSingle -> Just Opt_WarnIncompleteUniPatterns+  ArrowLamAlt _         -> Just Opt_WarnIncompletePatterns  -- | Check whether any part of pattern match checking is enabled for this -- 'HsMatchContext' (does not matter whether it is the redundancy check or the -- exhaustiveness check).-isMatchContextPmChecked :: DynFlags -> Origin -> HsMatchContext id -> Bool+isMatchContextPmChecked :: DynFlags -> Origin -> HsMatchContext fn -> Bool isMatchContextPmChecked dflags origin ctxt   =  requiresPMC origin   && (overlapping dflags ctxt || exhaustive dflags ctxt)  -- | Check whether exhaustivity checks are enabled for this 'HsMatchContext', -- when dealing with a single pattern (using the 'matchSinglePatVar' function).-isMatchContextPmChecked_SinglePat :: DynFlags -> Origin -> HsMatchContext id -> LPat GhcTc -> Bool+isMatchContextPmChecked_SinglePat :: DynFlags -> Origin -> HsMatchContext fn -> LPat GhcTc -> Bool isMatchContextPmChecked_SinglePat dflags origin ctxt pat   | not (needToRunPmCheck dflags origin)   = False
compiler/GHC/HsToCore/Quote.hs view
@@ -66,7 +66,6 @@  import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Misc import GHC.Utils.Monad @@ -694,21 +693,21 @@        ; addHsOuterFamEqnTyVarBinds outer_bndrs $ \mb_exp_bndrs ->          do { tys1 <- case fixity of                         Prefix -> repTyArgs (repNamedTyCon tc) tys-                        Infix  -> do { (HsValArg t1: HsValArg t2: args) <- checkTys tys+                        Infix  -> do { (HsValArg _ t1: HsValArg _ t2: args) <- checkTys tys                                      ; t1' <- repLTy t1                                      ; t2'  <- repLTy t2                                      ; repTyArgs (repTInfix t1' tc t2') args }             ; rhs1 <- repLTy rhs             ; repTySynEqn mb_exp_bndrs tys1 rhs1 } }      where checkTys :: [LHsTypeArg GhcRn] -> MetaM [LHsTypeArg GhcRn]-           checkTys tys@(HsValArg _:HsValArg _:_) = return tys+           checkTys tys@(HsValArg _ _:HsValArg _ _:_) = return tys            checkTys _ = panic "repTyFamEqn:checkTys"  repTyArgs :: MetaM (Core (M TH.Type)) -> [LHsTypeArg GhcRn] -> MetaM (Core (M TH.Type)) repTyArgs f [] = f-repTyArgs f (HsValArg ty : as) = do { f' <- f-                                    ; ty' <- repLTy ty-                                    ; repTyArgs (repTapp f' ty') as }+repTyArgs f (HsValArg _ ty : as)  = do { f' <- f+                                       ; ty' <- repLTy ty+                                       ; repTyArgs (repTapp f' ty') as } repTyArgs f (HsTypeArg _ ki : as) = do { f' <- f                                        ; ki' <- repLTy ki                                        ; repTyArgs (repTappKind f' ki') as }@@ -725,14 +724,14 @@        ; addHsOuterFamEqnTyVarBinds outer_bndrs $ \mb_exp_bndrs ->          do { tys1 <- case fixity of                         Prefix -> repTyArgs (repNamedTyCon tc) tys-                        Infix  -> do { (HsValArg t1: HsValArg t2: args) <- checkTys tys+                        Infix  -> do { (HsValArg _ t1: HsValArg _ t2: args) <- checkTys tys                                      ; t1' <- repLTy t1                                      ; t2'  <- repLTy t2                                      ; repTyArgs (repTInfix t1' tc t2') args }             ; repDataDefn tc (Right (mb_exp_bndrs, tys1)) defn } }        where checkTys :: [LHsTypeArg GhcRn] -> MetaM [LHsTypeArg GhcRn]-            checkTys tys@(HsValArg _: HsValArg _: _) = return tys+            checkTys tys@(HsValArg _ _: HsValArg _ _: _) = return tys             checkTys _ = panic "repDataFamInstD:checkTys"  repForD :: LForeignDecl GhcRn -> MetaM (SrcSpan, Core (M TH.Dec))@@ -782,15 +781,16 @@ repLFixD (L loc fix_sig) = rep_fix_d (locA loc) fix_sig  rep_fix_d :: SrcSpan -> FixitySig GhcRn -> MetaM [(SrcSpan, Core (M TH.Dec))]-rep_fix_d loc (FixitySig _ names (Fixity _ prec dir))+rep_fix_d loc (FixitySig ns_spec names (Fixity _ prec dir))   = do { MkC prec' <- coreIntLit prec        ; let rep_fn = case dir of-                        InfixL -> infixLDName-                        InfixR -> infixRDName-                        InfixN -> infixNDName+                        InfixL -> infixLWithSpecDName+                        InfixR -> infixRWithSpecDName+                        InfixN -> infixNWithSpecDName        ; let do_one name               = do { MkC name' <- lookupLOcc name-                   ; dec <- rep2 rep_fn [prec', name']+                   ; MkC ns_spec' <- repNamespaceSpecifier ns_spec+                   ; dec <- rep2 rep_fn [prec', ns_spec', name']                    ; return (loc,dec) }        ; mapM do_one names } @@ -998,7 +998,7 @@   = concatMapM (\t -> rep_specialise nm t ispec (locA loc)) tys rep_sig (L loc (SpecInstSig _ ty))  = rep_specialiseInst ty (locA loc) rep_sig (L _   (MinimalSig {}))       = notHandled ThMinimalPragmas-rep_sig (L _   (SCCFunSig {}))        = notHandled ThSCCPragmas+rep_sig (L loc (SCCFunSig _ nm str)) = rep_sccFun nm str (locA loc) rep_sig (L loc (CompleteMatchSig _ cls mty))   = rep_complete_sig cls mty (locA loc) rep_sig d@(L _ (XSig {}))             = pprPanic "rep_sig IdSig" (ppr d)@@ -1122,6 +1122,21 @@        ; pragma <- repPragSpecInst ty1        ; return [(loc, pragma)] } +rep_sccFun :: LocatedN Name+        -> Maybe (XRec GhcRn StringLiteral)+        -> SrcSpan+        -> MetaM [(SrcSpan, Core (M TH.Dec))]+rep_sccFun nm Nothing loc = do+  nm1 <- lookupLOcc nm+  scc <- repPragSCCFun nm1+  return [(loc, scc)]++rep_sccFun nm (Just (L _ str)) loc = do+  nm1 <- lookupLOcc nm+  str1 <- coreStringLit (sl_fs str)+  scc <- repPragSCCFunNamed nm1 str1+  return [(loc, scc)]+ repInline :: InlineSpec -> MetaM (Core TH.Inline) repInline (NoInline          _ )   = dataCon noInlineDataConName -- There is a mismatch between the TH and GHC representation because@@ -1144,11 +1159,11 @@                                   ; dataCon' fromPhaseDataConName [arg] } repPhases _                  = dataCon allPhasesDataConName -rep_complete_sig :: Located [LocatedN Name]+rep_complete_sig :: [LocatedN Name]                  -> Maybe (LocatedN Name)                  -> SrcSpan                  -> MetaM [(SrcSpan, Core (M TH.Dec))]-rep_complete_sig (L _ cls) mty loc+rep_complete_sig cls mty loc   = do { mty' <- repMaybe nameTyConName lookupLOcc mty        ; cls' <- repList nameTyConName lookupLOcc cls        ; sig <- repPragComplete cls' mty'@@ -1188,7 +1203,7 @@                                            ; rep2 kindedBndrTVName [nm, vis', ki] }  rep_bndr_vis :: HsBndrVis GhcRn -> MetaM (Core TH.BndrVis)-rep_bndr_vis HsBndrRequired      = rep2_nw bndrReqName []+rep_bndr_vis (HsBndrRequired _)  = rep2_nw bndrReqName [] rep_bndr_vis (HsBndrInvisible _) = rep2_nw bndrInvisName []  addHsOuterFamEqnTyVarBinds ::@@ -1387,21 +1402,23 @@   | n `hasKey` constraintKindTyConKey  = repTConstraint   | n `hasKey` unrestrictedFunTyConKey = repArrowTyCon   | n `hasKey` fUNTyConKey             = repMulArrowTyCon-  | isTvOcc occ   = do tv1 <- lookupOcc n-                       repTvar tv1-  | isDataOcc occ = do tc1 <- lookupOcc n-                       repPromotedDataCon tc1-  | n == eqTyConName = repTequality-  | otherwise     = do tc1 <- lookupOcc n-                       repNamedTyCon tc1+  | n `hasKey` eqTyConKey              = repTequality+  | isVarNameSpace     ns = do tv1 <- lookupOcc n+                               repTvar tv1+  | isDataConNameSpace ns = do dc1 <- lookupOcc n+                               repPromotedDataCon dc1+  | isTcClsNameSpace   ns = do tc1 <- lookupOcc n+                               repNamedTyCon tc1+  | otherwise = panic "repTy: HsTyVar: unknown namespace"   where     occ = nameOccName n+    ns  = occNameSpace occ  repTy (HsAppTy _ f a)       = do                                 f1 <- repLTy f                                 a1 <- repLTy a                                 repTapp f1 a1-repTy (HsAppKindTy _ ty _ ki) = do+repTy (HsAppKindTy _ ty ki) = do                                 ty1 <- repLTy ty                                 ki1 <- repLTy ki                                 repTappKind ty1 ki1@@ -1528,19 +1545,18 @@         -- HsOverlit can definitely occur repE (HsOverLit _ l) = do { a <- repOverloadedLiteral l; repLit a } repE (HsLit _ l)     = do { a <- repLiteral l;           repLit a }-repE (HsLam _ (MG { mg_alts = (L _ [m]) })) = repLambda m-repE e@(HsLam _ (MG { mg_alts = (L _ _) })) = pprPanic "repE: HsLam with multiple alternatives" (ppr e)-repE (HsLamCase _ LamCase (MG { mg_alts = (L _ ms) }))+repE (HsLam _ LamSingle (MG { mg_alts = L _ [m] })) = repLambda m+repE e@(HsLam _ LamSingle (MG { mg_alts = L _ _ })) = pprPanic "repE: HsLam with multiple alternatives" (ppr e)+repE (HsLam _ LamCase (MG { mg_alts = L _ ms }))                    = do { ms' <- mapM repMatchTup ms                         ; core_ms <- coreListM matchTyConName ms'                         ; repLamCase core_ms }-repE (HsLamCase _ LamCases (MG { mg_alts = (L _ ms) }))+repE (HsLam _ LamCases (MG { mg_alts = (L _ ms) }))                    = do { ms' <- mapM repClauseTup ms                         ; core_ms <- coreListM matchTyConName ms'                         ; repLamCases core_ms } repE (HsApp _ x y)   = do {a <- repLE x; b <- repLE y; repApp a b}-repE (HsAppType _ e _ t)-                       = do { a <- repLE e+repE (HsAppType _ e t) = do { a <- repLE e                             ; s <- repLTy (hswc_body t)                             ; repAppType a s } @@ -1553,7 +1569,7 @@                               a         <- repLE x                               negateVar <- lookupOcc negateName >>= repVar                               negateVar `repApp` a-repE (HsPar _ _ x _)        = repLE x+repE (HsPar _ x)            = repLE x repE (SectionL _ x y)       = do { a <- repLE x; b <- repLE y; repSectionL a b } repE (SectionR _ x y)       = do { a <- repLE x; b <- repLE y; repSectionR a b } repE (HsCase _ e (MG { mg_alts = (L _ ms) }))@@ -1570,10 +1586,10 @@   = do { (binds, alts') <- liftM unzip $ mapM repLGRHS alts        ; expr' <- repMultiIf (nonEmptyCoreList alts')        ; wrapGenSyms (concat binds) expr' }-repE (HsLet _ _ bs _ e)         = do { (ss,ds) <- repBinds bs-                                     ; e2 <- addBinds ss (repLE e)-                                     ; z <- repLetE ds e2-                                     ; wrapGenSyms ss z }+repE (HsLet _ bs e)       = do { (ss,ds) <- repBinds bs+                               ; e2 <- addBinds ss (repLE e)+                               ; z <- repLetE ds e2+                               ; wrapGenSyms ss z }  -- FIXME: I haven't got the types here right yet repE e@(HsDo _ ctxt (L _ sts))@@ -1666,11 +1682,19 @@   e1 <- repLE e   repGetField e1 f repE (HsProjection _ xs) = repProjection (fmap (field_label . unLoc . dfoLabel . unLoc) xs)-repE (XExpr (HsExpanded orig_expr ds_expr))+repE (HsEmbTy _ t) = do+  t1 <- repLTy (hswc_body t)+  rep2 typeEName [unC t1]+repE e@(XExpr (ExpandedThingRn o x))+  | OrigExpr e <- o   = do { rebindable_on <- lift $ xoptM LangExt.RebindableSyntax        ; if rebindable_on  -- See Note [Quotation and rebindable syntax]-         then repE ds_expr-         else repE orig_expr }+         then repE x+         else repE e }+  | otherwise+  = notHandled (ThExpressionForm e)++repE (XExpr (PopErrCtxt (L _ e))) = repE e repE e@(HsPragE _ (HsPragSCC {}) _) = notHandled (ThCostCentres e) repE e@(HsTypedBracket{})   = notHandled (ThExpressionForm e) repE e@(HsUntypedBracket{}) = notHandled (ThExpressionForm e)@@ -1696,7 +1720,7 @@       a type error from the splice.  We consult the module-wide RebindableSyntax flag here. We could instead record-the choice in HsExpanded, but it seems simpler to consult the flag (again).+the choice in ExpandedThingRn, but it seems simpler to consult the flag (again). -}  -----------------------------------------------------------------------------@@ -1713,7 +1737,7 @@      ; gs    <- repGuards guards      ; match <- repMatch p1 gs ds      ; wrapGenSyms (ss1++ss2) match }}}-repMatchTup _ = panic "repMatchTup: case alt with more than one arg"+repMatchTup _ = panic "repMatchTup: case alt with more than one arg or with invisible pattern"  repClauseTup ::  LMatch GhcRn (LHsExpr GhcRn) -> MetaM (Core (M TH.Clause)) repClauseTup (L _ (Match { m_pats = ps@@ -2082,9 +2106,9 @@ repP (VarPat _ x)       = do { x' <- lookupBinder (unLoc x); repPvar x' } repP (LazyPat _ p)      = do { p1 <- repLP p; repPtilde p1 } repP (BangPat _ p)      = do { p1 <- repLP p; repPbang p1 }-repP (AsPat _ x _ p)    = do { x' <- lookupNBinder x; p1 <- repLP p+repP (AsPat _ x p)      = do { x' <- lookupNBinder x; p1 <- repLP p                              ; repPaspat x' p1 }-repP (ParPat _ _ p _)   = repLP p+repP (ParPat _ p)       = repLP p repP (ListPat _ ps)     = do { qs <- repLPs ps; repPlist qs } repP (TuplePat _ ps boxed)   | isBoxed boxed       = do { qs <- repLPs ps; repPtup qs }@@ -2095,7 +2119,7 @@  = do { con_str <- lookupLOcc dc       ; case details of          PrefixCon tyargs ps -> do { qs <- repLPs ps-                                   ; let unwrapTyArg (HsConPatTyArg _ t) = unLoc (hsps_body t)+                                   ; let unwrapTyArg (HsConPatTyArg _ t) = unLoc (hstp_body t)                                    ; ts <- repListM typeTyConName (repTy . unwrapTyArg) tyargs                                    ; repPcon con_str ts qs }          RecCon rec   -> do { fps <- repListM fieldPatTyConName rep_fld (rec_flds rec)@@ -2123,6 +2147,10 @@ repP (SigPat _ p t) = do { p' <- repLP p                          ; t' <- repLTy (hsPatSigType t)                          ; repPsig p' t' }+repP (EmbTyPat _ t) = do { t' <- repLTy (hstp_body t)+                         ; repPtype t' }+repP (InvisPat _ t) = do { t' <- repLTy (hstp_body t)+                         ; repPinvis t' } repP (SplicePat (HsUntypedSpliceNested n) _) = rep_splice n repP p@(SplicePat (HsUntypedSpliceTop _ _) _) = pprPanic "repP: top level splice" (ppr p) repP other = notHandled (ThExoticPattern other)@@ -2379,6 +2407,12 @@ repPsig :: Core (M TH.Pat) -> Core (M TH.Type) -> MetaM (Core (M TH.Pat)) repPsig (MkC p) (MkC t) = rep2 sigPName [p, t] +repPtype :: Core (M TH.Type) -> MetaM (Core (M TH.Pat))+repPtype (MkC t) = rep2 typePName [t]++repPinvis :: Core (M TH.Type) -> MetaM (Core (M TH.Pat))+repPinvis (MkC t) = rep2 invisPName [t]+ --------------- Expressions ----------------- repVarOrCon :: Name -> Core TH.Name -> MetaM (Core (M TH.Exp)) repVarOrCon vc str@@ -2634,6 +2668,12 @@   just    = coreJust overlapTyConName  +repNamespaceSpecifier :: NamespaceSpecifier -> MetaM (Core (TH.NamespaceSpecifier))+repNamespaceSpecifier ns_spec = case ns_spec of+  NoNamespaceSpecifier{} -> dataCon noNamespaceSpecifierDataConName+  TypeNamespaceSpecifier{} -> dataCon typeNamespaceSpecifierDataConName+  DataNamespaceSpecifier{} -> dataCon dataNamespaceSpecifierDataConName+ repClass :: Core (M TH.Cxt) -> Core TH.Name -> Core [(M (TH.TyVarBndr TH.BndrVis))]          -> Core [TH.FunDep] -> Core [(M TH.Dec)]          -> MetaM (Core (M TH.Dec))@@ -2679,6 +2719,12 @@ repPragAnn :: Core TH.AnnTarget -> Core (M TH.Exp) -> MetaM (Core (M TH.Dec)) repPragAnn (MkC targ) (MkC e) = rep2 pragAnnDName [targ, e] +repPragSCCFun :: Core TH.Name -> MetaM (Core (M TH.Dec))+repPragSCCFun (MkC nm) = rep2 pragSCCFunDName [nm]++repPragSCCFunNamed :: Core TH.Name -> Core String -> MetaM (Core (M TH.Dec))+repPragSCCFunNamed (MkC nm) (MkC str) = rep2 pragSCCFunNamedDName [nm, str]+ repTySynInst :: Core (M TH.TySynEqn) -> MetaM (Core (M TH.Dec)) repTySynInst (MkC eqn)     = rep2 tySynInstDName [eqn]@@ -2750,11 +2796,11 @@ repGadtDataCons cons details res_ty     = do cons' <- mapM lookupLOcc cons -- See Note [Binders and occurrences]          case details of-           PrefixConGADT ps -> do+           PrefixConGADT _ ps -> do              arg_tys <- repPrefixConArgs ps              res_ty' <- repLTy res_ty              rep2 gadtCName [ unC (nonEmptyCoreList' cons'), unC arg_tys, unC res_ty']-           RecConGADT ips _ -> do+           RecConGADT _ ips -> do              arg_vtys <- repRecConArgs ips              res_ty'  <- repLTy res_ty              rep2 recGadtCName [unC (nonEmptyCoreList' cons'), unC arg_vtys,
compiler/GHC/HsToCore/Ticks.hs view
@@ -304,7 +304,7 @@   -- TODO: better name for rhs's for non-simple patterns?   let name = maybe "(...)" getOccString simplePatId -  (fvs, rhs') <- getFreeVars $ addPathEntry name $ addTickGRHSs False False rhs+  (fvs, rhs') <- getFreeVars $ addPathEntry name $ addTickGRHSs False False False rhs   let pat' = pat { pat_rhs = rhs'}    -- Should create ticks here?@@ -375,7 +375,9 @@   d <- getDensity   case d of     TickForBreakPoints | isGoodBreakExpr e0 -> tick_it-    TickForCoverage    -> tick_it+    TickForCoverage    | XExpr (ExpandedThingTc OrigStmt{} _) <- e0 -- expansion ticks are handled separately+                       -> dont_tick_it+                       | otherwise -> tick_it     TickCallSites      | isCallSite e0      -> tick_it     _other             -> dont_tick_it  where@@ -440,28 +442,31 @@ -- General heuristic: expressions which are calls (do not denote -- values) are good break points. isGoodBreakExpr :: HsExpr GhcTc -> Bool+isGoodBreakExpr (XExpr (ExpandedThingTc (OrigStmt{}) _)) = False isGoodBreakExpr e = isCallSite e  isCallSite :: HsExpr GhcTc -> Bool isCallSite HsApp{}     = True isCallSite HsAppType{} = True-isCallSite (XExpr (ExpansionExpr (HsExpanded _ e)))-                       = isCallSite e+isCallSite HsCase{}    = True+isCallSite (XExpr (ExpandedThingTc _ e))+  = isCallSite e+ -- NB: OpApp, SectionL, SectionR are all expanded out isCallSite _           = False  addTickLHsExprOptAlt :: Bool -> LHsExpr GhcTc -> TM (LHsExpr GhcTc)-addTickLHsExprOptAlt oneOfMany (L pos e0)+addTickLHsExprOptAlt oneOfMany e@(L pos e0)   = ifDensity TickForCoverage         (allocTickBox (ExpBox oneOfMany) False False (locA pos)-          $ addTickHsExpr e0)-        (addTickLHsExpr (L pos e0))+                           $ addTickHsExpr e0)+        (addTickLHsExpr e)  addBinTickLHsExpr :: (Bool -> BoxLabel) -> LHsExpr GhcTc -> TM (LHsExpr GhcTc)-addBinTickLHsExpr boxLabel (L pos e0)+addBinTickLHsExpr boxLabel e@(L pos e0)   = ifDensity TickForCoverage         (allocBinTickBox boxLabel (locA pos) $ addTickHsExpr e0)-        (addTickLHsExpr (L pos e0))+        (addTickLHsExpr e)   -- -----------------------------------------------------------------------------@@ -478,15 +483,14 @@ addTickHsExpr e@(HsOverLit {})          = return e addTickHsExpr e@(HsOverLabel{})         = return e addTickHsExpr e@(HsLit {})              = return e-addTickHsExpr (HsLam x mg)              = liftM (HsLam x)+addTickHsExpr e@(HsEmbTy {})            = return e+addTickHsExpr (HsLam x v mg)            = liftM (HsLam x v)                                                 (addTickMatchGroup True mg)-addTickHsExpr (HsLamCase x lc_variant mgs) = liftM (HsLamCase x lc_variant)-                                                   (addTickMatchGroup True mgs) addTickHsExpr (HsApp x e1 e2)          = liftM2 (HsApp x) (addTickLHsExprNever e1)                                                           (addTickLHsExpr      e2)-addTickHsExpr (HsAppType x e at ty) = do+addTickHsExpr (HsAppType x e ty) = do         e' <- addTickLHsExprNever e-        return (HsAppType x e' at ty)+        return (HsAppType x e' ty) addTickHsExpr (OpApp fix e1 e2 e3) =         liftM4 OpApp                 (return fix)@@ -497,9 +501,9 @@         liftM2 (NegApp x)                 (addTickLHsExpr e)                 (addTickSyntaxExpr hpcSrcSpan neg)-addTickHsExpr (HsPar x lpar e rpar) = do+addTickHsExpr (HsPar x e) = do         e' <- addTickLHsExprEvalInner e-        return (HsPar x lpar e' rpar)+        return (HsPar x e') addTickHsExpr (SectionL x e1 e2) =         liftM2 (SectionL x)                 (addTickLHsExpr e1)@@ -520,6 +524,7 @@                 (addTickLHsExpr e) -- not an EvalInner; e might not necessarily                                    -- be evaluated.                 (addTickMatchGroup False mgs)+ addTickHsExpr (HsIf x e1 e2 e3) =         liftM3 (HsIf x)                 (addBinTickLHsExpr (BinBox CondBinBox) e1)@@ -527,20 +532,13 @@                 (addTickLHsExprOptAlt True e3) addTickHsExpr (HsMultiIf ty alts)   = do { let isOneOfMany = case alts of [_] -> False; _ -> True-       ; alts' <- mapM (traverse $ addTickGRHS isOneOfMany False) alts+       ; alts' <- mapM (traverse $ addTickGRHS isOneOfMany False False) alts        ; return $ HsMultiIf ty alts' }-addTickHsExpr (HsLet x tkLet binds tkIn e) =+addTickHsExpr (HsLet x binds e) =         bindLocals (collectLocalBinders CollNoDictBinders binds) $ do           binds' <- addTickHsLocalBinds binds -- to think about: !patterns.           e' <- addTickLHsExprLetBody e-          return (HsLet x tkLet binds' tkIn e')-addTickHsExpr (HsDo srcloc cxt (L l stmts))-  = do { (stmts', _) <- addTickLStmts' forQual stmts (return ())-       ; return (HsDo srcloc cxt (L l stmts')) }-  where-        forQual = case cxt of-                    ListComp -> Just $ BinBox QualBinBox-                    _        -> Nothing+          return (HsLet x binds' e') addTickHsExpr (ExplicitList ty es)   = liftM2 ExplicitList (return ty) (mapM (addTickLHsExpr) es) @@ -591,9 +589,7 @@ addTickHsExpr (XExpr (WrapExpr (HsWrap w e))) =         liftM (XExpr . WrapExpr . HsWrap w) $               (addTickHsExpr e)        -- Explicitly no tick on inside-addTickHsExpr (XExpr (ExpansionExpr (HsExpanded a b))) =-        liftM (XExpr . ExpansionExpr . HsExpanded a) $-              (addTickHsExpr b)+addTickHsExpr (XExpr (ExpandedThingTc o e)) = addTickHsExpanded o e  addTickHsExpr e@(XExpr (ConLikeTc {})) = return e   -- We used to do a freeVar on a pat-syn builder, but actually@@ -606,6 +602,29 @@ addTickHsExpr (XExpr (HsBinTick t0 t1 e)) =         liftM (XExpr . HsBinTick t0 t1) (addTickLHsExprNever e) +addTickHsExpr (HsDo srcloc cxt (L l stmts))+  = do { (stmts', _) <- addTickLStmts' forQual stmts (return ())+       ; return (HsDo srcloc cxt (L l stmts')) }+  where+        forQual = case cxt of+                    ListComp -> Just $ BinBox QualBinBox+                    _        -> Nothing++addTickHsExpanded :: HsThingRn -> HsExpr GhcTc -> TM (HsExpr GhcTc)+addTickHsExpanded o@(OrigStmt (L pos LastStmt{})) e+  -- LastStmt always gets a tick for breakpoint and hpc coverage+  = do d <- getDensity+       case d of+          TickForCoverage    -> liftM (XExpr . ExpandedThingTc o) $ tick_it e+          TickForBreakPoints -> liftM (XExpr . ExpandedThingTc o) $ tick_it e+          _                  -> liftM (XExpr . ExpandedThingTc o) $ addTickHsExpr e+  where+    tick_it e  = unLoc <$> allocTickBox (ExpBox False) False False (locA pos)+                               (addTickHsExpr e)+addTickHsExpanded o e+  = liftM (XExpr . ExpandedThingTc o) $ addTickHsExpr e++ addTickTupArg :: HsTupArg GhcTc -> TM (HsTupArg GhcTc) addTickTupArg (Present x e)  = do { e' <- addTickLHsExpr e                                   ; return (Present x e') }@@ -614,41 +633,51 @@  addTickMatchGroup :: Bool{-is lambda-} -> MatchGroup GhcTc (LHsExpr GhcTc)                   -> TM (MatchGroup GhcTc (LHsExpr GhcTc))-addTickMatchGroup is_lam mg@(MG { mg_alts = L l matches }) = do+addTickMatchGroup is_lam mg@(MG { mg_alts = L l matches, mg_ext = ctxt }) = do   let isOneOfMany = matchesOneOfMany matches-  matches' <- mapM (traverse (addTickMatch isOneOfMany is_lam)) matches+      isDoExp     = isDoExpansionGenerated $ mg_origin ctxt+  matches' <- mapM (traverse (addTickMatch isOneOfMany is_lam isDoExp)) matches   return $ mg { mg_alts = L l matches' } -addTickMatch :: Bool -> Bool -> Match GhcTc (LHsExpr GhcTc)+addTickMatch :: Bool -> Bool -> Bool {-Is this Do Expansion-} ->  Match GhcTc (LHsExpr GhcTc)              -> TM (Match GhcTc (LHsExpr GhcTc))-addTickMatch isOneOfMany isLambda match@(Match { m_pats = pats-                                               , m_grhss = gRHSs }) =+addTickMatch isOneOfMany isLambda isDoExp match@(Match { m_pats = pats+                                                       , m_grhss = gRHSs }) =   bindLocals (collectPatsBinders CollNoDictBinders pats) $ do-    gRHSs' <- addTickGRHSs isOneOfMany isLambda gRHSs+    gRHSs' <- addTickGRHSs isOneOfMany isLambda isDoExp gRHSs     return $ match { m_grhss = gRHSs' } -addTickGRHSs :: Bool -> Bool -> GRHSs GhcTc (LHsExpr GhcTc)+addTickGRHSs :: Bool -> Bool -> Bool -> GRHSs GhcTc (LHsExpr GhcTc)              -> TM (GRHSs GhcTc (LHsExpr GhcTc))-addTickGRHSs isOneOfMany isLambda (GRHSs x guarded local_binds) =+addTickGRHSs isOneOfMany isLambda isDoExp (GRHSs x guarded local_binds) =   bindLocals binders $ do     local_binds' <- addTickHsLocalBinds local_binds-    guarded' <- mapM (traverse (addTickGRHS isOneOfMany isLambda)) guarded+    guarded' <- mapM (traverse (addTickGRHS isOneOfMany isLambda isDoExp)) guarded     return $ GRHSs x guarded' local_binds'   where     binders = collectLocalBinders CollNoDictBinders local_binds -addTickGRHS :: Bool -> Bool -> GRHS GhcTc (LHsExpr GhcTc)+addTickGRHS :: Bool -> Bool -> Bool -> GRHS GhcTc (LHsExpr GhcTc)             -> TM (GRHS GhcTc (LHsExpr GhcTc))-addTickGRHS isOneOfMany isLambda (GRHS x stmts expr) = do+addTickGRHS isOneOfMany isLambda isDoExp (GRHS x stmts expr) = do   (stmts',expr') <- addTickLStmts' (Just $ BinBox $ GuardBinBox) stmts-                        (addTickGRHSBody isOneOfMany isLambda expr)+                        (addTickGRHSBody isOneOfMany isLambda isDoExp expr)   return $ GRHS x stmts' expr' -addTickGRHSBody :: Bool -> Bool -> LHsExpr GhcTc -> TM (LHsExpr GhcTc)-addTickGRHSBody isOneOfMany isLambda expr@(L pos e0) = do+addTickGRHSBody :: Bool -> Bool -> Bool -> LHsExpr GhcTc -> TM (LHsExpr GhcTc)+addTickGRHSBody isOneOfMany isLambda isDoExp expr@(L pos e0) = do   d <- getDensity   case d of-    TickForCoverage  -> addTickLHsExprOptAlt isOneOfMany expr+    TickForBreakPoints+      | isDoExp       -- ticks for do-expansions are handled by `addTickHsExpanded`+      -> addTickLHsExprNever expr+      | otherwise+      -> addTickLHsExprRHS expr+    TickForCoverage+      | isDoExp       -- ticks for do-expansions are handled by `addTickHsExpanded`+      -> addTickLHsExprNever expr+      | otherwise+      -> addTickLHsExprOptAlt isOneOfMany expr     TickAllFunctions | isLambda ->        addPathEntry "\\" $          allocTickBox (ExpBox False) True{-count-} False{-not top-} (locA pos) $@@ -813,8 +842,8 @@         return $ L pos c1  addTickHsCmd :: HsCmd GhcTc -> TM (HsCmd GhcTc)-addTickHsCmd (HsCmdLam x matchgroup) =-        liftM (HsCmdLam x) (addTickCmdMatchGroup matchgroup)+addTickHsCmd (HsCmdLam x lam_variant mgs) =+        liftM (HsCmdLam x lam_variant) (addTickCmdMatchGroup mgs) addTickHsCmd (HsCmdApp x c e) =         liftM2 (HsCmdApp x) (addTickLHsCmd c) (addTickLHsExpr e) {-@@ -825,25 +854,23 @@                 (return fix)                 (addTickLHsCmd c3) -}-addTickHsCmd (HsCmdPar x lpar e rpar) = do+addTickHsCmd (HsCmdPar x e) = do         e' <- addTickLHsCmd e-        return (HsCmdPar x lpar e' rpar)+        return (HsCmdPar x e') addTickHsCmd (HsCmdCase x e mgs) =         liftM2 (HsCmdCase x)                 (addTickLHsExpr e)                 (addTickCmdMatchGroup mgs)-addTickHsCmd (HsCmdLamCase x lc_variant mgs) =-        liftM (HsCmdLamCase x lc_variant) (addTickCmdMatchGroup mgs) addTickHsCmd (HsCmdIf x cnd e1 c2 c3) =         liftM3 (HsCmdIf x cnd)                 (addBinTickLHsExpr (BinBox CondBinBox) e1)                 (addTickLHsCmd c2)                 (addTickLHsCmd c3)-addTickHsCmd (HsCmdLet x tkLet binds tkIn c) =+addTickHsCmd (HsCmdLet x binds c) =         bindLocals (collectLocalBinders CollNoDictBinders binds) $ do           binds' <- addTickHsLocalBinds binds -- to think about: !patterns.           c' <- addTickLHsCmd c-          return (HsCmdLet x tkLet binds' tkIn c')+          return (HsCmdLet x binds' c') addTickHsCmd (HsCmdDo srcloc (L l stmts))   = do { (stmts', _) <- addTickLCmdStmts' stmts (return ())        ; return (HsCmdDo srcloc (L l stmts')) }@@ -1060,6 +1087,7 @@                                        (r2,fv2,st2) ->                                           (r2, fv1 `plusOccEnv` fv2, st2) + -- | Get the next HPC cost centre index for a given centre name getCCIndexM :: FastString -> TM CostCentreIndex getCCIndexM n = TM $ \_ st -> let (idx, is') = getCCIndex n $@@ -1142,8 +1170,8 @@     (fvs, e) <- getFreeVars m     env <- getEnv     tickish <- mkTickish boxLabel countEntries topOnly pos fvs (declPath env)-    return (L (noAnnSrcSpan pos) (XExpr $ HsTick tickish $ L (noAnnSrcSpan pos) e))-  ) (do+    return (L (noAnnSrcSpan pos) (XExpr $ HsTick tickish $ L (noAnnSrcSpan pos) e)))+  (do     e <- m     return (L (noAnnSrcSpan pos) e)   )@@ -1195,7 +1223,9 @@           count = countEntries && tte_countEntries env       return $ ProfNote cc count True{-scopes-} -    Breakpoints -> Breakpoint noExtField <$> addMixEntry me <*> pure ids+    Breakpoints -> do+      i <- addMixEntry me+      pure (Breakpoint noExtField i ids (this_mod env))      SourceNotes | RealSrcSpan pos' _ <- pos ->       return $ SourceNote pos' $ LexicalFastString cc_name
compiler/GHC/HsToCore/Usage.hs view
@@ -235,7 +235,7 @@                             else mod                 -- This lambda function is really just a                 -- specialised (++); originally came about to-                -- avoid quadratic behaviour (trac #2680)+                -- avoid quadratic behaviour (#2680)                 in extendModuleEnvWith (\_ xs -> occ:xs) mv_map mod' [occ]             where occ = nameOccName name 
compiler/GHC/HsToCore/Utils.hs view
@@ -15,7 +15,7 @@ -- | Utility functions for constructing Core syntax, principally for desugaring module GHC.HsToCore.Utils (         EquationInfo(..),-        firstPat, shiftEqns,+        firstPat, shiftEqns, combineEqnRhss,          MatchResult (..), CaseAlt(..),         cantFailMatchResult, alwaysFailMatchResult,@@ -41,7 +41,7 @@          selectSimpleMatchVarL, selectMatchVars, selectMatchVar,         mkOptTickBox, mkBinaryTickBox, decideBangHood,-        isTrueLHsExpr+        isTrueLHsExpr,     ) where  import GHC.Prelude@@ -75,7 +75,6 @@ import GHC.Types.Name( isInternalName ) import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Types.SrcLoc import GHC.Types.Tickish import GHC.Utils.Misc@@ -132,7 +131,7 @@ -- Postcondition: the returned Id has an Internal Name selectMatchVar w (BangPat _ pat)    = selectMatchVar w (unLoc pat) selectMatchVar w (LazyPat _ pat)    = selectMatchVar w (unLoc pat)-selectMatchVar w (ParPat _ _ pat _) = selectMatchVar w (unLoc pat)+selectMatchVar w (ParPat _  pat)    = selectMatchVar w (unLoc pat) selectMatchVar _w (VarPat _ var)    = return (localiseId (unLoc var))                                   -- Note [Localise pattern binders]                                   --@@ -141,7 +140,7 @@                                   -- multiplicity stored within the variable                                   -- itself. It's easier to pull it from the                                   -- variable, so we ignore the multiplicity.-selectMatchVar _w (AsPat _ var _ _) = assert (isManyTy _w ) (return (localiseId (unLoc var)))+selectMatchVar _w (AsPat _ var _) = assert (isManyTy _w ) (return (localiseId (unLoc var))) selectMatchVar w other_pat        = newSysLocalDs w (hsPatType other_pat)  {- Note [Localise pattern binders]@@ -194,13 +193,17 @@ worthy of a type synonym and a few handy functions. -} -firstPat :: EquationInfo -> Pat GhcTc-firstPat eqn = assert (notNull (eqn_pats eqn)) $ head (eqn_pats eqn)+firstPat :: EquationInfoNE -> Pat GhcTc+firstPat (EqnMatch { eqn_pat = pat }) = unLoc pat+firstPat (EqnDone {}) = error "firstPat: no patterns" -shiftEqns :: Functor f => f EquationInfo -> f EquationInfo+shiftEqns :: Functor f => f EquationInfoNE -> f EquationInfo -- Drop the first pattern in each equation-shiftEqns = fmap $ \eqn -> eqn { eqn_pats = tail (eqn_pats eqn) }+shiftEqns = fmap eqn_rest +combineEqnRhss :: NonEmpty EquationInfo -> DsM (MatchResult CoreExpr)+combineEqnRhss eqns = return $ foldr1 combineMatchResults $ map eqnMatchResult (NEL.toList eqns)+ -- Functions on MatchResult CoreExprs  matchCanFail :: MatchResult a -> Bool@@ -247,6 +250,9 @@   | new==old    = body  -- variables, type variables or coercion variables   | otherwise   = Let (NonRec new (varToCoreExpr old)) body +-- Used to force variables when desugaring strict binders. It's crucial that the+-- variable is shadowed by the case binder. See Wrinkle 1 in+-- Note [Desugar Strict binds] in GHC.HsToCore.Binds. seqVar :: Var -> CoreExpr -> CoreExpr seqVar var body = mkDefaultCase (Var var) var body @@ -453,7 +459,7 @@ is disabled. -} -mkFailExpr :: HsMatchContext GhcTc -> Type -> DsM CoreExpr+mkFailExpr :: HsMatchContextRn -> Type -> DsM CoreExpr mkFailExpr ctxt ty   = mkErrorAppDs pAT_ERROR_ID ty (matchContextErrString ctxt) @@ -594,8 +600,13 @@ in a binding group:   let { ...; p = e; ... } in body where p binds x,y (this list of binders can be empty).-There are two cases. +mkSelectorBinds is also used to desugar irrefutable patterns, which is the+pattern syntax equivalent of a lazy pattern binding:+   f (~(a:as)) = rhs    ==>    f x = let (a:as) = x in rhs++There are three cases.+ ------ Special case (A) -------   For a pattern that is just a variable,      let !x = e in body@@ -631,7 +642,7 @@   Note that (C) /includes/ the situation where     * The pattern binds exactly one variable-        let !(Just (Just x) = e in body+        let !(Just (Just x)) = e in body      ==>        let { t = case e of Just (Just v) -> Solo v            ; v = case t of Solo v -> v }@@ -639,7 +650,7 @@     The 'Solo' is a one-tuple; see Note [One-tuples] in GHC.Builtin.Types     Note that forcing 't' makes the pattern match happen,     but does not force 'v'.  That's why we call `mkBigCoreVarTupSolo`-    in `mkSeletcorBinds`+    in `mkSelectorBinds`    * The pattern binds no variables         let !(True,False) = e in body@@ -723,15 +734,16 @@ -} -- Remark: pattern selectors only occur in unrestricted patterns so we are free -- to select Many as the multiplicity of every let-expression introduced.-mkSelectorBinds :: [[CoreTickish]] -- ^ ticks to add, possibly-                -> LPat GhcTc      -- ^ The pattern-                -> CoreExpr        -- ^ Expression to which the pattern is bound+mkSelectorBinds :: [[CoreTickish]]       -- ^ ticks to add, possibly+                -> LPat GhcTc            -- ^ The pattern+                -> HsMatchContextRn      -- ^ Where the pattern occurs+                -> CoreExpr              -- ^ Expression to which the pattern is bound                 -> DsM (Id,[(Id,CoreExpr)])                 -- ^ Id the rhs is bound to, for desugaring strict                 -- binds (see Note [Desugar Strict binds] in "GHC.HsToCore.Binds")                 -- and all the desugared binds -mkSelectorBinds ticks pat val_expr+mkSelectorBinds ticks pat ctx val_expr   | L _ (VarPat _ (L _ v)) <- pat'     -- Special case (A)   = return (v, [(v, val_expr)]) @@ -742,7 +754,7 @@        ; let mk_bind tick bndr_var                -- (mk_bind sv bv)  generates  bv = case sv of { pat -> bv }                -- Remember, 'pat' binds 'bv'-               = do { rhs_expr <- matchSimply (Var val_var) PatBindRhs pat'+               = do { rhs_expr <- matchSimply (Var val_var) ctx ManyTy pat'                                        (Var bndr_var)                                        (Var bndr_var)  -- Neat hack                       -- Neat hack: since 'pat' can't fail, the@@ -757,7 +769,7 @@   | otherwise                          -- General case (C)   = do { tuple_var  <- newSysLocalDs ManyTy tuple_ty        ; error_expr <- mkErrorAppDs pAT_ERROR_ID tuple_ty (ppr pat')-       ; tuple_expr <- matchSimply val_expr PatBindRhs pat+       ; tuple_expr <- matchSimply val_expr ctx ManyTy pat                                    local_tuple error_expr        ; let mk_tup_bind tick binder                = (binder, mkOptTickBox tick $@@ -779,7 +791,7 @@  strip_bangs :: LPat (GhcPass p) -> LPat (GhcPass p) -- Remove outermost bangs and parens-strip_bangs (L _ (ParPat _ _ p _))  = strip_bangs p+strip_bangs (L _ (ParPat _ p))  = strip_bangs p strip_bangs (L _ (BangPat _ p)) = strip_bangs p strip_bangs lp                  = lp @@ -788,7 +800,7 @@ is_flat_prod_lpat = is_flat_prod_pat . unLoc  is_flat_prod_pat :: Pat GhcTc -> Bool-is_flat_prod_pat (ParPat _ _ p _)      = is_flat_prod_lpat p+is_flat_prod_pat (ParPat _ p)          = is_flat_prod_lpat p is_flat_prod_pat (TuplePat _ ps Boxed) = all is_triv_lpat ps is_flat_prod_pat (ConPat { pat_con  = L _ pcon                          , pat_args = ps})@@ -805,7 +817,7 @@ is_triv_pat :: Pat (GhcPass p) -> Bool is_triv_pat (VarPat {})  = True is_triv_pat (WildPat{})  = True-is_triv_pat (ParPat _ _ p _) = is_triv_lpat p+is_triv_pat (ParPat _ p) = is_triv_lpat p is_triv_pat _            = False  @@ -909,7 +921,7 @@ mkFailurePair :: CoreExpr       -- Result type of the whole case expression               -> DsM (CoreBind, -- Binds the newly-created fail variable                                 -- to \ _ -> expression-                      CoreExpr) -- Fail variable applied to realWorld#+                      CoreExpr) -- Fail variable applied to (# #) -- See Note [Failure thunks and CPR] mkFailurePair expr   = do { fail_fun_var <- newFailLocalDs ManyTy (unboxedUnitTy `mkVisFunTyMany` ty)@@ -1046,7 +1058,7 @@   where     go lp@(L l p)       = case p of-           ParPat x lpar p rpar -> L l (ParPat x lpar (go p) rpar)+           ParPat x p -> L l (ParPat x (go p))            LazyPat _ lp' -> lp'            BangPat _ _   -> lp            _             -> L l (BangPat noExtField lp)@@ -1078,5 +1090,5 @@                      this_mod <- getModule                      return (Tick (HpcTick this_mod ixT) e)) -isTrueLHsExpr (L _ (HsPar _ _ e _)) = isTrueLHsExpr e-isTrueLHsExpr _                     = Nothing+isTrueLHsExpr (L _ (HsPar _ e)) = isTrueLHsExpr e+isTrueLHsExpr _                 = Nothing
compiler/GHC/Iface/Ext/Ast.hs view
@@ -12,8 +12,10 @@ {-# LANGUAGE TypeFamilies            #-} {-# LANGUAGE UndecidableInstances    #-} {-# LANGUAGE UndecidableSuperClasses #-}+{-# LANGUAGE RankNTypes #-}  {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}+{-# OPTIONS_GHC -Wno-orphans #-} -- For the HasLoc instances  {- Main functions for .hie file generation@@ -53,7 +55,6 @@ import GHC.Builtin.Uniques import GHC.Iface.Make             ( mkIfaceExports ) import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Misc import GHC.Data.Maybe import GHC.Data.FastString@@ -209,7 +210,8 @@ -- These synonyms match those defined in compiler/GHC.hs type RenamedSource     = ( HsGroup GhcRn, [LImportDecl GhcRn]                          , Maybe [(LIE GhcRn, Avails)]-                         , Maybe (LHsDoc GhcRn) )+                         , Maybe (LHsDoc GhcRn)+                         , Maybe (XRec GhcRn ModuleName) ) type TypecheckedSource = LHsBinds GhcTc  @@ -320,8 +322,9 @@  enrichHie :: TypecheckedSource -> RenamedSource -> Bag EvBind -> [ClsInst] -> [TyCon]   -> HieASTs Type-enrichHie ts (hsGrp, imports, exports, docs) ev_bs insts tcs =+enrichHie ts (hsGrp, imports, exports, docs, modName) ev_bs insts tcs =   runIdentity $ flip evalStateT initState $ flip runReaderT SourceInfo $ do+    modName <- toHie (IEC Export <$> modName)     tasts <- toHie $ fmap (BC RegularBind ModuleScope) ts     rasts <- processGrp hsGrp     imps <- toHie $ filter (not . ideclImplicit . ideclExt . unLoc) imports@@ -343,7 +346,8 @@               (realSrcSpanEnd   $ nodeSpan (NE.last children))          flat_asts = concat-          [ tasts+          [ modName+          , tasts           , rasts           , imps           , exps@@ -398,14 +402,14 @@       , toHie $ hs_docs grp       ] -getRealSpanA :: SrcSpanAnn' ann -> Maybe Span+getRealSpanA :: EpAnn ann -> Maybe Span getRealSpanA la = getRealSpan (locA la)  getRealSpan :: SrcSpan -> Maybe Span getRealSpan (RealSrcSpan sp _) = Just sp getRealSpan _ = Nothing -grhss_span :: (Anno (GRHS (GhcPass p) (LocatedA (body (GhcPass p)))) ~ SrcAnn NoEpAnns)+grhss_span :: (Anno (GRHS (GhcPass p) (LocatedA (body (GhcPass p)))) ~ EpAnn NoEpAnns)            => GRHSs (GhcPass p) (LocatedA (body (GhcPass p))) -> SrcSpan grhss_span (GRHSs _ xs bs) = foldl' combineSrcSpans (spanHsLocaLBinds bs) (map getLocA xs) @@ -506,11 +510,11 @@   :: Scope   -> Scope   -> [HsConPatTyArg (GhcPass a)]-  -> [TScoped (HsPatSigType (GhcPass a))]+  -> [TScoped (HsTyPat (GhcPass a))] taScopes scope rhsScope xs =   map (\(RS sc a) -> TS (ResolvedScopes [scope, sc]) (unLoc a)) $-    listScopes rhsScope (map (\(HsConPatTyArg _ hsps) -> L (getLoc $ hsps_body hsps) hsps) xs)-  -- We make the HsPatSigType into a Located one by using the location of the underlying LHsType.+    listScopes rhsScope (map (\(HsConPatTyArg _ hstp) -> L (getLoc $ hstp_body hstp) hstp) xs)+  -- We make the HsTyPat into a Located one by using the location of the underlying LHsType.   -- We then strip off the redundant location information afterward, and take the union of the given scope and those to the right when forming the TS.  -- | 'listScopes' specialised to 'TVScoped' things@@ -541,43 +545,26 @@ This case in handled in the instance for HsPatSigType -} -class HasLoc a where-  -- ^ conveniently calculate locations for things without locations attached-  loc :: a -> SrcSpan- instance HasLoc thing => HasLoc (PScoped thing) where-  loc (PS _ _ _ a) = loc a--instance HasLoc (Located a) where-  loc (L l _) = l--instance HasLoc (LocatedA a) where-  loc (L la _) = locA la--instance HasLoc (LocatedN a) where-  loc (L la _) = locA la--instance HasLoc a => HasLoc [a] where-  loc [] = noSrcSpan-  loc xs = foldl1' combineSrcSpans $ map loc xs+  getHasLoc (PS _ _ _ a) = getHasLoc a  instance HasLoc a => HasLoc (DataDefnCons a) where-  loc = loc . toList+  getHasLoc = getHasLocList . toList  instance (HasLoc a, HiePass p) => HasLoc (FamEqn (GhcPass p) a) where-  loc (FamEqn _ a outer_bndrs b _ c) = case outer_bndrs of+  getHasLoc (FamEqn _ a outer_bndrs b _ c) = case outer_bndrs of     HsOuterImplicit{} ->-      foldl1' combineSrcSpans [loc a, loc b, loc c]+      foldl1' combineSrcSpans [getHasLoc a, getHasLocList b, getHasLoc c]     HsOuterExplicit{hso_bndrs = tvs} ->-      foldl1' combineSrcSpans [loc a, loc tvs, loc b, loc c]+      foldl1' combineSrcSpans [getHasLoc a, getHasLocList tvs, getHasLocList b, getHasLoc c] -instance (HasLoc tm, HasLoc ty) => HasLoc (HsArg p tm ty) where-  loc (HsValArg tm) = loc tm-  loc (HsTypeArg _ ty) = loc ty-  loc (HsArgPar sp)  = sp+instance (HasLoc tm, HasLoc ty) => HasLoc (HsArg (GhcPass p) tm ty) where+  getHasLoc (HsValArg _ tm) = getHasLoc tm+  getHasLoc (HsTypeArg _ ty) = getHasLoc ty+  getHasLoc (HsArgPar sp)  = sp  instance HasLoc (HsDataDefn GhcRn) where-  loc def@(HsDataDefn{}) = loc $ dd_cons def+  getHasLoc def@(HsDataDefn{}) = getHasLoc $ dd_cons def     -- Only used for data family instances, so we only need rhs     -- Most probably the rest will be unhelpful anyway @@ -610,7 +597,7 @@   toHie = maybe (pure []) toHie  instance ToHie (IEContext (LocatedA ModuleName)) where-  toHie (IEC c (L (SrcSpanAnn _ (RealSrcSpan span _)) mname)) = do+  toHie (IEC c (L (EpAnn (EpaSpan (RealSrcSpan span _)) _ _) mname)) = do       org <- ask       pure $ [Node (mkSourcedNodeInfo org $ NodeInfo S.empty [] idents) span []]     where details = mempty{identInfo = S.singleton (IEThing c)}@@ -689,7 +676,7 @@           let evDeps = evVarsOfTermList $ eb_rhs evbind               depNames = EvBindDeps $ map varName evDeps           concatM $-            [ toHie (C (EvidenceVarBind (EvLetBind depNames) (combineScopes sc (mkScopeA span)) sp)+            [ toHie (C (EvidenceVarBind (EvLetBind depNames) (combineScopes sc (mkScope span)) sp)                                         (L span $ eb_lhs evbind))             , toHie $ map (C EvidenceVarUse . L span) $ evDeps             ]@@ -698,13 +685,13 @@ instance ToHie (LocatedA HsWrapper) where   toHie (L osp wrap)     = case wrap of-        (WpLet bs)      -> toHie $ EvBindContext (mkScopeA osp) (getRealSpanA osp) (L osp bs)+        (WpLet bs)      -> toHie $ EvBindContext (mkScope osp) (getRealSpanA osp) (L osp bs)         (WpCompose a b) -> concatM $           [toHie (L osp a), toHie (L osp b)]         (WpFun a b _)   -> concatM $           [toHie (L osp a), toHie (L osp b)]         (WpEvLam a) ->-          toHie $ C (EvidenceVarBind EvWrapperBind (mkScopeA osp) (getRealSpanA osp))+          toHie $ C (EvidenceVarBind EvWrapperBind (mkScope osp) (getRealSpanA osp))                 $ L osp a         (WpEvApp a) ->           concatMapM (toHie . C EvidenceVarUse . L osp) $ evVarsOfTermList a@@ -752,15 +739,17 @@         HsApp{} -> Nothing         HsAppType{} -> Nothing         NegApp{} -> Nothing-        HsPar _ _ e _ -> computeLType e+        HsPar _ e -> computeLType e         ExplicitTuple{} -> Nothing         HsIf _ _ t f -> computeLType t <|> computeLType f-        HsLet _ _ _ _ body -> computeLType body+        HsLet _ _ body -> computeLType body         RecordCon con_expr _ _ -> computeType con_expr         ExprWithTySig _ e _ -> computeLType e         HsPragE _ _ e -> computeLType e-        XExpr (ExpansionExpr (HsExpanded (HsGetField _ _ _) e)) -> Just (hsExprType e) -- for record-dot-syntax-        XExpr (ExpansionExpr (HsExpanded _ e)) -> computeType e+        XExpr (ExpandedThingTc thing e)+          | OrigExpr (HsGetField{}) <- thing -- for record-dot-syntax+          -> Just (hsExprType e)+          | otherwise -> computeType e         XExpr (HsTick _ e) -> computeLType e         XExpr (HsBinTick _ _ e) -> computeLType e         e -> Just (hsExprType e)@@ -839,7 +828,7 @@     , Anno [LocatedA (Match (GhcPass p) (LocatedA (body (GhcPass p))))]                    ~ SrcSpanAnnL     , Anno (GRHS (GhcPass p) (LocatedA (body (GhcPass p))))-                   ~ SrcAnn NoEpAnns+                   ~ EpAnn NoEpAnns     , Anno (StmtLR (GhcPass p) (GhcPass p) (LocatedA (body (GhcPass p)))) ~ SrcSpanAnnA      , Data (body (GhcPass p))@@ -866,9 +855,6 @@         [ toHie expr         ]       XHsBindsLR ext -> case hiePass @p of-#if __GLASGOW_HASKELL__ < 811-        HieRn -> dataConCantHappen ext-#endif         HieTc           | AbsBinds{ abs_exports = xs, abs_binds = binds                     , abs_ev_binds = ev_binds@@ -878,11 +864,11 @@                     (toHie $ fmap (BC context scope) binds)             , toHie $ map (L span . abe_wrap) xs             , toHie $-                map (EvBindContext (mkScopeA span) (getRealSpanA span)+                map (EvBindContext (mkScope span) (getRealSpanA span)                     . L span) ev_binds             , toHie $                 map (C (EvidenceVarBind EvSigBind-                                        (mkScopeA span)+                                        (mkScope span)                                         (getRealSpanA span))                     . L span) ev_vars             ]@@ -918,14 +904,14 @@         ]         where           lhsScope = combineScopes varScope detScope-          varScope = mkLScopeN var-          patScope = mkScopeA $ getLoc pat+          varScope = mkScope var+          patScope = mkScope $ getLoc pat           detScope = case dets of-            (PrefixCon _ args) -> foldr combineScopes NoScope $ map mkLScopeN args-            (InfixCon a b) -> combineScopes (mkLScopeN a) (mkLScopeN b)+            (PrefixCon _ args) -> foldr combineScopes NoScope $ map mkScope args+            (InfixCon a b) -> combineScopes (mkScope a) (mkScope b)             (RecCon r) -> foldr go NoScope r           go (RecordPatSynField a b) c = combineScopes c-            $ combineScopes (mkLScopeN (foLabel a)) (mkLScopeN b)+            $ combineScopes (mkScope (foLabel a)) (mkScope b)           detSpan = case detScope of             LocalScope a -> Just a             _ -> Nothing@@ -945,28 +931,34 @@          ) => ToHie (LocatedA (Match (GhcPass p) (LocatedA (body (GhcPass p))))) where   toHie (L span m ) = concatM $ makeNodeA m span : case m of     Match{m_ctxt=mctx, m_pats = pats, m_grhss =  grhss } ->-      [ toHie mctx+      [ toHieHsMatchContext @p mctx       , let rhsScope = mkScope $ grhss_span grhss           in toHie $ patScopes Nothing rhsScope NoScope pats       , toHie grhss       ] -instance HiePass p => ToHie (HsMatchContext (GhcPass p)) where-  toHie (FunRhs{mc_fun=name}) = toHie $ C MatchBind name'-    where+toHieHsMatchContext :: forall p. HiePass p => HsMatchContext (LIdP (NoGhcTc (GhcPass p)))+                                           -> HieM [HieAST Type]+toHieHsMatchContext ctxt+  = case ctxt of+      FunRhs{mc_fun=name} -> toHie $ C MatchBind (get_name name)+      StmtCtxt a          -> toHieHsStmtContext @p a+      _                   -> pure []+  where       -- See a paragraph about Haddock in #20415.-      name' :: LocatedN Name-      name' = case hiePass @p of-        HieRn -> name-        HieTc -> name-  toHie (StmtCtxt a) = toHie a-  toHie _ = pure []+    get_name :: LIdP (NoGhcTc (GhcPass p)) -> LocatedN Name+    get_name name = case hiePass @p of+                      HieRn -> name+                      HieTc -> name -instance HiePass p => ToHie (HsStmtContext (GhcPass p)) where-  toHie (PatGuard a) = toHie a-  toHie (ParStmtCtxt a) = toHie a-  toHie (TransStmtCtxt a) = toHie a-  toHie _ = pure []+toHieHsStmtContext :: forall p. HiePass p => HsStmtContext (LIdP (NoGhcTc (GhcPass p)))+                                          -> HieM [HieAST Type]+toHieHsStmtContext ctxt+  = case ctxt of+      PatGuard a      -> toHieHsMatchContext @p a+      ParStmtCtxt a   -> toHieHsStmtContext  @p a+      TransStmtCtxt a -> toHieHsStmtContext  @p a+      _               -> pure []  instance HiePass p => ToHie (PScoped (LocatedA (Pat (GhcPass p)))) where   toHie (PS rsp scope pscope lpat@(L ospan opat)) =@@ -979,14 +971,14 @@       LazyPat _ p ->         [ toHie $ PS rsp scope pscope p         ]-      AsPat _ lname _ pat ->+      AsPat _ lname pat ->         [ toHie $ C (PatternBind scope-                                 (combineScopes (mkLScopeA pat) pscope)+                                 (combineScopes (mkScope pat) pscope)                                  rsp)                     lname         , toHie $ PS rsp scope pscope pat         ]-      ParPat _ _ pat _ ->+      ParPat _ pat ->         [ toHie $ PS rsp scope pscope pat         ]       BangPat _ pat ->@@ -1009,7 +1001,7 @@             , let ev_binds = cpt_binds ext                   ev_vars = cpt_dicts ext                   wrap = cpt_wrap ext-                  evscope = mkScopeA ospan `combineScopes` scope `combineScopes` pscope+                  evscope = mkScope ospan `combineScopes` scope `combineScopes` pscope                  in concatM [ toHie $ EvBindContext scope rsp $ L ospan ev_binds                             , toHie $ L ospan wrap                             , toHie $ map (C (EvidenceVarBind EvPatternBind evscope rsp)@@ -1029,20 +1021,30 @@         ]       LitPat _ _ ->         []-      NPat _ _ _ _ ->-        []-      NPlusKPat _ n _ _ _ _ ->+      NPat _ (L loc lit) _ eq ->+        [ toHie $ L (l2l loc :: SrcSpanAnnA) lit+        , toHieSyntax (L ospan eq)+        ]+      NPlusKPat _ n (L loc lit) _ ord _ ->         [ toHie $ C (PatternBind scope pscope rsp) n+        , toHie $ L (l2l loc :: SrcSpanAnnA) lit+        , toHieSyntax (L ospan ord)         ]       SigPat _ pat sig ->         [ toHie $ PS rsp scope pscope pat         , case hiePass @p of             HieTc ->-              let cscope = mkLScopeA pat in+              let cscope = mkScope pat in                 toHie $ TS (ResolvedScopes [cscope, scope, pscope])                            sig             HieRn -> pure []         ]+      EmbTyPat _ tp ->+        [ toHie $ TS (ResolvedScopes [scope, pscope]) tp+        ]+      InvisPat _ tp ->+        [ toHie $ TS (ResolvedScopes [scope, pscope]) tp+        ]       XPat e ->         case hiePass @p of           HieRn -> case e of@@ -1055,11 +1057,11 @@             ExpansionPat _ p -> [ toHie $ PS rsp scope pscope (L ospan p) ]     where       contextify :: a ~ LPat (GhcPass p) => HsConDetails (HsConPatTyArg GhcRn) a (HsRecFields (GhcPass p) a)-                 -> HsConDetails (TScoped (HsPatSigType GhcRn)) (PScoped a) (RContext (HsRecFields (GhcPass p) (PScoped a)))+                 -> HsConDetails (TScoped (HsTyPat GhcRn)) (PScoped a) (RContext (HsRecFields (GhcPass p) (PScoped a)))       contextify (PrefixCon tyargs args) =         PrefixCon (taScopes scope argscope tyargs)                   (patScopes rsp scope pscope args)-        where argscope = foldr combineScopes NoScope $ map mkLScopeA args+        where argscope = foldr combineScopes NoScope $ map mkScope args       contextify (InfixCon a b) = InfixCon a' b'         where [a', b'] = patScopes rsp scope pscope [a,b]       contextify (RecCon r) = RecCon $ RC RecFieldMatch $ contextify_rec r@@ -1071,13 +1073,36 @@             L spn $ HsFieldBind x lbl (PS rsp scope fscope pat) pun           scoped_fds = listScopes pscope fds +toHieSyntax :: forall p. HiePass p => LocatedA (SyntaxExpr (GhcPass p)) -> HieM [HieAST Type]+toHieSyntax s = local (const GeneratedInfo) $ case hiePass @p of+  HieRn -> toHie s+  HieTc -> toHie s++instance ToHie (LocatedA SyntaxExprRn) where+  toHie (L mspan (SyntaxExprRn expr)) = toHie (L mspan expr)+  toHie (L _ NoSyntaxExprRn) = pure []++instance ToHie (LocatedA SyntaxExprTc) where+  toHie (L mspan (SyntaxExprTc expr w1 w2)) = concatM+      [ toHie (L mspan expr)+      , concatMapM (toHie . L mspan) w1+      , toHie (L mspan w2)+      ]+  toHie (L _ NoSyntaxExprTc) = pure []+ instance ToHie (TScoped (HsPatSigType GhcRn)) where   toHie (TS sc (HsPS (HsPSRn wcs tvs) body@(L span _))) = concatM $-      [ bindingsOnly $ map (C $ TyVarBind (mkScopeA span) sc) (wcs++tvs)+      [ bindingsOnly $ map (C $ TyVarBind (mkScope span) sc) (wcs++tvs)       , toHie body       ]   -- See Note [Scoping Rules for SigPat] +instance ToHie (TScoped (HsTyPat GhcRn)) where+  toHie (TS sc (HsTP (HsTPRn wcs imp_tvs exp_tvs) body@(L span _))) = concatM $+      [ bindingsOnly $ map (C $ TyVarBind (mkScope span) sc) (wcs ++ imp_tvs ++ exp_tvs)+      , toHie body+      ]+ instance ( ToHie (LocatedA (body (GhcPass p)))          , HiePass p          , AnnoBody p body@@ -1094,10 +1119,54 @@          ) => ToHie (LocatedAn NoEpAnns (GRHS (GhcPass p) (LocatedA (body (GhcPass p))))) where   toHie (L span g) = concatM $ makeNodeA g span : case g of     GRHS _ guards body ->-      [ toHie $ listScopes (mkLScopeA body) guards+      [ toHie $ listScopes (mkScope body) guards       , toHie body       ] +{-+Note [Source locations for implicit function calls]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+While calls to e.g. 'fromString' with -XOverloadedStrings do not actually+appear in the source code, giving their HsWrapper the location of the+overloaded bit of syntax that triggered them is useful for assigning+their type class evidence uses to the right location in the HIE AST.+Without this, we only get type class instance information under the+expected top-level node if the type had to be inferred. (#23540)++We currently handle the following constructors with this in mind,+all largely in the renamer as their locations are normally inherited by+the typechecker:++  * HsOverLit, where we assign the SrcSpan of the overloaded literal+    to ol_from_fun.+  * HsDo, where we give the SrcSpan of the entire do block to each+    ApplicativeStmt.+  * Expanded (via ExpandedThingRn) ExplicitList{}, where we give the SrcSpan of the original+    list expression to the 'fromListN' call.++In order for the implicit function calls to not be confused for actual+occurrences of functions in the source code, most of this extra information+is put under 'GeneratedInfo'.+-}++whenPostTc :: forall p t m. (HiePass p, Applicative t, Monoid m) => ((p ~ 'Typechecked) => t m) -> t m+whenPostTc a = case hiePass @p of+  HieTc -> a+  HieRn -> pure mempty++-- | Helper function for a common pattern where we are only interested in+-- implicit evidence information: runs only post-typecheck and marks the+-- current 'NodeOrigin' as generated.+whenPostTcGen :: forall p. HiePass p => ((p ~ 'Typechecked) => HieM [HieAST Type]) -> HieM [HieAST Type]+whenPostTcGen a = local (const GeneratedInfo) $ whenPostTc @p a++instance HiePass p => ToHie (LocatedA (HsOverLit (GhcPass p))) where+  toHie (L span (OverLit x _)) = whenPostTcGen @p $ concatM $ case x of+      OverLitTc _ witness _ ->+        [ toHie (L span witness)+        ]+      -- See Note [Source locations for implicit function calls]+ instance HiePass p => ToHie (LocatedA (HsExpr (GhcPass p))) where   toHie e@(L mspan oexpr) = concatM $ getTypeNode e : case oexpr of       HsVar _ (L _ var) ->@@ -1106,23 +1175,22 @@         ]       HsUnboundVar _ _ -> []  -- there is an unbound name here, but that causes trouble       HsRecSel _ fld ->-        [ toHie $ RFC RecFieldOcc Nothing (L (l2l mspan:: SrcAnn NoEpAnns) fld)+        [ toHie $ RFC RecFieldOcc Nothing (L mspan fld)         ]       HsOverLabel {} -> []       HsIPVar _ _ -> []-      HsOverLit _ _ -> []-      HsLit _ _ -> []-      HsLam _ mg ->-        [ toHie mg+      HsOverLit _ o ->+        [ toHie (L mspan o)         ]-      HsLamCase _ _ mg ->+      HsLit _ _ -> []+      HsLam _ _ mg ->         [ toHie mg         ]       HsApp _ a b ->         [ toHie a         , toHie b         ]-      HsAppType _ expr _ sig ->+      HsAppType _ expr sig ->         [ toHie expr         , toHie $ TS (ResolvedScopes []) sig         ]@@ -1134,7 +1202,7 @@       NegApp _ a _ ->         [ toHie a         ]-      HsPar _ _ a _ ->+      HsPar _ a ->         [ toHie a         ]       SectionL _ a b ->@@ -1163,8 +1231,8 @@       HsMultiIf _ grhss ->         [ toHie grhss         ]-      HsLet _ _ binds _ expr ->-        [ toHie $ RS (mkLScopeA expr) binds+      HsLet _ binds expr ->+        [ toHie $ RS (mkScope expr) binds         , toHie expr         ]       HsDo _ _ (L ispan stmts) ->@@ -1194,21 +1262,25 @@         ]       ExprWithTySig _ expr sig ->         [ toHie expr-        , toHie $ TS (ResolvedScopes [mkLScopeA expr]) sig+        , toHie $ TS (ResolvedScopes [mkScope expr]) sig         ]-      ArithSeq _ _ info ->+      ArithSeq enum _ info ->         [ toHie info+        , whenPostTcGen @p $ toHie (L mspan enum)         ]       HsPragE _ _ expr ->         [ toHie expr         ]       HsProc _ pat cmdtop ->-        [ toHie $ PS Nothing (mkLScopeA cmdtop) NoScope pat+        [ toHie $ PS Nothing (mkScope cmdtop) NoScope pat         , toHie cmdtop         ]       HsStatic _ expr ->         [ toHie expr         ]+      HsEmbTy _ ty ->+        [ toHie $ TS (ResolvedScopes []) ty+        ]       HsTypedBracket xbracket b -> case hiePass @p of         HieRn ->           [ toHie b@@ -1240,8 +1312,8 @@              WrapExpr (HsWrap w a)                -> [ toHie $ L mspan a                   , toHie (L mspan w) ]-             ExpansionExpr (HsExpanded _ b)-               -> [ toHie (L mspan b) ]+             ExpandedThingTc _ e+               -> [ toHie (L mspan e) ]              ConLikeTc con _ _                -> [ toHie $ C Use $ L mspan $ conLikeName con ]              HsTick _ expr@@ -1268,15 +1340,22 @@       LastStmt _ body _ _ ->         [ toHie body         ]-      BindStmt _ pat body ->+      BindStmt monad pat body ->         [ toHie $ PS (getRealSpan $ getLocA body) scope NoScope pat         , toHie body+        , whenPostTcGen @p $+            toHieSyntax $ L span (xbstc_bindOp monad)         ]       ApplicativeStmt _ stmts _ ->         [ concatMapM (toHie . RS scope . snd) stmts+        , let applicative_or_functor = map fst stmts+           in whenPostTcGen @p $+                concatMapM (toHieSyntax . L span) applicative_or_functor         ]-      BodyStmt _ body _ _ ->+      BodyStmt _ body monad alternative ->         [ toHie body+        , whenPostTc @p $+            concatMapM (toHieSyntax . L span) [monad, alternative]         ]       LetStmt _ binds ->         [ toHie $ RS scope binds@@ -1323,19 +1402,19 @@   = foldr combineScopes NoScope (bsScope ++ sigsScope)   where     bsScope :: [Scope]-    bsScope = map (mkScopeA . getLoc) $ bagToList bs+    bsScope = map (mkScope . getLoc) $ bagToList bs     sigsScope :: [Scope]     sigsScope = map (mkScope . getLocA) sigs scopeHsLocaLBinds (HsValBinds _ (XValBindsLR (NValBinds bs sigs)))   = foldr combineScopes NoScope (bsScope ++ sigsScope)   where     bsScope :: [Scope]-    bsScope = map (mkScopeA . getLoc) $ concatMap (bagToList . snd) bs+    bsScope = map (mkScope . getLoc) $ concatMap (bagToList . snd) bs     sigsScope :: [Scope]     sigsScope = map (mkScope . getLocA) sigs  scopeHsLocaLBinds (HsIPBinds _ (IPBinds _ bs))-  = foldr combineScopes NoScope (map (mkScopeA . getLoc) bs)+  = foldr combineScopes NoScope (map (mkScope . getLoc) bs) scopeHsLocaLBinds (EmptyLocalBinds _) = NoScope  instance HiePass p => ToHie (RScoped (LocatedA (IPBind (GhcPass p)))) where@@ -1370,18 +1449,19 @@          ) => ToHie (RContext (LocatedA (HsFieldBind label arg))) where   toHie (RC c (L span recfld)) = concatM $ makeNode recfld (locA span) : case recfld of     HsFieldBind _ label expr _ ->-      [ toHie $ RFC c (getRealSpan $ loc expr) label+      [ toHie $ RFC c (getRealSpan $ getHasLoc expr) label       , toHie expr       ] -instance HiePass p => ToHie (RFContext (LocatedAn NoEpAnns (FieldOcc (GhcPass p)))) where+instance HiePass p => ToHie (RFContext (LocatedA (FieldOcc (GhcPass p)))) where   toHie (RFC c rhs (L nspan f)) = concatM $ case f of     FieldOcc fld _ ->       case hiePass @p of         HieRn -> [toHie $ C (RecField c rhs) (L (locA nspan) fld)]         HieTc -> [toHie $ C (RecField c rhs) (L (locA nspan) fld)] -instance HiePass p => ToHie (RFContext (LocatedAn NoEpAnns (AmbiguousFieldOcc (GhcPass p)))) where+instance HiePass p => ToHie (RFContext (LocatedA (AmbiguousFieldOcc (GhcPass p)))) where+   toHie (RFC c rhs (L nspan afo)) = concatM $ case afo of     Unambiguous fld _ ->       case hiePass @p of@@ -1408,8 +1488,8 @@   toHie (InfixCon a b) = concatM [ toHie a, toHie b]  instance ToHie (HsConDeclGADTDetails GhcRn) where-  toHie (PrefixConGADT args) = toHie args-  toHie (RecConGADT rec _) = toHie rec+  toHie (PrefixConGADT _ args) = toHie args+  toHie (RecConGADT _ rec) = toHie rec  instance HiePass p => ToHie (LocatedAn NoEpAnns (HsCmdTop (GhcPass p))) where   toHie (L span top) = concatM $ makeNodeA top span : case top of@@ -1431,17 +1511,14 @@         [ toHie a         , toHie b         ]-      HsCmdLam _ mg ->-        [ toHie mg-        ]-      HsCmdPar _ _ a _ ->+      HsCmdPar _ a ->         [ toHie a         ]       HsCmdCase _ expr alts ->         [ toHie expr         , toHie alts         ]-      HsCmdLamCase _ _ alts ->+      HsCmdLam _ _ alts ->         [ toHie alts         ]       HsCmdIf _ _ a b c ->@@ -1449,8 +1526,8 @@         , toHie b         , toHie c         ]-      HsCmdLet _ _ binds _ cmd' ->-        [ toHie $ RS (mkLScopeA cmd') binds+      HsCmdLet _ binds cmd' ->+        [ toHie $ RS (mkScope cmd') binds         , toHie cmd'         ]       HsCmdDo _ (L ispan stmts) ->@@ -1487,11 +1564,11 @@         , toHie defn         ]         where-          quant_scope = mkLScopeA $ fromMaybe (noLocA []) $ dd_ctxt defn+          quant_scope = mkScope $ fromMaybe (noLocA []) $ dd_ctxt defn           rhs_scope = sig_sc `combineScopes` con_sc `combineScopes` deriv_sc-          sig_sc = maybe NoScope mkLScopeA $ dd_kindSig defn-          con_sc = foldr combineScopes NoScope $ mkLScopeA <$> dd_cons defn-          deriv_sc = foldr combineScopes NoScope $ mkLScopeA <$> dd_derivs defn+          sig_sc = maybe NoScope mkScope $ dd_kindSig defn+          con_sc = foldr combineScopes NoScope $ mkScope <$> dd_cons defn+          deriv_sc = foldr combineScopes NoScope $ mkScope <$> dd_derivs defn       ClassDecl { tcdCtxt = context                 , tcdLName = name                 , tcdTyVars = vars@@ -1512,9 +1589,9 @@         , toHie deftyps         ]         where-          context_scope = mkLScopeA $ fromMaybe (noLocA []) context+          context_scope = mkScope $ fromMaybe (noLocA []) context           rhs_scope = foldl1' combineScopes $ map mkScope-            [ loc deps, loc sigs, loc (bagToList meths), loc typs, loc deftyps]+            [ getHasLocList deps, getHasLocList sigs, getHasLocList (bagToList meths), getHasLocList typs, getHasLocList deftyps]  instance ToHie (LocatedA (FamilyDecl GhcRn)) where   toHie (L span decl) = concatM $ makeNodeA decl span : case decl of@@ -1536,7 +1613,7 @@     , toHie $ map go eqns     ]     where-      go (L l ib) = TS (ResolvedScopes [mkScopeA l]) ib+      go (L l ib) = TS (ResolvedScopes [mkScope l]) ib   toHie _ = pure []  instance ToHie (RScoped (LocatedAn NoEpAnns (FamilyResultSig GhcRn))) where@@ -1567,14 +1644,14 @@ instance (ToHie rhs, HasLoc rhs)     => ToHie (FamEqn GhcRn rhs) where   toHie fe@(FamEqn _ var outer_bndrs pats _ rhs) = concatM $-    [ toHie $ C (Decl InstDec $ getRealSpan $ loc fe) var+    [ toHie $ C (Decl InstDec $ getRealSpan $ getHasLoc fe) var     , toHie $ TVS (ResolvedScopes []) scope outer_bndrs     , toHie pats     , toHie rhs     ]     where scope = combineScopes patsScope rhsScope-          patsScope = mkScope (loc pats)-          rhsScope = mkScope (loc rhs)+          patsScope = mkScope (getHasLocList pats)+          rhsScope = mkScope (getHasLoc rhs)  instance ToHie (LocatedAn NoEpAnns (InjectivityAnn GhcRn)) where   toHie (L span ann) = concatM $ makeNodeA ann span : case ann of@@ -1600,7 +1677,7 @@ instance ToHie (LocatedAn NoEpAnns (HsDerivingClause GhcRn)) where   toHie (L span cl) = concatM $ makeNodeA cl span : case cl of       HsDerivingClause _ strat dct ->-        [ toHie (RS (mkLScopeA dct) <$> strat)+        [ toHie (RS (mkScope dct) <$> strat)         , toHie dct         ] @@ -1630,7 +1707,7 @@         [ toHie $ C (Decl ConDec $ getRealSpanA span) <$> names         , case outer_bndrs of             HsOuterImplicit{hso_ximplicit = imp_vars} ->-              bindingsOnly $ map (C $ TyVarBind (mkScopeA outer_bndrs_loc) resScope)+              bindingsOnly $ map (C $ TyVarBind (mkScope outer_bndrs_loc) resScope)                              imp_vars             HsOuterExplicit{hso_bndrs = exp_bndrs} ->               toHie $ tvScopes resScope NoScope exp_bndrs@@ -1641,11 +1718,11 @@         ]         where           rhsScope = combineScopes argsScope tyScope-          ctxScope = maybe NoScope mkLScopeA ctx+          ctxScope = maybe NoScope mkScope ctx           argsScope = case args of-            PrefixConGADT xs -> scaled_args_scope xs-            RecConGADT x _   -> mkLScopeA x-          tyScope = mkLScopeA typ+            PrefixConGADT _ xs -> scaled_args_scope xs+            RecConGADT _ x     -> mkScope x+          tyScope = mkScope typ           resScope = ResolvedScopes [ctxScope, rhsScope]       ConDeclH98 { con_name = name, con_ex_tvs = qvars                  , con_mb_cxt = ctx, con_args = dets@@ -1658,13 +1735,13 @@         ]         where           rhsScope = combineScopes ctxScope argsScope-          ctxScope = maybe NoScope mkLScopeA ctx+          ctxScope = maybe NoScope mkScope ctx           argsScope = case dets of             PrefixCon _ xs -> scaled_args_scope xs             InfixCon a b   -> scaled_args_scope [a, b]-            RecCon x       -> mkLScopeA x+            RecCon x       -> mkScope x     where scaled_args_scope :: [HsScaled GhcRn (LHsType GhcRn)] -> Scope-          scaled_args_scope = foldr combineScopes NoScope . map (mkLScopeA . hsScaledThing)+          scaled_args_scope = foldr combineScopes NoScope . map (mkScope . hsScaledThing)  instance ToHie (LocatedL [LocatedA (ConDeclField GhcRn)]) where   toHie (L span decls) = concatM $@@ -1677,14 +1754,14 @@       [ bindingsOnly $ map (C $ TyVarBind (mkScope span) sc) names       , toHie $ TS sc a       ]-    where span = loc a+    where span = getHasLoc a  instance ToHie (TScoped (HsWildCardBndrs GhcRn (LocatedA (HsType GhcRn)))) where   toHie (TS sc (HsWC names a)) = concatM $       [ bindingsOnly $ map (C $ TyVarBind (mkScope span) sc) names       , toHie a       ]-    where span = loc a+    where span = getHasLoc a  instance ToHie (LocatedA (StandaloneKindSig GhcRn)) where   toHie (L sp sig) = concatM [makeNodeA sig sp, toHie sig]@@ -1735,16 +1812,15 @@           [ toHie $ (C Use) name           , maybe (pure []) (locOnly . getLocA) mtxt           ]-        CompleteMatchSig _ (L ispan names) typ ->-          [ locOnly ispan-          , toHie $ map (C Use) names+        CompleteMatchSig _ names typ ->+          [ toHie $ map (C Use) names           , toHie $ fmap (C Use) typ           ]         XSig _ -> []  instance ToHie (TScoped (LocatedA (HsSigType GhcRn))) where   toHie (TS tsc (L span t@HsSig{sig_bndrs=bndrs,sig_body=body})) = concatM $ makeNodeA t span :-      [ toHie (TVS tsc (mkScopeA span) bndrs)+      [ toHie (TVS tsc (mkScope span) bndrs)       , toHie body       ] @@ -1776,7 +1852,7 @@         [ toHie a         , toHie b         ]-      HsAppKindTy _ ty _ ki ->+      HsAppKindTy _ ty ki ->         [ toHie ty         , toHie ki         ]@@ -1834,8 +1910,8 @@       HsStarTy _ _ -> []       XHsType _ -> [] -instance (ToHie tm, ToHie ty) => ToHie (HsArg p tm ty) where-  toHie (HsValArg tm) = toHie tm+instance (ToHie tm, ToHie ty) => ToHie (HsArg (GhcPass p) tm ty) where+  toHie (HsValArg _ tm) = toHie tm   toHie (HsTypeArg _ ty) = toHie ty   toHie (HsArgPar sp) = locOnly sp @@ -1855,7 +1931,7 @@     , toHie $ tvScopes sc NoScope vars     ]     where-      varLoc = loc vars+      varLoc = getHasLocList vars       bindings = map (C $ TyVarBind (mkScope varLoc) sc) implicits  instance ToHie (LocatedC [LocatedA (HsType GhcRn)]) where@@ -1867,7 +1943,7 @@ instance ToHie (LocatedA (ConDeclField GhcRn)) where   toHie (L span field) = concatM $ makeNode field (locA span) : case field of       ConDeclField _ fields typ doc ->-        [ toHie $ map (RFC RecFieldDecl (getRealSpan $ loc typ)) fields+        [ toHie $ map (RFC RecFieldDecl (getRealSpan $ getHasLoc typ)) fields         , toHie typ         , toHie doc         ]@@ -1956,7 +2032,7 @@  instance ToHie (LocatedA (ClsInstDecl GhcRn)) where   toHie (L span decl) = concatM-    [ toHie $ TS (ResolvedScopes [mkScopeA span]) $ cid_poly_ty decl+    [ toHie $ TS (ResolvedScopes [mkScope span]) $ cid_poly_ty decl     , toHie $ fmap (BC InstanceBind ModuleScope) $ cid_binds decl     , toHie $ map (SC $ SI InstSig $ getRealSpanA span) $ cid_sigs decl     , concatMapM (locOnly . getLocA) $ cid_tyfam_insts decl@@ -1967,10 +2043,10 @@     ]  instance ToHie (LocatedA (DataFamInstDecl GhcRn)) where-  toHie (L sp (DataFamInstDecl d)) = toHie $ TS (ResolvedScopes [mkScopeA sp]) d+  toHie (L sp (DataFamInstDecl d)) = toHie $ TS (ResolvedScopes [mkScope sp]) d  instance ToHie (LocatedA (TyFamInstDecl GhcRn)) where-  toHie (L sp (TyFamInstDecl _ d)) = toHie $ TS (ResolvedScopes [mkScopeA sp]) d+  toHie (L sp (TyFamInstDecl _ d)) = toHie $ TS (ResolvedScopes [mkScope sp]) d  instance HiePass p => ToHie (Context (FieldOcc (GhcPass p))) where   toHie (C c (FieldOcc n (L l _))) = case hiePass @p of@@ -1987,7 +2063,7 @@   toHie (L span decl) = concatM $ makeNodeA decl span : case decl of       DerivDecl _ typ strat overlap ->         [ toHie $ TS (ResolvedScopes []) typ-        , toHie $ (RS (mkScopeA span) <$> strat)+        , toHie $ (RS (mkScope span) <$> strat)         , toHie overlap         ] @@ -2018,15 +2094,15 @@  instance ToHie (ForeignImport GhcRn) where   toHie (CImport (L c _) (L a _) (L b _) _ _) = concatM $-    [ locOnly a-    , locOnly b-    , locOnly c+    [ locOnlyE a+    , locOnlyE b+    , locOnlyE c     ]  instance ToHie (ForeignExport GhcRn) where   toHie (CExport (L b _) (L a _)) = concatM $-    [ locOnly a-    , locOnly b+    [ locOnlyE a+    , locOnlyE b     ]  instance ToHie (LocatedA (WarnDecls GhcRn)) where@@ -2069,9 +2145,9 @@         , toHie exprB         ]     where scope = bndrs_sc `combineScopes` exprA_sc `combineScopes` exprB_sc-          bndrs_sc = maybe NoScope mkLScopeA (listToMaybe bndrs)-          exprA_sc = mkLScopeA exprA-          exprB_sc = mkLScopeA exprB+          bndrs_sc = maybe NoScope mkScope (listToMaybe bndrs)+          exprA_sc = mkScope exprA+          exprB_sc = mkScope exprB  instance ToHie (RScoped (LocatedAn NoEpAnns (RuleBndr GhcRn))) where   toHie (RS sc (L span bndr)) = concatM $ makeNodeA bndr span : case bndr of@@ -2105,16 +2181,16 @@  instance ToHie (IEContext (LocatedA (IE GhcRn))) where   toHie (IEC c (L span ie)) = concatM $ makeNode ie (locA span) : case ie of-      IEVar _ n ->+      IEVar _ n _ ->         [ toHie $ IEC c n         ]-      IEThingAbs _ n ->+      IEThingAbs _ n _ ->         [ toHie $ IEC c n         ]-      IEThingAll _ n ->+      IEThingAll _ n _ ->         [ toHie $ IEC c n         ]-      IEThingWith _ n _ ns ->+      IEThingWith _ n _ ns _ ->         [ toHie $ IEC c n         , toHie $ map (IEC c) ns         ]
compiler/GHC/Iface/Ext/Binary.hs view
@@ -1,8 +1,6 @@ {- Binary serialization for .hie files. -}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE BangPatterns #-}  module GHC.Iface.Ext.Binary    ( readHieFile
compiler/GHC/Iface/Ext/Utils.hs view
@@ -107,8 +107,14 @@   , evidenceSpan :: RealSrcSpan   , evidenceType :: a   , evidenceDetails :: Maybe (EvVarSource, Scope, Maybe Span)-  } deriving (Eq,Ord,Functor)+  } deriving (Eq, Functor) +instance Ord a => Ord (EvidenceInfo a) where+  compare (EvidenceInfo name span typ dets) (EvidenceInfo name' span' typ' dets') =+    case stableNameCmp name name' of+      EQ -> compare (span, typ, dets) (span', typ', dets')+      r -> r+ instance (Outputable a) => Outputable (EvidenceInfo a) where   ppr (EvidenceInfo name span typ dets) =     hang (ppr name <+> text "at" <+> ppr span O.<> text ", of type:" <+> ppr typ) 4 $@@ -527,21 +533,14 @@   pure [Node e span []] locOnly _ = pure [] -mkScopeA :: SrcSpanAnn' ann -> Scope-mkScopeA l = mkScope (locA l)--mkScope :: SrcSpan -> Scope-mkScope (RealSrcSpan sp _) = LocalScope sp-mkScope _ = NoScope--mkLScope :: Located a -> Scope-mkLScope = mkScope . getLoc--mkLScopeA :: GenLocated (SrcSpanAnn' a) e -> Scope-mkLScopeA = mkScope . locA . getLoc+locOnlyE :: Monad m => EpaLocation -> ReaderT NodeOrigin m [HieAST a]+locOnlyE (EpaSpan s) = locOnly s+locOnlyE _ = pure [] -mkLScopeN :: LocatedN a -> Scope-mkLScopeN = mkScope . getLocA+mkScope :: (HasLoc a) => a -> Scope+mkScope a = case getHasLoc a of+              (RealSrcSpan sp _) -> LocalScope sp+              _ -> NoScope  combineScopes :: Scope -> Scope -> Scope combineScopes ModuleScope _ = ModuleScope@@ -557,8 +556,8 @@ {-# INLINEABLE makeNodeA #-} makeNodeA   :: (Monad m, Data a)-  => a                       -- ^ helps fill in 'nodeAnnotations' (with 'Data')-  -> SrcSpanAnn' ann         -- ^ return an empty list if this is unhelpful+  => a                 -- ^ helps fill in 'nodeAnnotations' (with 'Data')+  -> EpAnn ann         -- ^ return an empty list if this is unhelpful   -> ReaderT NodeOrigin m [HieAST b] makeNodeA x spn = makeNode x (locA spn) 
compiler/GHC/Iface/Load.hs view
@@ -4,10 +4,9 @@  -} -{-# LANGUAGE BangPatterns, NondecreasingIndentation #-}+{-# LANGUAGE NondecreasingIndentation #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE LambdaCase #-}-{-# LANGUAGE FlexibleContexts #-}  {-# OPTIONS_GHC -fno-warn-orphans #-} {-# LANGUAGE ViewPatterns #-}@@ -67,7 +66,6 @@ import GHC.Utils.Error import GHC.Utils.Outputable as Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Constants (debugIsOn) import GHC.Utils.Logger @@ -1064,7 +1062,7 @@ all names that don't originate in the current module. In order to keep visual noise as low as possible, we keep local names unqualified. -For some background on this choice see trac #15269.+For some background on this choice see #15269. -}  -- | Read binary interface, and print it out
compiler/GHC/Iface/Make.hs view
@@ -14,6 +14,7 @@    , mkFullIface    , mkIfaceTc    , mkIfaceExports+   , toIfaceWarningTxt    ) where @@ -71,7 +72,6 @@  import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Logger  import GHC.Data.FastString@@ -367,7 +367,8 @@ instanceToIfaceInst (ClsInst { is_dfun = dfun_id, is_flag = oflag                              , is_cls_nm = cls_name, is_cls = cls                              , is_tcs = rough_tcs-                             , is_orphan = orph })+                             , is_orphan = orph+                             , is_warn = warn })   = assert (cls_name == className cls) $     IfaceClsInst { ifDFun     = idName dfun_id                  , ifOFlag    = oflag@@ -375,7 +376,8 @@                  , ifInstTys  = ifaceRoughMatchTcs $ tail rough_tcs                    -- N.B. Drop the class name from the rough match template                    --      It is put back by GHC.Core.InstEnv.mkImportedClsInst-                 , ifInstOrph = orph }+                 , ifInstOrph = orph+                 , ifInstWarn = fmap toIfaceWarningTxt warn }  -------------------------- famInstToIfaceFamInst :: FamInst -> IfaceFamInst@@ -403,8 +405,8 @@     ds' = [(occ, toIfaceWarningTxt txt) | (occ, txt) <- ds]  toIfaceWarningTxt :: WarningTxt GhcRn -> IfaceWarningTxt-toIfaceWarningTxt (WarningTxt mb_cat src strs) = IfWarningTxt (unLoc . iwc_wc . unLoc <$> mb_cat) (unLoc src) (map (toIfaceStringLiteralWithNames . unLoc) strs)-toIfaceWarningTxt (DeprecatedTxt src strs) = IfDeprecatedTxt (unLoc src) (map (toIfaceStringLiteralWithNames . unLoc) strs)+toIfaceWarningTxt (WarningTxt mb_cat src strs) = IfWarningTxt (unLoc . iwc_wc . unLoc <$> mb_cat) src (map (toIfaceStringLiteralWithNames . unLoc) strs)+toIfaceWarningTxt (DeprecatedTxt src strs) = IfDeprecatedTxt src (map (toIfaceStringLiteralWithNames . unLoc) strs)  toIfaceStringLiteralWithNames :: WithHsDocIdentifiers StringLiteral GhcRn -> (IfaceStringLiteral, [IfExtName]) toIfaceStringLiteralWithNames (WithHsDocIdentifiers src names) = (toIfaceStringLiteral src, map unLoc names)
compiler/GHC/Iface/Recomp.hs view
@@ -43,7 +43,6 @@  import GHC.Utils.Error import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Outputable as Outputable import GHC.Utils.Misc as Utils import GHC.Utils.Binary
compiler/GHC/Iface/Recomp/Flags.hs view
@@ -70,10 +70,7 @@         -- Other flags which affect code generation         codegen = map (`gopt` dflags) (EnumSet.toList codeGenFlags) -        -- Did we include core for all bindings?-        fat_iface = gopt Opt_WriteIfSimplifiedCore dflags--        flags = ((mainis, safeHs, lang, cpp), (paths, prof, ticky, codegen, debugLevel, callerCcFilters, fat_iface))+        flags = ((mainis, safeHs, lang, cpp), (paths, prof, ticky, codegen, debugLevel, callerCcFilters))      in -- pprTrace "flags" (ppr flags) $        computeFingerprint nameio flags
compiler/GHC/Iface/Rename.hs view
@@ -668,8 +668,9 @@     = IfaceTyConAppCo role <$> rnIfaceTyCon tc <*> mapM rnIfaceCo cos rnIfaceCo (IfaceAppCo co1 co2)     = IfaceAppCo <$> rnIfaceCo co1 <*> rnIfaceCo co2-rnIfaceCo (IfaceForAllCo bndr co1 co2)-    = IfaceForAllCo <$> rnIfaceBndr bndr <*> rnIfaceCo co1 <*> rnIfaceCo co2+rnIfaceCo (IfaceForAllCo bndr visL visR co1 co2)+    = (\bndr' co1' co2' -> IfaceForAllCo bndr' visL visR co1' co2')+      <$> rnIfaceBndr bndr <*> rnIfaceCo co1 <*> rnIfaceCo co2 rnIfaceCo (IfaceFreeCoVar c) = pure (IfaceFreeCoVar c) rnIfaceCo (IfaceCoVarCo lcl) = IfaceCoVarCo <$> pure lcl rnIfaceCo (IfaceHoleCo lcl)  = IfaceHoleCo  <$> pure lcl
compiler/GHC/Iface/Tidy.hs view
@@ -8,7 +8,34 @@ (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 -} --- | Tidying up Core+{-| Tidying up Core++This module's purpose is to prepare the Core program for two distinct purposes:+* To be serialised into the module's interface file+* To feed to the code generator++The most important tasks are:+* Determine which `Name`s should ultimately be `Internal` and `External`+  (which may differ to whether they were originally `Internal` or `External`).+  See `Note [About the NameSorts]` in GHC.Types.Name.+  For example, in:+          module M where+            f x = x + y+              where y = factorial 4+  could be optimized during the Core pass to:+          module M where+            y = factorial 4+            f x = x + y+  in which case `y` would be changed from `Internal` to `External`.++* Rename local identifiers to avoid name clashes, so that unfoldings etc can+  be serialialised using the OccName, without Uniques.++  For example (`x_5` means `x` with a `Unique` of `5`):+          f x_12 x_23 = x_12+  would be changed to:+          f x_12 x1_23 = x_12+-} module GHC.Iface.Tidy   ( TidyOpts (..)   , UnfoldingExposure (..)@@ -357,6 +384,7 @@       -- ^ Are rules exposed or not?   , opt_static_ptr_opts :: !(Maybe StaticPtrOpts)       -- ^ Options for generated static pointers, if enabled (/= Nothing).+  , opt_keep_auto_rules :: !Bool   }  tidyProgram :: TidyOpts -> ModGuts -> IO (CgGuts, ModDetails)@@ -391,6 +419,8 @@     Nothing    -> pure ([], Nothing, tidy_binds)     Just sopts -> sptCreateStaticBinds sopts mod tidy_binds +  -- pprTraceM "trimmed_rules" (ppr trimmed_rules)+   let all_foreign_stubs = case mcstub of         Nothing    -> foreign_stubs         Just cstub -> foreign_stubs `appendStubC` cstub@@ -615,11 +645,8 @@  getTyConImplicitBinds :: TyCon -> [CoreBind] getTyConImplicitBinds tc-  | isDataTyCon tc = map get_defn (mapMaybe dataConWrapId_maybe (tyConDataCons tc))-  | otherwise      = []-    -- The 'otherwise' includes family TyCons of course, but also (less obviously)-    --  * Newtypes: see Note [Compulsory newtype unfolding] in GHC.Types.Id.Make-    --  * type data: we don't want any code for type-only stuff (#24620)+  | isNewTyCon tc = []  -- See Note [Compulsory newtype unfolding] in GHC.Types.Id.Make+  | otherwise     = map get_defn (mapMaybe dataConWrapId_maybe (tyConDataCons tc))  getClassImplicitBinds :: Class -> [CoreBind] getClassImplicitBinds cls@@ -854,7 +881,7 @@ dffvExpr (Var v)              = insert v dffvExpr (App e1 e2)          = dffvExpr e1 >> dffvExpr e2 dffvExpr (Lam v e)            = extendScope v (dffvExpr e)-dffvExpr (Tick (Breakpoint _ _ ids) e) = mapM_ insert ids >> dffvExpr e+dffvExpr (Tick (Breakpoint _ _ ids _) e) = mapM_ insert ids >> dffvExpr e dffvExpr (Tick _other e)    = dffvExpr e dffvExpr (Cast e _)           = dffvExpr e dffvExpr (Let (NonRec x r) e) = dffvBind (x,r) >> extendScope x (dffvExpr e)@@ -965,12 +992,18 @@  This stuff is the only reason for the ru_auto field in a Rule. -NB: In #18532 we looked at keeping auto-rules and it turned out to just make-compiler performance worse while increasing code sizes at the same time. The impact-varied. Compiling Cabal got ~3% slower, allocated ~3% more and wrote 15% more code to disk.-Nofib only saw 0.7% more compiler allocations and executable file size growth. But given-there was no difference in runtime for these benchmarks it turned out to be flat out worse.-See the ticket for more details.+We discard auto-rules by default, but keep them if -fkeep-auto-rules is on.++* Discard by default: in #18532 we looked at keeping auto-rules and it turned out to just make+  compiler performance worse while increasing code sizes at the same time. The+  impact varied. Compiling Cabal got ~3% slower, allocated ~3% more and wrote 15%+  more code to disk.  Nofib only saw 0.7% more compiler allocations and executable+  file size growth. But given there was no difference in runtime for these+  benchmarks it turned out to be flat out worse.  See the ticket for more details.++* Keep with -fkeep-auto-rules: in #21917 we found cases where we get a lot code+  duplication when we discard specialisations.  Agda is a case in point.  Having+  a flag gives us control over the rule-trimming decision. -}  findExternalRules :: TidyOpts@@ -982,11 +1015,12 @@ findExternalRules opts binds imp_id_rules unfold_env   = (trimmed_binds, filter keep_rule all_rules)   where-    imp_rules | (opt_expose_rules opts) = filter expose_rule imp_id_rules-              | otherwise               = []+    imp_rules | opt_expose_rules opts = filter expose_rule imp_id_rules+              | otherwise             = []     imp_user_rule_fvs = mapUnionVarSet user_rule_rhs_fvs imp_rules -    user_rule_rhs_fvs rule | isAutoRule rule = emptyVarSet+    user_rule_rhs_fvs rule | isAutoRule rule && not (opt_keep_auto_rules opts)+                                             = emptyVarSet                            | otherwise       = ruleRhsFreeVars rule      (trimmed_binds, local_bndrs, _, all_rules) = trim_binds binds@@ -1047,7 +1081,7 @@             -- In needed_fvs', we don't bother to delete binders from the fv set           local_rules  = [ rule-                        | (opt_expose_rules opts)+                        | opt_expose_rules opts                         , id <- bndrs                         , is_external_id id   -- Only collect rules for external Ids                         , rule <- idCoreRules id@@ -1083,11 +1117,9 @@                             -- See #19619                             let new_local_name = occ' `seq` mkInternalName uniq occ' loc                             return (occ_env', new_local_name)-        -- Even local, internal names must get a unique occurrence, because-        -- if we do -split-objs we externalise the name later, in the code generator-        ---        -- Similarly, we must make sure it has a system-wide Unique, because-        -- the byte-code generator builds a system-wide Name->BCO symbol table+        -- Even local, internal names must get a unique occurrence.+        -- This is necessary because the byte-code generator the byte-code+        -- generator builds a system-wide Name->BCO symbol table.    | local  && external = do new_external_name <- allocateGlobalBinder name_cache mod occ' loc                             return (occ_env', new_external_name)
compiler/GHC/IfaceToCore.hs view
@@ -87,7 +87,6 @@ import GHC.Utils.Outputable import GHC.Utils.Misc import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Constants (debugIsOn) import GHC.Utils.Logger @@ -131,6 +130,7 @@ import Data.Foldable import GHC.Builtin.Names (ioTyConName, rOOT_MAIN) import GHC.Iface.Errors.Types+import Language.Haskell.Syntax.Extension (NoExtField (NoExtField))  {- This module takes@@ -1227,11 +1227,12 @@ tcIfaceInst :: IfaceClsInst -> IfL ClsInst tcIfaceInst (IfaceClsInst { ifDFun = dfun_name, ifOFlag = oflag                           , ifInstCls = cls, ifInstTys = mb_tcs-                          , ifInstOrph = orph })+                          , ifInstOrph = orph, ifInstWarn = iface_warn })   = do { dfun <- forkM (text "Dict fun" <+> ppr dfun_name) $                     fmap tyThingId (tcIfaceImplicit dfun_name)        ; let mb_tcs' = map tcRoughTyCon mb_tcs-       ; return (mkImportedClsInst cls mb_tcs' dfun_name dfun oflag orph) }+             warn = fmap fromIfaceWarningTxt iface_warn+       ; return (mkImportedClsInst cls mb_tcs' dfun_name dfun oflag orph warn) }  tcIfaceFamInst :: IfaceFamInst -> IfL FamInst tcIfaceFamInst (IfaceFamInst { ifFamInstFam = fam, ifFamInstTys = mb_tcs@@ -1462,9 +1463,9 @@     go (IfaceFunCo r w c1 c2)    = mkFunCoNoFTF r <$> go w <*> go c1 <*> go c2     go (IfaceTyConAppCo r tc cs) = TyConAppCo r <$> tcIfaceTyCon tc <*> mapM go cs     go (IfaceAppCo c1 c2)        = AppCo <$> go c1 <*> go c2-    go (IfaceForAllCo tv k c)    = do { k' <- go k+    go (IfaceForAllCo tv visL visR k c) = do { k' <- go k                                       ; bindIfaceBndr tv $ \ tv' ->-                                        ForAllCo tv' k' <$> go c }+                                        ForAllCo tv' visL visR k' <$> go c }     go (IfaceCoVarCo n)          = CoVarCo <$> go_var n     go (IfaceAxiomInstCo n i cs) = AxiomInstCo <$> tcIfaceCoAxiom n <*> pure i <*> mapM go cs     go (IfaceUnivCo p r t1 t2)   = UnivCo <$> tcIfaceUnivCoProv p <*> pure r@@ -1491,7 +1492,6 @@ tcIfaceUnivCoProv (IfacePhantomProv kco)    = PhantomProv <$> tcIfaceCo kco tcIfaceUnivCoProv (IfaceProofIrrelProv kco) = ProofIrrelProv <$> tcIfaceCo kco tcIfaceUnivCoProv (IfacePluginProv str)     = return $ PluginProv str-tcIfaceUnivCoProv (IfaceCorePrepProv b)     = return $ CorePrepProv b  {- ************************************************************************@@ -1585,7 +1585,7 @@         ; id_info <- tcIdInfo False {- Don't ignore prags; we are inside one! -}                               NotTopLevel name ty' info         ; let id = mkLocalIdWithInfo name ManyTy ty' id_info-                     `asJoinId_maybe` tcJoinInfo ji+                     `asJoinId_maybe` ji         ; rhs' <- tcIfaceExpr rhs         ; body' <- extendIfaceIdEnv [id] (tcIfaceExpr body)         ; return (Let (NonRec id rhs') body') }@@ -1600,7 +1600,7 @@    tc_rec_bndr (IfLetBndr fs ty _ ji)      = do { name <- newIfaceName (mkVarOccFS fs)           ; ty'  <- tcIfaceType ty-          ; return (mkLocalId name ManyTy ty' `asJoinId_maybe` tcJoinInfo ji) }+          ; return (mkLocalId name ManyTy ty' `asJoinId_maybe` ji) }    tc_pair (IfLetBndr _ _ info _, rhs) id      = do { rhs' <- tcIfaceExpr rhs           ; id_info <- tcIdInfo False {- Don't ignore prags; we are inside one! -}@@ -1619,10 +1619,13 @@         return (Tick tickish' expr')  --------------------------tcIfaceTickish :: IfaceTickish -> IfM lcl CoreTickish+tcIfaceTickish :: IfaceTickish -> IfL CoreTickish tcIfaceTickish (IfaceHpcTick modl ix)   = return (HpcTick modl ix) tcIfaceTickish (IfaceSCC  cc tick push) = return (ProfNote cc tick push) tcIfaceTickish (IfaceSource src name)   = return (SourceNote src (LexicalFastString name))+tcIfaceTickish (IfaceBreakpoint ix fvs modl) = do+  fvs' <- mapM tcIfaceExpr fvs+  return (Breakpoint NoExtField ix [f | Var f <- fvs'] modl)  ------------------------- tcIfaceLit :: Literal -> IfL Literal@@ -1684,7 +1687,16 @@   = do { tc' <- either (fmap RecSelData . tcIfaceTyCon)                        (fmap (RecSelPatSyn . tyThingPatSyn) . tcIfaceDecl False)                        tc-       ; return (RecSelId { sel_tycon = tc', sel_naughty = naughty, sel_fieldLabel = fl { flSelector = nm } }) }+       ; let all_cons = recSelParentCons tc'+             cons_partitioned+                 = conLikesWithFields all_cons [flLabel fl]+       ; return (RecSelId+                   { sel_tycon = tc'+                   , sel_naughty = naughty+                   , sel_fieldLabel = fl { flSelector = nm }+                   , sel_cons = cons_partitioned }+                       -- Reconstructed here since we don't want Uniques in the Iface file+                ) }   where     tyThingPatSyn (AConLike (PatSynCon ps)) = ps     tyThingPatSyn _ = panic "tcIdDetails: expecting patsyn"@@ -1730,10 +1742,6 @@            ; let info1 | lb        = info `setOccInfo` strongLoopBreaker                        | otherwise = info            ; return (info1 `setUnfoldingInfo` unf) }--tcJoinInfo :: IfaceJoinInfo -> Maybe JoinArity-tcJoinInfo (IfaceJoinPoint ar) = Just ar-tcJoinInfo IfaceNotJoinPoint   = Nothing  tcLFInfo :: IfaceLFInfo -> IfL LambdaFormInfo tcLFInfo lfi = case lfi of
+ compiler/GHC/JS/Opt/Expr.hs view
@@ -0,0 +1,186 @@+{-# LANGUAGE ViewPatterns #-}+-----------------------------------------------------------------------------+-- |+-- Module      :  GHC.JS.Opt.Expr+-- Copyright   :  (c) The University of Glasgow 2001+-- License     :  BSD-style (see the file LICENSE)+--+-- Maintainer  :  Jeffrey Young  <jeffrey.young@iohk.io>+--                Luite Stegeman <luite.stegeman@iohk.io>+--                Sylvain Henry  <sylvain.henry@iohk.io>+--                Josh Meredith  <josh.meredith@iohk.io>+-- Stability   :  experimental+--+--+--  This module contains a simple expression optimizer that performs constant+--  folding and some boolean expression optimizations.+-----------------------------------------------------------------------------++module GHC.JS.Opt.Expr (optExprs) where++import GHC.Prelude hiding (shiftL, shiftR)++import GHC.JS.Syntax++import Data.Bifunctor (second)+import Data.Bits (shiftL, shiftR, (.^.))+import Data.Int (Int32)++{-+  Optimize expressions in a statement.++  This is best done after running the simple optimizer in GHC.JS.Opt.Simple,+  which eliminates redundant assignments and produces expressions that can be+  optimized more effectively.+ -}+optExprs :: JStat -> JStat+optExprs s = go s+  where+    go (DeclStat v mb_e) = DeclStat v (fmap opt mb_e)+    go (AssignStat lhs op rhs) = AssignStat (opt lhs) op (opt rhs)+    go (ReturnStat e) = ReturnStat (opt e)+    go (BlockStat ss) = BlockStat (map go ss)+    go (IfStat e s1 s2) = IfStat (optCond e) (go s1) (go s2)+    go (WhileStat b e s) = WhileStat b (optCond e) (go s)+    go (ForStat s1 e s2 s3) = ForStat (go s1) (optCond e) (go s2) (go s3)+    go (ForInStat b v e s) = ForInStat b v (opt e) (go s)+    go (SwitchStat e cases s) = SwitchStat (opt e)+                                           (map (second go) cases)+                                           (go s)+    go (TryStat s1 v s2 s3) = TryStat (go s1) v (go s2) (go s3)+    go (ApplStat e es) = ApplStat (opt e) (map opt es)+    go (UOpStat op e) = UOpStat op (opt e)+    go (LabelStat lbl s) = LabelStat lbl (go s)+    go s@(BreakStat{}) = s+    go s@(ContinueStat{}) = s+    go (FuncStat n vs s) = FuncStat n vs (go s)++ -- remove double negation if we're using the expression in a loop/if condition+optCond :: JExpr -> JExpr+optCond e = let f (UOpExpr NotOp (UOpExpr NotOp e')) = f e'+                f e' = e'+            in f (opt e)++opt :: JExpr -> JExpr+opt (ValExpr v)          = ValExpr v+opt (SelExpr e i)        = SelExpr (opt e) i+opt (IdxExpr e1 e2)      = IdxExpr (opt e1) (opt e2)+-- ((c_e ? 1 : 0) === 1)   ==> !!c_e+-- ((c_e ? 1 : 0) === 0)   ==> !c_e+opt(InfixExpr StrictEqOp (IfExpr c_e (opt -> t_e) (opt -> f_e)) (opt -> e))+    | ValExpr t_v <- t_e+    , ValExpr v <- e+    , eqVal t_v v = UOpExpr NotOp (UOpExpr NotOp c_e)+    | ValExpr f_v <- f_e+    , ValExpr v <- e+    , eqVal f_v v = UOpExpr NotOp (opt c_e)+    | otherwise = InfixExpr StrictEqOp (IfExpr c_e t_e f_e) e+-- (1 === (c_e ? 1 : 0))   ==> !!c_e+-- (0 === (c_e ? 1 : 0))   ==> !c_e+opt(InfixExpr StrictEqOp (opt -> e) (IfExpr (opt -> c_e) (opt -> t_e) (opt -> f_e)))+    | ValExpr t_v <- t_e+    , ValExpr v <- e+    , eqVal t_v v = UOpExpr NotOp (UOpExpr NotOp c_e)+    | ValExpr f_v <- f_e+    , ValExpr v <- e+    , eqVal f_v v = UOpExpr NotOp c_e+    | otherwise = InfixExpr StrictEqOp e (IfExpr c_e t_e f_e)+opt (InfixExpr op (opt -> e1) (opt -> e2))+  | (ValExpr (JInt n1)) <- e1+  , (ValExpr (JInt n2)) <- e2+  , Just v <- optInt op n1 n2 = ValExpr v+  | (ValExpr (JBool b1)) <- e1+  , (ValExpr (JBool b2)) <- e2+  , Just v <- optBool op b1 b2 = ValExpr v+  | otherwise = InfixExpr op e1 e2+opt (UOpExpr op e)       = UOpExpr op (opt e)+opt (IfExpr e1 e2 e3)    = IfExpr (optCond e1) (opt e2) (opt e3)+opt (ApplExpr e es)      = ApplExpr (opt e) (map opt es)++{-+  Optimizations for operations on two known boolean values+ -}+optBool :: Op -> Bool -> Bool -> Maybe JVal+optBool LAndOp x y = Just (JBool (x && y))+optBool LOrOp x y = Just (JBool (x || y))+optBool EqOp x y = Just (JBool (x == y))+optBool StrictEqOp x y = Just (JBool (x == y))+optBool NeqOp x y = Just (JBool (x /= y))+optBool StrictNeqOp x y = Just (JBool (x /= y))+optBool _ _ _ = Nothing++{-+  Optimizations for operations on two known integer values+ -}+optInt :: Op -> Integer -> Integer -> Maybe JVal+optInt ZRightShiftOp n m = Just $+  JInt (toInteger $ (n .&. 0xffffffff) `shiftR` fromInteger (m .&. 0x1f))+optInt BOrOp n m = Just (truncOp (.|.) n m)+optInt BAndOp n m = Just (truncOp (.&.) n m)+optInt BXorOp n m = Just (truncOp (.^.) n m)+optInt RightShiftOp n m = Just (shiftOp shiftR n m)+optInt LeftShiftOp n m = Just (shiftOp shiftL n m)+optInt AddOp n m = smallIntOp (+) n m+optInt SubOp n m = smallIntOp (-) n m+optInt MulOp n m = smallIntOp (*) n m+optInt op n m+  | Just cmp <- getCmpOp op, isSmall52 n && isSmall52 m+  = Just (JBool (cmp n m))+optInt _ _ _ = Nothing++smallIntOp :: (Integer -> Integer -> Integer)+           -> Integer -> Integer -> Maybe JVal+smallIntOp op n m+  | isSmall52 n && isSmall52 m && isSmall52 r = Just (JInt r)+  | otherwise                                 = Nothing+  where+    r = op n m++getCmpOp :: Op -> Maybe (Integer -> Integer -> Bool)+getCmpOp EqOp = Just (==)+getCmpOp StrictEqOp = Just (==)+getCmpOp NeqOp = Just (/=)+getCmpOp StrictNeqOp = Just (/=)+getCmpOp GtOp = Just (>)+getCmpOp GeOp = Just (>=)+getCmpOp LtOp = Just (<)+getCmpOp LeOp = Just (<=)+getCmpOp _ = Nothing++shiftOp :: (Int32 -> Int -> Int32) -> Integer -> Integer -> JVal+shiftOp op n m = JInt $ toInteger+   (fromInteger n `op` (fromInteger m .&. 0x1f))++{-+  JavaScript bitwise operations truncate numbers to 32 bit signed integers.+  Here we do the same when constant folding with this kind of operators.+ -}+truncOp :: (Int32 -> Int32 -> Int32) -> Integer -> Integer -> JVal+truncOp op n m = JInt $ toInteger+   (fromInteger n `op` fromInteger m)++{-+  JavaScript numbers are IEEE 754 double precision floats, which have a+  52-bit mantissa. This returns True if the given integer can definitely+  be represented without loss of precision in a JavaScript number.+ -}+isSmall52 :: Integer -> Bool+isSmall52 n = n >= -0x10000000000000 && n <= 0xfffffffffffff++{-+  In JavaScript, e1 === e2 is not always true even if expressions e1 and e2+  are syntactically equal, examples:++    - NaN !== NaN  (NaN is not equal to itself)+    - [1] !== [1]  (different arrays allocated)+    - f() !== f()++  This returns True if the values are definitely equal in JavaScript+ -}+eqVal :: JVal -> JVal -> Bool+eqVal (JInt n1) (JInt n2)   = n1 == n2+eqVal (JStr s1) (JStr s2)   = s1 == s2+eqVal (JBool b1) (JBool b2) = b1 == b2+eqVal (JDouble (SaneDouble d1)) (JDouble (SaneDouble d2))+  | not (isNaN d1) && not (isNaN d2) = d1 == d2+eqVal _ _ = False
+ compiler/GHC/JS/Opt/Simple.hs view
@@ -0,0 +1,607 @@+-----------------------------------------------------------------------------+-- |+-- Module      :  GHC.JS.Opt.Simple+-- Copyright   :  (c) The University of Glasgow 2001+-- License     :  BSD-style (see the file LICENSE)+--+-- Maintainer  :  Jeffrey Young  <jeffrey.young@iohk.io>+--                Luite Stegeman <luite.stegeman@iohk.io>+--                Sylvain Henry  <sylvain.henry@iohk.io>+--                Josh Meredith  <josh.meredith@iohk.io>+-- Stability   :  experimental+--+--+-- * Simple optimizer for the JavaScript IR+--+--     This is a simple optimizer for the JavaScript IR. It is intended to be+--     the first optimization pass after generating the JavaScript IR.+--+-- * Design+--+--     The optimizer is invoked on the top-level JStat. It leaves the top-level+--     scope alone, but traverses into each function body and optimizes it.+--     Nested functions are mostly left alone, since they are uncommon in+--     generated code.+--+--     The optimizations are:+--+--       - rename local variables to shorter names+--       - remove unused variables+--       - remove trivial assignments: x = x+--       - "float" expressions without side effects:+--       -   var x = 1; var y = x + 1; -> var y = 1 + 1;+--+-- * Limitations+--+--     The simple optimization pass is intended to be fast and applicable to+--     almost all generated JavaScript code. Limitations are:+--+--       - optimization is disabled if an `eval` statement is encountered+--       - variables declared in nested scopes are not renamed+--+-----------------------------------------------------------------------------++{-# LANGUAGE OverloadedStrings #-}+module GHC.JS.Opt.Simple (simpleOpt) where++import GHC.Prelude++import GHC.JS.Opt.Expr+import GHC.JS.Syntax++import GHC.Data.FastString+import qualified GHC.Types.Unique.Map as UM+import GHC.Types.Unique.Map (UniqMap)+import qualified GHC.Types.Unique.Set as US++import Control.Monad+import Data.Function+import Data.List (sortBy)+import Data.Maybe+import qualified Data.Semigroup as Semi+++data Multiplicity = Zero | One | Many+    deriving (Eq, Ord, Show)++data VarValue = Unassigned+              | AssignedOnce+              | AssignedOnceKnown !JExpr+              | AssignedMany++data VarDecl = NoDecl -- not declared in analyzed scope (possibly deeper or global)+             | ArgDecl !Int -- argument in analyzed scope+             | LocalDecl !Int -- local variable in analyzed scope+  deriving (Eq, Show)++isLocalOrArg :: VarDecl -> Bool+isLocalOrArg (LocalDecl {}) = True+isLocalOrArg (ArgDecl {})   = True+isLocalOrArg _              = False++isDecl :: VarDecl -> Bool+isDecl NoDecl = False+isDecl _      = True++instance Semi.Semigroup VarDecl where+  NoDecl <> x = x+  x <> NoDecl = x+  ArgDecl n <> ArgDecl m = ArgDecl (min n m)+  LocalDecl n <> LocalDecl m = LocalDecl (min n m)+  ArgDecl n <> _ = ArgDecl n+  _ <> ArgDecl n = ArgDecl n++instance Ord VarDecl where+  compare NoDecl NoDecl = EQ+  compare NoDecl _      = LT+  compare _      NoDecl = GT+  compare (ArgDecl n) (ArgDecl m) = compare n m+  compare (ArgDecl {}) _ = LT+  compare _ (ArgDecl {}) = GT+  compare (LocalDecl n) (LocalDecl m) = compare n m++data JFunction = JFunction [Ident] JStat++instance Semi.Semigroup VarValue where+  Unassigned <> x = x+  x <> Unassigned = x+  _ <> _ = AssignedMany++instance Monoid VarValue where+  mempty = Unassigned+  mappend = (Semi.<>)++instance Semigroup Multiplicity where+    Zero <> x = x+    x <> Zero = x+    _ <> _    = Many++instance Monoid Multiplicity where+    mempty = Zero+    mappend = (Semi.<>)++data VarUsage = VarUsage+    { varUsed :: !Multiplicity+    , varAssigned :: !VarValue+    , varDeclared :: !VarDecl+    , varDeepDeclared :: !Bool+    }++assignedMultiple :: VarUsage -> Bool+assignedMultiple VarUsage { varAssigned = AssignedMany } = True+assignedMultiple _                                       = False++data SimpleRewrite = SimpleRewrite+    { renameVar :: UniqMap Ident Ident+    , varUsage :: UniqMap Ident VarUsage+    }++instance Semigroup VarUsage where+    x <> y = VarUsage+        { varUsed = varUsed x Semi.<> varUsed y+        , varAssigned = varAssigned x Semi.<> varAssigned y+        , varDeclared = varDeclared x Semi.<> varDeclared y+        , varDeepDeclared = varDeepDeclared x || varDeepDeclared y+        }++instance Monoid VarUsage where+    mempty = VarUsage Zero Unassigned NoDecl False++disableOpt :: Bool+-- disableOpt = True+disableOpt = False++simpleOpt :: JStat -> JStat+simpleOpt x | disableOpt = x+simpleOpt (BlockStat xs) = BlockStat (map simpleOpt xs)+simpleOpt (AssignStat lhs AssignOp (ValExpr (JFunc args body)))  =+     let JFunction args' body' = simpleOptFunction (JFunction args body)+     in AssignStat lhs AssignOp (ValExpr (JFunc args' body'))+simpleOpt (FuncStat name args body) =+     let JFunction args' body' = simpleOptFunction (JFunction args body)+     in  FuncStat name args' body'+simpleOpt s = s++simpleOptFunction :: JFunction -> JFunction+simpleOptFunction jf = s_opt+  where+    -- we need to run it twice since floating in the first pass can+    -- cause unused variables that can be removed in the second pass+    s_opt  = functionOptExprs $ maybe jf (`simpleRewrite` s_opt0) mb_rw+    mb_rw  = mkRewrite True (simpleAnalyze s_opt0)+    s_opt0 = functionOptExprs $ maybe jf (`simpleRewrite` jf) mb_rw0+    mb_rw0 = mkRewrite False (simpleAnalyze jf)++functionOptExprs :: JFunction -> JFunction+functionOptExprs (JFunction args s) = JFunction args (optExprs s)++newLocals :: [Ident]+newLocals = filter (not . isReserved  ) $+            map (TxtI . mkFastString) $+            map (:[]) chars0 ++ concatMap mkIdents [1..]+  where+    mkIdents n = [c0:cs | c0 <- chars0, cs <- replicateM n chars]+    chars0 = ['a'..'z']++['A'..'Z']+    chars = chars0++['0'..'9']+    isReserved (TxtI i) = i `US.elementOfUniqSet` reservedSet+    reservedSet = US.mkUniqSet reserved+    reserved = [  -- reserved words+                  "abstract", "arguments", "await", "boolean"+                , "break", "byte", "case", "catch"+                , "char", "class", "const", "continue"+                , "debugger", "default", "delete", "do"+                , "double", "else", "enum", "eval"+                , "export", "extends", "false", "final"+                , "finally", "float", "for", "function"+                , "goto", "if", "implements", "import"+                , "in", "instanceof", "int", "interface"+                , "let", "long", "native", "new"+                , "null", "package", "private", "protected"+                , "public", "return", "short", "static"+                , "super", "switch", "synchronized", "this"+                , "throw", "throws", "transient", "true"+                , "try", "typeof", "var", "void"+                , "volatile", "while", "with", "yield"+                -- some special values+                , "as", "async", "from", "get"+                , "of", "NaN", "prototype", "undefined"+                ]++mkRewrite :: Bool -> AnalysisResult -> Maybe SimpleRewrite+mkRewrite do_rename a+  | arBailout a = Nothing+  | otherwise  = Just $+  SimpleRewrite { renameVar = if do_rename+                              then UM.listToUniqMap (zip localVars newVars)+                              else UM.emptyUniqMap+                , varUsage = vu+                }+  where+    vu :: UM.UniqMap Ident VarUsage+    vu = arVarUsage a++    -- local variables in the order that they were declared+    localVars :: [Ident]+    localVars =+        map fst+         -- recover original order and remove non-determinism+      . sortBy (compare `on` snd)+      . map (\(v, u) -> (v, varDeclared u))+      . filter (isDecl . varDeclared . snd)+      -- non-determinism is removed by sorting afterwards+      $ UM.nonDetUniqMapToList vu+    -- we can't rename variables that are used in the global scope+    blockedNames :: US.UniqSet Ident+    blockedNames =+      US.mkUniqSet $+      map fst (+      filter (\(_k,v) -> (not . isDecl) (varDeclared v) || varDeepDeclared v)+             (UM.nonDetUniqMapToList vu))+++    newVars :: [Ident]+    newVars = filter (not . (`US.elementOfUniqSet` blockedNames)) newLocals++simpleRewrite :: SimpleRewrite -> JFunction -> JFunction+simpleRewrite rw (JFunction args stat)= JFunction (map varReplace args) (go stat)+  where+    zeroUsed :: JExpr -> Bool+    zeroUsed (ValExpr (JVar v)) =+      maybe True ((== Zero) . varUsed) (UM.lookupUniqMap (varUsage rw) v) &&+      maybe False (isDecl . varDeclared) (UM.lookupUniqMap (varUsage rw) v)+    zeroUsed _                  = False++    varReplace :: Ident -> Ident+    varReplace v = fromMaybe v (UM.lookupUniqMap (renameVar rw) v)++    {-+      We can sometimes float down an expression to avoid an assignment:++      var x = e;+      f(x);+        ==>+      f(e);++      This can only be done if the expression has no side effects and x is+      only used once.++      Heap object property lookups cannot be floated just yet, since we+      don't know whether an object is mutable or not. For example a thunk+      can be blackholed, which would change the result if we float the lookup+      after the blackholing.+     -}++    mayBeFloated :: JExpr -> Bool+    mayBeFloated (ValExpr v) = mayBeFloatedV v+    mayBeFloated (SelExpr _e _) = False+    mayBeFloated (IdxExpr _e1 _e2) = False+    mayBeFloated (InfixExpr _ e1 e2)= mayBeFloated e1 && mayBeFloated e2+    mayBeFloated (UOpExpr _ _e) = False+    mayBeFloated (IfExpr e1 e2 e3) = mayBeFloated e1 &&+                                     mayBeFloated e2 &&+                                     mayBeFloated e3+    mayBeFloated (ApplExpr e es)+      | ValExpr (JVar (TxtI i)) <- e, isClosureAllocator i = all mayBeFloated es+      | otherwise                                          = False++    mayBeFloatedV :: JVal -> Bool+    mayBeFloatedV (JVar v)+      | Just vu <- UM.lookupUniqMap (varUsage rw) v+      = isDecl (varDeclared vu) && not (assignedMultiple vu)+      | otherwise = False+    mayBeFloatedV (JList es) = all mayBeFloated es+    mayBeFloatedV (JDouble {}) = True+    mayBeFloatedV (JInt {}) = True+    mayBeFloatedV (JStr {}) = True+    mayBeFloatedV (JRegEx {}) = True+    mayBeFloatedV (JBool {}) = True+    mayBeFloatedV (JHash ps) = all (mayBeFloated . snd)+                                   (UM.nonDetUniqMapToList ps)+    mayBeFloatedV (JFunc {}) = False++    {-+       we allow small literals and local variables and arguments to be+       duplicated, since they tend to take up little space.+      -}+    mayDuplicate :: JExpr -> Bool+    mayDuplicate (ValExpr (JVar i))+      | Just vu <- (UM.lookupUniqMap (varUsage rw) i)+      = isLocalOrArg (varDeclared vu)+    mayDuplicate (ValExpr (JInt n))     = abs n < 1000000+    mayDuplicate (ValExpr (JDouble {})) = True+    mayDuplicate _                      = False++    zeroAssigned :: Ident -> Bool+    zeroAssigned v+       | Just vu <- UM.lookupUniqMap (varUsage rw) v+       = case varAssigned vu of+          Unassigned -> True+          _          -> False+      | otherwise = False++    assignedAtMostOnce :: Ident -> Bool+    assignedAtMostOnce v+      | Just vu <- UM.lookupUniqMap (varUsage rw) v =+        case varAssigned vu of+          Unassigned           -> True+          AssignedOnce         -> True+          AssignedOnceKnown {} -> True+          AssignedMany         -> False+      | otherwise = False++    go :: JStat -> JStat+    go (DeclStat v mb_e)+        | zeroUsed (ValExpr (JVar v)) =+          case mb_e of+            Nothing | zeroAssigned v -> BlockStat []+                    | otherwise      -> DeclStat (varReplace v) Nothing+            Just e | not (mayHaveSideEffects e) && assignedAtMostOnce v+                                                -> BlockStat []+                   | otherwise                  -> DeclStat (varReplace v) (Just (goE True e))+        | otherwise = DeclStat (varReplace v) (fmap (goE True) mb_e)+    go (AssignStat lhs aop e)+        | ValExpr (JVar i) <- lhs, isTrivialAssignment i aop e = BlockStat []+        | zeroUsed lhs && not (mayHaveSideEffects e) = BlockStat []+        | zeroUsed lhs = AssignStat (goE False lhs) aop (goE True e)+        | otherwise = AssignStat (goE False lhs) aop (goE True e)+    go (ReturnStat e) = ReturnStat (goE True e)+    go (BlockStat ss) = flattenBlock (map go ss)+    go (IfStat e s1 s2) = IfStat (goE True e) (go s1) (go s2)+    go (WhileStat b e s) = WhileStat b (goE True e) (go s)+    go (ForStat s1 e s2 s3) = ForStat (go s1) (goE True e) (go s2) (go s3)+    go (ForInStat b v e s) = ForInStat b (varReplace v) (goE True e) (go s)+    go (SwitchStat e cases s) = SwitchStat (goE True e)+                                           (map (\(c,cs) -> (c, go cs)) cases)+                                           (go s)+    go (TryStat s1 v s2 s3) = TryStat (go s1) (varReplace v) (go s2) (go s3)+    go (ApplStat e es) = ApplStat (goE True e) (map (goE True) es)+    go (UOpStat uop e) = UOpStat uop (goE False e)+    go (LabelStat lbl s) = LabelStat lbl (go s)+    go s@(BreakStat {}) = s+    go s@(ContinueStat {}) = s+    go (FuncStat i args s) = FuncStat i (map varReplace args) (go s)++    goE :: Bool -> JExpr -> JExpr+    goE rhs (ValExpr (JVar v))+      | rhs+      , Just vu <- UM.lookupUniqMap (varUsage rw) v+      , AssignedOnceKnown ee <- varAssigned vu+      , varUsed vu == One || mayDuplicate ee+      , isDecl (varDeclared vu)+      , mayBeFloated ee+      = goE rhs ee+    goE _rhs (ValExpr v) = ValExpr (goV v)+    goE rhs (SelExpr e i) = SelExpr (goE rhs e) i+    goE rhs (IdxExpr e1 e2) = IdxExpr (goE rhs e1) (goE rhs e2)+    goE rhs (InfixExpr op e1 e2) = InfixExpr op (goE rhs e1) (goE rhs e2)+    goE rhs (UOpExpr op e) = UOpExpr op (goE rhs e)+    goE rhs (IfExpr e1 e2 e3) = IfExpr (goE rhs e1) (goE rhs e2) (goE rhs e3)+    goE rhs (ApplExpr e es) = ApplExpr (goE rhs e) (map (goE rhs) es)++    goV :: JVal -> JVal+    goV (JVar v) = JVar (varReplace v)+    goV (JList es) = JList (map (goE True) es)+    goV (JHash ps) = JHash (fmap (goE True) ps)+    goV v@(JFunc {}) = v+    goV v@(JDouble {}) = v+    goV v@(JInt {}) = v+    goV v@(JStr {}) = v+    goV v@(JRegEx {}) = v+    goV v@(JBool {}) = v++flattenBlock :: [JStat] -> JStat+flattenBlock stats =+    case filter (/= BlockStat []) stats of+        []  -> BlockStat []+        [s] -> s+        ss  -> BlockStat ss++data AnalysisResult = AnalysisResult+  { arBailout       :: !Bool+  , arVarUsage      :: !(UniqMap Ident VarUsage)+  , arDeclaredCount :: !Int+  }++simpleAnalyze :: JFunction -> AnalysisResult+simpleAnalyze (JFunction args body) = go False (AnalysisResult False start 0) body+  where+    start :: UniqMap Ident VarUsage+    start = UM.listToUniqMap+          $ zipWith (\n v -> (v, VarUsage Zero Unassigned (ArgDecl n) False))+                    [0..]+                    args++    add :: Ident -> VarUsage -> AnalysisResult -> AnalysisResult+    add i vu m = m { arVarUsage = UM.addToUniqMap_C (Semi.<>) (arVarUsage m) i vu }+++    declare :: Bool -> Ident -> Maybe JExpr -> AnalysisResult -> AnalysisResult+    declare True i _assign m = -- declaration in deeper scope+      let vu = VarUsage Zero AssignedMany NoDecl True+      in  m { arVarUsage = UM.addToUniqMap_C (Semi.<>) (arVarUsage m) i vu}+    declare False i assign m = -- declaration in analyzed scope+      let count  = arDeclaredCount m+          !newCount+            | Just (VarUsage _ _ (LocalDecl _) _) <-+                UM.lookupUniqMap (arVarUsage m) i = count -- already declared+            | otherwise                           = count + 1+          vassign | Just e <- assign = AssignedOnceKnown e+                  | otherwise        = Unassigned+          !vu = VarUsage Zero vassign (LocalDecl count) False+      in m { arDeclaredCount = newCount+           , arVarUsage = UM.addToUniqMap_C (Semi.<>) (arVarUsage m) i vu+           }++    go :: Bool -> AnalysisResult -> JStat -> AnalysisResult+    go deep u (DeclStat v mb_e) =+        case mb_e of+            Nothing -> declare deep v mb_e u+            Just e  -> declare deep v mb_e (goE u e)+    go _deep u (AssignStat (ValExpr (JVar v)) aop e) =+        let use = case aop of+                    AssignOp -> Zero+                    _        -> One+        in add v (VarUsage use (AssignedOnceKnown e) NoDecl False) (goE u e)+    go _deep u (AssignStat lhs _aop rhs) = goE (goE u lhs) rhs+    go _deep u (ReturnStat e) = goE u e+    go deep u (BlockStat ss) = foldl' (go deep) u ss+    go deep u (IfStat e s1 s2) = go deep (go deep (goE u e) s1) s2+    go deep u (WhileStat _b e s) = go deep (goE u e) s+    go deep u (ForStat s1 e s2 s3)+      = go deep (go deep (goE (go deep u s1) e) s2) s3+    go deep u (ForInStat b v e s) =+      let !u' = if b then declare deep v Nothing u else u+      in  add v (VarUsage Zero AssignedMany NoDecl True)+                (go deep (go deep (goE u' e) s) s)+    go deep u (SwitchStat e cases s)+      = go deep (goE (foldl' (go deep) u (map snd cases)) e) s+    go deep u (TryStat s1 v s2 s3)+      = add v (VarUsage Zero AssignedMany NoDecl True)+              (go deep (go deep (go deep u s1) s2) s3)+    go _deep u (ApplStat e es)+      | (ValExpr (JVar (TxtI i))) <- e, i == "eval" = u { arBailout = True }+      | otherwise = foldl' goE (goE u e) es+    go _deep u (UOpStat op e)+      | ValExpr (JVar v) <- e+      , op `elem` [PreIncOp, PostIncOp, PreDecOp, PostDecOp] =+          add v (VarUsage One AssignedOnce NoDecl False) u+      | otherwise = goE u e+    go deep u (LabelStat _ s) = go deep u s+    go _deep u (BreakStat _) = u+    go _deep u (ContinueStat _) = u+    go _deep u (FuncStat _ vs s)+      = go True (foldl' (\u v -> add v (VarUsage Zero AssignedOnce NoDecl True) u) u vs) s++    goE :: AnalysisResult -> JExpr -> AnalysisResult+    goE u (ValExpr v) = goV u v+    goE u (SelExpr e _i) = goE u e+    goE u (IdxExpr e1 e2) = goE (goE u e1) e2+    goE u (InfixExpr _ e1 e2) = goE (goE u e1) e2+    goE u (UOpExpr _ e) = goE u e+    goE u (IfExpr e1 e2 e3) = goE (goE (goE u e1) e2) e3+    goE u (ApplExpr e es)+      | (ValExpr (JVar (TxtI i))) <- e, i == "eval" = u { arBailout = True }+      | otherwise = foldl' goE (goE u e) es++    goV :: AnalysisResult -> JVal -> AnalysisResult+    goV u (JVar v)   = add v (VarUsage One Unassigned NoDecl False) u+    goV u (JList es) = foldl' goE u es+    goV u (JDouble _) = u+    goV u (JInt _) = u+    goV u (JStr _) = u+    goV u (JRegEx _) = u+    goV u (JBool _) = u+    goV u (JHash ps) = foldl' goE u (map snd $ UM.nonDetUniqMapToList ps)+    goV u (JFunc vs s)+      = go True (foldl (\u v -> add v (VarUsage Zero AssignedOnce NoDecl True) u) u vs) s++-- | A trivial assignment is an assignment of a variable to itself: x = x+isTrivialAssignment :: Ident -> AOp -> JExpr -> Bool+isTrivialAssignment v AssignOp (ValExpr (JVar v')) = v == v'+isTrivialAssignment _ _ _                          = False++-- | Does the expression have side effects?+--+-- This only returns False if the expression definitely does not have side+-- effects, i.e. it can be removed without changing the semantics if the+-- result is not used.+--+-- Note: We have some assumptions here about Haskell RTS related values, which+--       may not be true for all JavaScript code. We should really replace+--       these with explicit nodes or annotations in the AST.+--+mayHaveSideEffects :: JExpr -> Bool+-- special cases for Haskell things. These should really be special operations+-- in the AST:+-- 1. stack indexing does not have side effects+mayHaveSideEffects (IdxExpr (ValExpr (JVar (TxtI i))) e)+  | i == "h$stack" = mayHaveSideEffects e+-- 2. we assume that x.d1, x.d2, ... are heap object property lookups,+--    which do not have side effects+mayHaveSideEffects (SelExpr e (TxtI i))+  | isHeapObjectProperty i = mayHaveSideEffects e++-- general cases (no Haskell RTS specific assumptions here):+mayHaveSideEffects (ValExpr v) = mayHaveSideEffectsV v+mayHaveSideEffects (SelExpr {}) = True+mayHaveSideEffects (IdxExpr {}) = True+mayHaveSideEffects (UOpExpr uop e) = uo || mayHaveSideEffects e+    where+        uo = case uop of+              NotOp    -> False+              BNotOp   -> False+              NegOp    -> False+              PlusOp   -> False+              TypeofOp -> False+              _        -> True+mayHaveSideEffects (InfixExpr _o e1 e2) =+  mayHaveSideEffects e1 || mayHaveSideEffects e2+mayHaveSideEffects (IfExpr e1 e2 e3) =+  mayHaveSideEffects e1 || mayHaveSideEffects e2 || mayHaveSideEffects e3+mayHaveSideEffects (ApplExpr {}) = True++mayHaveSideEffectsV :: JVal -> Bool+mayHaveSideEffectsV (JVar {}) = False+mayHaveSideEffectsV (JList es) = any mayHaveSideEffects es+mayHaveSideEffectsV (JDouble {}) = False+mayHaveSideEffectsV (JInt {}) = False+mayHaveSideEffectsV (JStr {}) = False+mayHaveSideEffectsV (JRegEx {}) = False+mayHaveSideEffectsV (JBool {}) = False+mayHaveSideEffectsV (JHash ps) = UM.anyUniqMap mayHaveSideEffects ps+mayHaveSideEffectsV (JFunc {}) = True++isHeapObjectProperty :: FastString -> Bool+isHeapObjectProperty "d1"  = True+isHeapObjectProperty "d2"  = True+isHeapObjectProperty "d3"  = True+isHeapObjectProperty "d4"  = True+isHeapObjectProperty "d5"  = True+isHeapObjectProperty "d6"  = True+isHeapObjectProperty "d7"  = True+isHeapObjectProperty "d8"  = True+isHeapObjectProperty "d9"  = True+isHeapObjectProperty "d10" = True+isHeapObjectProperty "d11" = True+isHeapObjectProperty "d12" = True+isHeapObjectProperty "d13" = True+isHeapObjectProperty "d14" = True+isHeapObjectProperty "d15" = True+isHeapObjectProperty "d16" = True+isHeapObjectProperty "d17" = True+isHeapObjectProperty "d18" = True+isHeapObjectProperty "d19" = True+isHeapObjectProperty "d20" = True+isHeapObjectProperty "d21" = True+isHeapObjectProperty "d22" = True+isHeapObjectProperty "d23" = True+isHeapObjectProperty "d24" = True++isHeapObjectProperty _     = False++isClosureAllocator :: FastString -> Bool+isClosureAllocator "h$c1" = True+isClosureAllocator "h$c2" = True+isClosureAllocator "h$c3" = True+isClosureAllocator "h$c4" = True+isClosureAllocator "h$c5" = True+isClosureAllocator "h$c6" = True+isClosureAllocator "h$c7" = True+isClosureAllocator "h$c8" = True+isClosureAllocator "h$c9" = True+isClosureAllocator "h$c10" = True+isClosureAllocator "h$c11" = True+isClosureAllocator "h$c12" = True+isClosureAllocator "h$c13" = True+isClosureAllocator "h$c14" = True+isClosureAllocator "h$c15" = True+isClosureAllocator "h$c16" = True+isClosureAllocator "h$c17" = True+isClosureAllocator "h$c18" = True+isClosureAllocator "h$c19" = True+isClosureAllocator "h$c20" = True+isClosureAllocator "h$c21" = True+isClosureAllocator "h$c22" = True+isClosureAllocator "h$c23" = True+isClosureAllocator "h$c24" = True+isClosureAllocator _       = False
compiler/GHC/JS/Optimizer.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE LambdaCase, OverloadedStrings #-}  ----------------------------------------------------------------------------- -- |@@ -46,6 +46,8 @@  import Control.Arrow +import qualified GHC.JS.Opt.Simple as Simple+ {- Note [Unsafe JavaScript optimizations] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -85,9 +87,12 @@ --                        Top level Driver -------------------------------------------------------------------------------- jsOptimize :: JStat -> JStat-jsOptimize = go+jsOptimize s0 = jsOptimizeStat (Simple.simpleOpt s0)++jsOptimizeStat :: JStat -> JStat+jsOptimizeStat s0 = go s0   where-    p_opt = jsOptimize+    p_opt = jsOptimizeStat     opt   = jsOptimize'     e_opt = jExprOptimize     -- base case@@ -147,7 +152,7 @@ -- | drive optimizations to anonymous functions and over expressions jValOptimize ::  JVal -> JVal -- base case-jValOptimize (JFunc args body) = JFunc args (jsOptimize body)+jValOptimize (JFunc args body) = JFunc args (jsOptimizeStat body) -- recursive cases jValOptimize (JList exprs)     = JList (jExprOptimize <$> exprs) jValOptimize (JHash hash)      = JHash (jExprOptimize <$> hash)@@ -157,6 +162,7 @@ jValOptimize x@JInt{}          = x jValOptimize x@JStr{}          = x jValOptimize x@JRegEx{}        = x+jValOptimize x@JBool{}         = x  -- | A block transformation is a function from a stream of syntax to another -- stream@@ -193,11 +199,7 @@     -- this call to jsOptimize is required or else the optimizer will not     -- properly recur down JStat. See the 'deadCodeElim' test for examples which     -- were failing before this change-    (x:xs) -> next (jsOptimize x : loop xs)-------------------------------------------------------------------------------------                        Single Slot Optimizations---------------------------------------------------------------------------------+    (x:xs) -> next (jsOptimizeStat x : loop xs)  {- |    Catch modify and assign operators:@@ -212,9 +214,26 @@ -} combineOps :: BlockOpt combineOps = BlockOpt $ \loop next ->-  \case-    -- find a op pattern, and rerun the optimizer on its result unless there is+    -- find an op pattern, and rerun the optimizer on its result unless there is     -- nothing to optimize, in which case call the next optimization+  \case+    -- var x = expr; return x; ==> return expr;+    (DeclStat i (Just e) : ReturnStat (ValExpr (JVar i')) : xs)+      | i == i' -> loop $ ReturnStat e : xs++    -- x = expr; return x; ==> return expr;+    (AssignStat (ValExpr (JVar i)) AssignOp e : ReturnStat (ValExpr (JVar i')) : xs)+      | i == i' -> loop $ ReturnStat e : xs++    -- h$sp -= 2; h$sp += 5; ==> h$sp += 3;+    (op1 : op2 : xs)+      | Just s1 <- isStackAdjust op1+      , Just s2 <- isStackAdjust op2 -> loop $ mkStackAdjust (s1 + s2) ++ xs++    -- x = x + 1; ==> ++x;+    -- x = x - 1; ==> --x;+    -- x = x + n; ==> x += n;+    -- x = x - n; ==> x -= n;     (unchanged@(AssignStat                   ident@(ValExpr (JVar i))                   AssignOp@@ -232,18 +251,13 @@                   (InfixExpr op e (ValExpr (JVar i')))) : xs)       | i == i' -> case (op, e) of                      (AddOp, (ValExpr (JInt 1))) -> loop $ UOpStat PreIncOp ident          : xs-                     (SubOp, (ValExpr (JInt 1))) -> loop $ UOpStat PreDecOp ident          : xs                      (AddOp, e')                 -> loop $ AssignStat ident AddAssignOp e' : xs-                     (SubOp, e')                 -> loop $ AssignStat ident SubAssignOp e' : xs                      _                           -> next $ unchanged : xs     -- general case, we had nothing to optimize in this case so call the next     -- optimization     xs -> next xs  ------------------------------------------------------------------------------------                        Dual Slot Optimizations--------------------------------------------------------------------------------- -- | Catch 'var i; i = q;' ==> 'var i = q;' declareAssign :: BlockOpt declareAssign = BlockOpt $@@ -268,3 +282,30 @@ flattenBlocks (BlockStat y : ys) = flattenBlocks y ++ flattenBlocks ys flattenBlocks (x:xs)             = x : flattenBlocks xs flattenBlocks []                 = []++-- | stack adjustments+sp :: JExpr+sp = ValExpr (JVar (TxtI "h$sp"))++isStackAdjust :: JStat -> Maybe Integer+isStackAdjust (UOpStat op (ValExpr (JVar (TxtI "h$sp"))))+  | op == PreIncOp || op == PostIncOp = Just 1+isStackAdjust (UOpStat op (ValExpr (JVar (TxtI "h$sp"))))+  | op == PreDecOp || op == PostDecOp = Just (-1)+isStackAdjust (AssignStat (ValExpr (JVar (TxtI "h$sp"))) op (ValExpr (JInt n)))+  | op == AddAssignOp = Just n+  | op == SubAssignOp = Just (-n)+isStackAdjust (AssignStat (ValExpr (JVar (TxtI "h$sp"))) AssignOp (InfixExpr op (ValExpr (JVar (TxtI "h$sp"))) (ValExpr (JInt n))))+  | op == AddOp = Just n+  | op == SubOp = Just (-n)+isStackAdjust (AssignStat (ValExpr (JVar (TxtI "h$sp"))) AssignOp (InfixExpr AddOp (ValExpr (JInt n)) (ValExpr (JVar (TxtI "h$sp")))))+  = Just n+isStackAdjust _ = Nothing++mkStackAdjust :: Integer -> [JStat]+mkStackAdjust 0 = []+mkStackAdjust 1 = [UOpStat PostIncOp sp]+mkStackAdjust (-1) = [UOpStat PostDecOp sp]+mkStackAdjust x+  | x < 0 = [AssignStat sp AssignOp (InfixExpr SubOp sp (ValExpr (JInt (-x))))]+  | otherwise = [AssignStat sp AssignOp (InfixExpr AddOp sp (ValExpr (JInt x)))]
− compiler/GHC/Linker/Config.hs
@@ -1,13 +0,0 @@--- | Linker configuration--module GHC.Linker.Config-  ( FrameworkOpts(..)-  ) where--import GHC.Prelude---- used on darwin only-data FrameworkOpts = FrameworkOpts-  { foFrameworkPaths    :: [String]-  , foCmdlineFrameworks :: [String]-  }
compiler/GHC/Linker/Deps.hs view
@@ -4,10 +4,8 @@ {-# OPTIONS_GHC -fspec-constr-threshold=10000 #-}  {-# LANGUAGE CPP #-}-{-# LANGUAGE TupleSections, RecordWildCards #-}-{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE LambdaCase #-}-{-# LANGUAGE RankNTypes #-}  module GHC.Linker.Deps   ( LinkDepsOpts (..)@@ -31,7 +29,6 @@  import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Error  import GHC.Unit.Env@@ -56,7 +53,6 @@ import qualified Data.Set as Set import qualified Data.Map as M import Data.List (isSuffixOf)-import Data.Either  import System.FilePath import System.Directory@@ -132,7 +128,7 @@       let         -- 2.  Exclude ones already linked         --      Main reason: avoid findModule calls in get_linkable-            (mods_needed, links_got) = partitionEithers (map split_mods mods_s)+            (mods_needed, links_got) = partitionWith split_mods mods_s             pkgs_needed = eltsUDFM $ getUniqDSet pkgs_s `minusUDFM` pkgs_loaded pls              split_mods mod =@@ -323,9 +319,8 @@ {- Note [Using Byte Code rather than Object Code for Template Haskell] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~- The `-fprefer-byte-code` flag allows a user to specify that they want to use-byte code (if availble) rather than object code for home module dependenices+byte code (if available) rather than object code for home module dependencies when executing Template Haskell splices.  Why might you want to use byte code rather than object code?@@ -336,7 +331,7 @@ So we allow the user to choose to use byte code rather than object files if they want to avoid these two pitfalls. -When using `-fprefer-byte-code` you have to arrange to have the byte code availble.+When using `-fprefer-byte-code` you have to arrange to have the byte code available. In normal --make mode it will not be produced unless you enable `-fbyte-code-and-object-code`. See Note [Home module build products] for some more information about that. 
compiler/GHC/Linker/Dynamic.hs view
@@ -21,7 +21,7 @@ import GHC.Unit.State import GHC.Linker.MacOS import GHC.Linker.Unit-import GHC.SysTools.Tasks+import GHC.Linker.External import GHC.Utils.Logger import GHC.Utils.TmpFs @@ -99,6 +99,8 @@     pkg_framework_opts <- getUnitFrameworkOpts unit_env (map unitId pkgs)     let framework_opts = getFrameworkOpts (initFrameworkOpts dflags) platform +    let linker_config = initLinkerConfig dflags+     case os of         OSMinGW32 -> do             -------------------------------------------------------------@@ -108,7 +110,7 @@                             Just s -> s                             Nothing -> "HSdll.dll" -            runLink logger tmpfs dflags (+            runLink logger tmpfs linker_config (                     map Option verbFlags                  ++ [ Option "-o"                     , FileOption "" output_fn@@ -171,7 +173,7 @@             instName <- case dylibInstallName dflags of                 Just n -> return n                 Nothing -> return $ "@rpath" `combine` (takeFileName output_fn)-            runLink logger tmpfs dflags (+            runLink logger tmpfs linker_config (                     map Option verbFlags                  ++ [ Option "-dynamiclib"                     , Option "-o"@@ -219,7 +221,7 @@                                 -- See Note [-Bsymbolic assumptions by GHC]                                 ["-Wl,-Bsymbolic" | not unregisterised] -            runLink logger tmpfs dflags (+            runLink logger tmpfs linker_config (                     map Option verbFlags                  ++ libmLinkOpts platform                  ++ [ Option "-o"
+ compiler/GHC/Linker/External.hs view
@@ -0,0 +1,26 @@+-- | External ("system") linker+module GHC.Linker.External+  ( LinkerConfig(..)+  , runLink+  )+where++import GHC.Prelude+import GHC.Utils.TmpFs+import GHC.Utils.Logger+import GHC.Utils.Error+import GHC.Utils.CliOption+import GHC.SysTools.Process+import GHC.Linker.Config++-- | Run the external linker+runLink :: Logger -> TmpFs -> LinkerConfig -> [Option] -> IO ()+runLink logger tmpfs cfg args = traceSystoolCommand logger "linker" $ do+  let all_args = linkerOptionsPre cfg ++ args ++ linkerOptionsPost cfg++  -- on Windows, mangle environment variables to account for a bug in Windows+  -- Vista+  mb_env <- getGccEnv all_args++  runSomethingResponseFile logger tmpfs (linkerTempDir cfg) (linkerFilter cfg)+    "Linker" (linkerProgram cfg) all_args mb_env
compiler/GHC/Linker/ExtraObj.hs view
@@ -12,7 +12,6 @@    , mkNoteObjsToLinkIntoBinary    , checkLinkInfo    , getLinkInfo-   , getCompilerInfo    , ghcLinkInfoSectionName    , ghcLinkInfoNoteName    , platformSupportsSavingLinkOpts@@ -40,10 +39,8 @@  import GHC.SysTools.Elf import GHC.SysTools.Tasks-import GHC.SysTools.Info import GHC.Linker.Unit -import Control.Monad.IO.Class import Control.Monad import Data.Maybe @@ -52,7 +49,6 @@  = do cFile <- newTempName logger tmpfs (tmpDir dflags) TFL_CurrentModule extn       oFile <- newTempName logger tmpfs (tmpDir dflags) TFL_GhcSession "o"       writeFile cFile xs-      ccInfo <- liftIO $ getCompilerInfo logger dflags       runCc Nothing logger tmpfs dflags             ([Option        "-c",               FileOption "" cFile,@@ -60,7 +56,7 @@               FileOption "" oFile]               ++ if extn /= "s"                     then cOpts-                    else asmOpts ccInfo)+                    else [])       return oFile     where       -- Pass a different set of options to the C compiler depending one whether@@ -69,14 +65,6 @@       cOpts = map Option (picCCOpts dflags)                     ++ map (FileOption "-I" . ST.unpack)                             (unitIncludeDirs $ unsafeLookupUnit unit_state rtsUnit)--      -- When compiling assembler code, we drop the usual C options, and if the-      -- compiler is Clang, we add an extra argument to tell Clang to ignore-      -- unused command line options. See trac #11684.-      asmOpts ccInfo =-            if any (ccInfo ==) [Clang, AppleClang, AppleClang51]-                then [Option "-Qunused-arguments"]-                else []  -- When linking a binary, we need to create a C main() function that -- starts everything off.  This used to be compiled statically as part
compiler/GHC/Linker/Loader.hs view
@@ -1,6 +1,5 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE TupleSections, RecordWildCards #-}-{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE LambdaCase #-}  --@@ -56,7 +55,6 @@ import GHC.Runtime.Interpreter import GHCi.RemoteTypes import GHC.Iface.Load-import GHCi.Message (LoadedDLL)  import GHC.ByteCode.Linker import GHC.ByteCode.Asm@@ -111,6 +109,34 @@  import GHC.Utils.Exception +-- Note [Linkers and loaders]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~+--+-- Linkers are used to produce linked objects (.so, executables); loaders are+-- used to link in memory (e.g., in GHCi) with the already loaded libraries+-- (ghc-lib, rts, etc.).+--+-- Linking can usually be done with an external linker program ("ld"), but+-- loading is more tricky:+--+--    * Fully dynamic:+--       when GHC is built as a set of dynamic libraries (ghc-lib, rts, etc.)+--       and the modules to load are also compiled for dynamic linking, a+--       solution is to fully rely on external tools:+--+--       1) link a .so with the external linker+--       2) load the .so with POSIX's "dlopen"+--+--    * When GHC is built as a static program or when libraries we want to load+--    aren't compiled for dynamic linking, GHC uses its own loader ("runtime+--    linker"). The runtime linker is part of the rts (rts/Linker.c).+--+-- Note that within GHC's codebase we often use the word "linker" to refer to+-- the static object loader in the runtime system.+--+-- Loading can be delegated to an external interpreter ("iserv") when+-- -fexternal-interpreter is used.+ uninitialised :: a uninitialised = panic "Loader not initialised" @@ -146,7 +172,7 @@   --   -- The linker's symbol table is populated with RTS symbols using an   -- explicit list.  See rts/Linker.c for details.-  where init_pkgs = unitUDFM rtsUnitId (LoadedPkgInfo rtsUnitId [] [] [] emptyUniqDSet)+  where init_pkgs = unitUDFM rtsUnitId (LoadedPkgInfo rtsUnitId [] [] emptyUniqDSet)  extendLoadedEnv :: Interp -> [(Name,ForeignHValue)] -> IO () extendLoadedEnv interp new_bindings =@@ -195,8 +221,8 @@   -> SrcSpan   -> [Module]   -> IO (LoaderState, SuccessFlag, [Linkable], PkgsLoaded) -- ^ returns the set of linkables required--- When called, the loader state must have been initialized (see `initLoaderState`) loadDependencies interp hsc_env pls span needed_mods = do+--   initLoaderState (hsc_dflags hsc_env) dl    let opts = initLinkDepsOpts hsc_env     -- Find what packages and linkables are required@@ -486,25 +512,25 @@     DLL dll_unadorned -> do       maybe_errstr <- loadDLL interp (platformSOName platform dll_unadorned)       case maybe_errstr of-         Right _ -> maybePutStrLn logger "done"-         Left mm | platformOS platform /= OSDarwin ->+         Nothing -> maybePutStrLn logger "done"+         Just mm | platformOS platform /= OSDarwin ->            preloadFailed mm lib_paths lib_spec-         Left mm | otherwise -> do+         Just mm | otherwise -> do            -- As a backup, on Darwin, try to also load a .so file            -- since (apparently) some things install that way - see            -- ticket #8770.            let libfile = ("lib" ++ dll_unadorned) <.> "so"            err2 <- loadDLL interp libfile            case err2 of-             Right _ -> maybePutStrLn logger "done"-             Left _  -> preloadFailed mm lib_paths lib_spec+             Nothing -> maybePutStrLn logger "done"+             Just _  -> preloadFailed mm lib_paths lib_spec       return pls      DLLPath dll_path -> do       do maybe_errstr <- loadDLL interp dll_path          case maybe_errstr of-            Right _ -> maybePutStrLn logger "done"-            Left mm -> preloadFailed mm lib_paths lib_spec+            Nothing -> maybePutStrLn logger "done"+            Just mm -> preloadFailed mm lib_paths lib_spec          return pls      Framework framework ->@@ -587,9 +613,8 @@         -- Load the expression itself         -- Load the necessary packages and linkables         let le = linker_env pls-            nobreakarray = error "no break array"             bco_ix = mkNameEnv [(unlinkedBCOName root_ul_bco, 0)]-        resolved <- linkBCO interp (pkgs_loaded pls) le bco_ix nobreakarray root_ul_bco+        resolved <- linkBCO interp le bco_ix root_ul_bco         [root_hvref] <- createBCOs interp [resolved]         fhv <- mkFinalizedHValue interp root_hvref         return (pls, fhv)@@ -652,7 +677,7 @@                        , addr_env = plusNameEnv (addr_env le) bc_strs }            -- Link the necessary packages and linkables-          new_bindings <- linkSomeBCOs interp (pkgs_loaded pls) le2 [cbc]+          new_bindings <- linkSomeBCOs interp le2 [cbc]           nms_fhvs <- makeForeignNamedHValueRefs interp new_bindings           let ce2  = extendClosureEnv (closure_env le2) nms_fhvs               !pls2 = pls { linker_env = le2 { closure_env = ce2 } }@@ -833,8 +858,8 @@     changeTempFilesLifetime tmpfs TFL_GhcSession [soFile]     m <- loadDLL interp soFile     case m of-      Right _ -> return $! pls { temp_sos = (libPath, libName) : temp_sos }-      Left err -> linkFail msg err+        Nothing -> return $! pls { temp_sos = (libPath, libName) : temp_sos }+        Just err -> linkFail msg err   where     msg = "GHC.Linker.Loader.dynLoadObjs: Loading temp shared object failed" @@ -874,7 +899,7 @@             ae2 = foldr plusNameEnv (addr_env le1) (map bc_strs cbcs)             le2 = le1 { itbl_env = ie2, addr_env = ae2 } -        names_and_refs <- linkSomeBCOs interp (pkgs_loaded pls) le2 cbcs+        names_and_refs <- linkSomeBCOs interp le2 cbcs          -- We only want to add the external ones to the ClosureEnv         let (to_add, to_drop) = partition (isExternalName.fst) names_and_refs@@ -889,7 +914,6 @@  -- Link a bunch of BCOs and return references to their values linkSomeBCOs :: Interp-             -> PkgsLoaded              -> LinkerEnv              -> [CompiledByteCode]              -> IO [(Name,HValueRef)]@@ -897,21 +921,16 @@                         -- the incoming unlinked BCOs.  Each gives the                         -- value of the corresponding unlinked BCO -linkSomeBCOs interp pkgs_loaded le mods = foldr fun do_link mods []+linkSomeBCOs interp le mods = foldr fun do_link mods []  where-  fun CompiledByteCode{..} inner accum =-    case bc_breaks of-      Nothing -> inner ((panic "linkSomeBCOs: no break array", bc_bcos) : accum)-      Just mb -> withForeignRef (modBreaks_flags mb) $ \breakarray ->-                   inner ((breakarray, bc_bcos) : accum)+  fun CompiledByteCode{..} inner accum = inner (bc_bcos : accum)    do_link [] = return []   do_link mods = do-    let flat = [ (breakarray, bco) | (breakarray, bcos) <- mods, bco <- bcos ]-        names = map (unlinkedBCOName . snd) flat+    let flat = [ bco | bcos <- mods, bco <- bcos ]+        names = map unlinkedBCOName flat         bco_ix = mkNameEnv (zip names [0..])-    resolved <- sequence [ linkBCO interp pkgs_loaded le bco_ix breakarray bco-                         | (breakarray, bco) <- flat ]+    resolved <- sequence [ linkBCO interp le bco_ix bco | bco <- flat ]     hvrefs <- createBCOs interp resolved     return (zip names hvrefs) @@ -1073,18 +1092,18 @@                -- Link dependents first              ; pkgs' <- link pkgs deps                 -- Now link the package itself-             ; (hs_cls, extra_cls, loaded_dlls) <- loadPackage interp hsc_env pkg_cfg+             ; (hs_cls, extra_cls) <- loadPackage interp hsc_env pkg_cfg              ; let trans_deps = unionManyUniqDSets [ addOneToUniqDSet (loaded_pkg_trans_deps loaded_pkg_info) dep_pkg                                                    | dep_pkg <- deps                                                    , Just loaded_pkg_info <- pure (lookupUDFM pkgs' dep_pkg)                                                    ]-             ; return (addToUDFM pkgs' new_pkg (LoadedPkgInfo new_pkg hs_cls extra_cls loaded_dlls trans_deps)) }+             ; return (addToUDFM pkgs' new_pkg (LoadedPkgInfo new_pkg hs_cls extra_cls trans_deps)) }          | otherwise         = throwGhcExceptionIO (CmdLineError ("unknown package: " ++ unpackFS (unitIdFS new_pkg)))  -loadPackage :: Interp -> HscEnv -> UnitInfo -> IO ([LibrarySpec], [LibrarySpec], [RemotePtr LoadedDLL])+loadPackage :: Interp -> HscEnv -> UnitInfo -> IO ([LibrarySpec], [LibrarySpec]) loadPackage interp hsc_env pkg    = do         let dflags    = hsc_dflags hsc_env@@ -1126,9 +1145,7 @@         let classifieds = hs_classifieds ++ extra_classifieds          -- Complication: all the .so's must be loaded before any of the .o's.-        let known_hs_dlls    = [ dll | DLLPath dll <- hs_classifieds ]-            known_extra_dlls = [ dll | DLLPath dll <- extra_classifieds ]-            known_dlls       = known_hs_dlls ++ known_extra_dlls+        let known_dlls = [ dll  | DLLPath dll    <- classifieds ] #if defined(CAN_LOAD_DLL)             dlls       = [ dll  | DLL dll        <- classifieds ] #endif@@ -1149,13 +1166,10 @@         loadFrameworks interp platform pkg         -- See Note [Crash early load_dyn and locateLib]         -- Crash early if can't load any of `known_dlls`-        mapM_ (load_dyn interp hsc_env True) known_extra_dlls-        loaded_dlls <- mapMaybeM (load_dyn interp hsc_env True) known_hs_dlls+        mapM_ (load_dyn interp hsc_env True) known_dlls         -- For remaining `dlls` crash early only when there is surely         -- no package's DLL around ... (not is_dyn)         mapM_ (load_dyn interp hsc_env (not is_dyn) . platformSOName platform) dlls-#else-        let loaded_dlls = [] #endif         -- After loading all the DLLs, we can load the static objects.         -- Ordering isn't important here, because we do one final link@@ -1175,7 +1189,7 @@         if succeeded ok            then do              maybePutStrLn logger "done."-             return (hs_classifieds, extra_classifieds, loaded_dlls)+             return (hs_classifieds, extra_classifieds)            else let errmsg = text "unable to load unit `"                              <> pprUnitInfoForUser pkg <> text "'"                  in throwGhcExceptionIO (InstallationError (showSDoc dflags errmsg))@@ -1228,20 +1242,19 @@ -- can be passed directly to loadDLL.  They are either fully-qualified -- ("/usr/lib/libfoo.so"), or unqualified ("libfoo.so").  In the latter case, -- loadDLL is going to search the system paths to find the library.-load_dyn :: Interp -> HscEnv -> Bool -> FilePath -> IO (Maybe (RemotePtr LoadedDLL))+load_dyn :: Interp -> HscEnv -> Bool -> FilePath -> IO () load_dyn interp hsc_env crash_early dll = do   r <- loadDLL interp dll   case r of-    Right loaded_dll -> pure (Just loaded_dll)-    Left err ->+    Nothing  -> return ()+    Just err ->       if crash_early         then cmdLineErrorIO err-        else do+        else           when (diag_wopt Opt_WarnMissedExtraSharedLib diag_opts)             $ logMsg logger                 (mkMCDiagnostic diag_opts (WarningWithFlag Opt_WarnMissedExtraSharedLib) Nothing)                   noSrcSpan $ withPprStyle defaultUserStyle (note err)-          pure Nothing   where     diag_opts = initDiagOpts (hsc_dflags hsc_env)     logger = hsc_logger hsc_env
compiler/GHC/Linker/MacOS.hs view
@@ -172,6 +172,6 @@      findLoadDLL (p:ps) errs =        do { dll <- loadDLL interp (p </> fwk_file)           ; case dll of-              Right _  -> return Nothing-              Left err -> findLoadDLL ps ((p ++ ": " ++ err):errs)+              Nothing  -> return Nothing+              Just err -> findLoadDLL ps ((p ++ ": " ++ err):errs)           }
compiler/GHC/Linker/Static.hs view
@@ -26,6 +26,7 @@ import GHC.Linker.Unit import GHC.Linker.Dynamic import GHC.Linker.ExtraObj+import GHC.Linker.External import GHC.Linker.Windows import GHC.Linker.Static.Utils @@ -181,14 +182,12 @@       OSMinGW32 | gopt Opt_GenManifest dflags -> maybeCreateManifest logger tmpfs dflags output_fn       _                                       -> return [] -    let link dflags args | platformOS platform == OSDarwin-                            = do-                                 GHC.SysTools.runLink logger tmpfs dflags args-                                 -- Make sure to honour -fno-use-rpaths if set on darwin as well; see #20004-                                 when (gopt Opt_RPath dflags) $-                                   GHC.Linker.MacOS.runInjectRPaths logger (toolSettings dflags) pkg_lib_paths output_fn-                         | otherwise-                            = GHC.SysTools.runLink logger tmpfs dflags args+    let linker_config = initLinkerConfig dflags+    let link dflags args = do+          runLink logger tmpfs linker_config args+          -- Make sure to honour -fno-use-rpaths if set on darwin as well; see #20004+          when (platformOS platform == OSDarwin && gopt Opt_RPath dflags) $+            GHC.Linker.MacOS.runInjectRPaths logger (toolSettings dflags) pkg_lib_paths output_fn      link dflags (                        map GHC.SysTools.Option verbFlags@@ -239,6 +238,7 @@                           then ["-Wl,-read_only_relocs,suppress"]                           else []) +                          -- We should rather be asking does it support --gc-sections?                       ++ (if toolSettings_ldIsGnuLd toolSettings' &&                              not (gopt Opt_WholeArchiveHsLibs dflags)                           then ["-Wl,--gc-sections"]
compiler/GHC/Llvm.hs view
@@ -42,6 +42,10 @@          -- ** Metadata types         MetaExpr(..), MetaAnnot(..), MetaDecl(..), MetaId(..),+        -- *** Module flags+        ModuleFlagBehavior(..),+        ModuleFlag(..),+        moduleFlagToMetaExpr,          -- ** Operations on the type system.         isGlobal, getLitType, getVarType,
compiler/GHC/Llvm/MetaData.hs view
@@ -1,6 +1,16 @@ {-# LANGUAGE GeneralizedNewtypeDeriving #-} -module GHC.Llvm.MetaData where+module GHC.Llvm.MetaData+  ( MetaId(..)+  , ppMetaId+  , MetaExpr(..)+  , MetaAnnot(..)+  , MetaDecl(..)+    -- * Module flags+  , ModuleFlagBehavior(..)+  , ModuleFlag(..)+  , moduleFlagToMetaExpr+  ) where  import GHC.Prelude @@ -73,6 +83,7 @@  -- | LLVM metadata expressions data MetaExpr = MetaStr !LMString+              | MetaLit !LlvmLit               | MetaNode !MetaId               | MetaVar !LlvmVar               | MetaStruct [MetaExpr]@@ -91,3 +102,42 @@     -- | Metadata node declaration.     -- ('!0 = metadata !{ \<metadata expression> }' form).     | MetaUnnamed !MetaId !MetaExpr++----------------------------------------------------------------+-- Module flags+----------------------------------------------------------------+data ModuleFlagBehavior+  = MFBError+  | MFBWarning+  | MFBRequire+  | MFBOverride+  | MFBAppend+  | MFBAppendUnique+  | MFBMax+  | MFBMin++moduleFlagBehaviorToMetaExpr :: ModuleFlagBehavior -> MetaExpr+moduleFlagBehaviorToMetaExpr mfb =+    MetaLit $ LMIntLit n i32+  where+    n = case mfb of+      MFBError -> 1+      MFBWarning -> 2+      MFBRequire -> 3+      MFBOverride -> 4+      MFBAppend -> 5+      MFBAppendUnique -> 6+      MFBMax -> 7+      MFBMin -> 8++data ModuleFlag = ModuleFlag { mfBehavior :: ModuleFlagBehavior+                             , mfName :: LMString+                             , mfValue :: MetaExpr+                             }++moduleFlagToMetaExpr :: ModuleFlag -> MetaExpr+moduleFlagToMetaExpr flag = MetaStruct+    [ moduleFlagBehaviorToMetaExpr (mfBehavior flag)+    , MetaStr (mfName flag)+    , mfValue flag+    ]
compiler/GHC/Llvm/Ppr.hs view
@@ -297,6 +297,7 @@ ppMetaExpr opts = \case   MetaVar (LMLitVar (LMNullLit _)) -> text "null"   MetaStr    s                     -> char '!' <> doubleQuotes (ftext s)+  MetaLit    l                     -> ppTypeLit opts l   MetaNode   n                     -> ppMetaId n   MetaVar    v                     -> ppVar opts v   MetaStruct es                    -> char '!' <> braces (ppCommaJoin (ppMetaExpr opts) es)
compiler/GHC/Rename/Bind.hs view
@@ -1,5 +1,3 @@-{-# LANGUAGE ConstraintKinds #-}-{-# LANGUAGE ScopedTypeVariables, BangPatterns #-} {-# LANGUAGE TypeFamilies #-}  {-# OPTIONS_GHC -Wno-incomplete-uni-patterns   #-}@@ -25,7 +23,7 @@    -- Other bindings    rnMethodBinds, renameSigs,    rnMatchGroup, rnGRHSs, rnGRHS, rnSrcFixityDecl,-   makeMiniFixityEnv, MiniFixityEnv,+   makeMiniFixityEnv, MiniFixityEnv, emptyMiniFixityEnv,    HsSigCtxt(..),     -- Utility for hs-boot files@@ -47,7 +45,6 @@ import GHC.Rename.Utils ( mapFvRn                         , checkDupRdrNames                         , warnUnusedLocalBinds-                        , warnForallIdentifier                         , checkUnusedRecordWildcard                         , checkDupAndShadowedNames, bindLocalNamesFV                         , addNoNestedForallsContextsErr, checkInferredVars )@@ -397,7 +394,7 @@               -- Insert fake uses for variables introduced implicitly by               -- wildcards (#4404)               rec_uses = hsValBindsImplicits binds'-              implicit_uses = mkNameSet $ concatMap snd+              implicit_uses = mkNameSet $ concatMap (concatMap implFlBndr_binders . snd)                                         $ rec_uses         ; mapM_ (\(loc, ns) ->                     checkUnusedRecordWildcard loc real_uses (Just ns))@@ -443,11 +440,12 @@           -- (i.e., any free variables of the pattern)           -> RnM (HsBindLR GhcRn GhcPs) -rnBindLHS name_maker _ bind@(PatBind { pat_lhs = pat })+rnBindLHS name_maker _ bind@(PatBind { pat_lhs = pat, pat_mult = pat_mult })   = do       -- we don't actually use the FV processing of rnPatsAndThen here       (pat',pat'_fvs) <- rnBindPat name_maker pat-      return (bind { pat_lhs = pat', pat_ext = pat'_fvs })+      (pat_mult', mult'_fvs) <- rnHsMultAnn pat_mult+      return (bind { pat_lhs = pat', pat_ext = pat'_fvs `plusFV` mult'_fvs, pat_mult = pat_mult' })                 -- We temporarily store the pat's FVs in bind_fvs;                 -- gets updated to the FVs of the whole bind                 -- when doing the RHS below@@ -459,7 +457,7 @@  rnBindLHS name_maker _ (PatSynBind x psb@PSB{ psb_id = rdrname })   | isTopRecNameMaker name_maker-  = do { addLocMA checkConName rdrname+  = do { addLocM checkConName rdrname        ; name <-            lookupLocatedTopConstructorRnN rdrname -- Should be in scope already        ; return (PatSynBind x psb{ psb_ext = noAnn, psb_id = name }) }@@ -571,8 +569,8 @@           -- Recursive cases           BangPat _ lp -> lpatternContainsSplice lp           LazyPat _ lp -> lpatternContainsSplice lp-          AsPat _ _ _ lp  -> lpatternContainsSplice lp-          ParPat _ _ lp _ -> lpatternContainsSplice lp+          AsPat _ _ lp  -> lpatternContainsSplice lp+          ParPat _ lp -> lpatternContainsSplice lp           ViewPat _ _ lp -> lpatternContainsSplice lp           SigPat _ lp _  -> lpatternContainsSplice lp           ListPat _ lps  -> any lpatternContainsSplice lps@@ -581,6 +579,12 @@           ConPat _ _ cpd  -> any lpatternContainsSplice (hsConPatArgs cpd)           XPat (HsPatExpanded _orig new) -> patternContainsSplice new +          -- The behavior of this case is unimportant, as GHC will throw an error shortly+          -- after reaching this case for other reasons (see TcRnIllegalTypePattern).+          EmbTyPat{} -> True++          InvisPat{} -> True+ {- Note [Pattern bindings that bind no variables] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Generally, we want to warn about pattern bindings like@@ -614,7 +618,7 @@ The reason is that trim is sometimes something like     \xs -> intersectNameSet (mkNameSet bound_names) xs and we don't want to retain the list bound_names. This showed up in-trac ticket #1136.+ticket #1136. -}  {- *********************************************************************@@ -684,30 +688,58 @@  makeMiniFixityEnv :: [LFixitySig GhcPs] -> RnM MiniFixityEnv -makeMiniFixityEnv decls = foldlM add_one_sig emptyFsEnv decls+makeMiniFixityEnv decls = foldlM add_one_sig emptyMiniFixityEnv decls  where    add_one_sig :: MiniFixityEnv -> LFixitySig GhcPs -> RnM MiniFixityEnv-   add_one_sig env (L loc (FixitySig _ names fixity)) =-     foldlM add_one env [ (locA loc,locA name_loc,name,fixity)+   add_one_sig env (L loc (FixitySig ns_spec names fixity)) =+     foldlM add_one env [ (locA loc,locA name_loc,name,fixity, ns_spec)                         | L name_loc name <- names ] -   add_one env (loc, name_loc, name,fixity) = do+   add_one env (loc, name_loc, name, fixity, ns_spec) = do      { -- this fixity decl is a duplicate iff        -- the ReaderName's OccName's FastString is already in the env        -- (we only need to check the local fix_env because        --  definitions of non-local will be caught elsewhere)        let { fs = occNameFS (rdrNameOcc name)-           ; fix_item = L loc fixity };+           ; fix_item = L loc fixity}; -       case lookupFsEnv env fs of-         Nothing -> return $ extendFsEnv env fs fix_item+       case search_for_dups ns_spec env fs of+         Nothing -> return $ extend_mini_fixity_env ns_spec env fs fix_item          Just (L loc' _) -> do            { setSrcSpan loc $              addErrAt name_loc (TcRnMultipleFixityDecls loc' name)            ; return env}      }+   search_for_dups ns_spec MFE{mfe_data_level_names, mfe_type_level_names} fs+    = case ns_spec of+      NoNamespaceSpecifier -> case lookupFsEnv mfe_data_level_names fs of+        -- We only need to find a single duplicate to emit an error about+        -- multiple fixity decls. Therefore, if we find a duplicate in the+        -- term-level namespace, then there is no need to look in the type-level namespace.+        Nothing -> lookupFsEnv mfe_type_level_names fs+        just_dup -> just_dup+      TypeNamespaceSpecifier{} -> lookupFsEnv mfe_type_level_names fs+      DataNamespaceSpecifier{} -> lookupFsEnv mfe_data_level_names fs +   extend_mini_fixity_env ns_spec env@MFE{mfe_data_level_names, mfe_type_level_names} fs fix_item+    = case ns_spec of+      NoNamespaceSpecifier     -> MFE { mfe_data_level_names = (extendFsEnv mfe_data_level_names fs fix_item)+                                      , mfe_type_level_names = (extendFsEnv mfe_type_level_names fs fix_item)} +      TypeNamespaceSpecifier{} -> env { mfe_type_level_names = (extendFsEnv mfe_type_level_names fs fix_item)}++      DataNamespaceSpecifier{} -> env { mfe_data_level_names = (extendFsEnv mfe_data_level_names fs fix_item)}+++-- | Multiplicity annotations are a simple wrapper around types. As such,+-- renaming them is a straightforward wrapper around 'rnLHsType'.+rnHsMultAnn :: HsMultAnn GhcPs -> RnM (HsMultAnn GhcRn, FreeVars)+rnHsMultAnn (HsNoMultAnn _) = return (HsNoMultAnn noExtField, emptyFVs)+rnHsMultAnn (HsPct1Ann _) = return (HsPct1Ann noExtField, emptyFVs)+rnHsMultAnn (HsMultAnn _ p) = do+  (p', freeVars') <- rnLHsType PatCtx p+  return $ (HsMultAnn noExtField p', freeVars')+ {- ********************************************************************* *                                                                      *                 Pattern synonym bindings@@ -1042,7 +1074,6 @@   = do  { defaultSigs_on <- xoptM LangExt.DefaultSignatures         ; when (is_deflt && not defaultSigs_on) $           addErr (TcRnUnexpectedDefaultSig sig)-        ; mapM_ warnForallIdentifier vs         ; new_v <- mapM (lookupSigOccRnN ctxt sig) vs         ; (new_ty, fvs) <- rnHsSigType ty_ctxt TypeLevel ty         ; return (ClassOpSig noAnn is_deflt new_v new_ty, fvs) }@@ -1107,7 +1138,7 @@  -- COMPLETE Sigs can refer to imported IDs which is why we use -- lookupLocatedOccRn rather than lookupSigOccRn-renameSig _ctxt sig@(CompleteMatchSig (_, s) (L l bf) mty)+renameSig _ctxt sig@(CompleteMatchSig (_, s) bf mty)   = do new_bf <- traverse lookupLocatedOccRn bf        new_mty  <- traverse lookupLocatedOccRn mty @@ -1116,7 +1147,7 @@          -- Why 'any'? See Note [Orphan COMPLETE pragmas]          addErrCtxt (text "In" <+> ppr sig) $ failWithTc TcRnOrphanCompletePragma -       return (CompleteMatchSig (noAnn, s) (L l new_bf) new_mty, emptyFVs)+       return (CompleteMatchSig (noAnn, s) new_bf new_mty, emptyFVs)   {-@@ -1238,8 +1269,8 @@     , Anno [LocatedA (Match GhcPs (LocatedA (body GhcPs)))] ~ SrcSpanAnnL     , Anno (Match GhcRn (LocatedA (body GhcRn))) ~ SrcSpanAnnA     , Anno (Match GhcPs (LocatedA (body GhcPs))) ~ SrcSpanAnnA-    , Anno (GRHS GhcRn (LocatedA (body GhcRn))) ~ SrcAnn NoEpAnns-    , Anno (GRHS GhcPs (LocatedA (body GhcPs))) ~ SrcAnn NoEpAnns+    , Anno (GRHS GhcRn (LocatedA (body GhcRn))) ~ EpAnnCO+    , Anno (GRHS GhcPs (LocatedA (body GhcPs))) ~ EpAnnCO     , Outputable (body GhcPs)     ) @@ -1266,7 +1297,7 @@ -- \cases expressions or commands. In that case, or if we encounter an empty -- MatchGroup but -XEmptyCases is disabled, we add an error. -rnMatchGroup :: (Outputable (body GhcPs), AnnoBody body) => HsMatchContext GhcRn+rnMatchGroup :: (Outputable (body GhcPs), AnnoBody body) => HsMatchContextRn              -> (LocatedA (body GhcPs) -> RnM (LocatedA (body GhcRn), FreeVars))              -> MatchGroup GhcPs (LocatedA (body GhcPs))              -> RnM (MatchGroup GhcRn (LocatedA (body GhcRn)), FreeVars)@@ -1277,19 +1308,19 @@        ; return (mkMatchGroup origin (L lm new_ms), ms_fvs) }   where     mustn't_be_empty = case ctxt of-      LamCaseAlt LamCases -> return True-      ArrowMatchCtxt (ArrowLamCaseAlt LamCases) -> return True+      LamAlt LamCases -> return True+      ArrowMatchCtxt (ArrowLamAlt LamCases) -> return True       _ -> not <$> xoptM LangExt.EmptyCase  rnMatch :: AnnoBody body-        => HsMatchContext GhcRn+        => HsMatchContextRn         -> (LocatedA (body GhcPs) -> RnM (LocatedA (body GhcRn), FreeVars))         -> LMatch GhcPs (LocatedA (body GhcPs))         -> RnM (LMatch GhcRn (LocatedA (body GhcRn)), FreeVars) rnMatch ctxt rnBody = wrapLocFstMA (rnMatch' ctxt rnBody)  rnMatch' :: (AnnoBody body)-         => HsMatchContext GhcRn+         => HsMatchContextRn          -> (LocatedA (body GhcPs) -> RnM (LocatedA (body GhcRn), FreeVars))          -> Match GhcPs (LocatedA (body GhcPs))          -> RnM (Match GhcRn (LocatedA (body GhcRn)), FreeVars)@@ -1313,7 +1344,7 @@ -}  rnGRHSs :: AnnoBody body-        => HsMatchContext GhcRn+        => HsMatchContextRn         -> (LocatedA (body GhcPs) -> RnM (LocatedA (body GhcRn), FreeVars))         -> GRHSs GhcPs (LocatedA (body GhcPs))         -> RnM (GRHSs GhcRn (LocatedA (body GhcRn)), FreeVars)@@ -1323,13 +1354,13 @@     return (GRHSs emptyComments grhss' binds', fvGRHSs)  rnGRHS :: AnnoBody body-       => HsMatchContext GhcRn+       => HsMatchContextRn        -> (LocatedA (body GhcPs) -> RnM (LocatedA (body GhcRn), FreeVars))        -> LGRHS GhcPs (LocatedA (body GhcPs))        -> RnM (LGRHS GhcRn (LocatedA (body GhcRn)), FreeVars) rnGRHS ctxt rnBody = wrapLocFstMA (rnGRHS' ctxt rnBody) -rnGRHS' :: HsMatchContext GhcRn+rnGRHS' :: HsMatchContextRn         -> (LocatedA (body GhcPs) -> RnM (LocatedA (body GhcRn), FreeVars))         -> GRHS GhcPs (LocatedA (body GhcPs))         -> RnM (GRHS GhcRn (LocatedA (body GhcRn)), FreeVars)@@ -1369,16 +1400,19 @@         -- for con-like things; hence returning a list         -- If neither are in scope, report an error; otherwise         -- return a fixity sig for each (slightly odd)-    rn_decl (FixitySig _ fnames fixity)-      = do names <- concatMapM lookup_one fnames-           return (FixitySig noExtField names fixity)+    rn_decl sig@(FixitySig ns_spec fnames fixity)+      = do unlessXOptM LangExt.ExplicitNamespaces $+             when (ns_spec /= NoNamespaceSpecifier) $+             addErr (TcRnNamespacedFixitySigWithoutFlag sig)+           names <- concatMapM (lookup_one ns_spec) fnames+           return (FixitySig ns_spec names fixity) -    lookup_one :: LocatedN RdrName -> RnM [LocatedN Name]-    lookup_one (L name_loc rdr_name)+    lookup_one :: NamespaceSpecifier -> LocatedN RdrName -> RnM [LocatedN Name]+    lookup_one ns_spec (L name_loc rdr_name)       = setSrcSpanA name_loc $                     -- This lookup will fail if the name is not defined in the                     -- same binding group as this fixity declaration.-        do names <- lookupLocalTcNames sig_ctxt what rdr_name+        do names <- lookupLocalTcNames sig_ctxt what ns_spec rdr_name            return [ L name_loc name | (_, name) <- names ]     what = text "fixity signature" 
compiler/GHC/Rename/Env.hs view
@@ -83,7 +83,6 @@ import GHC.Types.Error import GHC.Unit.Module import GHC.Unit.Module.ModIface-import GHC.Unit.Module.Warnings  ( WarningTxt(..) ) import GHC.Core.ConLike import GHC.Core.DataCon import GHC.Core.TyCon@@ -96,7 +95,6 @@ import GHC.Types.Unique.Set import GHC.Utils.Misc import GHC.Utils.Panic-import GHC.Utils.Panic.Plain (assert) import GHC.Data.Maybe import GHC.Driver.Env import GHC.Driver.Session@@ -114,7 +112,6 @@ import Data.Either      ( partitionEithers ) import Data.Function    ( on ) import Data.List        ( find, partition, groupBy, sortBy )-import Data.Foldable    ( for_ ) import qualified Data.List.NonEmpty as NE import qualified Data.Semigroup as Semi import System.IO.Unsafe ( unsafePerformIO )@@ -182,7 +179,7 @@ warning until you use the identifier further downstream.  This would require adjusting addUsedGRE so that during signature compilation, we do not report deprecation warnings for LocalDef.  See also-Note [Handling of deprecations]+Note [Handling of deprecations] in GHC.Rename.Utils -}  newTopSrcBinder :: LocatedN RdrName -> RnM Name@@ -990,20 +987,20 @@ -}  -lookupLocatedOccRn :: GenLocated (SrcSpanAnn' ann) RdrName-                   -> TcRn (GenLocated (SrcSpanAnn' ann) Name)+lookupLocatedOccRn :: GenLocated (EpAnn ann) RdrName+                   -> TcRn (GenLocated (EpAnn ann) Name) lookupLocatedOccRn = wrapLocMA lookupOccRn -lookupLocatedOccRnConstr :: GenLocated (SrcSpanAnn' ann) RdrName-                         -> TcRn (GenLocated (SrcSpanAnn' ann) Name)+lookupLocatedOccRnConstr :: GenLocated (EpAnn ann) RdrName+                         -> TcRn (GenLocated (EpAnn ann) Name) lookupLocatedOccRnConstr = wrapLocMA lookupOccRnConstr -lookupLocatedOccRnRecField :: GenLocated (SrcSpanAnn' ann) RdrName-                           -> TcRn (GenLocated (SrcSpanAnn' ann) Name)+lookupLocatedOccRnRecField :: GenLocated (EpAnn ann) RdrName+                           -> TcRn (GenLocated (EpAnn ann) Name) lookupLocatedOccRnRecField = wrapLocMA lookupOccRnRecField -lookupLocatedOccRnNone :: GenLocated (SrcSpanAnn' ann) RdrName-                       -> TcRn (GenLocated (SrcSpanAnn' ann) Name)+lookupLocatedOccRnNone :: GenLocated (EpAnn ann) RdrName+                       -> TcRn (GenLocated (EpAnn ann) Name) lookupLocatedOccRnNone = wrapLocMA lookupOccRnNone  lookupLocalOccRn_maybe :: RdrName -> RnM (Maybe Name)@@ -1061,9 +1058,6 @@ lookupTypeOccRn :: RdrName -> RnM Name -- see Note [Demotion] lookupTypeOccRn rdr_name-  | (isVarOcc <||> isFieldOcc) (rdrNameOcc rdr_name)  -- See Note [Promoted variables in types]-  = badVarInType rdr_name-  | otherwise   = do { mb_gre <- lookupOccRn_maybe rdr_name        ; case mb_gre of              Just gre -> return $ greName gre@@ -1086,6 +1080,7 @@ but emit appropriate warnings. -} +-- Used when looking up a term name (varName or dataName) in a type lookup_demoted :: RdrName -> RnM Name lookup_demoted rdr_name   | Just demoted_rdr <- demoteRdrName rdr_name@@ -1111,16 +1106,111 @@                                      | otherwise                                      = star_is_type_hints                     ; unboundNameX looking_for rdr_name suggestion } }-  | Just demoted_rdr_name <- demoteRdrNameTv rdr_name,-    isQual rdr_name++  | isQual rdr_name,+    Just demoted_rdr_name <- demoteRdrNameTv rdr_name+    -- Definitely an illegal term variable, as type variables are never exported.+    -- See Note [Demotion of unqualified variables] (W2)   = report_qualified_term_in_types rdr_name demoted_rdr_name +  | isUnqual rdr_name,+    Just demoted_rdr_name <- demoteRdrNameTv rdr_name+    -- See Note [Demotion of unqualified variables]+  = do { required_type_arguments <- xoptM LangExt.RequiredTypeArguments+       ; if required_type_arguments+         then do { mb_demoted_gre <- lookupOccRn_maybe demoted_rdr_name+                 ; case mb_demoted_gre of+                     Nothing -> unboundName (LF WL_Anything WL_Anywhere) rdr_name+                     Just demoted_gre -> return $ greName demoted_gre }+         else unboundName looking_for rdr_name }+   | otherwise-  = reportUnboundName' (lf_which looking_for) rdr_name+  = unboundName looking_for rdr_name    where     looking_for = LF WL_Constructor WL_Anywhere +{- Note [Demotion of unqualified variables]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Under RequiredTypeArguments, a term-level variable name (i.e. a name whose+`occNameSpace` is `varName` as opposed to `tvName`) does not necessarily denote+a term variable. It can actually stand for a type:++  {-# LANGUAGE RequiredTypeArguments #-}+  idv :: forall a -> a -> a     -- Note the "forall a ->" in the type+  idv  t  (x :: t) = id @t x    -- #23739+  --   ^        ^        ^+  --  varName  tvName  tvName   -- NameSpace (GHC.Types.Name.Occurrence)++The variable `t` is an alias for the type variable `a`, so it's valid to use it+in type-level contexts. The only problem is that the namespaces do not match.+Demotion allows us to connect the `tvName` usages to the `varName` binding.++Demotion of an RdrName means that we change its namespace from tvName/tcClsName+to varName/dataName. Suppose we are looking up an occurrence of a variable `a`+in a type (in `lookupTypeOccRn`). The parser gave `a` a `tvName` occurrence,+so we try looking that up first.  If that fails, and RequiredTypeArguments is+on, then "demote" it to the `varName` namespace with `demoteRdrNameTv` and look+that up instead. If that succeeds, use it.++(W1) Wrinkle 1+  As a side effect of demotion, the renamer accepts all these examples:+    t = True         -- Ordinary term-level binding+    x = Proxy @t     -- (1) Bad usage in a HsExpr+    type T = t       -- (2) Bad usage in a TyClDecl+    f :: t -> t      -- (3) Bad usage in a SigDecl++  However, GHC doesn't promote arbitrary terms to types. See the "T2T-Mapping"+  section of GHC Proposal #281: "In the type checking environment, the variable+  must stand for a type variable". Even though the renamer accepts these+  constructs, the type checker has to reject the uses of `t` shown above.++  All three examples are rejected with the `TermVariablePE` promotion error.+  The error is generated by `tcTyVar` (GHC.Tc.Gen.HsType)+      tcTyVar :: Name -> TcM (TcType, TcKind)+  The first thing `tcTyVar` does is call the `tcLookup` helper (GHC.Tc.Utils.Env)+  to find the variable in the type checking environment+      tcLookup :: Name -> TcM TcTyThing+  What happens next depends on the example in question.++  * In the HsExpr example (1), `tcLookup` finds `ATcId` that corresponds to+    the `t = True` binding. The `ATcId` is then then turned into an error by+    the following clause in `tcTyVar`:+       ATcId{} -> promotionErr name TermVariablePE++  * In the TyClDecl example (2) and the SigDecl example (3), we don't have+    `ATcId` in the environment just yet because type declarations and signatures+    are type-checked /before/ term-level bindings.++    This means that `tcLookup` fails to find `t` in the local environment and+    calls `tcLookupGlobal` (GHC.Tc.Utils.Env)+        tcLookupGlobal :: Name -> TcM TyThing++    The global environment does not contain `t` either, so `tcLookupGlobal`+    calls `notFound` (GHC.Tc.Utils.Env)+        notFound :: Name -> TcM TyThing++    At this point GHC would normally generate a panic: if the variable is+    neither in the local nor in the global environment, then it shouldn't have+    passed the renamer. Unfortunately, this expectation is tiresome and+    expensive to maintain, so we add a special case in `notFound` instead.+    If the namespace of the variable is `varName`, the only explanation other+    than a bug in GHC is that the user tried to use a term variable in a type+    context. Hence the following clause in `notFound`:+      _ | isTermVarOrFieldNameSpace (nameNameSpace name) ->+          failWithTc $ TcRnUnpromotableThing name TermVariablePE++(W2) Wrinkle 2+   Only unqualified variable names are demoted, e.g. `f` but not `M.f`.+   The reason is that type variables are never bound to a qualified name:+   they can't be bound at the top level of a module, nor can they be+   exported or imported, so a qualified occurrence `M.f` must refer to a+   term-level definition and is never legal at the type level.+   Demotion of qualified names would not allow us to accept any new programs.+   We use this fact to generate better suggestions in error messages,+   see `report_qualified_term_in_types`.+-}+ -- Report a qualified variable name in a type signature: --   badSig :: Prelude.head --             ^^^^^^^^^^^@@ -1144,28 +1234,8 @@   | otherwise   = return Nothing -badVarInType :: RdrName -> RnM Name-badVarInType rdr_name-  = do { addErr (TcRnUnpromotableThing name TermVariablePE)-       ; return name }-      where-        name = mkUnboundNameRdr rdr_name--{- Note [Promoted variables in types]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Consider this (#12686):-   x = True-   data Bad = Bad 'x--The parser treats the quote in 'x as saying "use the term-namespace", so we'll get (Bad x{v}), with 'x' in the-VarName namespace.  If we don't test for this, the renamer-will happily rename it to the x bound at top level, and then-the typecheck falls over because it doesn't have 'x' in scope-when kind-checking.--Note [Demotion]-~~~~~~~~~~~~~~~+{- Note [Demotion]+~~~~~~~~~~~~~~~~~~ When the user writes:   data Nat = Zero | Succ Nat   foo :: f Zero -> Int@@ -1701,25 +1771,18 @@ *                                                      * ********************************************************* -Note [Handling of deprecations]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-* We report deprecations at each *occurrence* of the deprecated thing-  (see #5867 and #4879)--* We do not report deprecations for locally-defined names. For a-  start, we may be exporting a deprecated thing. Also we may use a-  deprecated thing in the defn of another deprecated things.  We may-  even use a deprecated thing in the defn of a non-deprecated thing,-  when changing a module's interface.+Note [Using isImportedGRE in addUsedGRE]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+In addUsedGRE, we want to add any used imported GREs to the tcg_used_gres field,+so that we can emit appropriate warnings (see GHC.Rename.Names.warnUnusedImportDecls). -* We also report deprecations at export sites, but only for names-  deprecated with export deprecations (since those are not transitive as opposed-  to regular name deprecations and are only reported at the importing module)+We want to do this for GREs that were brought into scope through imports. As per+Note [GlobalRdrElt provenance] in GHC.Types.Name.Reader, this means we should+check that gre_imp is non-empty. Checking that gre_lcl is False is INCORRECT,+because we might have obtained the GRE by an Exact or Orig direct reference,+in which case we have both gre_lcl = False and gre_imp = emptyBag. -* addUsedGREs: we do not report deprecations for sub-binders:-     - the ".." completion for records-     - the ".." in an export item 'T(..)'-     - the things exported by a module export 'module M'+Geting this wrong can lead to panics in e.g. bestImport, see #23240. -}  addUsedDataCons :: GlobalRdrEnv -> TyCon -> RnM ()@@ -1730,21 +1793,11 @@       | dc <- tyConDataCons tycon       , Just gre <- [lookupGRE_Name rdr_env (dataConName dc)] ] --- | Whether to report deprecation warnings when registering a used GRE------ There is no option to only emit declaration warnings since everywhere--- we emit the declaration warnings we also emit export warnings--- (See Note [Handling of deprecations] for details)-data DeprecationWarnings-  = NoDeprecationWarnings-  | ExportDeprecationWarnings-  | AllDeprecationWarnings- addUsedGRE :: DeprecationWarnings -> GlobalRdrElt -> RnM () -- Called for both local and imported things -- Add usage *and* warn if deprecated addUsedGRE warn_if_deprec gre-  = do { condWarnIfDeprecated warn_if_deprec [gre]+  = do { warnIfDeprecated warn_if_deprec [gre]        ; when (isImportedGRE gre) $ -- See Note [Using isImportedGRE in addUsedGRE]          do { env <- getGblEnv              -- Do not report the GREInfo (#23424)@@ -1754,9 +1807,9 @@ addUsedGREs :: DeprecationWarnings -> [GlobalRdrElt] -> RnM () -- Record uses of any *imported* GREs -- Used for recording used sub-bndrs--- NB: no call to warnIfDeprecated; see Note [Handling of deprecations]+-- NB: no call to warnIfDeprecated; see Note [Handling of deprecations] in GHC.Rename.Utils addUsedGREs warn_if_deprec gres-  = do { condWarnIfDeprecated warn_if_deprec gres+  = do { warnIfDeprecated warn_if_deprec gres        ; unless (null imp_gres) $          do { env <- getGblEnv               -- Do not report the GREInfo (#23424)@@ -1766,86 +1819,6 @@     imp_gres = filter isImportedGRE gres     -- See Note [Using isImportedGRE in addUsedGRE] -{- Note [Using isImportedGRE in addUsedGRE]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-In addUsedGRE, we want to add any used imported GREs to the tcg_used_gres field,-so that we can emit appropriate warnings (see GHC.Rename.Names.warnUnusedImportDecls).--We want to do this for GREs that were brought into scope through imports. As per-Note [GlobalRdrElt provenance] in GHC.Types.Name.Reader, this means we should-check that gre_imp is non-empty. Checking that gre_lcl is False is INCORRECT,-because we might have obtained the GRE by an Exact or Orig direct reference,-in which case we have both gre_lcl = False and gre_imp = emptyBag.--Geting this wrong can lead to panics in e.g. bestImport, see #23240.--}--condWarnIfDeprecated :: DeprecationWarnings -> [GlobalRdrElt] -> RnM ()-condWarnIfDeprecated NoDeprecationWarnings _ = return ()-condWarnIfDeprecated opt gres = do-  this_mod <- getModule-  let external_gres-        = filterOut (nameIsLocalOrFrom this_mod . greName) gres-  mapM_ (\gre -> warnIfExportDeprecated gre >> maybeWarnDeclDepr gre) external_gres-  where-    maybeWarnDeclDepr = case opt of-      ExportDeprecationWarnings -> const $ return ()-      AllDeprecationWarnings    -> warnIfDeclDeprecated--warnIfDeclDeprecated :: GlobalRdrElt -> RnM ()-warnIfDeclDeprecated gre@(GRE { gre_imp = iss })-  | Just imp_spec <- headMaybe iss-  = do { dflags <- getDynFlags-       ; when (wopt_any_custom dflags) $-                   -- See Note [Handling of deprecations]-         do { iface <- loadInterfaceForName doc name-            ; case lookupImpDeclDeprec iface gre of-                Just deprText -> addDiagnostic $-                  TcRnPragmaWarning {-                    pragma_warning_occ = occ,-                    pragma_warning_msg = deprText,-                    pragma_warning_import_mod = importSpecModule imp_spec,-                    pragma_warning_defined_mod = Just definedMod-                  }-                Nothing  -> return () } }-  | otherwise-  = return ()-  where-    occ = greOccName gre-    name = greName gre-    definedMod = moduleName $ assertPpr (isExternalName name) (ppr name) (nameModule name)-    doc = text "The name" <+> quotes (ppr occ) <+> text "is mentioned explicitly"--lookupImpDeclDeprec :: ModIface -> GlobalRdrElt -> Maybe (WarningTxt GhcRn)-lookupImpDeclDeprec iface gre-  -- Bleat if the thing, or its parent, is warn'd-  = mi_decl_warn_fn (mi_final_exts iface) (greOccName gre) `mplus`-    case greParent gre of-       ParentIs p -> mi_decl_warn_fn (mi_final_exts iface) (nameOccName p)-       NoParent   -> Nothing--warnIfExportDeprecated :: GlobalRdrElt -> RnM ()-warnIfExportDeprecated gre@(GRE { gre_imp = iss })-  = do { mod_warn_mbs <- mapBagM process_import_spec iss-       ; for_ (sequence mod_warn_mbs) $ mapM-           $ \(importing_mod, warn_txt) -> addDiagnostic $-             TcRnPragmaWarning {-               pragma_warning_occ = occ,-               pragma_warning_msg = warn_txt,-               pragma_warning_import_mod = importing_mod,-               pragma_warning_defined_mod = Nothing-             } }-  where-    occ = greOccName gre-    name = greName gre-    doc = text "The name" <+> quotes (ppr occ) <+> text "is mentioned explicitly"-    process_import_spec :: ImportSpec -> RnM (Maybe (ModuleName, WarningTxt GhcRn))-    process_import_spec is = do-      let mod = is_mod $ is_decl is-      iface <- loadInterfaceForModule doc mod-      let mb_warn_txt = mi_export_warn_fn (mi_final_exts iface) name-      return $ (moduleName mod, ) <$> mb_warn_txt- {- Note [Used names with interface not loaded] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -2090,12 +2063,12 @@ lookupSigCtxtOccRn :: HsSigCtxt                    -> SDoc         -- ^ description of thing we're looking up,                                    -- like "type family"-                   -> GenLocated (SrcSpanAnn' ann) RdrName-                   -> RnM (GenLocated (SrcSpanAnn' ann) Name)+                   -> GenLocated (EpAnn ann) RdrName+                   -> RnM (GenLocated (EpAnn ann) Name) lookupSigCtxtOccRn ctxt what   = wrapLocMA $ \ rdr_name ->     do { let also_try_tycons = False-       ; mb_names <- lookupBindGroupOcc ctxt what rdr_name also_try_tycons+       ; mb_names <- lookupBindGroupOcc ctxt what rdr_name also_try_tycons NoNamespaceSpecifier        ; case mb_names of            Right name NE.:| rest ->              do { massertPpr (null rest) $@@ -2112,12 +2085,13 @@                    -> Bool -- ^ if the 'RdrName' we are looking up is in                            -- a value 'NameSpace', should we also look up                            -- in the type constructor 'NameSpace'?+                   -> NamespaceSpecifier                    -> RnM (NE.NonEmpty (Either NotInScopeError Name)) -- ^ Looks up the 'RdrName', expecting it to resolve to one of the -- bound names currently in scope. If not, return an appropriate error message. -- -- See Note [Looking up signature names].-lookupBindGroupOcc ctxt what rdr_name also_try_tycon_ns+lookupBindGroupOcc ctxt what rdr_name also_try_tycon_ns ns_spec   | Just n <- isExact_maybe rdr_name   = do { mb_gre <- lookupExactOcc_either n        ; return $ case mb_gre of@@ -2132,24 +2106,27 @@    | otherwise   = case ctxt of-      HsBootCtxt ns    -> lookup_top (`elemNameSet` ns)-      TopSigCtxt ns    -> lookup_top (`elemNameSet` ns)-      RoleAnnotCtxt ns -> lookup_top (`elemNameSet` ns)+      HsBootCtxt ns    -> lookup_top (elem_name_set_with_namespace ns)+      TopSigCtxt ns    -> lookup_top (elem_name_set_with_namespace ns)+      RoleAnnotCtxt ns -> lookup_top (elem_name_set_with_namespace ns)       LocalBindCtxt ns -> lookup_group ns       ClsDeclCtxt  cls -> lookup_cls_op cls       InstDeclCtxt ns  -> if uniqSetAny isUnboundName ns -- #16610                           then return $ NE.singleton $ Right $ mkUnboundNameRdr rdr_name-                          else lookup_top (`elemNameSet` ns)+                          else lookup_top (elem_name_set_with_namespace ns)   where+    elem_name_set_with_namespace ns n = check_namespace n && (n `elemNameSet` ns) -    ns = occNameSpace occ+    check_namespace = coveredByNamespaceSpecifier ns_spec . nameNameSpace++    namespace = occNameSpace occ     occ = rdrNameOcc rdr_name     relevant_gres =       RelevantGREs         { includeFieldSelectors = WantBoth         , lookupVariablesForFields = True         , lookupTyConsAsWell = also_try_tycon_ns }-    ok_gre = greIsRelevant relevant_gres ns+    ok_gre = greIsRelevant relevant_gres namespace      finish err gre       | ok_gre gre@@ -2207,16 +2184,16 @@   ----------------lookupLocalTcNames :: HsSigCtxt -> SDoc -> RdrName -> RnM [(RdrName, Name)]+lookupLocalTcNames :: HsSigCtxt -> SDoc -> NamespaceSpecifier -> RdrName -> RnM [(RdrName, Name)] -- GHC extension: look up both the tycon and data con or variable. -- Used for top-level fixity signatures and deprecations. -- Complain if neither is in scope. -- See Note [Fixity signature lookup]-lookupLocalTcNames ctxt what rdr+lookupLocalTcNames ctxt what ns_spec rdr   = do { this_mod <- getModule        ; let also_try_tycon_ns = True        ; nms_eithers <- fmap (guard_builtin_syntax this_mod rdr) <$>-                        lookupBindGroupOcc ctxt what rdr also_try_tycon_ns+                        lookupBindGroupOcc ctxt what rdr also_try_tycon_ns ns_spec        ; let (errs, names) = partitionEithers (NE.toList nms_eithers)        ; when (null names) $           addErr (head errs) -- Bleat about one only@@ -2368,16 +2345,13 @@  -- Lookup operations for a qualified do. If the context is not a qualified -- do, then use lookupSyntaxExpr. See Note [QualifiedDo].-lookupQualifiedDoExpr :: HsStmtContext p -> Name -> RnM (HsExpr GhcRn, FreeVars)+lookupQualifiedDoExpr :: HsStmtContext fn -> Name -> RnM (HsExpr GhcRn, FreeVars) lookupQualifiedDoExpr ctxt std_name   = first nl_HsVar <$> lookupQualifiedDoName ctxt std_name  -- Like lookupQualifiedDoExpr but for producing SyntaxExpr. -- See Note [QualifiedDo].-lookupQualifiedDo-  :: HsStmtContext p-  -> Name-  -> RnM (SyntaxExpr GhcRn, FreeVars)+lookupQualifiedDo :: HsStmtContext fn -> Name -> RnM (SyntaxExpr GhcRn, FreeVars) lookupQualifiedDo ctxt std_name   = first mkSyntaxExpr <$> lookupQualifiedDoExpr ctxt std_name @@ -2387,10 +2361,7 @@        ; return (qname, unitFV qname) }  -- See Note [QualifiedDo].-lookupQualifiedDoName-  :: HsStmtContext p-  -> Name-  -> RnM (Name, FreeVars)+lookupQualifiedDoName :: HsStmtContext fn -> Name -> RnM (Name, FreeVars) lookupQualifiedDoName ctxt std_name   = case qualifiedDoModuleName_maybe ctxt of       Nothing -> lookupSyntaxName std_name
compiler/GHC/Rename/Expr.hs view
@@ -24,7 +24,7 @@ -}  module GHC.Rename.Expr (-        rnLExpr, rnExpr, rnStmts, mkExpandedExpr,+        rnLExpr, rnExpr, rnStmts,         AnnoBody, UnexpectedStatement(..)    ) where @@ -46,8 +46,8 @@                         , warnUnusedLocalBinds, typeAppErr                         , checkUnusedRecordWildcard                         , wrapGenSpan, genHsIntegralLit, genHsTyLit-                        , genHsVar, genLHsVar, genHsApp, genHsApps-                        , genAppType, isIrrefutableHsPatRn )+                        , genHsVar, genLHsVar, genHsApp, genHsApps, genHsApps'+                        , genAppType, isIrrefutableHsPat ) import GHC.Rename.Unbound ( reportUnboundName ) import GHC.Rename.Splice  ( rnTypedBracket, rnUntypedBracket, rnTypedSplice, rnUntypedSpliceExpr, checkThLocalName ) import GHC.Rename.HsType@@ -71,7 +71,6 @@ import GHC.Data.Maybe import GHC.Utils.Error import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Outputable as Outputable  import qualified GHC.LanguageExtensions as LangExt@@ -88,18 +87,26 @@  {- Note [Handling overloaded and rebindable constructs] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++Nomenclature+-------------+* Expansion (`HsExpr GhcRn -> HsExpr GhcRn`): expand between renaming and+  typechecking, using the `XXExprGhcRn` constructor of `HsExpr`.+* Desugaring (`HsExpr GhcTc -> Core.Expr`): convert the typechecked `HsSyn` to Core.  This is done in GHC.HsToCore++ For overloaded constructs (overloaded literals, lists, strings), and rebindable constructs (e.g. if-then-else), our general plan is this, using overloaded labels #foo as an example:  * In the RENAMER: transform       HsOverLabel "foo"-      ==> XExpr (HsExpansion (HsOverLabel #foo)-                             (fromLabel `HsAppType` "foo"))+      ==> XExpr (ExpandedThingRn (HsOverLabel #foo)+                                 (fromLabel `HsAppType` "foo"))   We write this more compactly in concrete-syntax form like this       #foo  ==>  fromLabel @"foo" -  Recall that in (HsExpansion orig expanded), 'orig' is the original term+  Recall that in (ExpandedThingRn orig expanded), 'orig' is the original term   the user wrote, and 'expanded' is the expanded or desugared version   to be typechecked. @@ -108,7 +115,7 @@   The typechecker (and desugarer) will never see HsOverLabel  In effect, the renamer does a bit of desugaring. Recall GHC.Hs.Expr-Note [Rebindable syntax and HsExpansion], which describes the use of HsExpansion.+Note [Rebindable syntax and XXExprGhcRn], which describes the use of XXExprGhcRn.  RebindableSyntax:   If RebindableSyntax is off we use the built-in 'fromLabel', defined in@@ -134,7 +141,7 @@ * OverLabel (overloaded labels, #lbl)      #lbl  ==>  fromLabel @"lbl"   As ever, we use lookupSyntaxName to look up 'fromLabel'-  See Note [Overloaded labels]+  See Note [Overloaded labels] below  * ExplicitList (explicit lists [a,b,c])   When (and only when) OverloadedLists is on@@ -148,13 +155,8 @@   where `leftSection` and `rightSection` are representation-polymorphic   wired-in Ids. See Note [Left and right sections] -* It's a bit painful to transform `OpApp e1 op e2` to a `HsExpansion`-  form, because the renamer does precedence rearrangement after name-  resolution.  So the renamer leaves an OpApp as an OpApp.--  The typechecker turns `OpApp` into a use of `HsExpansion`-  on the fly, in GHC.Tc.Gen.Head.splitHsApps.  RebindableSyntax-  does not affect this.+* To understand why expansions for `OpApp` is done in `GHC.Tc.Gen.Head.splitHsApps`+  see Note [Doing XXExprGhcRn in the Renamer vs Typechecker] below.  * RecordUpd: we desugar record updates into case expressions,   in GHC.Tc.Gen.Expr.tcExpr.@@ -176,21 +178,25 @@    See Note [Record Updates] in GHC.Tc.Gen.Expr for more details. -  This is done in the typechecker, not the renamer, for two reasons:+  To understand Why is this done in the typechecker, and not in the renamer+  see Note [Doing XXExprGhcRn in the Renamer vs Typechecker] -    - (Until we implement GHC proposal #366)-      We need to know the type of the record to disambiguate its fields.+* HsDo: We expand `HsDo` statements in `Ghc.Tc.Gen.Do`. -    - We use the type signature of the data constructor to provide IdSigs-      to the let-bound variables (x', y' in the example above). This is-      needed to accept programs such as+    - For example, a user written code: -        data R b = MkR { f :: (forall a. a -> a) -> (Int,b), c :: Int }-        foo r = r { f = \ k -> (k 3, k 'x') }+                  do { x <- e1 ; g x ; return (f x) } -      in which an updated field has a higher-rank type.-      See Wrinkle [Using IdSig] in Note [Record Updates] in GHC.Tc.Gen.Expr.+      is expanded to: +                   (>>=) e1+                         (\x -> ((>>) (g x)+                                      (return (f x))))++     See Note [Expanding HsDo with XXExprGhcRn] in `Ghc.Tc.Gen.Do` for more details.+     To understand why is this done in the typechecker and not in the renamer.+     See Note [Doing XXExprGhcRn in the Renamer vs Typechecker]+ Note [Overloaded labels] ~~~~~~~~~~~~~~~~~~~~~~~~ For overloaded labels, note that we /only/ apply `fromLabel` to the@@ -209,6 +215,66 @@  And those inferred kind quantifiers will indeed be instantiated when we typecheck the renamed-syntax call (fromLabel @"foo").++Note [Doing XXExprGhcRn in the Renamer vs Typechecker]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+We expand some `HsExpr GhcRn` code at various places, usually, on the fly,+depending on when it is more convenient. It may be beneficial to have a+separate `HsExpr GhcRn -> HsExpr GhcRn` pass that does this expansion uniformly+in the future when we have enough cases to cater for. For the time being,+this note documents which language feature is expanded at which phase,+and the reasons for doing so.++  ** `HsIf` Expansions+  --------------------+  `HsIf` expansions are expanded in the Renamer becuase it is more convinent+  to do so there and then not worry about it in the later stage.+  `-XRebindableSyntax` is used to decide whether we use the `HsIf` or user defined if+++  ** `OpApp` Expansions+  ---------------------+  The typechecker turns `OpApp` into a use of `XXExprGhcRn`+  on the fly, in `GHC.Tc.Gen.Head.splitHsApps`.+  The language extension `RebindableSyntax` does not affect this behaviour.++  It's a bit painful to transform `OpApp e1 op e2` to a `XXExprGhcRn`+  form, because the renamer does precedence rearrangement after name+  resolution. So the renamer leaves an `OpApp` as an `OpApp`.++  ** Record Update Syntax `RecordUpd` Expansions+  ----------------------------------------------+  This is done in the typechecker on the fly (`GHC.Tc.Expr.tcExpr`), and not the renamer, for two reasons:++    - (Until we implement GHC proposal #366)+      We need to know the type of the record to disambiguate its fields.++    - We use the type signature of the data constructor to provide `IdSigs`+      to the let-bound variables (x', y' in the example of+      Note [Handling overloaded and rebindable constructs] above).+      This is needed to accept programs such as++          data R b = MkR { f :: (forall a. a -> a) -> (Int,b), c :: Int }+          foo r = r { f = \ k -> (k 3, k 'x') }++      in which an updated field has a higher-rank type.+      See Wrinkle [Using IdSig] in Note [Record Updates] in GHC.Tc.Gen.Expr.++  ** `HsDo` Statement Expansions+  -----------------------------------+  The expansion for do block statements is done on the fly right before typechecking in `GHC.Tc.Gen.Expr`+  using `GHC.Tc.Gen.Do.expandDoStmts`. There are 2 main reasons:++  -  During the renaming phase, we may not have all the constructor details `HsConDetails` populated in the+     data structure. This would result in an inaccurate irrefutability analysis causing+     the continuation lambda body to be wrapped with `fail` alternatives when not needed.+     See Part 1. of Note [Expanding HsDo with XXExprGhcRn] (test pattern-fails.hs)++  -  If the expansion is done on the fly during renaming, expressions that+     have explicit type applications using (-XTypeApplciations) will not work (cf. Let statements expansion)+     as the name freshening happens from the root of the AST to the leaves,+     but the expansion happens in the opposite direction (from leaves to the root),+     causing the renamer to miss the scoped type variables. -}  {-@@ -245,7 +311,7 @@  = do { this_mod <- getModule       ; when (nameIsLocalOrFrom this_mod name) $         checkThLocalName name-      ; return (HsVar noExtField (L (la2na l) name), unitFV name) }+      ; return (HsVar noExtField (L (l2l l) name), unitFV name) }  rnUnboundVar :: RdrName -> RnM (HsExpr GhcRn, FreeVars) rnUnboundVar v = do@@ -281,7 +347,7 @@             -> rnExpr (ExplicitList noAnn [])              | otherwise-            -> finishHsVar (L (na2la l) nm)+            -> finishHsVar (L (l2l l) nm)         }}}  rnExpr (HsIPVar x v)@@ -293,8 +359,8 @@ -- HsOverLabel: see Note [Handling overloaded and rebindable constructs] rnExpr (HsOverLabel _ src v)   = do { (from_label, fvs) <- lookupSyntaxName fromLabelClassOpName-       ; return ( mkExpandedExpr (HsOverLabel noAnn src v) $-                  HsAppType noExtField (genLHsVar from_label) noHsTok hs_ty_arg+       ; return ( mkExpandedExpr (HsOverLabel noExtField src v) $+                  HsAppType noExtField (genLHsVar from_label) hs_ty_arg                 , fvs ) }   where     hs_ty_arg = mkEmptyWildCardBndrs $ wrapGenSpan $@@ -317,7 +383,7 @@        ; case mb_neg of               Nothing -> return (HsOverLit x lit', fvs)               Just neg ->-                 return (HsApp noComments (noLocA neg) (noLocA (HsOverLit x lit'))+                 return (HsApp noExtField (noLocA neg) (noLocA (HsOverLit x lit'))                         , fvs ) }  rnExpr (HsApp x fun arg)@@ -325,12 +391,12 @@        ; (arg',fvArg) <- rnLExpr arg        ; return (HsApp x fun' arg', fvFun `plusFV` fvArg) } -rnExpr (HsAppType _ fun at arg)+rnExpr (HsAppType _ fun arg)   = do { type_app <- xoptM LangExt.TypeApplications        ; unless type_app $ addErr $ typeAppErr TypeLevel $ hswc_body arg        ; (fun',fvFun) <- rnLExpr fun        ; (arg',fvArg) <- rnHsWcType HsTypeCtx arg-       ; return (HsAppType NoExtField fun' at arg', fvFun `plusFV` fvArg) }+       ; return (HsAppType noExtField fun' arg', fvFun `plusFV` fvArg) }  rnExpr (OpApp _ e1 op e2)   = do  { (e1', fv_e1) <- rnLExpr e1@@ -392,17 +458,17 @@ --------------------------------------------- --      Sections -- See Note [Parsing sections] in GHC.Parser-rnExpr (HsPar x lpar (L loc (section@(SectionL {}))) rpar)+rnExpr (HsPar _ (L loc (section@(SectionL {}))))   = do  { (section', fvs) <- rnSection section-        ; return (HsPar x lpar (L loc section') rpar, fvs) }+        ; return (HsPar noExtField (L loc section'), fvs) } -rnExpr (HsPar x lpar (L loc (section@(SectionR {}))) rpar)+rnExpr (HsPar _ (L loc (section@(SectionR {}))))   = do  { (section', fvs) <- rnSection section-        ; return (HsPar x lpar (L loc section') rpar, fvs) }+        ; return (HsPar noExtField (L loc section'), fvs) } -rnExpr (HsPar x lpar e rpar)+rnExpr (HsPar _ e)   = do  { (e', fvs_e) <- rnLExpr e-        ; return (HsPar x lpar e' rpar, fvs_e) }+        ; return (HsPar noExtField e', fvs_e) }  rnExpr expr@(SectionL {})   = do  { addErr (sectionErr expr); rnSection expr }@@ -417,23 +483,19 @@     rn_prag :: HsPragE GhcPs -> HsPragE GhcRn     rn_prag (HsPragSCC x ann) = HsPragSCC x ann -rnExpr (HsLam x matches)-  = do { (matches', fvMatch) <- rnMatchGroup LambdaExpr rnLExpr matches-       ; return (HsLam x matches', fvMatch) }--rnExpr (HsLamCase x lc_variant matches)-  = do { (matches', fvs_ms) <- rnMatchGroup (LamCaseAlt lc_variant) rnLExpr matches-       ; return (HsLamCase x lc_variant matches', fvs_ms) }+rnExpr (HsLam x lam_variant matches)+  = do { (matches', fvs_ms) <- rnMatchGroup (LamAlt lam_variant) rnLExpr matches+       ; return (HsLam x lam_variant matches', fvs_ms) }  rnExpr (HsCase _ expr matches)   = do { (new_expr, e_fvs) <- rnLExpr expr        ; (new_matches, ms_fvs) <- rnMatchGroup CaseAlt rnLExpr matches        ; return (HsCase CaseAlt new_expr new_matches, e_fvs `plusFV` ms_fvs) } -rnExpr (HsLet _ tkLet binds tkIn expr)+rnExpr (HsLet _ binds expr)   = rnLocalBindsAndThen binds $ \binds' _ -> do       { (expr',fvExpr) <- rnLExpr expr-      ; return (HsLet noExtField tkLet binds' tkIn expr', fvExpr) }+      ; return (HsLet noExtField binds' expr', fvExpr) }  rnExpr (HsDo _ do_or_lc (L l stmts))  = do { ((stmts1, _), fvs1) <-@@ -441,7 +503,6 @@             (\ _ -> return ((), emptyFVs))       ; (pp_stmts, fvs2) <- postProcessStmtsForApplicativeDo do_or_lc stmts1       ; return ( HsDo noExtField do_or_lc (L l pp_stmts), fvs1 `plusFV` fvs2 ) }- -- ExplicitList: see Note [Handling overloaded and rebindable constructs] rnExpr (ExplicitList _ exps)   = do  { (exps', fvs) <- rnExprs exps@@ -450,10 +511,11 @@           then return  (ExplicitList noExtField exps', fvs)           else     do { (from_list_n_name, fvs') <- lookupSyntaxName fromListNName+       ; loc <- getSrcSpanM -- See Note [Source locations for implicit function calls]        ; let rn_list  = ExplicitList noExtField exps'              lit_n    = mkIntegralLit (length exps)              hs_lit   = genHsIntegralLit lit_n-             exp_list = genHsApps from_list_n_name [hs_lit, wrapGenSpan rn_list]+             exp_list = genHsApps' (L (noAnnSrcSpan loc) from_list_n_name) [hs_lit, wrapGenSpan rn_list]        ; return ( mkExpandedExpr rn_list exp_list                 , fvs `plusFV` fvs') } } @@ -530,24 +592,7 @@ -- HsIf: see Note [Handling overloaded and rebindable constructs] -- Because of the coverage checker it is most convenient /not/ to -- expand HsIf; unless we are in rebindable syntax.-rnExpr (HsIf _ p b1 b2)-  = do { (p',  fvP)  <- rnLExpr p-       ; (b1', fvB1) <- rnLExpr b1-       ; (b2', fvB2) <- rnLExpr b2-       ; let fvs_if = plusFVs [fvP, fvB1, fvB2]-             rn_if  = HsIf noExtField  p' b1' b2'--       -- Deal with rebindable syntax-       -- See Note [Handling overloaded and rebindable constructs]-       ; mb_ite <- lookupIfThenElse-       ; case mb_ite of-            Nothing  -- Non rebindable-syntax case-              -> return (rn_if, fvs_if)--            Just ite_name   -- Rebindable-syntax case-              -> do { let ds_if = genHsApps ite_name [p', b1', b2']-                          fvs   = plusFVs [fvs_if, unitFV ite_name]-                    ; return (mkExpandedExpr rn_if ds_if, fvs) } }+rnExpr (HsIf _ p b1 b2) = rnHsIf p b1 b2  rnExpr (HsMultiIf _ alts)   = do { (alts', fvs) <- mapFvRn (rnGRHS IfAlt rnLExpr) alts@@ -564,6 +609,10 @@            else             return (ArithSeq noExtField Nothing new_seq, fvs) } +rnExpr (HsEmbTy _ ty)+  = do { (ty', fvs) <- rnHsWcType HsTypeCtx ty+       ; return (HsEmbTy noExtField ty', fvs) }+ {- ************************************************************************ *                                                                      *@@ -639,9 +688,9 @@                         -- Note [Left and right sections]         ; let rn_section = SectionL x expr' op'               ds_section-                | postfix_ops = HsApp noAnn op' expr'+                | postfix_ops = HsApp noExtField op' expr'                 | otherwise   = genHsApps leftSectionName-                                   [wrapGenSpan $ HsApp noAnn op' expr']+                                   [wrapGenSpan $ HsApp noExtField op' expr']         ; return ( mkExpandedExpr rn_section ds_section                  , fvs_op `plusFV` fvs_expr) } @@ -878,13 +927,14 @@        ; (arg',fvArg) <- rnLExpr arg        ; return (HsCmdApp x fun' arg', fvFun `plusFV` fvArg) } -rnCmd (HsCmdLam _ matches)-  = do { (matches', fvMatch) <- rnMatchGroup (ArrowMatchCtxt KappaExpr) rnLCmd matches-       ; return (HsCmdLam noExtField matches', fvMatch) }+rnCmd (HsCmdLam x lam_variant matches)+  = do { let ctxt = ArrowMatchCtxt $ ArrowLamAlt lam_variant+       ; (new_matches, ms_fvs) <- rnMatchGroup ctxt rnLCmd matches+       ; return (HsCmdLam x lam_variant new_matches, ms_fvs) } -rnCmd (HsCmdPar x lpar e rpar)+rnCmd (HsCmdPar _ e)   = do  { (e', fvs_e) <- rnLCmd e-        ; return (HsCmdPar x lpar e' rpar, fvs_e) }+        ; return (HsCmdPar noExtField e', fvs_e) }  rnCmd (HsCmdCase _ expr matches)   = do { (new_expr, e_fvs) <- rnLExpr expr@@ -892,11 +942,6 @@        ; return (HsCmdCase noExtField new_expr new_matches                 , e_fvs `plusFV` ms_fvs) } -rnCmd (HsCmdLamCase x lc_variant matches)-  = do { (new_matches, ms_fvs) <--           rnMatchGroup (ArrowMatchCtxt $ ArrowLamCaseAlt lc_variant) rnLCmd matches-       ; return (HsCmdLamCase x lc_variant new_matches, ms_fvs) }- rnCmd (HsCmdIf _ _ p b1 b2)   = do { (p', fvP) <- rnLExpr p        ; (b1', fvB1) <- rnLCmd b1@@ -909,10 +954,10 @@         ; return (HsCmdIf noExtField ite p' b1' b2', plusFVs [fvITE, fvP, fvB1, fvB2])} -rnCmd (HsCmdLet _ tkLet binds tkIn cmd)+rnCmd (HsCmdLet _ binds cmd)   = rnLocalBindsAndThen binds $ \ binds' _ -> do       { (cmd',fvExpr) <- rnLCmd cmd-      ; return (HsCmdLet noExtField tkLet binds' tkIn cmd', fvExpr) }+      ; return (HsCmdLet noExtField binds' cmd', fvExpr) }  rnCmd (HsCmdDo _ (L l stmts))   = do  { ((stmts', _), fvs) <-@@ -935,20 +980,18 @@   = unitFV appAName methodNamesCmd (HsCmdArrForm {}) = emptyFVs -methodNamesCmd (HsCmdPar _ _ c _) = methodNamesLCmd c+methodNamesCmd (HsCmdPar _ c) = methodNamesLCmd c  methodNamesCmd (HsCmdIf _ _ _ c1 c2)   = methodNamesLCmd c1 `plusFV` methodNamesLCmd c2 `addOneFV` choiceAName -methodNamesCmd (HsCmdLet _ _ _ _ c)      = methodNamesLCmd c+methodNamesCmd (HsCmdLet _ _ c)          = methodNamesLCmd c methodNamesCmd (HsCmdDo _ (L _ stmts))   = methodNamesStmts stmts methodNamesCmd (HsCmdApp _ c _)          = methodNamesLCmd c-methodNamesCmd (HsCmdLam _ match)        = methodNamesMatch match -methodNamesCmd (HsCmdCase _ _ matches)-  = methodNamesMatch matches `addOneFV` choiceAName-methodNamesCmd (HsCmdLamCase _ _ matches)-  = methodNamesMatch matches `addOneFV` choiceAName+methodNamesCmd (HsCmdCase _ _ matches)        = methodNamesMatch matches `addOneFV` choiceAName+methodNamesCmd (HsCmdLam _ LamSingle matches) = methodNamesMatch matches+methodNamesCmd (HsCmdLam _ _         matches) = methodNamesMatch matches `addOneFV` choiceAName  --methodNamesCmd _ = emptyFVs    -- Other forms can't occur in commands, but it's not convenient@@ -1058,7 +1101,7 @@  -- | Rename some Stmts rnStmts :: AnnoBody body-        => HsStmtContext GhcRn+        => HsStmtContextRn         -> (body GhcPs -> RnM (body GhcRn, FreeVars))            -- ^ How to rename the body of each statement (e.g. rnLExpr)         -> [LStmt GhcPs (LocatedA (body GhcPs))]@@ -1094,14 +1137,14 @@  -- | strip the FreeVars annotations from statements noPostProcessStmts-  :: HsStmtContext GhcRn+  :: HsStmtContextRn   -> [(LStmt GhcRn (LocatedA (body GhcRn)), FreeVars)]   -> RnM ([LStmt GhcRn (LocatedA (body GhcRn))], FreeVars) noPostProcessStmts _ stmts = return (map fst stmts, emptyNameSet)   rnStmtsWithFreeVars :: AnnoBody body-        => HsStmtContext GhcRn+        => HsStmtContextRn         -> ((body GhcPs) -> RnM ((body GhcRn), FreeVars))         -> [LStmt GhcPs (LocatedA (body GhcPs))]         -> ([Name] -> RnM (thing, FreeVars))@@ -1164,7 +1207,7 @@ -}  rnStmt :: AnnoBody body-       => HsStmtContext GhcRn+       => HsStmtContextRn        -> (body GhcPs -> RnM (body GhcRn, FreeVars))           -- ^ How to rename the body of the statement        -> LStmt GhcPs (LocatedA (body GhcPs))@@ -1183,7 +1226,7 @@                             else return (noSyntaxExpr, emptyFVs)                             -- The 'return' in a LastStmt is used only                             -- for MonadComp; and we don't want to report-                            -- "non in scope: return" in other cases+                            -- "not in scope: return" in other cases                             -- #15607          ; (thing,  fvs3) <- thing_inside []@@ -1309,7 +1352,7 @@ rnStmt _ _ (L _ ApplicativeStmt{}) _ =   panic "rnStmt: ApplicativeStmt" -rnParallelStmts :: forall thing. HsStmtContext GhcRn+rnParallelStmts :: forall thing. HsStmtContextRn                 -> SyntaxExpr GhcRn                 -> [ParStmtBlock GhcPs GhcPs]                 -> ([Name] -> RnM (thing, FreeVars))@@ -1341,7 +1384,7 @@      dupErr vs = addErr $ TcRnListComprehensionDuplicateBinding (NE.head vs) -lookupQualifiedDoStmtName :: HsStmtContext GhcRn -> Name -> RnM (SyntaxExpr GhcRn, FreeVars)+lookupQualifiedDoStmtName :: HsStmtContextRn -> Name -> RnM (SyntaxExpr GhcRn, FreeVars) -- Like lookupStmtName, but respects QualifiedDo lookupQualifiedDoStmtName ctxt n   = case qualifiedDoModuleName_maybe ctxt of@@ -1349,7 +1392,7 @@       Just modName ->         first (mkSyntaxExpr . nl_HsVar) <$> lookupNameWithQualifier n modName -lookupStmtName :: HsStmtContext GhcRn -> Name -> RnM (SyntaxExpr GhcRn, FreeVars)+lookupStmtName :: HsStmtContextRn -> Name -> RnM (SyntaxExpr GhcRn, FreeVars) -- Like lookupSyntax, but respects contexts lookupStmtName ctxt n   | rebindableContext ctxt@@ -1357,7 +1400,7 @@   | otherwise   = return (mkRnSyntaxExpr n, emptyFVs) -lookupStmtNamePoly :: HsStmtContext GhcRn -> Name -> RnM (HsExpr GhcRn, FreeVars)+lookupStmtNamePoly :: HsStmtContextRn -> Name -> RnM (HsExpr GhcRn, FreeVars) lookupStmtNamePoly ctxt name   | rebindableContext ctxt   = do { rebindable_on <- xoptM LangExt.RebindableSyntax@@ -1373,7 +1416,7 @@ -- | Is this a context where we respect RebindableSyntax? -- but ListComp are never rebindable -- Neither is ArrowExpr, which has its own desugarer in GHC.HsToCore.Arrows-rebindableContext :: HsStmtContext GhcRn -> Bool+rebindableContext :: HsStmtContextRn -> Bool rebindableContext ctxt = case ctxt of   HsDoStmt flavour -> rebindableDoStmtContext flavour   ArrowExpr -> False@@ -1429,7 +1472,7 @@  -- wrapper that does both the left- and right-hand sides rnRecStmtsAndThen :: AnnoBody body-                  => HsStmtContext GhcRn+                  => HsStmtContextRn                   -> (body GhcPs -> RnM (body GhcRn, FreeVars))                   -> [LStmt GhcPs (LocatedA (body GhcPs))]                          -- assumes that the FreeVars returned includes@@ -1448,7 +1491,7 @@         ; let bound_names = collectLStmtsBinders CollNoDictBinders (map fst new_lhs_and_fv)               -- Fake uses of variables introduced implicitly (warning suppression, see #4404)               rec_uses = lStmtsImplicits (map fst new_lhs_and_fv)-              implicit_uses = mkNameSet $ concatMap snd $ rec_uses+              implicit_uses = mkNameSet $ concatMap (concatMap implFlBndr_binders . snd) $ rec_uses         ; bindLocalNamesFV bound_names $           addLocalFixities fix_env bound_names $ do @@ -1534,7 +1577,7 @@ -- right-hand-sides  rn_rec_stmt :: AnnoBody body =>-               HsStmtContext GhcRn+               HsStmtContextRn             -> (body GhcPs -> RnM (body GhcRn, FreeVars))             -> [Name]             -> (LStmtLR GhcRn GhcPs (LocatedA (body GhcPs)), FreeVars)@@ -1593,7 +1636,7 @@   = pprPanic "rn_rec_stmt: ApplicativeStmt" (ppr stmt)  rn_rec_stmts :: AnnoBody body-             => HsStmtContext GhcRn+             => HsStmtContextRn              -> (body GhcPs -> RnM (body GhcRn, FreeVars))              -> [Name]              -> [(LStmtLR GhcRn GhcPs (LocatedA (body GhcPs)), FreeVars)]@@ -1603,7 +1646,7 @@        ; return (concat segs_s) }  ----------------------------------------------segmentRecStmts :: SrcSpan -> HsStmtContext GhcRn+segmentRecStmts :: SrcSpan -> HsStmtContextRn                 -> Stmt GhcRn (LocatedA (body GhcRn))                 -> [Segment (LStmt GhcRn (LocatedA (body GhcRn)))]                 -> (FreeVars, Bool)@@ -1743,7 +1786,7 @@ be used later. -} -glomSegments :: HsStmtContext GhcRn+glomSegments :: HsStmtContextRn              -> [Segment (LStmt GhcRn body)]              -> [Segment [LStmt GhcRn body]]                                   -- Each segment has a non-empty list of Stmts@@ -1829,7 +1872,7 @@      (y,z) <- (,) <$> B x <*> C      return (f x y z) -But this isn't enough! A and C were also independent, and this+But this isn't enough! If A and C were also independent, then this transformation loses the ability to do A and C in parallel.  The algorithm works by first splitting the sequence of statements into@@ -2192,7 +2235,7 @@              -- Need 'pureAName' and not 'returnMName' here, so that it requires              -- 'Applicative' and not 'Monad' whenever possible (until #20540 is fixed).              (ret, _) <- lookupQualifiedDoExpr (HsDoStmt ctxt) pureAName-             let expr = HsApp noComments (noLocA ret) tup+             let expr = HsApp noExtField (noLocA ret) tup              return (expr, emptyFVs)      return ( ApplicativeArgMany               { xarg_app_arg_many = noExtField@@ -2288,8 +2331,8 @@     WildPat{}       -> False     VarPat{}        -> False     LazyPat{}       -> False-    AsPat _ _ _ p   -> isStrictPattern p-    ParPat _ _ p _  -> isStrictPattern p+    AsPat _ _ p     -> isStrictPattern p+    ParPat _ p      -> isStrictPattern p     ViewPat _ _ p   -> isStrictPattern p     SigPat _ p _    -> isStrictPattern p     BangPat{}       -> True@@ -2301,10 +2344,13 @@     NPat{}          -> True     NPlusKPat{}     -> True     SplicePat{}     -> True++    -- The behavior of this case is unimportant, as GHC will throw an error shortly+    -- after reaching this case for other reasons (see TcRnIllegalTypePattern).+    EmbTyPat{}  -> False+    InvisPat{}  -> False+     XPat ext        -> case ghcPass @p of-#if __GLASGOW_HASKELL__ < 811-      GhcPs -> dataConCantHappen ext-#endif       GhcRn         | HsPatExpanded _ p <- ext         -> isStrictPattern (L loc p)@@ -2324,7 +2370,7 @@ hasRefutablePattern :: DynFlags -> ApplicativeArg GhcRn -> Bool hasRefutablePattern dflags (ApplicativeArgOne { app_arg_pattern = pat                                               , is_body_stmt = False}) =-                                         not (isIrrefutableHsPatRn dflags pat)+                                         not (isIrrefutableHsPat dflags pat) hasRefutablePattern _ _ = False  isLetStmt :: LStmt (GhcPass a) b -> Bool@@ -2409,7 +2455,11 @@                 ; return (Just join_op, fvs) }            else              return (Nothing, emptyNameSet)-       ; let applicative_stmt = noLocA $ ApplicativeStmt noExtField+       -- We cannot really say where the ApplicativeStmt is located with more accuracy+       -- than the span of the do-block, but it is better than nothing for IDE info+       -- See Note [Source locations for implicit function calls]+       ; loc <- getSrcSpanM+       ; let applicative_stmt = L (noAnnSrcSpan loc) $ ApplicativeStmt noExtField                (zip (fmap_op : repeat ap_op) args)                mb_join        ; return ( applicative_stmt : body_stmts@@ -2447,7 +2497,7 @@             -- If this is @Nothing@, strip the return/pure             -> Maybe (HsExpr GhcRn)             -> Maybe (LHsExpr GhcRn, Maybe Bool)-isReturnApp monad_names (L _ (HsPar _ _ expr _)) mb_pure =+isReturnApp monad_names (L _ (HsPar _ expr)) mb_pure =   isReturnApp monad_names expr mb_pure isReturnApp monad_names (L loc e) mb_pure = case e of   OpApp x l op r@@ -2460,8 +2510,8 @@     | is_return f -> Just (arg, Just False)   _otherwise -> Nothing  where-  is_var f (L _ (HsPar _ _ e _)) = is_var f e-  is_var f (L _ (HsAppType _ e _ _)) = is_var f e+  is_var f (L _ (HsPar _ e)) = is_var f e+  is_var f (L _ (HsAppType _ e _)) = is_var f e   is_var f (L _ (HsVar _ (L _ r))) = f r        -- TODO: I don't know how to get this right for rebindable syntax   is_var _ _ = False@@ -2479,7 +2529,7 @@ ************************************************************************ -} -checkEmptyStmts :: HsStmtContext GhcRn -> RnM ()+checkEmptyStmts :: HsStmtContextRn -> RnM () -- We've seen an empty sequence of Stmts... is that ok? checkEmptyStmts ctxt   = mapM_ (addErr . TcRnEmptyStmtsGroup) mb_err@@ -2493,7 +2543,7 @@  ---------------------- checkLastStmt :: AnnoBody body-              => HsStmtContext GhcRn+              => HsStmtContextRn               -> LStmt GhcPs (LocatedA (body GhcPs))               -> RnM (LStmt GhcPs (LocatedA (body GhcPs))) checkLastStmt ctxt lstmt@(L loc stmt)@@ -2525,7 +2575,7 @@  -- Checking when a particular Stmt is ok checkStmt :: AnnoBody body-          => HsStmtContext GhcRn+          => HsStmtContextRn           -> LStmt GhcPs (LocatedA (body GhcPs))           -> RnM () checkStmt ctxt (L _ stmt)@@ -2541,7 +2591,7 @@ emptyInvalid = NotValid Nothing -- Invalid, and no extension to suggest  okStmt, okDoStmt, okCompStmt, okParStmt-   :: DynFlags -> HsStmtContext GhcRn+   :: DynFlags -> HsStmtContextRn    -> Stmt GhcPs (LocatedA (body GhcPs)) -> Validity' (Maybe LangExt.Extension) -- Return Nothing if OK, (Just extra) if not ok -- The "extra" is an SDoc that is appended to a generic error message@@ -2555,7 +2605,7 @@       TransStmtCtxt ctxt -> okStmt dflags ctxt stmt  okDoFlavourStmt-  :: DynFlags -> HsDoFlavour -> HsStmtContext GhcRn+  :: DynFlags -> HsDoFlavour -> HsStmtContextRn   -> Stmt GhcPs (LocatedA (body GhcPs)) -> Validity' (Maybe LangExt.Extension) okDoFlavourStmt dflags flavour ctxt stmt = case flavour of       DoExpr{}     -> okDoStmt   dflags ctxt stmt@@ -2626,13 +2676,13 @@ ---------  monadFailOp :: LPat GhcPs-            -> HsStmtContext GhcRn+            -> HsStmtContextRn             -> RnM (FailOperator GhcRn, FreeVars) monadFailOp pat ctxt = do     dflags <- getDynFlags         -- If the pattern is irrefutable (e.g.: wildcard, tuple, ~pat, etc.)         -- we should not need to fail.-    if | isIrrefutableHsPatRn dflags pat -> return (Nothing, emptyFVs)+    if | isIrrefutableHsPat dflags pat -> return (Nothing, emptyFVs)          -- For non-monadic contexts (e.g. guard patterns, list         -- comprehensions, etc.) we should not need to fail, or failure is handled in@@ -2677,7 +2727,7 @@                         Nothing -> M.fail (fromString "Pattern match error")  -}-getMonadFailOp :: HsStmtContext p -> RnM (FailOperator GhcRn, FreeVars) -- Syntax expr fail op+getMonadFailOp :: HsStmtContext fn -> RnM (FailOperator GhcRn, FreeVars) -- Syntax expr fail op getMonadFailOp ctxt  = do { xOverloadedStrings <- fmap (xopt LangExt.OverloadedStrings) getDynFlags       ; xRebindableSyntax <- fmap (xopt LangExt.RebindableSyntax) getDynFlags@@ -2707,19 +2757,31 @@  {- ********************************************************************* *                                                                      *-              Generating code for HsExpanded+              Generating code for ExpandedThingRn       See Note [Handling overloaded and rebindable constructs] *                                                                      * ********************************************************************* -} --- | Build a 'HsExpansion' out of an extension constructor,---   and the two components of the expansion: original and---   desugared expressions.-mkExpandedExpr-  :: HsExpr GhcRn           -- ^ source expression-  -> HsExpr GhcRn           -- ^ expanded expression-  -> HsExpr GhcRn           -- ^ suitably wrapped 'HsExpansion'-mkExpandedExpr a b = XExpr (HsExpanded a b)+-- | Expand `HsIf` if rebindable syntax is turned on+--   See Note [Handling overloaded and rebindable constructs]+rnHsIf :: LHsExpr GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs -> RnM (HsExpr GhcRn, FreeVars)+rnHsIf p b1 b2+  = do { (p',  fvP)  <- rnLExpr p+       ; (b1', fvB1) <- rnLExpr b1+       ; (b2', fvB2) <- rnLExpr b2+       ; let fvs_if = plusFVs [fvP, fvB1, fvB2]+             rn_if  = HsIf noExtField  p' b1' b2'++       -- Deal with rebindable syntax+       ; mb_ite <- lookupIfThenElse+       ; case mb_ite of+            Nothing  -- Non rebindable-syntax case+              -> return (rn_if, fvs_if)++            Just ite_name   -- Rebindable-syntax case+              -> do { let ds_if = genHsApps ite_name [p', b1', b2']+                          fvs   = plusFVs [fvs_if, unitFV ite_name]+                    ; return (mkExpandedExpr rn_if ds_if, fvs) } }  ----------------------------------------- -- Bits and pieces for RecordDotSyntax.
compiler/GHC/Rename/Expr.hs-boot view
@@ -18,7 +18,7 @@     )  rnStmts :: --forall thing body.-           AnnoBody body => HsStmtContext GhcRn+           AnnoBody body => HsStmtContextRn         -> (body GhcPs -> RnM (body GhcRn, FreeVars))         -> [LStmt GhcPs (LocatedA (body GhcPs))]         -> ([Name] -> RnM (thing, FreeVars))
compiler/GHC/Rename/Fixity.hs view
@@ -4,8 +4,10 @@ -}  module GHC.Rename.Fixity-   ( MiniFixityEnv+   ( MiniFixityEnv(..)    , addLocalFixities+   , lookupMiniFixityEnv+   , emptyMiniFixityEnv    , lookupFixityRn    , lookupFixityRn_help    , lookupFieldFixityRn@@ -63,31 +65,60 @@ -}  ---------------------------------type MiniFixityEnv = FastStringEnv (Located Fixity)-        -- Mini fixity env for the names we're about-        -- to bind, in a single binding group-        ---        -- It is keyed by the *FastString*, not the *OccName*, because-        -- the single fixity decl       infix 3 T-        -- affects both the data constructor T and the type constructor T-        ---        -- We keep the location so that if we find-        -- a duplicate, we can report it sensibly +-- | Mini fixity env for the names we're about+-- to bind, in a single binding group+--+-- It is keyed by the *FastString*, not the *OccName*, because+-- the single fixity decl       @infix 3 T@+-- affects both the data constructor T and the type constructor T+--+-- We keep the location so that if we find+-- a duplicate, we can report it sensibly+--+-- Fixity declarations may influence names in a single namespace by using+-- a type or data specifier, e.g. in:+--+-- >  data a :*: b = a :*: b+-- >  infix 3 type :*:+--+-- To handle that correctly, MiniFixityEnv contains separate+-- fields for type-level and data-level names.+-- If no namespace specifier is provided, the declaration will+-- populate both the type-level and data-level fields.+data MiniFixityEnv = MFE+  { mfe_data_level_names :: FastStringEnv (Located Fixity)+  , mfe_type_level_names :: FastStringEnv (Located Fixity)+  }+ -------------------------------- -- Used for nested fixity decls to bind names along with their fixities. -- the fixities are given as a UFM from an OccName's FastString to a fixity decl  addLocalFixities :: MiniFixityEnv -> [Name] -> RnM a -> RnM a-addLocalFixities mini_fix_env names thing_inside+addLocalFixities env names thing_inside   = extendFixityEnv (mapMaybe find_fixity names) thing_inside   where-    find_fixity name-      = case lookupFsEnv mini_fix_env (occNameFS occ) of+    find_fixity name = case lookupMiniFixityEnv env name of           Just lfix -> Just (name, FixItem occ (unLoc lfix))           Nothing   -> Nothing       where         occ = nameOccName name++lookupMiniFixityEnv :: MiniFixityEnv -> Name -> Maybe (Located Fixity)+lookupMiniFixityEnv MFE{mfe_data_level_names, mfe_type_level_names} name+  | isValNameSpace namespace = find_fixity_in_env mfe_data_level_names name+  | otherwise                = find_fixity_in_env mfe_type_level_names name+  where+    namespace = nameNameSpace name++    find_fixity_in_env mini_fix_env name+      = lookupFsEnv mini_fix_env (occNameFS occ)+      where+        occ = nameOccName name++emptyMiniFixityEnv :: MiniFixityEnv+emptyMiniFixityEnv = MFE emptyFsEnv emptyFsEnv  {- --------------------------------
compiler/GHC/Rename/HsType.hs view
@@ -14,11 +14,11 @@         -- Type related stuff         rnHsType, rnLHsType, rnLHsTypes, rnContext, rnMaybeContext,         rnLHsKind, rnLHsTypeArgs,-        rnHsSigType, rnHsWcType, rnHsPatSigTypeBindingVars,-        HsPatSigTypeScoping(..), rnHsSigWcType, rnHsPatSigType,+        rnHsSigType, rnHsWcType, rnHsTyLit,+        HsPatSigTypeScoping(..), rnHsSigWcType, rnHsPatSigType, rnHsPatSigKind,         newTyVarNameRn,         rnConDeclFields,-        lookupField,+        lookupField, mkHsOpTyRn,         rnLTyVar,          rnScaledLHsType,@@ -37,26 +37,31 @@         extractHsTysRdrTyVars, extractRdrKindSigVars,         extractConDeclGADTDetailsTyVars, extractDataDefnKindVars,         extractHsOuterTvBndrs, extractHsTyArgRdrKiTyVars,-        nubL, nubN+        nubL, nubN,++        -- Error helpers+        badKindSigErr   ) where  import GHC.Prelude -import {-# SOURCE #-} GHC.Rename.Splice( rnSpliceType )+import {-# SOURCE #-} GHC.Rename.Splice( rnSpliceType, checkThLocalTyName )  import GHC.Core.TyCo.FVs ( tyCoVarsOfTypeList )+import GHC.Core.TyCon    ( isKindName ) import GHC.Hs import GHC.Rename.Env import GHC.Rename.Doc import GHC.Rename.Utils  ( mapFvRn, bindLocalNamesFV                          , typeAppErr, newLocalBndrRn, checkDupRdrNames-                         , checkShadowedRdrNames, warnForallIdentifier )+                         , checkShadowedRdrNames ) import GHC.Rename.Fixity ( lookupFieldFixityRn, lookupFixityRn                          , lookupTyFixityRn ) import GHC.Rename.Unbound ( notInScopeErr, WhereLooking(WL_LocalOnly) ) import GHC.Tc.Errors.Types import GHC.Tc.Errors.Ppr ( pprHsDocContext ) import GHC.Tc.Utils.Monad+import GHC.Unit.Module ( getModule ) import GHC.Types.Name.Reader import GHC.Builtin.Names import GHC.Types.Hint ( UntickedPromotedThing(..) )@@ -72,15 +77,12 @@ import GHC.Types.Basic  ( TypeOrKind(..) ) import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Data.Maybe import qualified GHC.LanguageExtensions as LangExt  import Language.Haskell.Syntax.Basic (FieldLabelString(..))  import Data.List (nubBy, partition)-import qualified Data.List.NonEmpty as NE-import Data.List.NonEmpty (NonEmpty(..)) import Control.Monad  {-@@ -138,7 +140,7 @@        ; (nwc_rdrs', imp_tv_nms) <- partition_nwcs free_vars        ; let nwc_rdrs = nubL nwc_rdrs'        ; bindHsOuterTyVarBndrs doc Nothing imp_tv_nms outer_bndrs $ \outer_bndrs' ->-    do { (wcs, body_ty', fvs) <- rnWcBody doc nwc_rdrs body_ty+    do { (wcs, body_ty', fvs) <- rnWcBodyType doc nwc_rdrs body_ty        ; pure ( HsWC  { hswc_ext = wcs, hswc_body = L loc $                 HsSig { sig_ext = noExtField                       , sig_bndrs = outer_bndrs', sig_body = body_ty' }}@@ -149,6 +151,21 @@                -> HsPatSigType GhcPs                -> (HsPatSigType GhcRn -> RnM (a, FreeVars))                -> RnM (a, FreeVars)+rnHsPatSigType = rnHsPatSigTyKi TypeLevel++rnHsPatSigKind :: HsPatSigTypeScoping+               -> HsDocContext+               -> HsPatSigType GhcPs+               -> (HsPatSigType GhcRn -> RnM (a, FreeVars))+               -> RnM (a, FreeVars)+rnHsPatSigKind = rnHsPatSigTyKi KindLevel++rnHsPatSigTyKi :: TypeOrKind+               -> HsPatSigTypeScoping+               -> HsDocContext+               -> HsPatSigType GhcPs+               -> (HsPatSigType GhcRn -> RnM (a, FreeVars))+               -> RnM (a, FreeVars) -- Used for --   - Pattern type signatures, which are only allowed with ScopedTypeVariables --   - Signatures on binders in a RULE, which are allowed even if@@ -156,7 +173,7 @@ -- Wildcards are allowed -- -- See Note [Pattern signature binders and scoping] in GHC.Hs.Type-rnHsPatSigType scoping ctx sig_ty thing_inside+rnHsPatSigTyKi level scoping ctx sig_ty thing_inside   = do { ty_sig_okay <- xoptM LangExt.ScopedTypeVariables        ; checkErr ty_sig_okay (unexpectedPatSigTypeErr sig_ty)        ; free_vars <- filterInScopeM (extractHsTyRdrTyVars pat_sig_ty)@@ -166,7 +183,7 @@                AlwaysBind -> tv_rdrs                NeverBind  -> []        ; rnImplicitTvOccs Nothing implicit_bndrs $ \ imp_tvs ->-    do { (nwcs, pat_sig_ty', fvs1) <- rnWcBody ctx nwc_rdrs pat_sig_ty+    do { (nwcs, pat_sig_ty', fvs1) <- rnWcBodyTyKi level ctx nwc_rdrs pat_sig_ty        ; let sig_names = HsPSRn { hsps_nwcs = nwcs, hsps_imp_tvs = imp_tvs }              sig_ty'   = HsPS { hsps_ext = sig_names, hsps_body = pat_sig_ty' }        ; (res, fvs2) <- thing_inside sig_ty'@@ -179,59 +196,20 @@   = do { free_vars <- filterInScopeM (extractHsTyRdrTyVars hs_ty)        ; (nwc_rdrs', _) <- partition_nwcs free_vars        ; let nwc_rdrs = nubL nwc_rdrs'-       ; (wcs, hs_ty', fvs) <- rnWcBody ctxt nwc_rdrs hs_ty+       ; (wcs, hs_ty', fvs) <- rnWcBodyType ctxt nwc_rdrs hs_ty        ; let sig_ty' = HsWC { hswc_ext = wcs, hswc_body = hs_ty' }        ; return (sig_ty', fvs) } --- Similar to rnHsWcType, but rather than requiring free variables in the type to--- already be in scope, we are going to require them not to be in scope,--- and we bind them.-rnHsPatSigTypeBindingVars :: HsDocContext-                          -> HsPatSigType GhcPs-                          -> (HsPatSigType GhcRn -> RnM (r, FreeVars))-                          -> RnM (r, FreeVars)-rnHsPatSigTypeBindingVars ctxt sigType thing_inside = case sigType of-  (HsPS { hsps_body = hs_ty }) -> do-    rdr_env <- getLocalRdrEnv-    let (varsInScope, varsNotInScope) =-          partition (inScope rdr_env . unLoc) (extractHsTyRdrTyVars hs_ty)-    -- TODO: Resolve and remove this comment.-    -- This next bit is in some contention. The original proposal #126-    -- (https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0126-type-applications-in-patterns.rst)-    -- says that in-scope variables are fine here: don't bind them, just use-    -- the existing vars, like in type signatures. An amendment #291-    -- (https://github.com/ghc-proposals/ghc-proposals/pull/291) says that the-    -- use of an in-scope variable should *shadow* an in-scope tyvar, like in-    -- terms. In an effort to make forward progress, the current implementation-    -- just rejects any use of an in-scope variable, meaning GHC will accept-    -- a subset of programs common to both variants. If this comment still exists-    -- in mid-to-late 2021 or thereafter, we have done a poor job on following-    -- up on this point.-    -- Example:-    --   f :: forall a. ...-    --   f (MkT @a ...) = ...-    -- Should the inner `a` refer to the outer one? shadow it? We are, as yet, undecided,-    -- so we currently reject.-    when (not (null varsInScope)) $-      addErr $ TcRnBindVarAlreadyInScope varsInScope-    (wcVars, ibVars) <- partition_nwcs varsNotInScope-    rnImplicitTvBndrs ctxt Nothing ibVars $ \ ibVars' -> do-      (wcVars', hs_ty', fvs) <- rnWcBody ctxt wcVars hs_ty-      let sig_ty = HsPS-            { hsps_body = hs_ty'-            , hsps_ext = HsPSRn-              { hsps_nwcs    = wcVars'-              , hsps_imp_tvs = ibVars'-              }-            }-      (res, fvs') <- thing_inside sig_ty-      return (res, fvs `plusFV` fvs') -rnWcBody :: HsDocContext -> [LocatedN RdrName] -> LHsType GhcPs+rnWcBodyType :: HsDocContext -> [LocatedN RdrName] -> LHsType GhcPs+  -> RnM ([Name], LHsType GhcRn, FreeVars)+rnWcBodyType = rnWcBodyTyKi TypeLevel++rnWcBodyTyKi :: TypeOrKind -> HsDocContext -> [LocatedN RdrName] -> LHsType GhcPs          -> RnM ([Name], LHsType GhcRn, FreeVars)-rnWcBody ctxt nwc_rdrs hs_ty+rnWcBodyTyKi level ctxt nwc_rdrs hs_ty   = do { nwcs <- mapM newLocalBndrRn nwc_rdrs-       ; let env = RTKE { rtke_level = TypeLevel+       ; let env = RTKE { rtke_level = level                         , rtke_what  = RnTypeBody                         , rtke_nwcs  = mkNameSet nwcs                         , rtke_ctxt  = ctxt }@@ -422,32 +400,6 @@ sites. This is less precise, but more accurate. -} --- | Create fresh type variables for binders, disallowing multiple occurrences of the same variable. Similar to `rnImplicitTvOccs` except that duplicate occurrences will--- result in an error, and the source locations of the variables are not adjusted, as these variable occurrences are themselves the binding sites for the type variables,--- rather than the variables being implicitly bound by a signature.-rnImplicitTvBndrs :: HsDocContext-                  -> Maybe assoc-                  -- ^ @'Just' _@ => an associated type decl-                  -> FreeKiTyVars-                  -- ^ Surface-syntax free vars that we will implicitly bind.-                  -- Duplicate variables will cause a compile-time error regarding repeated bindings.-                  -> ([Name] -> RnM (a, FreeVars))-                  -> RnM (a, FreeVars)-rnImplicitTvBndrs ctx mb_assoc implicit_vs_with_dups thing_inside-  = do { implicit_vs <- forM (NE.groupAllWith unLoc $ implicit_vs_with_dups) $ \case-           (x :| []) -> return x-           (x :| _) -> do-             addErr $ TcRnBindMultipleVariables ctx x-             return x--       ; traceRn "rnImplicitTvBndrs" $-         vcat [ ppr implicit_vs_with_dups, ppr implicit_vs ]--       ; vars <- mapM (newTyVarNameRn mb_assoc) implicit_vs--       ; bindLocalNamesFV vars $-         thing_inside vars }- {- ****************************************************** *                                                       *            LHsType and HsType@@ -515,12 +467,12 @@ -- renaming a type only, not a kind rnLHsTypeArg :: HsDocContext -> LHsTypeArg GhcPs                 -> RnM (LHsTypeArg GhcRn, FreeVars)-rnLHsTypeArg ctxt (HsValArg ty)+rnLHsTypeArg ctxt (HsValArg _ ty)    = do { (tys_rn, fvs) <- rnLHsType ctxt ty-        ; return (HsValArg tys_rn, fvs) }-rnLHsTypeArg ctxt (HsTypeArg l ki)+        ; return (HsValArg noExtField tys_rn, fvs) }+rnLHsTypeArg ctxt (HsTypeArg _ ki)    = do { (kis_rn, fvs) <- rnLHsKind ctxt ki-        ; return (HsTypeArg l kis_rn, fvs) }+        ; return (HsTypeArg noExtField kis_rn, fvs) } rnLHsTypeArg _ (HsArgPar sp)    = return (HsArgPar sp, emptyFVs) @@ -577,7 +529,7 @@                           , hst_body =  tau' }                 , fvs1 `plusFV` fvs2) } -rnHsTyKi env (HsTyVar _ ip (L loc rdr_name))+rnHsTyKi env tv@(HsTyVar _ ip (L loc rdr_name))   = do { when (isRnKindLevel env && isRdrTyVar rdr_name) $          unlessXOptM LangExt.PolyKinds $ addErr $          TcRnWithHsDocContext (rtke_ctxt env) $@@ -585,6 +537,15 @@            -- Any type variable at the kind level is illegal without the use            -- of PolyKinds (see #14710)        ; name <- rnTyVar env rdr_name+       ; this_mod <- getModule+       ; when (nameIsLocalOrFrom this_mod name) $+         checkThLocalTyName name+       ; when (isDataConName name && not (isKindName name)) $+           -- Any use of a promoted data constructor name (that is not+           -- specifically exempted by isKindName) is illegal without the use+           -- of DataKinds. See Note [Checking for DataKinds] in+           -- GHC.Tc.Validity.+           checkDataKinds env tv        ; when (isDataConName name && not (isPromoted ip)) $          -- NB: a prefix symbolic operator such as (:) is represented as HsTyVar.             addDiagnostic (TcRnUntickedPromotedThing $ UntickedConstructor Prefix name)@@ -616,17 +577,19 @@        ; (flds', fvs) <- rnConDeclFields ctxt fls flds        ; return (HsRecTy noExtField flds', fvs) }   where-    get_fields (ConDeclCtx names)+    get_fields ctxt@(ConDeclCtx names)       = do res <- concatMapM (lookupConstructorFields . unLoc) names            if equalLength res names            -- Lookup can fail when the record syntax is incorrect, e.g.            -- data D = D Int { fld :: Bool }. See T7943.            then return res-           else err-    get_fields _ = err+           else err ctxt+    get_fields ctxt = err ctxt -    err =-      do { addErr $ TcRnIllegalRecordSyntax (Left ty)+    err ctxt =+      do { addErr $+            TcRnWithHsDocContext ctxt $+            TcRnIllegalRecordSyntax (Left ty)          ; return [] }  rnHsTyKi env (HsFunTy u mult ty1 ty2)@@ -637,15 +600,14 @@                 , plusFVs [fvs1, fvs2, w_fvs]) }  rnHsTyKi env listTy@(HsListTy x ty)-  = do { data_kinds <- xoptM LangExt.DataKinds-       ; when (not data_kinds && isRnKindLevel env)-              (addErr (dataKindsErr env listTy))+  = do { when (isRnKindLevel env) $+           checkDataKinds env listTy        ; (ty', fvs) <- rnLHsTyKi env ty        ; return (HsListTy x ty', fvs) }  rnHsTyKi env (HsKindSig x ty k)   = do { kind_sigs_ok <- xoptM LangExt.KindSignatures-       ; unless kind_sigs_ok (badKindSigErr (rtke_ctxt env) ty)+       ; unless kind_sigs_ok (badKindSigErr (rtke_ctxt env) k)        ; (k', sig_fvs)  <- rnLHsTyKi (env { rtke_level = KindLevel }) k        ; (ty', lhs_fvs) <- bindSigTyVarsFV (hsScopedKvs k') $                            rnLHsTyKi env ty@@ -654,42 +616,34 @@ -- Unboxed tuples are allowed to have poly-typed arguments.  These -- sometimes crop up as a result of CPR worker-wrappering dictionaries. rnHsTyKi env tupleTy@(HsTupleTy x tup_con tys)-  = do { data_kinds <- xoptM LangExt.DataKinds-       ; when (not data_kinds && isRnKindLevel env)-              (addErr (dataKindsErr env tupleTy))+  = do { when (isRnKindLevel env) $+           checkDataKinds env tupleTy        ; (tys', fvs) <- mapFvRn (rnLHsTyKi env) tys        ; return (HsTupleTy x tup_con tys', fvs) }  rnHsTyKi env sumTy@(HsSumTy x tys)-  = do { data_kinds <- xoptM LangExt.DataKinds-       ; when (not data_kinds && isRnKindLevel env)-              (addErr (dataKindsErr env sumTy))+  = do { when (isRnKindLevel env) $+           checkDataKinds env sumTy        ; (tys', fvs) <- mapFvRn (rnLHsTyKi env) tys        ; return (HsSumTy x tys', fvs) }  -- Ensure that a type-level integer is nonnegative (#8306, #8412) rnHsTyKi env tyLit@(HsTyLit src t)-  = do { data_kinds <- xoptM LangExt.DataKinds-       ; unless data_kinds (addErr (dataKindsErr env tyLit))-       ; when (negLit t) (addErr $ TcRnNegativeNumTypeLiteral tyLit)-       ; return (HsTyLit src (rnHsTyLit t), emptyFVs) }-  where-    negLit :: HsTyLit (GhcPass p) -> Bool-    negLit (HsStrTy _ _) = False-    negLit (HsNumTy _ i) = i < 0-    negLit (HsCharTy _ _) = False+  = do { checkDataKinds env tyLit+       ; t' <- rnHsTyLit t+       ; return (HsTyLit src t', emptyFVs) }  rnHsTyKi env (HsAppTy _ ty1 ty2)   = do { (ty1', fvs1) <- rnLHsTyKi env ty1        ; (ty2', fvs2) <- rnLHsTyKi env ty2        ; return (HsAppTy noExtField ty1' ty2', fvs1 `plusFV` fvs2) } -rnHsTyKi env (HsAppKindTy _ ty at k)+rnHsTyKi env (HsAppKindTy _ ty k)   = do { kind_app <- xoptM LangExt.TypeApplications        ; unless kind_app (addErr (typeAppErr KindLevel k))        ; (ty', fvs1) <- rnLHsTyKi env ty        ; (k', fvs2) <- rnLHsTyKi (env {rtke_level = KindLevel }) k-       ; return (HsAppKindTy noExtField ty' at k', fvs1 `plusFV` fvs2) }+       ; return (HsAppKindTy noExtField ty' k', fvs1 `plusFV` fvs2) }  rnHsTyKi env t@(HsIParamTy x n ty)   = do { notInKinds env t@@ -724,16 +678,14 @@             TcRnNotInScope (notInScopeErr WL_LocalOnly rdr_name) rdr_name [] []  rnHsTyKi env ty@(HsExplicitListTy _ ip tys)-  = do { data_kinds <- xoptM LangExt.DataKinds-       ; unless data_kinds (addErr (dataKindsErr env ty))+  = do { checkDataKinds env ty        ; (tys', fvs) <- mapFvRn (rnLHsTyKi env) tys        ; unless (isPromoted ip) $            addDiagnostic (TcRnUntickedPromotedThing $ UntickedExplicitList)        ; return (HsExplicitListTy noExtField ip tys', fvs) }  rnHsTyKi env ty@(HsExplicitTupleTy _ tys)-  = do { data_kinds <- xoptM LangExt.DataKinds-       ; unless data_kinds (addErr (dataKindsErr env ty))+  = do { checkDataKinds env ty        ; (tys', fvs) <- mapFvRn (rnLHsTyKi env) tys        ; return (HsExplicitTupleTy noExtField tys', fvs) } @@ -742,18 +694,20 @@        ; return (HsWildCardTy noExtField, emptyFVs) }  -rnHsTyLit :: HsTyLit GhcPs -> HsTyLit GhcRn-rnHsTyLit (HsStrTy x s) = HsStrTy x s-rnHsTyLit (HsNumTy x i) = HsNumTy x i-rnHsTyLit (HsCharTy x c) = HsCharTy x c+rnHsTyLit :: HsTyLit GhcPs -> RnM (HsTyLit GhcRn)+rnHsTyLit (HsStrTy x s) = pure (HsStrTy x s)+rnHsTyLit tyLit@(HsNumTy x i) = do+  when (i < 0) $+    addErr $ TcRnNegativeNumTypeLiteral tyLit+  pure (HsNumTy x i)+rnHsTyLit (HsCharTy x c) = pure (HsCharTy x c)   rnHsArrow :: RnTyKiEnv -> HsArrow GhcPs -> RnM (HsArrow GhcRn, FreeVars)-rnHsArrow _env (HsUnrestrictedArrow arr) = return (HsUnrestrictedArrow arr, emptyFVs)-rnHsArrow _env (HsLinearArrow (HsPct1 pct1 arr)) = return (HsLinearArrow (HsPct1 pct1 arr), emptyFVs)-rnHsArrow _env (HsLinearArrow (HsLolly arr)) = return (HsLinearArrow (HsLolly arr), emptyFVs)-rnHsArrow env (HsExplicitMult pct p arr)-  = (\(mult, fvs) -> (HsExplicitMult pct mult arr, fvs)) <$> rnLHsTyKi env p+rnHsArrow _env (HsUnrestrictedArrow _) = return (HsUnrestrictedArrow noExtField, emptyFVs)+rnHsArrow _env (HsLinearArrow _) = return (HsLinearArrow noExtField, emptyFVs)+rnHsArrow env (HsExplicitMult _ p)+  = (\(mult, fvs) -> (HsExplicitMult noExtField mult, fvs)) <$> rnLHsTyKi env p  {- Note [Renaming HsCoreTys]@@ -916,7 +870,7 @@ --------------- bindHsQTyVars :: forall a b.                  HsDocContext-              -> Maybe a            -- Just _  => an associated type decl+              -> Maybe (a, [Name])  -- Just _  => an associated type decl               -> FreeKiTyVars       -- Kind variables from scope               -> LHsQTyVars GhcPs               -> (LHsQTyVars GhcRn -> FreeKiTyVars -> RnM (b, FreeVars))@@ -937,13 +891,19 @@         ; let -- See Note [bindHsQTyVars examples] for what              -- all these various things are doing-             bndrs, implicit_kvs :: [LocatedN RdrName]+             bndrs, all_implicit_kvs :: [LocatedN RdrName]              bndrs        = map hsLTyVarLocName hs_tv_bndrs-             implicit_kvs = filterFreeVarsToBind bndrs $+             all_implicit_kvs = filterFreeVarsToBind bndrs $                bndr_kv_occs ++ body_kv_occs              body_remaining = filterFreeVarsToBind bndr_kv_occs $               filterFreeVarsToBind bndrs body_kv_occs +       ; implicit_kvs <-+           case mb_assoc of+             Nothing -> filterInScopeM all_implicit_kvs+             Just (_, cls_tvs) -> filterInScopeNonClassM cls_tvs all_implicit_kvs+                 -- See Note [Class variables and filterInScope]+        ; traceRn "checkMixedVars3" $            vcat [ text "bndrs"   <+> ppr hs_tv_bndrs                 , text "bndr_kv_occs"   <+> ppr bndr_kv_occs@@ -1016,8 +976,13 @@   That's one of the rules for a CUSK, so we pass that info on   as the second argument to thing_inside. -* Order is not important in these lists.  All we are doing is-  bring Names into scope.+* Order is important in these lists. Consider+    data T (a::k1) (b::k2)+  We want implicit_kvs to be [k1,k2], not [k2,k1], so that the inferred kind for+  T quantifies over kind variables in the user-specified order+    T :: forall k1 k2. k1 -> k2 -> Type  -- OK+    T :: forall k2 k1. k1 -> k2 -> Type  -- Bad+  This matters with TypeApplications  * bndr_kv_occs, body_kv_occs, and implicit_kvs can contain duplicates. All   duplicate occurrences are removed when we bind them with rnImplicitTvOccs.@@ -1235,12 +1200,10 @@       addErr (TcRnIllegalInvisTyVarBndr lbndr)   return lbndr --- rnHsBndrVis is a no-op. We could use 'coerce' in an ideal world,--- but GHC can't crack this nut because type families are involved:--- HsBndrInvisible stores (LHsToken "@" pass), which is defined via XRec.+-- rnHsBndrVis is almost a no-op, it simply discards the token for "@". rnHsBndrVis :: HsBndrVis GhcPs -> HsBndrVis GhcRn-rnHsBndrVis HsBndrRequired = HsBndrRequired-rnHsBndrVis (HsBndrInvisible at) = HsBndrInvisible at+rnHsBndrVis (HsBndrRequired _)    = HsBndrRequired  noExtField+rnHsBndrVis (HsBndrInvisible _at) = HsBndrInvisible noExtField  newTyVarNameRn, newTyVarNameRnImplicit   :: Maybe a -- associated class@@ -1266,14 +1229,14 @@ Section 7.3: https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0281-visible-forall.rst#73implicit-quantification  Its purpose is to notify users when implicit quantification occurs that would-stop working under RequiredTypeArguments (a future GHC extension). Example:+stop working under RequiredTypeArguments. Example:     a = 42    id :: a -> a  As it stands, the `a` in the signature `id :: a -> a` is considered free and leads to implicit quantification, as if the user wrote `id :: forall a. a -> a`.-Under RequiredTypeArguments it will capture the term-level variable `a` (bound by `a = 42`),+Under RequiredTypeArguments it captures the term-level variable `a` (bound by `a = 42`), leading to a type error.  `warn_term_var_capture` detects this by demoting the namespace of the@@ -1331,8 +1294,7 @@ rnField :: FastStringEnv FieldLabel -> RnTyKiEnv -> LConDeclField GhcPs         -> RnM (LConDeclField GhcRn, FreeVars) rnField fl_env env (L l (ConDeclField _ names ty haddock_doc))-  = do { mapM_ (\(L _ (FieldOcc _ rdr_name)) -> warnForallIdentifier rdr_name) names-       ; let new_names = map (fmap (lookupField fl_env)) names+  = do { let new_names = map (fmap (lookupField fl_env)) names        ; (new_ty, fvs) <- rnLHsTyKi env ty        ; haddock_doc' <- traverse rnLHsDoc haddock_doc        ; return (L l (ConDeclField noAnn new_names new_ty haddock_doc')@@ -1677,11 +1639,16 @@     TcRnWithHsDocContext doc $     TcRnKindSignaturesDisabled (Left ty) -dataKindsErr :: RnTyKiEnv -> HsType GhcPs -> TcRnMessage-dataKindsErr env thing-  = TcRnDataKindsError type_or_Kind thing+-- | Check for DataKinds violations in a type context, as well as \"obvious\"+-- violations in kind contexts.+-- See @Note [Checking for DataKinds]@ in "GHC.Tc.Validity" for more on this.+checkDataKinds :: RnTyKiEnv -> HsType GhcPs -> TcM ()+checkDataKinds env thing+  = do data_kinds <- xoptM LangExt.DataKinds+       unless data_kinds $+         addErr $ TcRnDataKindsError type_or_kind $ Left thing   where-    type_or_Kind | isRnKindLevel env = KindLevel+    type_or_kind | isRnKindLevel env = KindLevel                  | otherwise         = TypeLevel  warnUnusedForAll :: OutputableBndrFlag flag 'Renamed@@ -1856,25 +1823,136 @@ -- Note [Ordering of implicit variables]. type FreeKiTyVars = [LocatedN RdrName] +-- When renaming a type, do we want to capture or ignore term variables?+-- Suppose we have a variable binding `a` and we are renaming a type signature+-- that mentions `a`:+--+--    f :: forall t -> ...+--    f a = ...+--      where g :: a -> Bool+--+-- Does the `a` in the signature for `g` refer to the term variable or is it+-- implicitly quantified, as if the user wrote `g :: forall a. a -> Bool`?+-- `CaptureTermVars` selects the former behavior, `DontCaptureTermVars` the latter.+data TermVariableCapture =+    CaptureTermVars+  | DontCaptureTermVars++getTermVariableCapture :: RnM TermVariableCapture+getTermVariableCapture+  = do { required_type_arguments <- xoptM LangExt.RequiredTypeArguments+       ; let tvc | required_type_arguments = CaptureTermVars+                 | otherwise               = DontCaptureTermVars+       ; return tvc }+ -- | Filter out any type and kind variables that are already in scope in the -- the supplied LocalRdrEnv. Note that this includes named wildcards, which -- look like perfectly ordinary type variables at this point.-filterInScope :: LocalRdrEnv -> FreeKiTyVars -> FreeKiTyVars-filterInScope rdr_env = filterOut (inScope rdr_env . unLoc)+filterInScope :: TermVariableCapture -> (GlobalRdrEnv, LocalRdrEnv) -> FreeKiTyVars -> FreeKiTyVars+filterInScope tvc envs = filterOut (inScope tvc envs . unLoc) +-- | Like 'filterInScope', but keep parent class variables intact.+-- Used with associated types. See Note [Class variables and filterInScope]+filterInScopeNonClass :: [Name] -> TermVariableCapture -> (GlobalRdrEnv, LocalRdrEnv) -> FreeKiTyVars -> FreeKiTyVars+filterInScopeNonClass cls_tvs tvc envs = filterOut (in_scope_non_class . unLoc)+  where+    in_scope_non_class :: RdrName -> Bool+    in_scope_non_class rdr+      | occName rdr `elemOccSet` cls_tvs_set = False+      | otherwise = inScope tvc envs rdr++    cls_tvs_set :: OccSet+    cls_tvs_set = mkOccSet (map nameOccName cls_tvs)+ -- | Filter out any type and kind variables that are already in scope in the -- the environment's LocalRdrEnv. Note that this includes named wildcards, -- which look like perfectly ordinary type variables at this point. filterInScopeM :: FreeKiTyVars -> RnM FreeKiTyVars filterInScopeM vars-  = do { rdr_env <- getLocalRdrEnv-       ; return (filterInScope rdr_env vars) }+  = do { tvc <- getTermVariableCapture+       ; envs <- getRdrEnvs+       ; return (filterInScope tvc envs vars) } -inScope :: LocalRdrEnv -> RdrName -> Bool-inScope rdr_env rdr = rdr `elemLocalRdrEnv` rdr_env+-- | Like 'filterInScopeM', but keep parent class variables intact.+-- Used with associated types. See Note [Class variables and filterInScope]+filterInScopeNonClassM :: [Name] -> FreeKiTyVars -> RnM FreeKiTyVars+filterInScopeNonClassM cls_tvs vars+  = do { tvc <- getTermVariableCapture+       ; envs <- getRdrEnvs+       ; return (filterInScopeNonClass cls_tvs tvc envs vars) } +inScope :: TermVariableCapture -> (GlobalRdrEnv, LocalRdrEnv) -> RdrName -> Bool+inScope tvc (gbl, lcl) rdr =+  case tvc of+    DontCaptureTermVars -> rdr_in_scope+    CaptureTermVars     -> rdr_in_scope || demoted_rdr_in_scope+  where+    rdr_in_scope, demoted_rdr_in_scope :: Bool+    rdr_in_scope         = elem_lcl rdr+    demoted_rdr_in_scope = maybe False (elem_lcl <||> elem_gbl) (demoteRdrNameTv rdr)++    elem_lcl, elem_gbl :: RdrName -> Bool+    elem_lcl name = elemLocalRdrEnv name lcl+    elem_gbl name = (not . null) (lookupGRE gbl (LookupRdrName name (RelevantGREsFOS WantBoth)))++{- Note [Class variables and filterInScope]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+In `bindHsQTyVars` free variables are collected and bound implicitly. Example:+  type ElemKind (a :: Maybe k) = k+Both occurrences of `k` are usages, so GHC creates an implicit binding for `k`.+We can also bind it explicitly with the help of TypeAbstractions:+  type ElemKind @k (a :: Maybe k) = k++This is similar to implicit quantification that happens in type signatures+  const :: a -> b -> a               -- `a` and `b` bound implicitly+  const :: forall a b. a -> b -> a   -- `a` and `b` bound explicitly++In both cases we need to compute the list of free variables to implicitly+quantify over (NB: list, not set, because order matters with TypeApplications)+  * implicitly bound variables in ElemKind:  [k]+  * implicitly bound variables in const:     [a, b]++However, variables that are already in scope are captured. Example:+  {-# LANGUAGE ScopedTypeVariables #-}+  f (x :: a) = ...+    where g :: a -> a+          g _ = x+When we look at `g` in isolation, `a` is a free variable:+  g :: a -> a+But due to ScopedTypeVariables, `a` is actually bound in the surrounding+context, namely the (x :: a) pattern.+It is important that we do /not/ insert an implicit forall in the type of `g`+  g :: forall a. a -> a   -- No! That would mean a different thing+The solution is to use `filterInScopeM` to remove variables already in scope+from candidates for implicit quantification.++Using `filterInScopeM` is additionally important when RequiredTypeArguments is+in effect. Consider+  import Prelude (id)+  data T (a :: id) = MkT    -- Test case T23740e++With RequiredTypeArguments, variables in the term namespace can be referred to+at the type level, so `id` in the `:: id` kind signature ought to refer to `id`+from Prelude. Of course it is not a valid program, but we want a proper error+message rather than implicit quantification:+  T23740e.hs:5:14: error: [GHC-45510]+      • Term variable ‘id’ cannot be used here+          (term variables cannot be promoted)++This leads us to use `filterInScopeM` in `bindHsQTyVars`.+Unfortunately, associated types make matters more complex. Consider+  class C (a::k1) (b::k2) (c::k3) where+    type T (a::k1) b+When renaming `T`, we have to implicitly quantify over the class variable `k1`,+despite the fact that `k1` is in scope from the class header. The type checker+expects to find `k1` in `HsQTvsRn` (the `hsq_ext` field of `LHsQTyVars`). But it+won't find it there if it is filtered out by `filterInScopeM`.++To account for that, we introduce another helper, `filterInScopeNonClassM`,+which acts much like `filterInScopeM` but leaves class variables intact. -}+ extract_tyarg :: LHsTypeArg GhcPs -> FreeKiTyVars -> FreeKiTyVars-extract_tyarg (HsValArg ty) acc = extract_lty ty acc+extract_tyarg (HsValArg _ ty) acc = extract_lty ty acc extract_tyarg (HsTypeArg _ ki) acc = extract_lty ki acc extract_tyarg (HsArgPar _) acc = acc @@ -1935,8 +2013,8 @@ extractConDeclGADTDetailsTyVars ::   HsConDeclGADTDetails GhcPs -> FreeKiTyVars -> FreeKiTyVars extractConDeclGADTDetailsTyVars con_args = case con_args of-  PrefixConGADT args      -> extract_scaled_ltys args-  RecConGADT (L _ flds) _ -> extract_ltys $ map (cd_fld_type . unLoc) $ flds+  PrefixConGADT _ args    -> extract_scaled_ltys args+  RecConGADT _ (L _ flds) -> extract_ltys $ map (cd_fld_type . unLoc) $ flds  -- | Get type/kind variables mentioned in the kind signature, preserving -- left-to-right order:@@ -1973,7 +2051,7 @@                                            flds       HsAppTy _ ty1 ty2           -> extract_lty ty1 $                                      extract_lty ty2 acc-      HsAppKindTy _ ty _ k        -> extract_lty ty $+      HsAppKindTy _ ty k          -> extract_lty ty $                                      extract_lty k acc       HsListTy _ ty               -> extract_lty ty acc       HsTupleTy _ _ tys           -> extract_ltys tys acc@@ -2022,7 +2100,7 @@  extract_hs_arrow :: HsArrow GhcPs -> FreeKiTyVars ->                    FreeKiTyVars-extract_hs_arrow (HsExplicitMult _ p _) acc = extract_lty p acc+extract_hs_arrow (HsExplicitMult _ p) acc = extract_lty p acc extract_hs_arrow _ acc = acc  extract_hs_for_all_telescope :: HsForAllTelescope GhcPs
compiler/GHC/Rename/Module.hs view
@@ -13,7 +13,7 @@ -}  module GHC.Rename.Module (-        rnSrcDecls, addTcgDUs, findSplice, rnWarningTxt+        rnSrcDecls, addTcgDUs, findSplice, rnWarningTxt, rnLWarningTxt     ) where  import GHC.Prelude hiding ( head )@@ -33,7 +33,7 @@                         , checkShadowedRdrNames, warnUnusedTypePatterns                         , newLocalBndrsRn                         , noNestedForallsContextsErr-                        , addNoNestedForallsContextsErr, checkInferredVars, warnForallIdentifier )+                        , addNoNestedForallsContextsErr, checkInferredVars ) import GHC.Rename.Unbound ( mkUnboundName, notInScopeErr, WhereLooking(WL_Global) ) import GHC.Rename.Names import GHC.Tc.Errors.Types@@ -273,20 +273,23 @@  rnSrcWarnDecls bndr_set decls'   = do { -- check for duplicates-       ; mapM_ (\ dups -> let ((L loc rdr) :| (lrdr':_)) = dups+       ; mapM_ (\ dups -> let ((L loc rdr) :| (lrdr':_)) = fmap snd dups                           in addErrAt (locA loc) (TcRnDuplicateWarningDecls lrdr' rdr))                warn_rdr_dups-       ; pairs_s <- mapM (addLocMA rn_deprec) decls+       ; pairs_s <- mapM (addLocM rn_deprec) decls        ; return $ concat pairs_s }  where    decls = concatMap (wd_warnings . unLoc) decls'     sig_ctxt = TopSigCtxt bndr_set -   rn_deprec (Warning _ rdr_names txt)+   rn_deprec w@(Warning (ns_spec, _) rdr_names txt)        -- ensures that the names are defined locally-     = do { names <- concatMapM (lookupLocalTcNames sig_ctxt what . unLoc)+     = do { names <- concatMapM (lookupLocalTcNames sig_ctxt what ns_spec . unLoc)                                 rdr_names+          ; unlessXOptM LangExt.ExplicitNamespaces $+            when (ns_spec /= NoNamespaceSpecifier) $+            addErr (TcRnNamespacedWarningPragmaWithoutFlag w)           ; txt' <- rnWarningTxt txt           ; return [(nameOccName nm, txt') | (_, nm) <- names] }   -- Use the OccName from the Name we looked up, rather than from the RdrName,@@ -295,23 +298,27 @@     what = text "deprecation" -   warn_rdr_dups = findDupRdrNames-                   $ concatMap (\(L _ (Warning _ ns _)) -> ns) decls+   warn_rdr_dups = find_dup_warning_names+                   $ concatMap (\(L _ (Warning (ns_spec, _) ns _)) -> (ns_spec,) <$> ns) decls +   find_dup_warning_names :: [(NamespaceSpecifier, LocatedN RdrName)] -> [NonEmpty (NamespaceSpecifier, LocatedN RdrName)]+   find_dup_warning_names = findDupsEq (\ (spec1, x) -> \ (spec2, y) ->+                              overlappingNamespaceSpecifiers spec1 spec2 &&+                              rdrNameOcc (unLoc x) == rdrNameOcc (unLoc y))+ rnWarningTxt :: WarningTxt GhcPs -> RnM (WarningTxt GhcRn) rnWarningTxt (WarningTxt mb_cat st wst) = do   forM_ mb_cat $ \(L _ (InWarningCategory _ _ (L loc cat))) ->     unless (validWarningCategory cat) $-      addErrAt loc (TcRnInvalidWarningCategory cat)+      addErrAt (locA loc) (TcRnInvalidWarningCategory cat)   wst' <- traverse (traverse rnHsDoc) wst   pure (WarningTxt mb_cat st wst') rnWarningTxt (DeprecatedTxt st wst) = do   wst' <- traverse (traverse rnHsDoc) wst   pure (DeprecatedTxt st wst') --findDupRdrNames :: [LocatedN RdrName] -> [NonEmpty (LocatedN RdrName)]-findDupRdrNames = findDupsEq (\ x -> \ y -> rdrNameOcc (unLoc x) == rdrNameOcc (unLoc y))+rnLWarningTxt :: LWarningTxt GhcPs -> RnM (LWarningTxt GhcRn)+rnLWarningTxt (L loc warn) = L loc <$> rnWarningTxt warn  -- look for duplicates among the OccNames; -- we check that the names are defined above@@ -371,7 +378,6 @@ rnHsForeignDecl :: ForeignDecl GhcPs -> RnM (ForeignDecl GhcRn, FreeVars) rnHsForeignDecl (ForeignImport { fd_name = name, fd_sig_ty = ty, fd_fi = spec })   = do { topEnv :: HscEnv <- getTopEnv-       ; warnForallIdentifier name        ; name' <- lookupLocatedTopBndrRnN name        ; (ty', fvs) <- rnHsSigType (ForeignDeclCtx name) TypeLevel ty @@ -558,7 +564,8 @@       addDiagnostic (TcRnNonCanonicalDefinition reason poly_ty)  rnClsInstDecl :: ClsInstDecl GhcPs -> RnM (ClsInstDecl GhcRn, FreeVars)-rnClsInstDecl (ClsInstDecl { cid_poly_ty = inst_ty, cid_binds = mbinds+rnClsInstDecl (ClsInstDecl { cid_ext = (inst_warn_ps, _, _)+                           , cid_poly_ty = inst_ty, cid_binds = mbinds                            , cid_sigs = uprags, cid_tyfam_insts = ats                            , cid_overlap_mode = oflag                            , cid_datafam_insts = adts })@@ -611,7 +618,8 @@         ; let all_fvs = meth_fvs `plusFV` more_fvs                                 `plusFV` inst_fvs-       ; return (ClsInstDecl { cid_ext = noExtField+       ; inst_warn_rn <- mapM rnLWarningTxt inst_warn_ps+       ; return (ClsInstDecl { cid_ext = inst_warn_rn                              , cid_poly_ty = inst_ty', cid_binds = mbinds'                              , cid_sigs = uprags', cid_tyfam_insts = ats'                              , cid_overlap_mode = oflag@@ -851,10 +859,11 @@  -- Rename associated type family decl in class rnATDecls :: Name      -- Class+          -> [Name]    -- Class variables. See Note [Class variables and filterInScope] in GHC.Rename.HsType           -> [LFamilyDecl GhcPs]           -> RnM ([LFamilyDecl GhcRn], FreeVars)-rnATDecls cls at_decls-  = rnList (rnFamDecl (Just cls)) at_decls+rnATDecls cls cls_tvs at_decls+  = rnList (rnFamDecl (Just (cls, cls_tvs))) at_decls  rnATInstDecls :: (AssocTyFamInfo ->           -- The function that renames                   decl GhcPs ->               -- an instance. rnTyFamInstDecl@@ -1107,7 +1116,7 @@ -}  rnSrcDerivDecl :: DerivDecl GhcPs -> RnM (DerivDecl GhcRn, FreeVars)-rnSrcDerivDecl (DerivDecl _ ty mds overlap)+rnSrcDerivDecl (DerivDecl (inst_warn_ps, ann) ty mds overlap)   = do { standalone_deriv_ok <- xoptM LangExt.StandaloneDeriving        ; unless standalone_deriv_ok (addErr TcRnUnexpectedStandaloneDerivingDecl)        ; checkInferredVars ctxt nowc_ty@@ -1120,7 +1129,8 @@            NFC_StandaloneDerivedInstanceHead            (getLHsInstDeclHead $ dropWildCards ty')        ; warnNoDerivStrat mds' loc-       ; return (DerivDecl noAnn ty' mds' overlap, fvs) }+       ; inst_warn_rn <- mapM rnLWarningTxt inst_warn_ps+       ; return (DerivDecl (inst_warn_rn, ann) ty' mds' overlap, fvs) }   where     ctxt    = DerivDeclCtx     loc = getLocA nowc_ty@@ -1150,7 +1160,6 @@                      , rd_lhs  = lhs                      , rd_rhs  = rhs })   = do { let rdr_names_w_loc = map (get_var . unLoc) tmvs-       ; mapM_ warnForallIdentifier rdr_names_w_loc        ; checkDupRdrNames rdr_names_w_loc        ; checkShadowedRdrNames rdr_names_w_loc        ; names <- newLocalBndrsRn rdr_names_w_loc@@ -1241,7 +1250,7 @@     check (OpApp _ e1 op e2)              = checkl op `mplus` checkl_e e1                                                       `mplus` checkl_e e2     check (HsApp _ e1 e2)                 = checkl e1 `mplus` checkl_e e2-    check (HsAppType _ e _ _)             = checkl e+    check (HsAppType _ e _)               = checkl e     check (HsVar _ lv)       | (unLoc lv) `notElem` foralls      = Nothing     check other                           = Just other  -- Failure@@ -1723,8 +1732,7 @@                           , tcdDataDefn = defn'                           , tcdDExt     = rn_info }, fvs) } } -rnTyClDecl (ClassDecl { tcdLayout = layout,-                        tcdCtxt = context, tcdLName = lcls,+rnTyClDecl (ClassDecl { tcdCtxt = context, tcdLName = lcls,                         tcdTyVars = tyvars, tcdFixity = fixity,                         tcdFDs = fds, tcdSigs = sigs,                         tcdMeths = mbinds, tcdATs = ats, tcdATDefs = at_defs,@@ -1741,7 +1749,7 @@              { (context', cxt_fvs) <- rnMaybeContext cls_doc context              ; fds'  <- rnFds fds                          -- The fundeps have no free variables-             ; (ats', fv_ats) <- rnATDecls cls' ats+             ; (ats', fv_ats) <- rnATDecls cls' (hsAllLTyVarNames tyvars') ats              ; let fvs = cxt_fvs     `plusFV`                          fv_ats              ; return ((tyvars', context', fds', ats'), fvs) }@@ -1778,8 +1786,7 @@          ; let all_fvs = meth_fvs `plusFV` stuff_fvs `plusFV` fv_at_defs         ; docs' <- traverse rnLDocDecl docs-        ; return (ClassDecl { tcdLayout = rnLayoutInfo layout,-                              tcdCtxt = context', tcdLName = lcls',+        ; return (ClassDecl { tcdCtxt = context', tcdLName = lcls',                               tcdTyVars = tyvars', tcdFixity = fixity,                               tcdFDs = fds', tcdSigs = sigs',                               tcdMeths = mbinds', tcdATs = ats', tcdATDefs = at_defs',@@ -1788,11 +1795,6 @@   where     cls_doc  = ClassDeclCtx lcls -rnLayoutInfo :: LayoutInfo GhcPs -> LayoutInfo GhcRn-rnLayoutInfo (ExplicitBraces ob cb) = ExplicitBraces ob cb-rnLayoutInfo (VirtualBraces n) = VirtualBraces n-rnLayoutInfo NoLayoutInfo = NoLayoutInfo- -- Does the data type declaration include a CUSK? data_decl_has_cusk :: LHsQTyVars (GhcPass p) -> NewOrData -> Bool -> Maybe (LHsKind (GhcPass p')) -> RnM Bool data_decl_has_cusk tyvars new_or_data no_rhs_kvs kind_sig = do@@ -1885,7 +1887,7 @@       = do { unlessXOptM LangExt.TypeData $ failWith TcRnIllegalTypeData            ; unless (null (fromMaybeContext context)) $                failWith $ TcRnTypeDataForbids TypeDataForbidsDatatypeContexts-           ; mapM_ (addLocMA check_type_data_condecl) condecls+           ; mapM_ (addLocM check_type_data_condecl) condecls            ; unless (null derivs) $                failWith $ TcRnTypeDataForbids TypeDataForbidsDerivingClauses            }@@ -1911,7 +1913,7 @@      is_strict (HsSrcBang _ _ s) = isSrcStrict s -    con_args (ConDeclGADT { con_g_args = PrefixConGADT args }) = args+    con_args (ConDeclGADT { con_g_args = PrefixConGADT _ args }) = args     con_args (ConDeclH98 { con_args = PrefixCon _ args }) = args     con_args (ConDeclH98 { con_args = InfixCon arg1 arg2 }) = [arg1, arg2]     con_args _ = []@@ -1970,8 +1972,6 @@      is never used (invariant (I1)), so it barely makes sense to talk about      the worker. A `type data` constructor only shows up in types, where it      appears as a TyCon, specifically a PromotedDataCon -- no Id in sight.-     See #24620 for an example of what happens if you accidentally include-     a wrapper.       See `wrapped_reqd` in GHC.Types.Id.Make.mkDataConRep` for the place where      this check is implemented.@@ -2020,13 +2020,17 @@            with the data constructor, else (I1) is violated. See GHC.Core.Utils            Note [Refine DEFAULT case alternatives] Exception 2 -     (W2c) In `GHC.Core.Opt.ConstantFold.caseRules`, disable the rule for-           `dataToTag#` in the case of `type data`.  We do not want to transform-              case dataToTag# x of t -> blah+     (W2c) In `GHC.Core.Opt.ConstantFold.caseRules`, we do not want to transform+              case dataToTagLarge# x of t -> blah            into               case x of { A -> ...; B -> .. }-           because again that conjures up the type-level-only data contructors+           because again that conjures up the type-level-only data constructors            `A` and `B` in a pattern, violating (I1) (#23023).+           So we check for "type data" TyCons before applying this+           transformation.  (In practice, this doesn't matter because+           we also refuse to solve DataToTag instances at types+           corresponding to type data declarations.  See rule C1 from+           Note [DataToTag overview] in GHC.Tc.Instance.Class.)  The main parts of the implementation are: @@ -2190,7 +2194,8 @@       (thing, fvs) <- thing_inside       pure (ds, thing, fvs) -rnFamDecl :: Maybe Name -- Just cls => this FamilyDecl is nested+rnFamDecl :: Maybe (Name, [Name])+                        -- Just (cls, cls_tvs) => this FamilyDecl is nested                         --             inside an *class decl* for cls                         --             used for associated types           -> FamilyDecl GhcPs@@ -2375,7 +2380,7 @@ rnConDecl decl@(ConDeclH98 { con_name = name, con_ex_tvs = ex_tvs                            , con_mb_cxt = mcxt, con_args = args                            , con_doc = mb_doc, con_forall = forall_ })-  = do  { _        <- addLocMA checkConName name+  = do  { _        <- addLocM checkConName name         ; new_name <- lookupLocatedTopConstructorRnN name          -- We bind no implicit binders here; this is just like@@ -2398,7 +2403,7 @@              , text "new_ex_dqtvs':" <+> ppr new_ex_tvs ])          ; mb_doc' <- traverse rnLHsDoc mb_doc-        ; return (decl { con_ext = noAnn+        ; return (decl { con_ext = noExtField                        , con_name = new_name, con_ex_tvs = new_ex_tvs                        , con_mb_cxt = new_context, con_args = new_args                        , con_doc = mb_doc'@@ -2406,13 +2411,12 @@                   all_fvs) }}  rnConDecl (ConDeclGADT { con_names   = names-                       , con_dcolon  = dcol                        , con_bndrs   = L l outer_bndrs                        , con_mb_cxt  = mcxt                        , con_g_args  = args                        , con_res_ty  = res_ty                        , con_doc     = mb_doc })-  = do  { mapM_ (addLocMA checkConName) names+  = do  { mapM_ (addLocM checkConName) names         ; new_names <- mapM (lookupLocatedTopConstructorRnN) names          ; let -- We must ensure that we extract the free tkvs in left-to-right@@ -2444,8 +2448,7 @@         ; traceRn "rnConDecl (ConDeclGADT)"             (ppr names $$ ppr outer_bndrs')         ; new_mb_doc <- traverse rnLHsDoc mb_doc-        ; return (ConDeclGADT { con_g_ext = noAnn, con_names = new_names-                              , con_dcolon = dcol+        ; return (ConDeclGADT { con_g_ext = noExtField, con_names = new_names                               , con_bndrs = L l outer_bndrs', con_mb_cxt = new_cxt                               , con_g_args = new_args, con_res_ty = new_res_ty                               , con_doc = new_mb_doc },@@ -2478,12 +2481,12 @@    -> HsDocContext    -> HsConDeclGADTDetails GhcPs    -> RnM (HsConDeclGADTDetails GhcRn, FreeVars)-rnConDeclGADTDetails _ doc (PrefixConGADT tys)+rnConDeclGADTDetails _ doc (PrefixConGADT _ tys)   = do { (new_tys, fvs) <- mapFvRn (rnScaledLHsType doc) tys-       ; return (PrefixConGADT new_tys, fvs) }-rnConDeclGADTDetails con doc (RecConGADT flds arr)+       ; return (PrefixConGADT noExtField new_tys, fvs) }+rnConDeclGADTDetails con doc (RecConGADT _ flds)   = do { (new_flds, fvs) <- rnRecConDeclFields con doc flds-       ; return (RecConGADT new_flds arr, fvs) }+       ; return (RecConGADT noExtField new_flds, fvs) }  rnRecConDeclFields ::      Name@@ -2536,7 +2539,7 @@           return ((PatSynName bnd_name, con_info) : names)       | L bind_loc (PatSynBind _ (PSB { psb_id = L _ n, psb_args = as })) <- bind       = do-        bnd_name <- newTopSrcBinder (L (la2na bind_loc) n)+        bnd_name <- newTopSrcBinder (L (l2l bind_loc) n)         let con_info = mkConInfo (conDetailsArity length as) []         return ((PatSynName bnd_name, con_info) : names)       | otherwise
compiler/GHC/Rename/Names.hs view
@@ -711,7 +711,7 @@      -- If there is a fixity decl for the gre, add it to the fixity env     extend_fix_env fix_env gre-      | Just (L _ fi) <- lookupFsEnv new_fixities (occNameFS occ)+      | Just (L _ fi) <- lookupMiniFixityEnv new_fixities name       = extendNameEnv fix_env name (FixItem occ fi)       | otherwise       = fix_env@@ -869,10 +869,10 @@     new_tc dup_fields_ok has_sel tc_decl -- NOT for type/data instances         = do { let TyDeclBinders (main_bndr, tc_flav) at_bndrs sig_bndrs                      (LConsWithFields cons_with_flds flds) = hsLTyClDeclBinders tc_decl-             ; tycon_name          <- newTopSrcBinder $ l2n main_bndr-             ; at_names            <- mapM (newTopSrcBinder . l2n . fst) at_bndrs-             ; sig_names           <- mapM (newTopSrcBinder . l2n) sig_bndrs-             ; con_names_with_flds <- mapM (\(con,flds) -> (,flds) <$> newTopSrcBinder (l2n con)) cons_with_flds+             ; tycon_name          <- newTopSrcBinder $ la2la main_bndr+             ; at_names            <- mapM (newTopSrcBinder . la2la . fst) at_bndrs+             ; sig_names           <- mapM (newTopSrcBinder . la2la) sig_bndrs+             ; con_names_with_flds <- mapM (\(con,flds) -> (,flds) <$> newTopSrcBinder (la2la con)) cons_with_flds              ; flds' <- mapM (newRecordFieldLabel dup_fields_ok has_sel $ map fst con_names_with_flds) flds              ; mapM_ (add_dup_fld_errs flds') con_names_with_flds              ; let tc_gre = mkLocalTyConGRE (fmap (const tycon_name) tc_flav) tycon_name@@ -947,7 +947,7 @@     new_di dup_fields_ok has_sel mb_cls dfid@(DataFamInstDecl { dfid_eqn = ti_decl })         = do { main_name <- unLoc <$> lookupFamInstName mb_cls (feqn_tycon ti_decl)              ; let LConsWithFields cons_with_flds flds = hsDataFamInstBinders dfid-             ; sub_names <- mapM (\(con,flds) -> (,flds) <$> newTopSrcBinder (l2n con)) cons_with_flds+             ; sub_names <- mapM (\(con,flds) -> (,flds) <$> newTopSrcBinder (la2la con)) cons_with_flds              ; flds' <- mapM (newRecordFieldLabel dup_fields_ok has_sel $ map fst sub_names) flds              ; mapM_ (add_dup_fld_errs flds') sub_names              ; let fld_env  = mk_fld_env sub_names flds'@@ -1287,12 +1287,11 @@               reason <- badImportItemErr iface decl_spec ie IsNotSubordinate all_avails               pure (TcRnDodgyImports (DodgyImportsHiding reason))             warning_msg (DeprecatedExport n w) =-              pure (TcRnPragmaWarning {-                      pragma_warning_occ = occName n-                    , pragma_warning_msg = w-                    , pragma_warning_import_mod = moduleName import_mod-                    , pragma_warning_defined_mod = Nothing-                    })+              pure $ TcRnPragmaWarning+                         PragmaWarningExport+                           { pwarn_occname = occName n+                           , pwarn_impmod  = moduleName import_mod }+                         w              run_lookup :: IELookupM a -> TcRn (Maybe a)             run_lookup m = case m of@@ -1319,7 +1318,7 @@               -> IELookupM ([(IE GhcRn, [GlobalRdrElt])], [IELookupWarning])     lookup_ie ie = handle_bad_import $       case ie of-        IEVar _ (L l n) -> do+        IEVar _ (L l n) _ -> do             -- See Note [Importing DuplicateRecordFields]             xs <- lookup_names ie (ieWrappedName n)             let gres = map imp_item $ NE.toList xs@@ -1327,14 +1326,19 @@                   | want_hiding == Exactly                       = mapMaybe mk_depr_export_warning gres                   | otherwise = []-            return ( [ (IEVar Nothing (L l (replaceWrappedName n name)), [gre])+            return ( [ (IEVar Nothing (L l (replaceWrappedName n name)) noDocstring, [gre])                      | gre <- gres                      , let name = greName gre ]                    , export_depr_warns ) -        IEThingAll _ (L l tc) -> do-            ImpOccItem gre child_gres _ <- lookup_parent ie $ ieWrappedName tc+        IEThingAll _ (L l tc) _ -> do+            ImpOccItem { imp_item      = gre+                       , imp_bundled   = bundled_gres+                       , imp_is_parent = is_par+                       }+              <- lookup_parent ie $ ieWrappedName tc             let name = greName gre+                child_gres = if is_par then bundled_gres else []                 imp_list_warn                    | null child_gres@@ -1348,7 +1352,7 @@                   | otherwise                   = [] -                renamed_ie = IEThingAll (Nothing, noAnn) (L l (replaceWrappedName tc name))+                renamed_ie = IEThingAll (Nothing, noAnn) (L l (replaceWrappedName tc name)) noDocstring                 export_depr_warn                   | want_hiding == Exactly                       = maybeToList $ mk_depr_export_warning gre@@ -1361,7 +1365,7 @@                    , imp_list_warn ++ export_depr_warn)  -        IEThingAbs _ (L l tc')+        IEThingAbs _ (L l tc') _             | want_hiding == EverythingBut   -- hiding ( C )                        -- Here the 'C' can be a data constructor                        --  *or* a type/class, or even both@@ -1377,9 +1381,9 @@                   return ( [mkIEThingAbs tc' l gre]                          , maybeToList $ mk_depr_export_warning gre) -        IEThingWith (deprecation, ann) ltc@(L l rdr_tc) wc rdr_ns -> do+        IEThingWith (deprecation, ann) ltc@(L l rdr_tc) wc rdr_ns _ -> do            ImpOccItem { imp_item = gre, imp_bundled = subnames }-               <- lookup_parent (IEThingAbs (Nothing, noAnn) ltc) (ieWrappedName rdr_tc)+               <- lookup_parent (IEThingAbs (Nothing, noAnn) ltc noDocstring) (ieWrappedName rdr_tc)            let name = greName gre             -- Look up the children in the sub-names of the parent@@ -1387,14 +1391,14 @@            case lookupChildren subnames rdr_ns of               Failed rdrs -> failLookupWith $-                            BadImport (IEThingWith (deprecation, ann) ltc wc rdrs) IsSubordinate+                            BadImport (IEThingWith (deprecation, ann) ltc wc rdrs noDocstring) IsSubordinate                                 -- We are trying to import T( a,b,c,d ), and failed                                 -- to find 'b' and 'd'.  So we make up an import item                                 -- to report as failing, namely T( b, d ).                                 -- c.f. #15412               Succeeded childnames ->-                return ([ (IEThingWith (Nothing, ann) (L l name') wc childnames'+                return ([ (IEThingWith (Nothing, ann) (L l name') wc childnames' noDocstring                           ,gres)]                        , export_depr_warns) @@ -1411,9 +1415,12 @@        where         mkIEThingAbs tc l gre-          = (IEThingAbs (Nothing, noAnn) (L l (replaceWrappedName tc n)), [gre])+          = (IEThingAbs (Nothing, noAnn) (L l (replaceWrappedName tc n)) noDocstring, [gre])           where n = greName gre +        -- N.B. imports never have docstrings+        noDocstring = Nothing+         handle_bad_import m = catchIELookup m $ \err -> case err of           BadImport ie _             | want_hiding == EverythingBut@@ -1483,18 +1490,23 @@ mkImportOccEnv :: HscEnv -> ImpDeclSpec -> [IfaceExport] -> OccEnv (NameEnv ImpOccItem) mkImportOccEnv hsc_env decl_spec all_avails =   mkOccEnv_C (plusNameEnv_C combine)-    [ (occ, mkNameEnv [(nm, ImpOccItem g bundled is_parent)])+    [ (occ, mkNameEnv [(nm, item)])     | avail <- all_avails-    , let gs = gresFromAvail hsc_env (Just hiding_spec) avail-    , g <- gs-    , let nm = greName g-          occ = greOccName g+    , let gres = gresFromAvail hsc_env (Just hiding_spec) avail+    , gre <- gres+    , let nm = greName gre+          occ = greOccName gre           (is_parent, bundled) = case avail of             AvailTC c _-              -> if c == nm -- (Recall the AvailTC invariant)-                 then ( True, case gs of { g0 : gs' | greName g0 == nm -> gs'; _ -> gs } )-                 else ( False, gs )+              | c == nm -- (Recall the AvailTC invariant from GHC.Types.AvailInfo)+              -> ( True, drop 1 gres ) -- "drop 1": don't include the parent itself.+              | otherwise+              -> ( False, gres )             _ -> ( False, [] )+          item = ImpOccItem+               { imp_item      = gre+               , imp_bundled   = bundled+               , imp_is_parent = is_parent }     ]   where @@ -1565,8 +1577,8 @@   = map set_gre_imp gres   where     is_explicit = case ie of-                    IEThingAll _ name -> \n -> n == lieWrappedName name-                    _                 -> \_ -> True+                    IEThingAll _ name _ -> \n -> n == lieWrappedName name+                    _                   -> \_ -> True     prov_fn name       = ImpSpec { is_decl = decl_spec, is_item = item_spec }       where@@ -1871,10 +1883,10 @@               _other -> emptyNameSet -- No explicit import list => no unused-name list          add_unused :: IE GhcRn -> NameSet -> NameSet-        add_unused (IEVar _ n)      acc = add_unused_name (lieWrappedName n) acc-        add_unused (IEThingAbs _ n) acc = add_unused_name (lieWrappedName n) acc-        add_unused (IEThingAll _ n) acc = add_unused_all  (lieWrappedName n) acc-        add_unused (IEThingWith _ p wc ns) acc =+        add_unused (IEVar _ n _)    acc   = add_unused_name (lieWrappedName n) acc+        add_unused (IEThingAbs _ n _) acc = add_unused_name (lieWrappedName n) acc+        add_unused (IEThingAll _ n _) acc = add_unused_all  (lieWrappedName n) acc+        add_unused (IEThingWith _ p wc ns _) acc =           add_wc_all (add_unused_with pn xs acc)           where pn = lieWrappedName p                 xs = map lieWrappedName ns@@ -1978,7 +1990,7 @@   where     -- In warning message, pretty-print identifiers unqualified unconditionally     -- to improve the consistent for ambiguous/unambiguous identifiers.-    -- See trac#14881.+    -- See #14881.     possible_field n =       case lookupGRE_Name rdr_env n of         Just (GRE { gre_par = par, gre_info = IAmRecField info }) ->@@ -2042,10 +2054,10 @@     to_ie rdr_env _ (Avail c)  -- Note [Overloaded field import]       = do { let                gre = expectJust "getMinimalImports Avail" $ lookupGRE_Name rdr_env c-           ; return $ [IEVar Nothing (to_ie_post_rn $ noLocA $ greName gre)] }+           ; return $ [IEVar Nothing (to_ie_post_rn $ noLocA $ greName gre) Nothing] }     to_ie _ _ avail@(AvailTC n [_])  -- Exporting the main decl and nothing else       | availExportsDecl avail-      = return [IEThingAbs (Nothing, noAnn) (to_ie_post_rn $ noLocA n)]+      = return [IEThingAbs (Nothing, noAnn) (to_ie_post_rn $ noLocA n) Nothing]     to_ie rdr_env iface (AvailTC n cs) =       case [ xs | avail@(AvailTC x xs) <- mi_exports iface            , x == n@@ -2053,12 +2065,12 @@            ] of         [xs]           | all_used xs-          -> return [IEThingAll (Nothing, noAnn) (to_ie_post_rn $ noLocA n)]+          -> return [IEThingAll (Nothing, noAnn) (to_ie_post_rn $ noLocA n) Nothing]           | otherwise           -> do { let ns_gres = map (expectJust "getMinimalImports AvailTC" . lookupGRE_Name rdr_env) cs                       ns = map greName ns_gres                 ; return [IEThingWith (Nothing, noAnn) (to_ie_post_rn $ noLocA n) NoIEWildcard-                                 (map (to_ie_post_rn . noLocA) (filter (/= n) ns))] }+                                 (map (to_ie_post_rn . noLocA) (filter (/= n) ns)) Nothing] }                                        -- Note [Overloaded field import]         _other           -> do { let infos = map (expectJust "getMinimalImports AvailTC" . lookupGRE_Name rdr_env) cs@@ -2067,9 +2079,9 @@                       fs = map fieldGREInfo fs_gres                 ; return $                   if all_non_overloaded fs-                  then map (IEVar Nothing . to_ie_post_rn_var . noLocA) ns+                  then map (\nm -> IEVar Nothing (to_ie_post_rn_var $ noLocA nm) Nothing) ns                   else [IEThingWith (Nothing, noAnn) (to_ie_post_rn $ noLocA n) NoIEWildcard-                         (map (to_ie_post_rn . noLocA) (filter (/= n) ns))] }+                         (map (to_ie_post_rn . noLocA) (filter (/= n) ns)) Nothing] }         where            all_used avail_cs = all (`elem` cs) avail_cs@@ -2124,14 +2136,14 @@  to_ie_post_rn_var :: LocatedA (IdP GhcRn) -> LIEWrappedName GhcRn to_ie_post_rn_var (L l n)-  | isDataOcc $ occName n = L l (IEPattern (la2e l)   (L (la2na l) n))-  | otherwise             = L l (IEName    noExtField (L (la2na l) n))+  | isDataOcc $ occName n = L l (IEPattern (entry l)   (L (l2l l) n))+  | otherwise             = L l (IEName    noExtField (L (l2l l) n))   to_ie_post_rn :: LocatedA (IdP GhcRn) -> LIEWrappedName GhcRn to_ie_post_rn (L l n)-  | isTcOcc occ && isSymOcc occ = L l (IEType (la2e l)   (L (la2na l) n))-  | otherwise                   = L l (IEName noExtField (L (la2na l) n))+  | isTcOcc occ && isSymOcc occ = L l (IEType (entry l)   (L (l2l l) n))+  | otherwise                   = L l (IEName noExtField (L (l2l l) n))   where occ = occName n  {-@@ -2203,15 +2215,16 @@   -> TcRn ImportLookupReason badImportItemErr iface decl_spec ie sub avails = do   patsyns_enabled <- xoptM LangExt.PatternSynonyms+  expl_ns_enabled <- xoptM LangExt.ExplicitNamespaces   dflags <- getDynFlags   hsc_env <- getTopEnv   let rdr_env = mkGlobalRdrEnv               $ gresFromAvails hsc_env (Just imp_spec) all_avails-  pure (ImportLookupBad (importErrorKind dflags rdr_env) iface decl_spec ie patsyns_enabled)+  pure (ImportLookupBad (importErrorKind dflags rdr_env expl_ns_enabled) iface decl_spec ie patsyns_enabled)   where-    importErrorKind dflags rdr_env+    importErrorKind dflags rdr_env expl_ns_enabled       | any checkIfTyCon avails = case sub of-          IsNotSubordinate -> BadImportAvailTyCon+          IsNotSubordinate -> BadImportAvailTyCon expl_ns_enabled           IsSubordinate -> BadImportNotExportedSubordinates unavailableChildren       | any checkIfVarName avails = BadImportAvailVar       | Just con <- find checkIfDataCon avails = BadImportAvailDataCon (availOccName con)@@ -2253,7 +2266,7 @@     imp_spec = ImpSpec { is_decl = decl_spec, is_item = ImpAll }     all_avails = mi_exports iface     unavailableChildren = case ie of-      IEThingWith _ _ _ ns -> map (rdrNameOcc . ieWrappedName  . unLoc) ns+      IEThingWith _ _ _ ns _ -> map (rdrNameOcc . ieWrappedName  . unLoc) ns       _ -> panic "importedChildren failed pattern match: no children"  addDupDeclErr :: NonEmpty GlobalRdrElt -> TcRn ()
compiler/GHC/Rename/Pat.hs view
@@ -1,13 +1,16 @@--{-# LANGUAGE TypeApplications    #-}-{-# LANGUAGE DeriveFunctor       #-}-{-# LANGUAGE FlexibleContexts    #-}-{-# LANGUAGE RankNTypes          #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TypeFamilies        #-}-{-# LANGUAGE ViewPatterns        #-}-{-# LANGUAGE DisambiguateRecordFields #-}+{-# LANGUAGE TypeApplications           #-}+{-# LANGUAGE DeriveFunctor              #-}+{-# LANGUAGE FlexibleContexts           #-}+{-# LANGUAGE RankNTypes                 #-}+{-# LANGUAGE ScopedTypeVariables        #-}+{-# LANGUAGE TypeFamilies               #-}+{-# LANGUAGE ViewPatterns               #-}+{-# LANGUAGE DisambiguateRecordFields   #-}+{-# LANGUAGE NamedFieldPuns             #-} {-# LANGUAGE MultiWayIf                 #-}+{-# LANGUAGE DerivingStrategies         #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+ {- (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 @@ -42,7 +45,7 @@ import GHC.Prelude  import {-# SOURCE #-} GHC.Rename.Expr ( rnLExpr )-import {-# SOURCE #-} GHC.Rename.Splice ( rnSplicePat )+import {-# SOURCE #-} GHC.Rename.Splice ( rnSplicePat, rnSpliceTyPat )  import GHC.Hs import GHC.Tc.Errors.Types@@ -54,7 +57,7 @@                            , warnUnusedMatches, newLocalBndrRn                            , checkUnusedRecordWildcard                            , checkDupNames, checkDupAndShadowedNames-                           , wrapGenSpan, genHsApps, genLHsVar, genHsIntegralLit, warnForallIdentifier )+                           , wrapGenSpan, genHsApps, genLHsVar, genHsIntegralLit, delLocalNames, typeAppErr ) import GHC.Rename.HsType import GHC.Builtin.Names @@ -68,6 +71,7 @@ import GHC.Utils.Misc import GHC.Data.FastString ( uniqCompareFS ) import GHC.Data.List.SetOps( removeDups )+import GHC.Data.Bag ( Bag, unitBag, unionBags, emptyBag, listToBag, bagToList ) import GHC.Utils.Outputable import GHC.Utils.Panic.Plain import GHC.Types.SrcLoc@@ -75,16 +79,25 @@ import GHC.Types.GREInfo   ( ConInfo(..), conInfoFields ) import GHC.Builtin.Types   ( nilDataCon ) import GHC.Core.DataCon+import GHC.Core.TyCon      ( isKindName ) import qualified GHC.LanguageExtensions as LangExt -import Control.Monad       ( when, ap, guard )+import Control.Monad       ( when, ap, guard, unless ) import Data.Foldable import Data.Function       ( on ) import Data.Functor.Identity ( Identity (..) ) import qualified Data.List.NonEmpty as NE import Data.Maybe import Data.Ratio-+import qualified Data.Semigroup as S+import Control.Monad.Trans.Writer.CPS+import Control.Monad.Trans.Class+import Control.Monad.Trans.Reader+import Data.Functor ((<&>))+import GHC.Rename.Doc (rnLHsDoc)+import GHC.Types.Hint+import GHC.Types.Fixity (LexicalFixity(..))+import Data.Coerce  {- *********************************************************@@ -215,7 +228,7 @@ localRecNameMaker :: MiniFixityEnv -> NameMaker localRecNameMaker fix_env = LetMk NotTopLevel fix_env -matchNameMaker :: HsMatchContext a -> NameMaker+matchNameMaker :: HsMatchContext fn -> NameMaker matchNameMaker ctxt = LamMk report_unused   where     -- Do not report unused names in interactive contexts@@ -235,16 +248,14 @@ newPatName :: NameMaker -> LocatedN RdrName -> CpsRn Name newPatName (LamMk report_unused) rdr_name   = CpsRn (\ thing_inside ->-        do { warnForallIdentifier rdr_name-           ; name <- newLocalBndrRn rdr_name+        do { name <- newLocalBndrRn rdr_name            ; (res, fvs) <- bindLocalNames [name] (thing_inside name)            ; when report_unused $ warnUnusedMatches [name] fvs            ; return (res, name `delFV` fvs) })  newPatName (LetMk is_top fix_env) rdr_name   = CpsRn (\ thing_inside ->-        do { warnForallIdentifier rdr_name-           ; name <- case is_top of+        do { name <- case is_top of                        NotTopLevel -> newLocalBndrRn rdr_name                        TopLevel    -> newTopSrcBinder rdr_name            ; bindLocalNames [name] $@@ -302,9 +313,9 @@  Note [Handling overloaded and rebindable patterns] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Overloaded paterns and rebindable patterns are desugared in the renamer+Overloaded patterns and rebindable patterns are desugared in the renamer using the HsPatExpansion mechanism detailed in:-Note [Rebindable syntax and HsExpansion]+Note [Rebindable syntax and XXExprGhcRn] The approach is similar to that of expressions, which is further detailed in Note [Handling overloaded and rebindable constructs] in GHC.Rename.Expr. @@ -332,7 +343,7 @@   toList -> [p1, p2, p3]  This happens directly in the renamer, using the HsPatExpansion mechanism-detailed in Note [Rebindable syntax and HsExpansion].+detailed in Note [Rebindable syntax and XXExprGhcRn].  Note that we emit a special view pattern: we additionally keep track of an inverse to the pattern.@@ -407,44 +418,62 @@ --   * local namemaker --   * unused and duplicate checking --   * no fixities-rnPats :: Traversable f-       => HsMatchContext GhcRn -- for error messages-       -> f (LPat GhcPs)-       -> (f (LPat GhcRn) -> RnM (a, FreeVars))-       -> RnM (a, FreeVars)-rnPats ctxt pats thing_inside-  = do  { envs_before <- getRdrEnvs -          -- (1) rename the patterns, bringing into scope all of the term variables-          -- (2) then do the thing inside.-        ; unCpsRn (rnLPatsAndThen (matchNameMaker ctxt) pats) $ \ pats' -> do-        { -- Check for duplicated and shadowed names-          -- Must do this *after* renaming the patterns-          -- See Note [Collect binders only after renaming] in GHC.Hs.Utils-          -- Because we don't bind the vars all at once, we can't-          --    check incrementally for duplicates;-          -- Nor can we check incrementally for shadowing, else we'll-          --    complain *twice* about duplicates e.g. f (x,x) = ...-          ---          -- See Note [Don't report shadowing for pattern synonyms]-        ; let bndrs = collectPatsBinders CollNoDictBinders (toList pats')-        ; addErrCtxt doc_pat $-          if isPatSynCtxt ctxt-             then checkDupNames bndrs-             else checkDupAndShadowedNames envs_before bndrs-        ; thing_inside pats' } }+-- rn_pats_general is the generalisation of two functions:+--    rnPats, rnPat+-- Those are the only call sites, so we inline it for improved performance.+-- Kind of like a macro.+{-# INLINE rn_pats_general #-}+rn_pats_general :: Traversable f => HsMatchContextRn+  -> f (LPat GhcPs)+  -> (f (LPat GhcRn) -> RnM (r, FreeVars))+  -> RnM (r, FreeVars)+rn_pats_general ctxt pats thing_inside = do+  envs_before <- getRdrEnvs++  -- (1) rename the patterns, bringing into scope all of the term variables+  -- (2) then do the thing inside.+  unCpsRn (rn_pats_fun (matchNameMaker ctxt) pats) $ \ pats' -> do+    -- Check for duplicated and shadowed names+    -- Must do this *after* renaming the patterns+    -- See Note [Collect binders only after renaming] in GHC.Hs.Utils+    -- Because we don't bind the vars all at once, we can't+    --    check incrementally for duplicates;+    -- Nor can we check incrementally for shadowing, else we'll+    --    complain *twice* about duplicates e.g. f (x,x) = ...+    --+    -- See Note [Don't report shadowing for pattern synonyms]+    let bndrs = collectPatsBinders CollVarTyVarBinders (toList pats')+    addErrCtxt doc_pat $+      if isPatSynCtxt ctxt+         then checkDupNames bndrs+         else checkDupAndShadowedNames envs_before bndrs+    thing_inside pats'   where     doc_pat = text "In" <+> pprMatchContext ctxt-{-# SPECIALIZE rnPats :: HsMatchContext GhcRn -> [LPat GhcPs] -> ([LPat GhcRn] -> RnM (a, FreeVars)) -> RnM (a, FreeVars) #-}-{-# SPECIALIZE rnPats :: HsMatchContext GhcRn -> Identity (LPat GhcPs) -> (Identity (LPat GhcRn) -> RnM (a, FreeVars)) -> RnM (a, FreeVars) #-} -rnPat :: HsMatchContext GhcRn -- for error messages+    -- See Note [Invisible binders in functions] in GHC.Hs.Pat+    --+    -- BTW, Or-patterns would be awesome here+    rn_pats_fun = case ctxt of+      FunRhs{} -> mapM . rnLArgPatAndThen+      LamAlt LamSingle -> mapM . rnLArgPatAndThen+      LamAlt LamCases -> mapM . rnLArgPatAndThen+      _ -> mapM . rnLPatAndThen++rnPats :: HsMatchContextRn   -- For error messages and choosing if @-patterns are allowed+       -> [LPat GhcPs]+       -> ([LPat GhcRn] -> RnM (a, FreeVars))+       -> RnM (a, FreeVars)+rnPats = rn_pats_general++rnPat :: forall a. HsMatchContextRn      -- For error messages and choosing if @-patterns are allowed       -> LPat GhcPs       -> (LPat GhcRn -> RnM (a, FreeVars))       -> RnM (a, FreeVars)     -- Variables bound by pattern do not                                -- appear in the result FreeVars-rnPat ctxt pat thing_inside-  = rnPats ctxt (Identity pat) (thing_inside . runIdentity)+rnPat+       = coerce (rn_pats_general @Identity @a)  applyNameMaker :: NameMaker -> LocatedN RdrName -> RnM (LocatedN Name) applyNameMaker mk rdr = do { (n, _fvs) <- runCps (newPatLName mk rdr)@@ -473,10 +502,21 @@ ********************************************************* -} ++rnLArgPatAndThen :: NameMaker -> LocatedA (Pat GhcPs) -> CpsRn (LocatedA (Pat GhcRn))+rnLArgPatAndThen mk = wrapSrcSpanCps rnArgPatAndThen where++  rnArgPatAndThen (InvisPat _ tp) = do+    liftCps $ unlessXOptM LangExt.TypeAbstractions $+      addErr (TcRnIllegalInvisibleTypePattern tp)+    tp' <- rnHsTyPat HsTypePatCtx tp+    pure (InvisPat noExtField tp')+  rnArgPatAndThen p = rnPatAndThen mk p+ -- ----------- Entry point 3: rnLPatAndThen ------------------- -- General version: parameterized by how you make new names -rnLPatsAndThen :: Traversable f => NameMaker -> f (LPat GhcPs) -> CpsRn (f (LPat GhcRn))+rnLPatsAndThen :: NameMaker -> [LPat GhcPs] -> CpsRn [LPat GhcRn] rnLPatsAndThen mk = mapM (rnLPatAndThen mk)   -- Despite the map, the monad ensures that each pattern binds   -- variables that may be mentioned in subsequent patterns in the list@@ -488,9 +528,9 @@  rnPatAndThen :: NameMaker -> Pat GhcPs -> CpsRn (Pat GhcRn) rnPatAndThen _  (WildPat _)   = return (WildPat noExtField)-rnPatAndThen mk (ParPat x lpar pat rpar) =+rnPatAndThen mk (ParPat _ pat) =   do { pat' <- rnLPatAndThen mk pat-     ; return (ParPat x lpar pat' rpar) }+     ; return (ParPat noExtField pat') } rnPatAndThen mk (LazyPat _ pat) = do { pat' <- rnLPatAndThen mk pat                                      ; return (LazyPat noExtField pat') } rnPatAndThen mk (BangPat _ pat) = do { pat' <- rnLPatAndThen mk pat@@ -546,7 +586,7 @@        ; return (NPat x (L l lit') mb_neg' eq') }  rnPatAndThen mk (NPlusKPat _ rdr (L l lit) _ _ _ )-  = do { new_name <- newPatName mk (l2n rdr)+  = do { new_name <- newPatName mk (la2la rdr)        ; (lit', _) <- liftCpsFV $ rnOverLit lit -- See Note [Negative zero]                                                 -- We skip negateName as                                                 -- negative zero doesn't make@@ -557,10 +597,10 @@                                       (L l lit') lit' ge minus) }                 -- The Report says that n+k patterns must be in Integral -rnPatAndThen mk (AsPat _ rdr at pat)+rnPatAndThen mk (AsPat _ rdr pat)   = do { new_name <- newPatLName mk rdr        ; pat' <- rnLPatAndThen mk pat-       ; return (AsPat noExtField new_name at pat') }+       ; return (AsPat noExtField new_name pat') }  rnPatAndThen mk p@(ViewPat _ expr pat)   = do { liftCps $ do { vp_flag <- xoptM LangExt.ViewPatterns@@ -623,6 +663,17 @@            (rn_splice, HsUntypedSpliceNested splice_name) -> return (SplicePat (HsUntypedSpliceNested splice_name) rn_splice) -- Splice was nested and thus already renamed        } +rnPatAndThen _ (EmbTyPat _ tp)+  = do { tp' <- rnHsTyPat HsTypePatCtx tp+       ; return (EmbTyPat noExtField tp') }+rnPatAndThen _ (InvisPat _ tp)+  = do { liftCps $ addErr (TcRnMisplacedInvisPat tp)+         -- Invisible patterns are handled in `rnLArgPatAndThen`+         -- so unconditionally emit error here+       ; tp' <- rnHsTyPat HsTypePatCtx tp+       ; return (InvisPat noExtField tp')+       }+ -------------------- rnConPatAndThen :: NameMaker                 -> LocatedN RdrName    -- the constructor@@ -647,26 +698,15 @@         do { type_abs   <- xoptM LangExt.TypeAbstractions            ; type_app   <- xoptM LangExt.TypeApplications            ; scoped_tvs <- xoptM LangExt.ScopedTypeVariables-           ; if | type_abs-                -> return ()--                -- As per [GHC Proposal 604](https://github.com/ghc-proposals/ghc-proposals/pull/604/),-                -- we allow type applications in constructor patterns when -XTypeApplications and-                -- -XScopedTypeVariables are both enabled, but we emit a warning when doing so.-                ---                -- This warning is scheduled to become an error in GHC 9.12, in-                -- which case we will get the usual error (below),-                -- which suggests enabling -XTypeAbstractions.-                | type_app && scoped_tvs-                -> addDiagnostic TcRnDeprecatedInvisTyArgInConPat--                | otherwise-                -> addErrTc $ TcRnTypeApplicationsDisabled (TypeApplicationInPattern arg)+           -- See Note [Deprecated type abstractions in constructor patterns]+           ; if | type_abs -> return ()+                | type_app && scoped_tvs -> addDiagnostic TcRnDeprecatedInvisTyArgInConPat+                | otherwise -> addErrTc $ TcRnTypeApplicationsDisabled (TypeApplicationInPattern arg)            } -    rnConPatTyArg (HsConPatTyArg at t) = do-      t' <- liftCpsWithCont $ rnHsPatSigTypeBindingVars HsTypeCtx t-      return (HsConPatTyArg at t')+    rnConPatTyArg (HsConPatTyArg _ t) = do+      t' <- rnHsTyPat HsTypePatCtx t+      return (HsConPatTyArg noExtField t')  rnConPatAndThen mk con (InfixCon pat1 pat2)   = do  { con' <- lookupConCps con@@ -685,12 +725,38 @@             }         } -checkUnusedRecordWildcardCps :: SrcSpan -> Maybe [Name] -> CpsRn ()+{- Note [Deprecated type abstractions in constructor patterns]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Type abstractions in constructor patterns allow the user to bind+existential type variables:++    import Type.Reflection (Typeable, typeRep)+    data Ex = forall e. (Typeable e, Show e) => MkEx e+    showEx (MkEx @e a) = show a ++ " :: " ++ show (typeRep @e)++Note the pattern `MkEx @e a`, and specifically the `@e` binder.++For historical reasons, using this feature only required TypeApplications+and ScopedTypeVariables to be enabled. As per GHC Proposal #448 (and especially+its amendment #604) we are now transitioning towards guarding this feature+behind TypeAbstractions instead.++As a compatibility measure, we continue to support old programs that use+TypeApplications with ScopedTypeVariables instead of TypeAbstractions,+but emit the appropriate compatibility warning, -Wdeprecated-type-abstractions.+This warning is scheduled to become an error in GHC 9.14, at which point+we can simply require TypeAbstractions.+-}++checkUnusedRecordWildcardCps :: SrcSpan+                             -> Maybe [ImplicitFieldBinders]+                             -> CpsRn () checkUnusedRecordWildcardCps loc dotdot_names =   CpsRn (\thing -> do                     (r, fvs) <- thing ()                     checkUnusedRecordWildcard loc fvs dotdot_names                     return (r, fvs) )+ -------------------- rnHsRecPatsAndThen :: NameMaker                    -> LocatedN Name      -- Constructor@@ -701,7 +767,7 @@   = do { flds <- liftCpsFV $ rnHsRecFields (HsRecFieldPat con) mkVarPat                                             hs_rec_fields        ; flds' <- mapM rn_field (flds `zip` [1..])-       ; check_unused_wildcard (implicit_binders flds' <$> dd)+       ; check_unused_wildcard (lHsRecFieldsImplicits flds' <$> unLoc <$> dd)        ; return (HsRecFields { rec_flds = flds', rec_dotdot = dd }) }   where     mkVarPat l n = VarPat noExtField (L (noAnnSrcSpan l) n)@@ -709,12 +775,7 @@       do { arg' <- rnLPatAndThen (nested_mk dd mk (RecFieldsDotDot n')) (hfbRHS fld)          ; return (L l (fld { hfbRHS = arg' })) } -    loc = maybe noSrcSpan getLoc dd--    -- Get the arguments of the implicit binders-    implicit_binders fs (unLoc -> RecFieldsDotDot n) = collectPatsBinders CollNoDictBinders implicit_pats-      where-        implicit_pats = map (hfbRHS . unLoc) (drop n fs)+    loc = maybe noSrcSpan getLocA dd      -- Don't warn for let P{..} = ... in ...     check_unused_wildcard = case mk of@@ -812,12 +873,12 @@                  , hfbRHS = arg'                  , hfbPun = pun } } -    rn_dotdot :: Maybe (Located RecFieldsDotDot)      -- See Note [DotDot fields] in GHC.Hs.Pat+    rn_dotdot :: Maybe (LocatedE RecFieldsDotDot)     -- See Note [DotDot fields] in GHC.Hs.Pat               -> Maybe Name -- The constructor (Nothing for an                                 --    out of scope constructor)               -> [LHsRecField GhcRn (LocatedA arg)] -- Explicit fields               -> RnM ([LHsRecField GhcRn (LocatedA arg)])   -- Field Labels we need to fill in-    rn_dotdot (Just (L loc (RecFieldsDotDot n))) (Just con) flds -- ".." on record construction / pat match+    rn_dotdot (Just (L loc_e (RecFieldsDotDot n))) (Just con) flds -- ".." on record construction / pat match       | not (isUnboundName con) -- This test is because if the constructor                                 -- isn't in scope the constructor lookup will add                                 -- an error but still return an unbound name. We@@ -849,6 +910,7 @@                              _other           -> True ]             ; addUsedGREs NoDeprecationWarnings dot_dot_gres+           ; let loc = locA loc_e            ; let locn = noAnnSrcSpan loc            ; return [ L (noAnnSrcSpan loc) (HsFieldBind                         { hfbAnn = noAnn@@ -1098,11 +1160,407 @@           }         ; let std_name = hsOverLitName val         ; (from_thing_name, fvs1) <- lookupSyntaxName std_name+        ; loc <- getSrcSpanM -- See Note [Source locations for implicit function calls] in GHC.Iface.Ext.Ast         ; let rebindable = from_thing_name /= std_name               lit' = lit { ol_ext = OverLitRn { ol_rebindable = rebindable-                                              , ol_from_fun = noLocA from_thing_name } }+                                              , ol_from_fun = L (noAnnSrcSpan loc) from_thing_name } }         ; if isNegativeZeroOverLit lit'           then do { (negate_name, fvs2) <- lookupSyntaxExpr negateName                   ; return ((lit' { ol_val = negateOverLitVal val }, Just negate_name)                                   , fvs1 `plusFV` fvs2) }           else return ((lit', Nothing), fvs1) }+++rnHsTyPat :: HsDocContext+          -> HsTyPat GhcPs+          -> CpsRn (HsTyPat GhcRn)+rnHsTyPat ctxt sigType = case sigType of+  (HsTP { hstp_body = hs_ty }) -> do+    (hs_ty', tpb) <- runTPRnM (rn_lty_pat hs_ty) ctxt+    pure HsTP+          { hstp_body = hs_ty'+          , hstp_ext = buildHsTyPatRn tpb+          }++-- | Type pattern renaming monad+-- For the OccSet in the ReaderT, see Note [Locally bound names in type patterns]+-- For the HsTyPatRnBuilderRn in the WriterT, see Note [Implicit and explicit type variable binders]+-- For the CpsRn base monad, see Note [CpsRn monad]+-- For why we need CpsRn in TPRnM see Note [Left-to-right scoping of type patterns]+newtype TPRnM a =+  MkTPRnM (ReaderT (HsDocContext, OccSet) (WriterT HsTyPatRnBuilder CpsRn) a)+  deriving newtype (Functor, Applicative, Monad)++runTPRnM :: TPRnM a -> HsDocContext -> CpsRn (a, HsTyPatRnBuilder)+runTPRnM (MkTPRnM thing_inside) doc_ctxt = runWriterT $ runReaderT thing_inside (doc_ctxt, emptyOccSet)++askLocals :: TPRnM OccSet+askLocals = MkTPRnM (asks snd)++askDocContext :: TPRnM HsDocContext+askDocContext = MkTPRnM (asks fst)++tellTPB :: HsTyPatRnBuilder -> TPRnM ()+tellTPB = MkTPRnM . lift . tell++liftRnFV :: RnM (a, FreeVars) -> TPRnM a+liftRnFV = liftTPRnCps . liftCpsFV++liftRn :: RnM a -> TPRnM a+liftRn = liftTPRnCps . liftCps++liftRnWithCont :: (forall r. (b -> RnM (r, FreeVars)) -> RnM (r, FreeVars)) -> TPRnM b+liftRnWithCont cont = liftTPRnCps (liftCpsWithCont cont)++liftTPRnCps :: CpsRn a -> TPRnM a+liftTPRnCps = MkTPRnM . lift . lift++liftTPRnRaw ::+  ( forall r .+    HsDocContext ->+    OccSet ->+    ((a, HsTyPatRnBuilder) -> RnM (r, FreeVars)) ->+    RnM (r, FreeVars)+  ) -> TPRnM a+liftTPRnRaw cont = MkTPRnM $ ReaderT $ \(doc_ctxt, locals) -> writerT $ liftCpsWithCont (cont doc_ctxt locals)++unTPRnRaw ::+  TPRnM a ->+  HsDocContext ->+  OccSet ->+  ((a, HsTyPatRnBuilder) -> RnM (r, FreeVars)) ->+  RnM (r, FreeVars)+unTPRnRaw (MkTPRnM m) doc_ctxt locals = unCpsRn $ runWriterT $ runReaderT m (doc_ctxt, locals)++wrapSrcSpanTPRnM :: (a -> TPRnM b) -> LocatedAn ann a -> TPRnM (LocatedAn ann b)+wrapSrcSpanTPRnM fn (L loc a) = do+  a' <- fn a+  pure (L loc a')++lookupTypeOccTPRnM :: RdrName -> TPRnM Name+lookupTypeOccTPRnM rdr_name = liftRnFV $ do+  name <- lookupTypeOccRn rdr_name+  pure (name, unitFV name)++-- | A variant of HsTyPatRn that uses Bags for efficient concatenation.+-- See Note [Implicit and explicit type variable binders]+data HsTyPatRnBuilder =+  HsTPRnB {+    hstpb_nwcs :: Bag Name,+    hstpb_imp_tvs :: Bag Name,+    hstpb_exp_tvs :: Bag Name+  }++tpb_exp_tv :: Name -> HsTyPatRnBuilder+tpb_exp_tv name = mempty {hstpb_exp_tvs = unitBag name}++tpb_hsps :: HsPSRn -> HsTyPatRnBuilder+tpb_hsps HsPSRn {hsps_nwcs, hsps_imp_tvs} =+  mempty {+    hstpb_nwcs = listToBag hsps_nwcs,+    hstpb_imp_tvs = listToBag hsps_imp_tvs+  }++instance Semigroup HsTyPatRnBuilder where+  HsTPRnB nwcs1 imp_tvs1 exptvs1 <> HsTPRnB nwcs2 imp_tvs2 exptvs2 =+    HsTPRnB+      (nwcs1    `unionBags` nwcs2)+      (imp_tvs1 `unionBags` imp_tvs2)+      (exptvs1  `unionBags` exptvs2)++instance Monoid HsTyPatRnBuilder where+  mempty = HsTPRnB emptyBag emptyBag emptyBag++buildHsTyPatRn :: HsTyPatRnBuilder -> HsTyPatRn+buildHsTyPatRn HsTPRnB {hstpb_nwcs, hstpb_imp_tvs, hstpb_exp_tvs} =+  HsTPRn {+    hstp_nwcs =    bagToList hstpb_nwcs,+    hstp_imp_tvs = bagToList hstpb_imp_tvs,+    hstp_exp_tvs = bagToList hstpb_exp_tvs+  }++rn_lty_pat :: LHsType GhcPs -> TPRnM (LHsType GhcRn)+rn_lty_pat (L l hs_ty) = do+  hs_ty' <- rn_ty_pat hs_ty+  pure (L l hs_ty')++rn_ty_pat_var :: LocatedN RdrName -> TPRnM (LocatedN Name)+rn_ty_pat_var lrdr@(L l rdr) = do+  locals <- askLocals+  if isRdrTyVar rdr+    && not (elemOccSet (occName rdr) locals) -- See Note [Locally bound names in type patterns]++    then do -- binder+      name <- liftTPRnCps $ newPatName (LamMk True) lrdr+      tellTPB (tpb_exp_tv name)+      pure (L l name)++    else do -- usage+      name <- lookupTypeOccTPRnM rdr+      pure (L l name)++-- | Rename type patterns+--+-- For the difference between `rn_ty_pat` and `rnHsTyKi` see Note [CpsRn monad]+-- and Note [Implicit and explicit type variable binders]+rn_ty_pat :: HsType GhcPs -> TPRnM (HsType GhcRn)+rn_ty_pat tv@(HsTyVar an prom lrdr) = do+  lname@(L _ name) <- rn_ty_pat_var lrdr+  when (isDataConName name && not (isKindName name)) $+    -- Any use of a promoted data constructor name (that is not specifically+    -- exempted by isKindName) is illegal without the use of DataKinds.+    -- See Note [Checking for DataKinds] in GHC.Tc.Validity.+    check_data_kinds tv+  pure (HsTyVar an prom lname)++rn_ty_pat (HsForAllTy an tele body) = liftTPRnRaw $ \ctxt locals thing_inside ->+  bindHsForAllTelescope ctxt tele $ \tele' -> do+    let+      tele_names = hsForAllTelescopeNames tele'+      locals' = locals `extendOccSetList` map occName tele_names++    unTPRnRaw (rn_lty_pat body) ctxt locals' $ \(body', tpb) ->+      delLocalNames tele_names $ -- locally bound names do not scope over the continuation+        thing_inside ((HsForAllTy an tele' body'), tpb)++rn_ty_pat (HsQualTy an lctx body) = do+  lctx' <- wrapSrcSpanTPRnM (mapM rn_lty_pat) lctx+  body' <- rn_lty_pat body+  pure (HsQualTy an lctx' body')++rn_ty_pat (HsAppTy _ fun_ty arg_ty) = do+  fun_ty' <- rn_lty_pat fun_ty+  arg_ty' <- rn_lty_pat arg_ty+  pure (HsAppTy noExtField fun_ty' arg_ty')++rn_ty_pat (HsAppKindTy _ ty ki) = do+  kind_app <- liftRn $ xoptM LangExt.TypeApplications+  unless kind_app (liftRn $ addErr (typeAppErr KindLevel ki))+  ty' <- rn_lty_pat ty+  ki' <- rn_lty_pat ki+  pure (HsAppKindTy noExtField ty' ki')++rn_ty_pat (HsFunTy an mult lhs rhs) = do+  lhs' <- rn_lty_pat lhs+  mult' <- rn_ty_pat_arrow mult+  rhs' <- rn_lty_pat rhs+  pure (HsFunTy an mult' lhs' rhs')++rn_ty_pat (HsListTy an ty) = do+  ty' <- rn_lty_pat ty+  pure (HsListTy an ty')++rn_ty_pat (HsTupleTy an con tys) = do+  tys' <- mapM rn_lty_pat tys+  pure (HsTupleTy an con tys')++rn_ty_pat (HsSumTy an tys) = do+  tys' <- mapM rn_lty_pat tys+  pure (HsSumTy an tys')++rn_ty_pat (HsOpTy _ prom ty1 l_op ty2) = do+  ty1' <- rn_lty_pat ty1+  l_op' <- rn_ty_pat_var l_op+  ty2' <- rn_lty_pat ty2+  fix  <- liftRn $ lookupTyFixityRn l_op'+  let op_name = unLoc l_op'+  when (isDataConName op_name && not (isPromoted prom)) $+    liftRn $ addDiagnostic (TcRnUntickedPromotedThing $ UntickedConstructor Infix op_name)+  liftRn $ mkHsOpTyRn prom l_op' fix ty1' ty2'++rn_ty_pat (HsParTy an ty) = do+  ty' <- rn_lty_pat ty+  pure (HsParTy an ty')++rn_ty_pat (HsIParamTy an n ty) = do+  ty' <- rn_lty_pat ty+  pure (HsIParamTy an n ty')++rn_ty_pat (HsStarTy an unicode) =+  pure (HsStarTy an unicode)++rn_ty_pat (HsDocTy an ty haddock_doc) = do+  ty' <- rn_lty_pat ty+  haddock_doc' <- liftRn $ rnLHsDoc haddock_doc+  pure (HsDocTy an ty' haddock_doc')++rn_ty_pat ty@(HsExplicitListTy _ prom tys) = do+  check_data_kinds ty++  unless (isPromoted prom) $+    liftRn $ addDiagnostic (TcRnUntickedPromotedThing $ UntickedExplicitList)++  tys' <- mapM rn_lty_pat tys+  pure (HsExplicitListTy noExtField prom tys')++rn_ty_pat ty@(HsExplicitTupleTy _ tys) = do+  check_data_kinds ty+  tys' <- mapM rn_lty_pat tys+  pure (HsExplicitTupleTy noExtField tys')++rn_ty_pat tyLit@(HsTyLit src t) = do+  check_data_kinds tyLit+  t' <- liftRn $ rnHsTyLit t+  pure (HsTyLit src t')++rn_ty_pat (HsWildCardTy _) =+  pure (HsWildCardTy noExtField)++rn_ty_pat (HsKindSig an ty ki) = do+  ctxt <- askDocContext+  kind_sigs_ok <- liftRn $ xoptM LangExt.KindSignatures+  unless kind_sigs_ok (liftRn $ badKindSigErr ctxt ki)+  ~(HsPS hsps ki') <- liftRnWithCont $+                      rnHsPatSigKind AlwaysBind ctxt (HsPS noAnn ki)+  ty' <- rn_lty_pat ty+  tellTPB (tpb_hsps hsps)+  pure (HsKindSig an ty' ki')++rn_ty_pat (HsSpliceTy _ splice) = do+  res <- liftRnFV $ rnSpliceTyPat splice+  case res of+    (rn_splice, HsUntypedSpliceTop mfs pat) -> do -- Splice was top-level and thus run, creating LHsType GhcPs+        pat' <- rn_lty_pat pat+        pure (HsSpliceTy (HsUntypedSpliceTop mfs (mb_paren pat')) rn_splice)+    (rn_splice, HsUntypedSpliceNested splice_name) ->+        pure (HsSpliceTy (HsUntypedSpliceNested splice_name) rn_splice) -- Splice was nested and thus already renamed+  where+    mb_paren :: LHsType GhcRn -> LHsType GhcRn+    mb_paren lhs_ty@(L loc hs_ty)+      | hsTypeNeedsParens maxPrec hs_ty = L loc (HsParTy noAnn lhs_ty)+      | otherwise                       = lhs_ty++rn_ty_pat (HsBangTy an bang_src lty) = do+  ctxt <- askDocContext+  lty'@(L _ ty') <- rn_lty_pat lty+  liftRn $ addErr $+    TcRnWithHsDocContext ctxt $+    TcRnUnexpectedAnnotation ty' bang_src+  pure (HsBangTy an bang_src lty')++rn_ty_pat ty@HsRecTy{} = do+  ctxt <- askDocContext+  liftRn $ addErr $+    TcRnWithHsDocContext ctxt $+    TcRnIllegalRecordSyntax (Left ty)+  pure (HsWildCardTy noExtField) -- trick to avoid `failWithTc`++rn_ty_pat ty@(XHsType{}) = do+  ctxt <- askDocContext+  liftRnFV $ rnHsType ctxt ty++rn_ty_pat_arrow :: HsArrow GhcPs -> TPRnM (HsArrow GhcRn)+rn_ty_pat_arrow (HsUnrestrictedArrow _) = pure (HsUnrestrictedArrow noExtField)+rn_ty_pat_arrow (HsLinearArrow _) = pure (HsLinearArrow noExtField)+rn_ty_pat_arrow (HsExplicitMult _ p)+  = rn_lty_pat p <&> (\mult -> HsExplicitMult noExtField mult)++check_data_kinds :: HsType GhcPs -> TPRnM ()+check_data_kinds thing = liftRn $ do+  data_kinds <- xoptM LangExt.DataKinds+  unless data_kinds $+    addErr $ TcRnDataKindsError TypeLevel $ Left thing++{- Note [Locally bound names in type patterns]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Type patterns can bind local names using forall. Compare the following examples:+  f (Proxy @(Either a b)) = ...+  g (Proxy @(forall a . Either a b)) = ...++In `f` both `a` and `b` are bound by the pattern and scope over the RHS of f.+In `g` only `b` is bound by the pattern, whereas `a` is locally bound in the pattern+and does not scope over the RHS of `g`.++We track locally bound names in the `OccSet` in `TPRnM` monad, and use it to+decide whether occurrences of type variables are usages or bindings.++The check is done in `rn_ty_pat_var`++Note [Implicit and explicit type variable binders]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Type patterns are renamed differently from ordinary types.+  * Types are renamed by `rnHsType` where all type variable occurrences are considered usages+  * Type patterns are renamed by `rnHsTyPat` where some type variable occurrences are usages+    and other are bindings++Here is an example:+  {-# LANGUAGE ScopedTypeVariables #-}+  f :: forall b. Proxy _ -> ...+  f (Proxy @(x :: (a, b))) = ...++In the (x :: (a,b)) type pattern+  * `x` is a type variable explicitly bound by type pattern+  * `a` is a type variable implicitly bound in a pattern signature+  * `b` is a usage of type variable bound by the outer forall++This classification is clear to us in `rnHsTyPat`, but it is also useful in later passes, such+as `collectPatBinders` and `tcHsTyPat`, so we store it in the extension field of `HsTyPat`, namely+`HsTyPatRn`.++To collect lists of those variables efficiently we use `HsTyPatRnBuilder` which is exactly like+`HsTyPatRn`, but uses Bags.++Note [Left-to-right scoping of type patterns]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+In term-level patterns, we use continuation passing to implement left-to-right+scoping, see Note [CpsRn monad]. Left-to-right scoping manifests itself when+e.g. view patterns are involved:++  f (x, g x -> Just y) = ...++Here the first occurrence of `x` is a binder, and the second occurrence is a+use of `x` in a view pattern. This example does not work if we swap the+components of the tuple:++  f (g x -> Just y, x) = ...+  --  ^^^+  -- Variable not in scope: x++In type patterns there are no view patterns, but there is a different feature+that is served well by left-to-right scoping: kind annotations. Compare:++  f (Proxy @(T k (a :: k))) = ...+  g (Proxy @(T (a :: k) k)) = ...++In `f`, the first occurrence of `k` is an explicit binder,+  and the second occurrence is a usage. Simple.+In `g`, the first occurrence of `k` is an implicit binder,+  and then the second occurrence is an explicit binder that shadows it.++So we get two different results after renaming:++  f (Proxy @(T k1 (a :: k1))) = ...+  g (Proxy @(T (a :: k1) k2)) = ...++This makes GHC accept the first example but rejects the second example with an+error about duplicate binders.++One could argue that we don't want order-sensitivity here. Historically, we+used a different principle when renaming types: collect all free variables,+bind them on the outside, and then rename all occurrences as usages.+This approach does not scale to multiple patterns. Consider:++  f' (MkP @k @(a :: k)) = ...+  g' (MkP @(a :: k) @k) = ...++Here a difference in behavior is inevitable, as we rename type patterns+one at a time. Could we perhaps concatenate the free variables from all+type patterns in a ConPat? But then we still get the same problem one level up,+when we have multiple patterns in a function LHS++  f'' (Proxy @k) (Proxy @(a :: k)) = ...+  g'' (Proxy @(a :: k)) (Proxy @k) = ...++And if we tried to avoid order sensitivity at this level, then we'd still be left+with lambdas:++  f''' (Proxy @k)        = \(Proxy @(a :: k)) -> ...+  g''' (Proxy @(a :: k)) = \(Proxy @k)        -> ...+++So we have at least three options where we could do free variable extraction:+HsConPatTyArg, ConPat, or a Match (used to represent a function LHS). And none+of those would be general enough. Rather than make an arbitrary choice, we+embrace left-to-right scoping in types and implement it with CPS, just like+it's done for view patterns in terms.+-}
compiler/GHC/Rename/Splice.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE MultiWayIf #-}  module GHC.Rename.Splice (         rnTopSpliceDecls,@@ -7,12 +8,13 @@         -- Typed splices         rnTypedSplice,         -- Untyped splices-        rnSpliceType, rnUntypedSpliceExpr, rnSplicePat, rnSpliceDecl,+        rnSpliceType, rnUntypedSpliceExpr, rnSplicePat, rnSpliceTyPat, rnSpliceDecl,          -- Brackets         rnTypedBracket, rnUntypedBracket, -        checkThLocalName, traceSplice, SpliceInfo(..)+        checkThLocalName, traceSplice, SpliceInfo(..),+        checkThLocalTyName,   ) where  import GHC.Prelude@@ -83,6 +85,38 @@   unlessXOptM LangExt.TemplateHaskellQuotes $     failWith $ thSyntaxError $ IllegalTHQuotes e +{-++Note [Untyped quotes in typed splices and vice versa]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider this typed splice+   $$(f [| x |])++Is there anything wrong with that /typed/ splice containing an /untyped/+quote [| x |]?   One could ask the same about an /untyped/ slice containing a+/typed/ quote.++In fact, both are fine (#24190). Presumably f's type looks something like:+   f :: Q Expr -> Code Q Int++It is pretty hard for `f` to use its (untyped code) argument to build a typed+syntax tree, but not impossible:+* `f` could use `unsafeCodeCoerce :: Q Exp -> Code Q a`+* `f` could just perform case analysis on the tree++But in the end all that matters is that in $$( e ), the expression `e` has the+right type.  It doesn't matter how `e` is built.  To put it another way, the+untyped quote `[| x |]` could also be written `varE 'x`, which is an ordinary+expression.++Moreover the ticked variable, 'x :: Name, is itself treated as an untyped quote;+but it is a perfectly fine sub-expression to have in a typed splice.++(Historical note: GHC used to unnecessarily  check that a typed quote only+occurred in a typed splice: #24190.)++-}+ rnTypedBracket :: HsExpr GhcPs -> LHsExpr GhcPs -> RnM (HsExpr GhcRn, FreeVars) rnTypedBracket e br_body   = addErrCtxt (typedQuotationCtxtDoc br_body) $@@ -91,9 +125,8 @@          -- Check for nested brackets        ; cur_stage <- getStage        ; case cur_stage of-           { Splice Typed   -> return ()-           ; Splice Untyped -> failWithTc $ thSyntaxError-                                          $ MismatchedSpliceType Untyped IsBracket+           { Splice _       -> return ()+               -- See Note [Untyped quotes in typed splices and vice versa]            ; RunSplice _    ->                -- See Note [RunSplice ThLevel] in GHC.Tc.Types.                pprPanic "rnTypedBracket: Renaming typed bracket when running a splice"@@ -121,9 +154,8 @@          -- Check for nested brackets        ; cur_stage <- getStage        ; case cur_stage of-           { Splice Typed   -> failWithTc $ thSyntaxError-                                          $ MismatchedSpliceType Typed IsBracket-           ; Splice Untyped -> return ()+           { Splice _       -> return ()+               -- See Note [Untyped quotes in typed splices and vice versa]            ; RunSplice _    ->                -- See Note [RunSplice ThLevel] in GHC.Tc.Types.                pprPanic "rnUntypedBracket: Renaming untyped bracket when running a splice"@@ -387,15 +419,15 @@ -- Return the expression (quoter "...quote...") -- which is what we must run in a quasi-quote mkQuasiQuoteExpr flavour quoter (L q_span' quote)-  = L q_span $ HsApp noComments (L q_span-             $ HsApp noComments (L q_span-                    (HsVar noExtField (L (la2na q_span) quote_selector)))+  = L q_span $ HsApp noExtField (L q_span+             $ HsApp noExtField (L q_span+                    (HsVar noExtField (L (l2l q_span) quote_selector)))                                 quoterExpr)                     quoteExpr   where     q_span = noAnnSrcSpan (locA q_span')-    quoterExpr = L q_span $! HsVar noExtField $! (L (la2na q_span) quoter)-    quoteExpr  = L q_span $! HsLit noComments $! HsString NoSourceText quote+    quoterExpr = L q_span $! HsVar noExtField $! (L (l2l q_span) quoter)+    quoteExpr  = L q_span $! HsLit noExtField $! HsString NoSourceText quote     quote_selector = case flavour of                        UntypedExpSplice  -> quoteExpName                        UntypedPatSplice  -> quotePatName@@ -475,18 +507,26 @@     pend_expr_splice name rn_splice         = (makePending UntypedExpSplice name rn_splice, HsUntypedSplice (HsUntypedSpliceNested name) rn_splice) -    run_expr_splice :: HsUntypedSplice GhcRn -> RnM (HsExpr GhcRn, FreeVars)     run_expr_splice rn_splice       = do { traceRn "rnUntypedSpliceExpr: untyped expression splice" empty-             -- Run it here, see Note [Running splices in the Renamer]-           ; (rn_expr, mod_finalizers) <--                runRnSplice UntypedExpSplice runMetaE ppr rn_splice-           ; (lexpr3, fvs) <- checkNoErrs (rnLExpr rn_expr)-             -- See Note [Delaying modFinalizers in untyped splices].-           ; let e =  flip HsUntypedSplice rn_splice-                    . HsUntypedSpliceTop (ThModFinalizers mod_finalizers)-                        <$> lexpr3-           ; return (gHsPar e, fvs)++           -- Run the splice here, see Note [Running splices in the Renamer]+           ; (expr_ps, mod_finalizers)+                <- runRnSplice UntypedExpSplice runMetaE ppr rn_splice+                -- mod_finalizers: See Note [Delaying modFinalizers in untyped splices].++           -- Rename the expanded expression+           ; (L l expr_rn, fvs) <- checkNoErrs (rnLExpr expr_ps)++           -- rn_splice :: HsUntypedSplice GhcRn is the original TH expression,+           --                                       before expansion+           -- expr_ps   :: LHsExpr GhcPs is the result of running the splice+           -- expr_rn   :: HsExpr GhcRn is the result of renaming ps_expr+           ; let res :: HsUntypedSpliceResult (HsExpr GhcRn)+                 res  = HsUntypedSpliceTop+                          { utsplice_result_finalizers = ThModFinalizers mod_finalizers+                          , utsplice_result            = expr_rn }+           ; return (gHsPar (L l (HsUntypedSplice res rn_splice)), fvs)            }  thSyntaxError :: THSyntaxError -> TcRnMessage@@ -741,6 +781,26 @@               -- Wrap the result of the quasi-quoter in parens so that we don't               -- lose the outermost location set by runQuasiQuote (#7918) +-- | Rename a splice type pattern. Much the same as `rnSplicePat`, but works with LHsType instead of LPat+rnSpliceTyPat :: HsUntypedSplice GhcPs -> RnM ( (HsUntypedSplice GhcRn, HsUntypedSpliceResult (LHsType GhcPs))+                                            , FreeVars)+rnSpliceTyPat splice+  = rnUntypedSpliceGen run_ty_pat_splice pend_ty_pat_splice splice+  where+    pend_ty_pat_splice name rn_splice+      = (makePending UntypedTypeSplice name rn_splice+        , (rn_splice, HsUntypedSpliceNested name)) -- HsType splice is nested and thus simply renamed++    run_ty_pat_splice rn_splice+      = do { traceRn "rnSpliceTyPat: untyped pattern splice" empty+           ; (ty, mod_finalizers) <-+                runRnSplice UntypedTypeSplice runMetaT ppr rn_splice+             -- See Note [Delaying modFinalizers in untyped splices].+           ; let t = HsUntypedSpliceTop (ThModFinalizers mod_finalizers) ty+           ; return ((rn_splice, t), emptyFVs) }+              -- Wrap the result of the quasi-quoter in parens so that we don't+              -- lose the outermost location set by runQuasiQuote (#7918)+ ---------------------- rnSpliceDecl :: SpliceDecl GhcPs -> RnM (SpliceDecl GhcRn, FreeVars) rnSpliceDecl (SpliceDecl _ (L loc splice) flg)@@ -875,6 +935,34 @@       = vcat [ text "--" <+> ppr loc <> colon <+> text "Splicing" <+> text sd              , gen ] +checkThLocalTyName :: Name -> RnM ()+checkThLocalTyName name+  | isUnboundName name   -- Do not report two errors for+  = return ()            --   $(not_in_scope args)++  | otherwise+  = do  { traceRn "checkThLocalTyName" (ppr name)+        ; mb_local_use <- getStageAndBindLevel name+        ; case mb_local_use of {+             Nothing -> return () ;  -- Not a locally-bound thing+             Just (top_lvl, bind_lvl, use_stage) ->+    do  { let use_lvl = thLevel use_stage+        -- We don't check the well stageness of name here.+        -- this would break test for #20969+        --+        -- Consequently there is no check&restiction for top level splices.+        -- But it's annoying anyway.+        --+        -- Therefore checkCrossStageLiftingTy shouldn't assume anything+        -- about bind_lvl and use_lvl relation.+        --+        -- ; checkWellStaged (StageCheckSplice name) bind_lvl use_lvl++        ; traceRn "checkThLocalTyName" (ppr name <+> ppr bind_lvl+                                                 <+> ppr use_stage+                                                 <+> ppr use_lvl)+        ; checkCrossStageLiftingTy top_lvl bind_lvl use_stage use_lvl name } } }+ checkThLocalName :: Name -> RnM () checkThLocalName name   | isUnboundName name   -- Do not report two errors for@@ -946,6 +1034,24 @@           -- Update the pending splices         ; ps <- readMutVar ps_var         ; writeMutVar ps_var (pend_splice : ps) }++checkCrossStageLiftingTy :: TopLevelFlag -> ThLevel -> ThStage -> ThLevel -> Name -> TcM ()+checkCrossStageLiftingTy top_lvl bind_lvl _use_stage use_lvl name+  | isTopLevel top_lvl+  = return ()++  -- There is no liftType (yet), so we could error, or more conservatively, just warn.+  --+  -- For now, we check here for both untyped and typed splices, as we don't create splices.+  | use_lvl > bind_lvl+  = addDiagnostic $ TcRnBadlyStagedType name bind_lvl use_lvl++  -- See comment in checkThLocalTyName: this can also happen.+  | bind_lvl < use_lvl+  = addDiagnostic $ TcRnBadlyStagedType name bind_lvl use_lvl++  | otherwise+  = return ()  {- Note [Keeping things alive for Template Haskell]
compiler/GHC/Rename/Splice.hs-boot view
@@ -2,12 +2,17 @@  import GHC.Hs import GHC.Tc.Utils.Monad+import GHC.Types.Name (Name) import GHC.Types.Name.Set   rnSpliceType :: HsUntypedSplice GhcPs -> RnM (HsType GhcRn, FreeVars) rnSplicePat  :: HsUntypedSplice GhcPs -> RnM ( (HsUntypedSplice GhcRn, HsUntypedSpliceResult (LPat GhcPs))                                              , FreeVars)+rnSpliceTyPat  :: HsUntypedSplice GhcPs -> RnM ( (HsUntypedSplice GhcRn, HsUntypedSpliceResult (LHsType GhcPs))+                                             , FreeVars) rnSpliceDecl :: SpliceDecl GhcPs -> RnM (SpliceDecl GhcRn, FreeVars)  rnTopSpliceDecls :: HsUntypedSplice GhcPs -> RnM ([LHsDecl GhcPs], FreeVars)++checkThLocalTyName :: Name -> RnM ()
compiler/GHC/Rename/Utils.hs view
@@ -1,6 +1,8 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE TypeFamilies     #-} {-# LANGUAGE GADTs            #-}+{-# LANGUAGE RecordWildCards  #-}+{-# LANGUAGE TupleSections    #-}  {- @@ -15,15 +17,19 @@         addFvRn, mapFvRn, mapMaybeFvRn,         warnUnusedMatches, warnUnusedTypePatterns,         warnUnusedTopBinds, warnUnusedLocalBinds,-        warnForallIdentifier,+        DeprecationWarnings(..), warnIfDeprecated,         checkUnusedRecordWildcard,         badQualBndrErr, typeAppErr, badFieldConErr,-        wrapGenSpan, genHsVar, genLHsVar, genHsApp, genHsApps, genLHsApp,-        genAppType,+        wrapGenSpan, genHsVar, genLHsVar, genHsApp, genHsApps, genHsApps', genHsExpApps,+        genLHsApp, genAppType,         genLHsLit, genHsIntegralLit, genHsTyLit, genSimpleConPat,         genVarPat, genWildPat,         genSimpleFunBind, genFunBind, +        genHsLamDoExp, genHsCaseAltDoExp, genSimpleMatch,++        genHsLet,+         newLocalBndrRn, newLocalBndrsRn,          bindLocalNames, bindLocalNamesFV, delLocalNames,@@ -33,7 +39,7 @@         checkInferredVars,         noNestedForallsContextsErr, addNoNestedForallsContextsErr, -        isIrrefutableHsPatRn+        isIrrefutableHsPat )  where@@ -56,17 +62,25 @@ import GHC.Types.SourceText ( SourceText(..), IntegralLit ) import GHC.Utils.Outputable import GHC.Utils.Misc+import GHC.Unit.Module.ModIface+import GHC.Utils.Panic import GHC.Types.Basic import GHC.Data.List.SetOps ( removeDupsOn ) import GHC.Data.Maybe ( whenIsJust ) import GHC.Driver.DynFlags import GHC.Data.FastString+import GHC.Data.Bag ( mapBagM, headMaybe ) import Control.Monad import GHC.Settings.Constants ( mAX_TUPLE_SIZE, mAX_CTUPLE_SIZE )+import GHC.Unit.Module+import GHC.Unit.Module.Warnings  ( WarningTxt(..) )+import GHC.Iface.Load import qualified GHC.LanguageExtensions as LangExt  import qualified Data.List as List import qualified Data.List.NonEmpty as NE+import Data.Foldable+import Data.Maybe   {-@@ -362,7 +376,7 @@                             _        -> False              -- Don't warn about unused bindings with parents in              -- .hs-boot files, as you are sometimes required to give-             -- unused bindings (trac #3449).+             -- unused bindings (#3449).              -- HOWEVER, in a signature file, you are never obligated to put a              -- definition in the main text.  Thus, if you define something              -- and forget to export it, we really DO want to warn.@@ -375,14 +389,17 @@ -- -Wredundant-record-wildcards checkUnusedRecordWildcard :: SrcSpan                           -> FreeVars-                          -> Maybe [Name]+                          -> Maybe [ImplicitFieldBinders]                           -> RnM () checkUnusedRecordWildcard _ _ Nothing     = return ()-checkUnusedRecordWildcard loc _ (Just []) =-  -- Add a new warning if the .. pattern binds no variables-  setSrcSpan loc $ warnRedundantRecordWildcard-checkUnusedRecordWildcard loc fvs (Just dotdot_names) =-  setSrcSpan loc $ warnUnusedRecordWildcard dotdot_names fvs+checkUnusedRecordWildcard loc fvs (Just dotdot_fields_binders)+  = setSrcSpan loc $ case concatMap implFlBndr_binders dotdot_fields_binders of+            -- Add a new warning if the .. pattern binds no variables+      [] -> warnRedundantRecordWildcard+      dotdot_names+        -> do+          warnUnusedRecordWildcard dotdot_names fvs+          deprecateUsedRecordWildcard dotdot_fields_binders fvs   -- | Produce a warning when the `..` pattern binds no new@@ -415,6 +432,33 @@   traceRn "warnUnused" (ppr ns $$ ppr used_names $$ ppr used)   warnIf (null used) (TcRnUnusedRecordWildcard ns) +-- | Emit a deprecation message whenever one of the implicit record wild+--   card field binders was used in FreeVars.+--+-- @+--   module A where+--   data P = P { x :: Int, y :: Int }+--   {-# DEPRECATED x, y "depr msg" #-}+--+--   module B where+--   import A+--   foo (P{..}) = x+-- @+--+-- Even though both `x` and `y` have deprecations, only `x`+-- will be deprecated since only its implicit variable is used in the RHS.+deprecateUsedRecordWildcard :: [ImplicitFieldBinders]+                            -> FreeVars -> RnM ()+deprecateUsedRecordWildcard dotdot_fields_binders fvs+  = mapM_ depr_field_binders dotdot_fields_binders+  where+    depr_field_binders (ImplicitFieldBinders {..})+      = when (mkFVs implFlBndr_binders `intersectsFVs` fvs) $ do+          env <- getGlobalRdrEnv+          let gre = fromJust $ lookupGRE_Name env implFlBndr_field+                -- Must be in the env since it was instantiated+                -- in the implicit binders+          warnIfDeprecated AllDeprecationWarnings [gre]   warnUnusedLocalBinds, warnUnusedMatches, warnUnusedTypePatterns@@ -427,13 +471,109 @@ check_unused prov bound_names used_names   = warnUnused prov (filterOut (`elemNameSet` used_names) bound_names) -warnForallIdentifier :: LocatedN RdrName -> RnM ()-warnForallIdentifier (L l rdr_name@(Unqual occ))-  | isKw (fsLit "forall") || isKw (fsLit "∀")-  = addDiagnosticAt (locA l) (TcRnForallIdentifier rdr_name)-  where isKw = (occNameFS occ ==)-warnForallIdentifier _ = return ()+{-+************************************************************************+*                                                                      *+\subsection{Custom deprecations utility functions}+*                                                                      *+************************************************************************ +Note [Handling of deprecations]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+* We report deprecations at each *occurrence* of the deprecated thing+  (see #5867 and #4879)++* We do not report deprecations for locally-defined names. For a+  start, we may be exporting a deprecated thing. Also we may use a+  deprecated thing in the defn of another deprecated things.  We may+  even use a deprecated thing in the defn of a non-deprecated thing,+  when changing a module's interface.++* We also report deprecations at export sites, but only for names+  deprecated with export deprecations (since those are not transitive as opposed+  to regular name deprecations and are only reported at the importing module)++* addUsedGREs: we do not report deprecations for sub-binders:+     - the ".." completion for records+     - the ".." in an export item 'T(..)'+     - the things exported by a module export 'module M'+-}++-- | Whether to report deprecation warnings when registering a used GRE+--+-- There is no option to only emit declaration warnings since everywhere+-- we emit the declaration warnings we also emit export warnings+-- (See Note [Handling of deprecations] for details)+data DeprecationWarnings+  = NoDeprecationWarnings+  | ExportDeprecationWarnings+  | AllDeprecationWarnings++warnIfDeprecated :: DeprecationWarnings -> [GlobalRdrElt] -> RnM ()+warnIfDeprecated NoDeprecationWarnings _ = return ()+warnIfDeprecated opt gres = do+  this_mod <- getModule+  let external_gres+        = filterOut (nameIsLocalOrFrom this_mod . greName) gres+  mapM_ (\gre -> warnIfExportDeprecated gre >> maybeWarnDeclDepr gre) external_gres+  where+    maybeWarnDeclDepr = case opt of+      ExportDeprecationWarnings -> const $ return ()+      AllDeprecationWarnings    -> warnIfDeclDeprecated++warnIfDeclDeprecated :: GlobalRdrElt -> RnM ()+warnIfDeclDeprecated gre@(GRE { gre_imp = iss })+  | Just imp_spec <- headMaybe iss+  = do { dflags <- getDynFlags+       ; when (wopt_any_custom dflags) $+                   -- See Note [Handling of deprecations]+         do { iface <- loadInterfaceForName doc name+            ; case lookupImpDeclDeprec iface gre of+                Just deprText -> addDiagnostic $+                  TcRnPragmaWarning+                      PragmaWarningName+                        { pwarn_occname = occ+                        , pwarn_impmod  = importSpecModule imp_spec+                        , pwarn_declmod = definedMod }+                      deprText+                Nothing  -> return () } }+  | otherwise+  = return ()+  where+    occ = greOccName gre+    name = greName gre+    definedMod = moduleName $ assertPpr (isExternalName name) (ppr name) (nameModule name)+    doc = text "The name" <+> quotes (ppr occ) <+> text "is mentioned explicitly"++lookupImpDeclDeprec :: ModIface -> GlobalRdrElt -> Maybe (WarningTxt GhcRn)+lookupImpDeclDeprec iface gre+  -- Bleat if the thing, or its parent, is warn'd+  = mi_decl_warn_fn (mi_final_exts iface) (greOccName gre) `mplus`+    case greParent gre of+       ParentIs p -> mi_decl_warn_fn (mi_final_exts iface) (nameOccName p)+       NoParent   -> Nothing++warnIfExportDeprecated :: GlobalRdrElt -> RnM ()+warnIfExportDeprecated gre@(GRE { gre_imp = iss })+  = do { mod_warn_mbs <- mapBagM process_import_spec iss+       ; for_ (sequence mod_warn_mbs) $ mapM+           $ \(importing_mod, warn_txt) -> addDiagnostic $+             TcRnPragmaWarning+                PragmaWarningExport+                  { pwarn_occname = occ+                  , pwarn_impmod  = importing_mod }+                warn_txt }+  where+    occ = greOccName gre+    name = greName gre+    doc = text "The name" <+> quotes (ppr occ) <+> text "is mentioned explicitly"+    process_import_spec :: ImportSpec -> RnM (Maybe (ModuleName, WarningTxt GhcRn))+    process_import_spec is = do+      let mod = is_mod $ is_decl is+      iface <- loadInterfaceForModule doc mod+      let mb_warn_txt = mi_export_warn_fn (mi_final_exts iface) name+      return $ (moduleName mod, ) <$> mb_warn_txt+ ------------------------- --      Helpers warnUnusedGREs :: [GlobalRdrElt] -> RnM ()@@ -565,21 +705,29 @@  {- ********************************************************************* *                                                                      *-              Generating code for HsExpanded+              Generating code for ExpandedThingRn       See Note [Handling overloaded and rebindable constructs] *                                                                      * ********************************************************************* -} -wrapGenSpan :: a -> LocatedAn an a+wrapGenSpan :: (NoAnn an) => a -> LocatedAn an a -- Wrap something in a "generatedSrcSpan"--- See Note [Rebindable syntax and HsExpansion]+-- See Note [Rebindable syntax and XXExprGhcRn] wrapGenSpan x = L (noAnnSrcSpan generatedSrcSpan) x  genHsApps :: Name -> [LHsExpr GhcRn] -> HsExpr GhcRn genHsApps fun args = foldl genHsApp (genHsVar fun) args +-- | Keeps the span given to the 'Name' for the application head only+genHsApps' :: LocatedN Name -> [LHsExpr GhcRn] -> HsExpr GhcRn+genHsApps' (L _ fun) [] = genHsVar fun+genHsApps' (L loc fun) (arg:args) = foldl genHsApp (unLoc $ mkHsApp (L (l2l loc) $ genHsVar fun) arg) args++genHsExpApps :: HsExpr GhcRn -> [LHsExpr GhcRn] -> HsExpr GhcRn+genHsExpApps fun arg = foldl genHsApp fun arg+ genHsApp :: HsExpr GhcRn -> LHsExpr GhcRn -> HsExpr GhcRn-genHsApp fun arg = HsApp noAnn (wrapGenSpan fun) arg+genHsApp fun arg = HsApp noExtField (wrapGenSpan fun) arg  genLHsApp :: HsExpr GhcRn -> LHsExpr GhcRn -> LHsExpr GhcRn genLHsApp fun arg = wrapGenSpan (genHsApp fun arg)@@ -591,12 +739,12 @@ genHsVar nm = HsVar noExtField $ wrapGenSpan nm  genAppType :: HsExpr GhcRn -> HsType (NoGhcTc GhcRn) -> HsExpr GhcRn-genAppType expr ty = HsAppType noExtField (wrapGenSpan expr) noHsTok (mkEmptyWildCardBndrs (wrapGenSpan ty))+genAppType expr ty = HsAppType noExtField (wrapGenSpan expr) (mkEmptyWildCardBndrs (wrapGenSpan ty)) -genLHsLit :: HsLit GhcRn -> LocatedAn an (HsExpr GhcRn)-genLHsLit = wrapGenSpan . HsLit noAnn+genLHsLit :: (NoAnn an) => HsLit GhcRn -> LocatedAn an (HsExpr GhcRn)+genLHsLit = wrapGenSpan . HsLit noExtField -genHsIntegralLit :: IntegralLit -> LocatedAn an (HsExpr GhcRn)+genHsIntegralLit :: (NoAnn an) => IntegralLit -> LocatedAn an (HsExpr GhcRn) genHsIntegralLit = genLHsLit . HsInt noExtField  genHsTyLit :: FastString -> HsType GhcRn@@ -618,21 +766,61 @@ genSimpleFunBind :: Name -> [LPat GhcRn]                  -> LHsExpr GhcRn -> LHsBind GhcRn genSimpleFunBind fun pats expr-  = L gen $ genFunBind (L gen fun)-        [mkMatch (mkPrefixFunRhs (L gen fun)) pats expr+  = L genA $ genFunBind (L genN fun)+        [mkMatch (mkPrefixFunRhs (L genN fun)) pats expr                  emptyLocalBinds]   where-    gen = noAnnSrcSpan generatedSrcSpan+    genA :: SrcSpanAnnA+    genA = noAnnSrcSpan generatedSrcSpan +    genN :: SrcSpanAnnN+    genN = noAnnSrcSpan generatedSrcSpan+ genFunBind :: LocatedN Name -> [LMatch GhcRn (LHsExpr GhcRn)]            -> HsBind GhcRn genFunBind fn ms   = FunBind { fun_id = fn-            , fun_matches = mkMatchGroup (Generated SkipPmc) (wrapGenSpan ms)+            , fun_matches = mkMatchGroup (Generated OtherExpansion SkipPmc) (wrapGenSpan ms)             , fun_ext = emptyNameSet             } -isIrrefutableHsPatRn :: forall p. (OutputableBndrId p)-                  => DynFlags -> LPat (GhcPass p) -> Bool-isIrrefutableHsPatRn dflags =-    isIrrefutableHsPat (xopt LangExt.Strict dflags)+isIrrefutableHsPat :: forall p. (OutputableBndrId p) => DynFlags -> LPat (GhcPass p) -> Bool+isIrrefutableHsPat dflags =+    isIrrefutableHsPatHelper (xopt LangExt.Strict dflags)++genHsLet :: HsLocalBindsLR GhcRn GhcRn -> LHsExpr GhcRn -> HsExpr GhcRn+genHsLet bindings body = HsLet noExtField bindings body++genHsLamDoExp :: (IsPass p, XMG (GhcPass p) (LHsExpr (GhcPass p)) ~ Origin)+        => HsDoFlavour+        -> [LPat (GhcPass p)]+        -> LHsExpr (GhcPass p)+        -> LHsExpr (GhcPass p)+genHsLamDoExp doFlav pats body = mkHsPar (wrapGenSpan $ HsLam noAnn LamSingle matches)+  where+    matches = mkMatchGroup (doExpansionOrigin doFlav)+                           (wrapGenSpan [genSimpleMatch (StmtCtxt (HsDoStmt doFlav)) pats' body])+    pats' = map (parenthesizePat appPrec) pats+++genHsCaseAltDoExp :: (Anno (GRHS (GhcPass p) (LocatedA (body (GhcPass p))))+                     ~ EpAnnCO,+                 Anno (Match (GhcPass p) (LocatedA (body (GhcPass p))))+                        ~ SrcSpanAnnA)+            => HsDoFlavour -> LPat (GhcPass p) -> (LocatedA (body (GhcPass p)))+            -> LMatch (GhcPass p) (LocatedA (body (GhcPass p)))+genHsCaseAltDoExp doFlav pat expr+  = genSimpleMatch (StmtCtxt (HsDoStmt doFlav)) [pat] expr+++genSimpleMatch :: (Anno (Match (GhcPass p) (LocatedA (body (GhcPass p))))+                        ~ SrcSpanAnnA,+                  Anno (GRHS (GhcPass p) (LocatedA (body (GhcPass p))))+                        ~ EpAnnCO)+              => HsMatchContext (LIdP (NoGhcTc (GhcPass p)))+              -> [LPat (GhcPass p)] -> LocatedA (body (GhcPass p))+              -> LMatch (GhcPass p) (LocatedA (body (GhcPass p)))+genSimpleMatch ctxt pats rhs+  = wrapGenSpan $+    Match { m_ext = noAnn, m_ctxt = ctxt, m_pats = pats+          , m_grhss = unguardedGRHSs generatedSrcSpan rhs noAnn }
compiler/GHC/Runtime/Eval.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE BangPatterns #-} {-# LANGUAGE RecordWildCards #-}  {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}@@ -80,7 +79,8 @@ import GHC.Tc.Types.Constraint import GHC.Tc.Types.Origin -import GHC.Builtin.Names ( toDynName, pretendNameIsInScope )+import GHC.Builtin.Names ( toDynName )+import GHC.Builtin.Types ( pretendNameIsInScope )  import GHC.Data.Maybe import GHC.Data.FastString@@ -130,7 +130,6 @@ import Control.Monad.Catch as MC import Data.Array import Data.Dynamic-import Data.Either import Data.IntMap (IntMap) import qualified Data.IntMap as IntMap import Data.List (find,intercalate)@@ -325,14 +324,14 @@   | otherwise              = not_tracing  where   tracing-    | EvalBreak is_exception apStack_ref ix mod_name resume_ctxt _ccs <- status-    , not is_exception+    | EvalBreak apStack_ref maybe_break resume_ctxt _ccs <- status+    , Just (EvalBreakpoint ix mod_name) <- maybe_break     = do        hsc_env <- getSession        let interp = hscInterp hsc_env        let dflags = hsc_dflags hsc_env        let hmi = expectJust "handleRunStatus" $-                   lookupHpt (hsc_HPT hsc_env) (mkModuleName mod_name)+                 lookupHpt (hsc_HPT hsc_env) (mkModuleName mod_name)            modl = mi_module (hm_iface hmi)            breaks = getModBreaks hmi @@ -357,17 +356,13 @@    not_tracing     -- Hit a breakpoint-    | EvalBreak is_exception apStack_ref ix mod_name resume_ctxt ccs <- status+    | EvalBreak apStack_ref maybe_break resume_ctxt ccs <- status     = do          hsc_env <- getSession          let interp = hscInterp hsc_env          resume_ctxt_fhv <- liftIO $ mkFinalizedHValue interp resume_ctxt          apStack_fhv <- liftIO $ mkFinalizedHValue interp apStack_ref-         let hmi = expectJust "handleRunStatus" $-                     lookupHpt (hsc_HPT hsc_env) (mkModuleName mod_name)-             modl = mi_module (hm_iface hmi)-             bp | is_exception = Nothing-                | otherwise = Just (BreakInfo modl ix)+         let bp = evalBreakInfo (hsc_HPT hsc_env) <$> maybe_break          (hsc_env1, names, span, decl) <- liftIO $            bindLocalsAtBreakpoint hsc_env apStack_fhv bp          let@@ -400,12 +395,7 @@     | EvalComplete alloc (EvalException e) <- status     = return (ExecComplete (Left (fromSerializableException e)) alloc) -#if __GLASGOW_HASKELL__ <= 810-    | otherwise-    = panic "not_tracing" -- actually exhaustive, but GHC can't tell-#endif - resumeExec :: GhcMonad m => (SrcSpan->Bool) -> SingleStep -> Maybe Int            -> m ExecResult resumeExec canLogSpan step mbCnt@@ -624,10 +614,8 @@         -- saved/restored, but not the linker state.  See #1743, test break026.    mkNewId :: OccName -> Type -> Id -> IO Id    mkNewId occ ty old_id-     = do { name <- newInteractiveBinder hsc_env (mkVarOccFS (occNameFS occ)) (getSrcSpan old_id)-              -- NB: use variable namespace.-              -- Don't use record field namespaces, lest we cause #25109.-          ; return $ Id.mkVanillaGlobalWithInfo name ty (idInfo old_id) }+     = do { name <- newInteractiveBinder hsc_env occ (getSrcSpan old_id)+          ; return (Id.mkVanillaGlobalWithInfo name ty (idInfo old_id)) }     newTyVars :: UniqSupply -> [TcTyVar] -> Subst      -- Similarly, clone the type variables mentioned in the types@@ -819,7 +807,7 @@ findGlobalRdrEnv hsc_env imports   = do { idecls_env <- hscRnImportDecls hsc_env idecls                     -- This call also loads any orphan modules-       ; return $ case partitionEithers (map mkEnv imods) of+       ; return $ case partitionWith mkEnv imods of          (err : _, _)     -> Left err          ([], imods_env0) ->             -- Need to rehydrate the 'GlobalRdrEnv' to recover the 'GREInfo's.@@ -1253,7 +1241,7 @@   parsed_expr <- parseExpr expr   -- > Data.Dynamic.toDyn expr   let loc = getLoc parsed_expr-      to_dyn_expr = mkHsApp (L loc . HsVar noExtField . L (la2na loc) $ getRdrName toDynName)+      to_dyn_expr = mkHsApp (L loc . HsVar noExtField . L (l2l loc) $ getRdrName toDynName)                             parsed_expr   hval <- compileParsedExpr to_dyn_expr   return (unsafeCoerce hval :: Dynamic)
compiler/GHC/Runtime/Heap/Inspect.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE BangPatterns, ScopedTypeVariables, MagicHash #-}+{-# LANGUAGE MagicHash #-}  ----------------------------------------------------------------------------- --@@ -60,7 +60,6 @@ import GHC.Driver.Ppr import GHC.Utils.Outputable as Ppr import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Char import GHC.Exts.Heap import GHC.Runtime.Heap.Layout ( roundUpTo )@@ -889,13 +888,13 @@            (ptr_i, arr_i, terms1) <- go ptr_i arr_i tys            return (ptr_i, arr_i, unboxedTupleTerm ty terms0 : terms1)       | otherwise-      = case typePrimRepArgs ty of-          rep_ty :| [] ->  do+      = case typePrimRep ty of+          [rep_ty] -> do             (ptr_i, arr_i, term0)  <- go_rep ptr_i arr_i ty rep_ty             (ptr_i, arr_i, terms1) <- go ptr_i arr_i tys             return (ptr_i, arr_i, term0 : terms1)-          rep_ty :| rep_tys -> do-           (ptr_i, arr_i, terms0) <- go_unary_types ptr_i arr_i (rep_ty:rep_tys)+          rep_tys -> do+           (ptr_i, arr_i, terms0) <- go_unary_types ptr_i arr_i rep_tys            (ptr_i, arr_i, terms1) <- go ptr_i arr_i tys            return (ptr_i, arr_i, unboxedTupleTerm ty terms0 : terms1) 
compiler/GHC/Runtime/Interpreter.hs view
@@ -1,10 +1,6 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE BangPatterns #-} {-# LANGUAGE RecordWildCards #-}-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE TupleSections #-} {-# LANGUAGE LambdaCase #-}-{-# LANGUAGE RankNTypes #-}  -- | Interacting with the iserv interpreter, whether it is running on an -- external process or in the current process.@@ -32,13 +28,13 @@   , getClosure   , getModBreaks   , seqHValue+  , evalBreakInfo   , interpreterDynamic   , interpreterProfiled    -- * The object-code linker   , initObjLinker   , lookupSymbol-  , lookupSymbolInDLL   , lookupClosure   , loadDLL   , loadArchive@@ -93,7 +89,6 @@ import GHC.Utils.Exception as Ex import GHC.Utils.Outputable(brackets, ppr, showSDocUnsafe) import GHC.Utils.Fingerprint-import GHC.Utils.Misc  import GHC.Unit.Module import GHC.Unit.Module.ModIface@@ -110,9 +105,7 @@ import Control.Monad.IO.Class import Control.Monad.Catch as MC (mask) import Data.Binary-import Data.Binary.Put import Data.ByteString (ByteString)-import qualified Data.ByteString.Lazy as LB import Data.Array ((!)) import Data.IORef import Foreign hiding (void)@@ -120,7 +113,6 @@ import GHC.Stack.CCS (CostCentre,CostCentreStack) import System.Directory import System.Process-import GHC.Conc (pseq, par)  {- Note [Remote GHCi]    ~~~~~~~~~~~~~~~~~~@@ -159,22 +151,22 @@   - implementation of Template Haskell (GHCi.TH)   - a few other things needed to run interpreted code -- top-level iserv directory, containing the code for the external-  server. This is a fairly simple wrapper, most of the functionality+- top-level iserv directory, containing the codefor the external+  server.  This is a fairly simple wrapper, most of the functionality   is provided by modules in libraries/ghci.  - This module which provides the interface to the server used   by the rest of GHC. -GHC works with and without -fexternal-interpreter. With the flag, all-interpreted code is run by the iserv binary. Without the flag,+GHC works with and without -fexternal-interpreter.  With the flag, all+interpreted code is run by the iserv binary.  Without the flag, interpreted code is run in the same process as GHC.  Things that do not work with -fexternal-interpreter ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~  dynCompileExpr cannot work, because we have no way to run code of an-unknown type in the remote process. This API fails with an error+unknown type in the remote process.  This API fails with an error message if it is used with -fexternal-interpreter.  Other Notes on Remote GHCi@@ -314,7 +306,7 @@   -> IO (EvalStatus_ [ForeignHValue] [HValueRef]) handleEvalStatus interp status =   case status of-    EvalBreak a b c d e f -> return (EvalBreak a b c d e f)+    EvalBreak a b c d -> return (EvalBreak a b c d)     EvalComplete alloc res ->       EvalComplete alloc <$> addFinalizer res  where@@ -353,19 +345,7 @@ -- | Create a set of BCOs that may be mutually recursive. createBCOs :: Interp -> [ResolvedBCO] -> IO [HValueRef] createBCOs interp rbcos = do-  -- Serializing ResolvedBCO is expensive, so we do it in parallel-  interpCmd interp (CreateBCOs puts)- where-  puts = parMap doChunk (chunkList 100 rbcos)--  -- make sure we force the whole lazy ByteString-  doChunk c = pseq (LB.length bs) bs-    where bs = runPut (put c)--  -- We don't have the parallel package, so roll our own simple parMap-  parMap _ [] = []-  parMap f (x:xs) = fx `par` (fxs `pseq` (fx : fxs))-    where fx = f x; fxs = parMap f xs+  interpCmd interp (CreateBCOs rbcos)  addSptEntry :: Interp -> Fingerprint -> ForeignHValue -> IO () addSptEntry interp fpr ref =@@ -414,19 +394,24 @@     status <- interpCmd interp (Seq hval)     handleSeqHValueStatus interp unit_env status +evalBreakInfo :: HomePackageTable -> EvalBreakpoint -> BreakInfo+evalBreakInfo hpt (EvalBreakpoint ix mod_name) =+  BreakInfo modl ix+  where+    modl = mi_module $+           hm_iface $+           expectJust "evalBreakInfo" $+           lookupHpt hpt (mkModuleName mod_name)+ -- | Process the result of a Seq or ResumeSeq message.             #2950 handleSeqHValueStatus :: Interp -> UnitEnv -> EvalStatus () -> IO (EvalResult ()) handleSeqHValueStatus interp unit_env eval_status =   case eval_status of-    (EvalBreak is_exception _ ix mod_name resume_ctxt _) -> do+    (EvalBreak _ maybe_break resume_ctxt _) -> do       -- A breakpoint was hit; inform the user and tell them       -- which breakpoint was hit.       resume_ctxt_fhv <- liftIO $ mkFinalizedHValue interp resume_ctxt-      let hmi = expectJust "handleRunStatus" $-                  lookupHpt (ue_hpt unit_env) (mkModuleName mod_name)-          modl = mi_module (hm_iface hmi)-          bp | is_exception = Nothing-             | otherwise = Just (BreakInfo modl ix)+      let bp = evalBreakInfo (ue_hpt unit_env) <$> maybe_break           sdocBpLoc = brackets . ppr . getSeqBpSpan       putStrLn ("*** Ignoring breakpoint " ++             (showSDocUnsafe $ sdocBpLoc bp))@@ -466,7 +451,7 @@       -- making cross-process LookupSymbol calls, so I added a GHC-side       -- cache which sped things up quite a lot.  We have to be careful       -- to purge this cache when unloading code though.-      cache <- readMVar (interpLookupSymbolCache interp)+      cache <- readMVar (instLookupSymbolCache inst)       case lookupUFM cache str of         Just p -> return (Just p)         Nothing -> do@@ -477,72 +462,35 @@             Just r -> do               let p        = fromRemotePtr r                   cache'   = addToUFM cache str p-              modifyMVar_ (interpLookupSymbolCache interp) (const (pure cache'))+              modifyMVar_ (instLookupSymbolCache inst) (const (pure cache'))               return (Just p)      ExtJS {} -> pprPanic "lookupSymbol not supported by the JS interpreter" (ppr str) -lookupSymbolInDLL :: Interp -> RemotePtr LoadedDLL -> FastString -> IO (Maybe (Ptr ()))-lookupSymbolInDLL interp dll str = withSymbolCache interp str $-  case interpInstance interp of-#if defined(HAVE_INTERNAL_INTERPRETER)-    InternalInterp -> fmap fromRemotePtr <$> run (LookupSymbolInDLL dll (unpackFS str))-#endif-    ExternalInterp ext -> case ext of-      ExtIServ i -> withIServ i $ \inst -> fmap fromRemotePtr <$> do-        uninterruptibleMask_ $-          sendMessage inst (LookupSymbolInDLL dll (unpackFS str))-      ExtJS {} -> pprPanic "lookupSymbol not supported by the JS interpreter" (ppr str)- lookupClosure :: Interp -> String -> IO (Maybe HValueRef) lookupClosure interp str =   interpCmd interp (LookupClosure str) --- | 'withSymbolCache' tries to find a symbol in the 'interpLookupSymbolCache'--- which maps symbols to the address where they are loaded.--- When there's a cache hit we simply return the cached address, when there is--- a miss we run the action which determines the symbol's address and populate--- the cache with the answer.-withSymbolCache :: Interp-                -> FastString-                -- ^ The symbol we are looking up in the cache-                -> IO (Maybe (Ptr ()))-                -- ^ An action which determines the address of the symbol we-                -- are looking up in the cache, which is run if there is a-                -- cache miss. The result will be cached.-                -> IO (Maybe (Ptr ()))-withSymbolCache interp str determine_addr = do--  -- Profiling of GHCi showed a lot of time and allocation spent-  -- making cross-process LookupSymbol calls, so I added a GHC-side-  -- cache which sped things up quite a lot. We have to be careful-  -- to purge this cache when unloading code though.-  ---  -- The analysis in #23415 further showed this cache should also benefit the-  -- internal interpreter's loading times, and needn't be used by the external-  -- interpreter only.-  cache <- readMVar (interpLookupSymbolCache interp)-  case lookupUFM cache str of-    Just p -> return (Just p)-    Nothing -> do--      maddr <- determine_addr-      case maddr of-        Nothing -> return Nothing-        Just p -> do-          let upd_cache cache' = addToUFM cache' str p-          modifyMVar_ (interpLookupSymbolCache interp) (pure . upd_cache)-          return (Just p)- purgeLookupSymbolCache :: Interp -> IO ()-purgeLookupSymbolCache interp = modifyMVar_ (interpLookupSymbolCache interp) (const (pure emptyUFM))+purgeLookupSymbolCache interp = case interpInstance interp of+#if defined(HAVE_INTERNAL_INTERPRETER)+  InternalInterp -> pure ()+#endif+  ExternalInterp ext -> withExtInterpMaybe ext $ \case+    Nothing   -> pure () -- interpreter stopped, nothing to do+    Just inst -> modifyMVar_ (instLookupSymbolCache inst) (const (pure emptyUFM))  -- | loadDLL loads a dynamic library using the OS's native linker -- (i.e. dlopen() on Unix, LoadLibrary() on Windows).  It takes either -- an absolute pathname to the file, or a relative filename -- (e.g. "libfoo.so" or "foo.dll").  In the latter case, loadDLL -- searches the standard locations for the appropriate library.-loadDLL :: Interp -> String -> IO (Either String (RemotePtr LoadedDLL))+--+-- Returns:+--+-- Nothing      => success+-- Just err_msg => failure+loadDLL :: Interp -> String -> IO (Maybe String) loadDLL interp str = interpCmd interp (LoadDLL str)  loadArchive :: Interp -> String -> IO ()@@ -601,9 +549,11 @@                   }    pending_frees <- newMVar []+  lookup_cache  <- newMVar emptyUFM   let inst = ExtInterpInstance         { instProcess           = process         , instPendingFrees      = pending_frees+        , instLookupSymbolCache = lookup_cache         , instExtra             = ()         }   pure inst
compiler/GHC/Runtime/Interpreter/JS.hs view
@@ -41,6 +41,7 @@ import GHC.Utils.Error (logInfo) import GHC.Utils.Outputable (text) import GHC.Data.FastString+import GHC.Types.Unique.FM  import Control.Concurrent import Control.Monad@@ -177,12 +178,26 @@         }    pending_frees <- newMVar []+  lookup_cache  <- newMVar emptyUFM   let inst = ExtInterpInstance         { instProcess           = proc         , instPendingFrees      = pending_frees+        , instLookupSymbolCache = lookup_cache         , instExtra             = extra         } +  -- TODO: to support incremental linking of wasm modules (e.g. produced from C+  -- sources), we should:+  --+  -- 1. link the emcc rts without trimming dead code as we don't know what might+  -- be needed later by the Wasm modules we will dynamically load (cf+  -- -sMAIN_MODULE).+  -- 2. make the RUN_SERVER command wait for the emcc rts to be loaded.+  -- 3. link wasm modules with -sSIDE_MODULE+  -- 4. add a new command to load side modules with Emscripten's dlopen+  --+  -- cf https://emscripten.org/docs/compiling/Dynamic-Linking.html+   -- link rts and its deps   jsLinkRts logger tmpfs tmp_dir codegen_cfg unit_env inst @@ -210,22 +225,26 @@         , lcForeignRefs     = False -- we don't need foreign references         , lcNoJSExecutables = True  -- we don't need executables         , lcNoHsMain        = True  -- nor HsMain+        , lcForceEmccRts    = False -- nor the emcc rts+        , lcLinkCsources    = False -- we know that there are no C sources to load for the RTS         }    -- link the RTS and its dependencies (things it uses from `base`, etc.)   let link_spec = LinkSpec-        { lks_unit_ids        = [rtsUnitId, baseUnitId, primUnitId]-        , lks_obj_files       = mempty+        { lks_unit_ids        = [rtsUnitId, ghcInternalUnitId, primUnitId]         , lks_obj_root_filter = const False         , lks_extra_roots     = mempty-        , lks_extra_js        = mempty+        , lks_objs_hs         = mempty+        , lks_objs_js         = mempty+        , lks_objs_cc         = mempty         }    let finder_opts  = instFinderOpts (instExtra inst)       finder_cache = instFinderCache (instExtra inst) -  link_plan <- computeLinkDependencies cfg unit_env link_spec finder_opts finder_cache-  jsLinkPlan logger tmpfs tmp_dir link_cfg cfg inst link_plan+  ar_cache <- newArchiveCache+  link_plan <- computeLinkDependencies cfg unit_env link_spec finder_opts finder_cache ar_cache+  jsLinkPlan logger tmpfs tmp_dir ar_cache link_cfg cfg inst link_plan  -- | Link JS interpreter jsLinkInterp :: Logger -> TmpFs -> TempDir -> StgToJSConfig -> UnitEnv -> ExtInterpInstance JSInterpExtra -> IO ()@@ -238,6 +257,8 @@         , lcForeignRefs     = False -- we don't need foreign references         , lcNoJSExecutables = True  -- we don't need executables         , lcNoHsMain        = True  -- nor HsMain+        , lcForceEmccRts    = False -- nor the emcc rts+        , lcLinkCsources    = True  -- enable C sources, if any         }    let is_root _ = True -- FIXME: we shouldn't consider every function as a root@@ -255,18 +276,19 @@   -- link the interpreter and its dependencies   let link_spec = LinkSpec         { lks_unit_ids        = units-        , lks_obj_files       = mempty         , lks_obj_root_filter = is_root         , lks_extra_roots     = root_deps-        , lks_extra_js        = mempty+        , lks_objs_hs         = mempty+        , lks_objs_js         = mempty+        , lks_objs_cc         = mempty         }    let finder_cache = instFinderCache (instExtra inst)       finder_opts  = instFinderOpts (instExtra inst) -  link_plan <- computeLinkDependencies cfg unit_env link_spec finder_opts finder_cache--  jsLinkPlan logger tmpfs tmp_dir link_cfg cfg inst link_plan+  ar_cache <- newArchiveCache+  link_plan <- computeLinkDependencies cfg unit_env link_spec finder_opts finder_cache ar_cache+  jsLinkPlan logger tmpfs tmp_dir ar_cache link_cfg cfg inst link_plan   -- | Link object files@@ -279,6 +301,8 @@         , lcForeignRefs     = False -- we don't need foreign references         , lcNoJSExecutables = True  -- we don't need executables         , lcNoHsMain        = True  -- nor HsMain+        , lcForceEmccRts    = False -- nor the emcc rts+        , lcLinkCsources    = True  -- enable C sources, if any         }    let units = preloadUnits (ue_units unit_env)@@ -287,19 +311,19 @@   -- compute dependencies   let link_spec = LinkSpec         { lks_unit_ids        = units-        , lks_obj_files       = fmap ObjFile objs         , lks_obj_root_filter = is_root         , lks_extra_roots     = mempty-        , lks_extra_js        = mempty+        , lks_objs_hs         = objs+        , lks_objs_js         = mempty+        , lks_objs_cc         = mempty         }    let finder_opts  = instFinderOpts (instExtra inst)       finder_cache = instFinderCache (instExtra inst) -  link_plan <- computeLinkDependencies cfg unit_env link_spec finder_opts finder_cache--  -- link-  jsLinkPlan logger tmpfs tmp_dir link_cfg cfg inst link_plan+  ar_cache <- newArchiveCache+  link_plan <- computeLinkDependencies cfg unit_env link_spec finder_opts finder_cache ar_cache+  jsLinkPlan logger tmpfs tmp_dir ar_cache link_cfg cfg inst link_plan   @@ -314,8 +338,8 @@ -- | Link the given link plan -- -- Perform incremental linking by removing what is already linked from the plan-jsLinkPlan :: Logger -> TmpFs -> TempDir -> JSLinkConfig -> StgToJSConfig -> ExtInterpInstance JSInterpExtra -> LinkPlan -> IO ()-jsLinkPlan logger tmpfs tmp_dir link_cfg cfg inst link_plan = do+jsLinkPlan :: Logger -> TmpFs -> TempDir -> ArchiveCache -> JSLinkConfig -> StgToJSConfig -> ExtInterpInstance JSInterpExtra -> LinkPlan -> IO ()+jsLinkPlan logger tmpfs tmp_dir ar_cache link_cfg cfg inst link_plan = do   ----------------------------------------------------------------   -- Get already linked stuff and compute incremental plan   ----------------------------------------------------------------@@ -330,7 +354,7 @@   ----------------------------------------------------------------    tmp_out <- newTempSubDir logger tmpfs tmp_dir-  void $ jsLink link_cfg cfg logger tmp_out diff_plan+  void $ jsLink link_cfg cfg logger tmpfs ar_cache tmp_out diff_plan    -- Code has been linked into the following files:   --  - generated rts from tmp_out/rts.js (depends on link options)
compiler/GHC/Settings/IO.hs view
@@ -16,11 +16,9 @@ import GHC.Utils.Fingerprint import GHC.Platform import GHC.Utils.Panic-import GHC.ResponseFile import GHC.Settings import GHC.SysTools.BaseDir -import Data.Char import Control.Monad.Trans.Except import Control.Monad.IO.Class import qualified Data.Map as Map@@ -40,7 +38,7 @@   let installed :: FilePath -> FilePath       installed file = top_dir </> file       libexec :: FilePath -> FilePath-      libexec file = top_dir </> "bin" </> file+      libexec file = top_dir </> ".." </> "bin" </> file       settingsFile = installed "settings"        readFileSafe :: FilePath -> ExceptT SettingsError m String@@ -74,30 +72,29 @@   -- just partially applying those functions and throwing 'Left's; they're   -- written in a very portable style to keep ghc-boot light.   let getSetting key = either pgmError pure $-        -- Escape the 'top_dir', to make sure we don't accidentally introduce an-        -- unescaped space-        getRawFilePathSetting (escapeArg top_dir) settingsFile mySettings key+        getRawFilePathSetting top_dir settingsFile mySettings key       getToolSetting :: String -> ExceptT SettingsError m String-        -- Escape the 'mtool_dir', to make sure we don't accidentally introduce-        -- an unescaped space-      getToolSetting key = expandToolDir useInplaceMinGW (fmap escapeArg mtool_dir) <$> getSetting key+      getToolSetting key = expandToolDir useInplaceMinGW mtool_dir <$> getSetting key   targetPlatformString <- getSetting "target platform string"   cc_prog <- getToolSetting "C compiler command"   cxx_prog <- getToolSetting "C++ compiler command"   cc_args_str <- getToolSetting "C compiler flags"   cxx_args_str <- getToolSetting "C++ compiler flags"   gccSupportsNoPie <- getBooleanSetting "C compiler supports -no-pie"-  cpp_prog <- getToolSetting "Haskell CPP command"-  cpp_args_str <- getToolSetting "Haskell CPP flags"+  cpp_prog <- getToolSetting "CPP command"+  cpp_args_str <- getToolSetting "CPP flags"+  hs_cpp_prog <- getToolSetting "Haskell CPP command"+  hs_cpp_args_str <- getToolSetting "Haskell CPP flags"    platform <- either pgmError pure $ getTargetPlatform settingsFile mySettings    let unreg_cc_args = if platformUnregisterised platform                       then ["-DNO_REGS", "-DUSE_MINIINTERPRETER"]                       else []-      cpp_args = map Option (unescapeArgs cpp_args_str)-      cc_args  = unescapeArgs cc_args_str ++ unreg_cc_args-      cxx_args = unescapeArgs cxx_args_str+      cpp_args    = map Option (words cpp_args_str)+      hs_cpp_args = map Option (words hs_cpp_args_str)+      cc_args  = words cc_args_str ++ unreg_cc_args+      cxx_args = words cxx_args_str        -- The extra flags we need to pass gcc when we invoke it to compile .hc code.       --@@ -110,8 +107,8 @@    ldSupportsCompactUnwind <- getBooleanSetting "ld supports compact unwind"   ldSupportsFilelist      <- getBooleanSetting "ld supports filelist"-  ldSupportsResponseFiles <- getBooleanSetting "ld supports response files"   ldSupportsSingleModule  <- getBooleanSetting "ld supports single module"+  mergeObjsSupportsResponseFiles <- getBooleanSetting "Merge objects supports response files"   ldIsGnuLd               <- getBooleanSetting "ld is GNU ld"   arSupportsDashL         <- getBooleanSetting "ar supports -L" @@ -129,12 +126,6 @@   install_name_tool_path <- getToolSetting "install_name_tool command"   ranlib_path <- getToolSetting "ranlib command" -  touch_path <- getToolSetting "touch command"--  mkdll_prog <- getToolSetting "dllwrap command"-  let mkdll_args = []--  -- cpp is derived from gcc on all platforms   -- HACK, see setPgmP below. We keep 'words' here to remember to fix   -- Config.hs one day. @@ -144,19 +135,19 @@   let   as_prog  = cc_prog         as_args  = map Option cc_args         ld_prog  = cc_prog-        ld_args  = map Option (cc_args ++ unescapeArgs cc_link_args_str)+        ld_args  = map Option (cc_args ++ words cc_link_args_str)   ld_r_prog <- getToolSetting "Merge objects command"   ld_r_args <- getToolSetting "Merge objects flags"   let ld_r         | null ld_r_prog = Nothing-        | otherwise      = Just (ld_r_prog, map Option $ unescapeArgs ld_r_args)+        | otherwise      = Just (ld_r_prog, map Option $ words ld_r_args)    llvmTarget <- getSetting "LLVM target"    -- We just assume on command line   lc_prog <- getSetting "LLVM llc command"   lo_prog <- getSetting "LLVM opt command"-  lcc_prog <- getSetting "LLVM clang command"+  las_prog <- getSetting "LLVM llvm-as command"    let iserv_prog = libexec "ghc-iserv" @@ -180,23 +171,22 @@     , sToolSettings = ToolSettings       { toolSettings_ldSupportsCompactUnwind = ldSupportsCompactUnwind       , toolSettings_ldSupportsFilelist      = ldSupportsFilelist-      , toolSettings_ldSupportsResponseFiles = ldSupportsResponseFiles       , toolSettings_ldSupportsSingleModule  = ldSupportsSingleModule+      , toolSettings_mergeObjsSupportsResponseFiles = mergeObjsSupportsResponseFiles       , toolSettings_ldIsGnuLd               = ldIsGnuLd       , toolSettings_ccSupportsNoPie         = gccSupportsNoPie       , toolSettings_useInplaceMinGW         = useInplaceMinGW       , toolSettings_arSupportsDashL         = arSupportsDashL        , toolSettings_pgm_L   = unlit_path-      , toolSettings_pgm_P   = (cpp_prog, cpp_args)+      , toolSettings_pgm_P   = (hs_cpp_prog, hs_cpp_args)       , toolSettings_pgm_F   = ""       , toolSettings_pgm_c   = cc_prog       , toolSettings_pgm_cxx = cxx_prog+      , toolSettings_pgm_cpp = (cpp_prog, cpp_args)       , toolSettings_pgm_a   = (as_prog, as_args)       , toolSettings_pgm_l   = (ld_prog, ld_args)       , toolSettings_pgm_lm  = ld_r-      , toolSettings_pgm_dll = (mkdll_prog,mkdll_args)-      , toolSettings_pgm_T   = touch_path       , toolSettings_pgm_windres = windres_path       , toolSettings_pgm_ar = ar_path       , toolSettings_pgm_otool = otool_path@@ -204,7 +194,7 @@       , toolSettings_pgm_ranlib = ranlib_path       , toolSettings_pgm_lo  = (lo_prog,[])       , toolSettings_pgm_lc  = (lc_prog,[])-      , toolSettings_pgm_lcc = (lcc_prog,[])+      , toolSettings_pgm_las = (las_prog, [])       , toolSettings_pgm_i   = iserv_prog       , toolSettings_opt_L       = []       , toolSettings_opt_P       = []@@ -216,9 +206,9 @@       , toolSettings_opt_l       = []       , toolSettings_opt_lm      = []       , toolSettings_opt_windres = []-      , toolSettings_opt_lcc     = []       , toolSettings_opt_lo      = []       , toolSettings_opt_lc      = []+      , toolSettings_opt_las     = []       , toolSettings_opt_i       = []        , toolSettings_extraGccViaCFlags = extraGccViaCFlags@@ -271,19 +261,3 @@     , platformHasLibm = targetHasLibm     , platform_constants = Nothing -- will be filled later when loading (or building) the RTS unit     }---- ------------------------------------------------------------------------------- Escape Args helpers--- -------------------------------------------------------------------------------- | Just like 'GHC.ResponseFile.escapeArg', but it is not exposed from base.-escapeArg :: String -> String-escapeArg = reverse . foldl' escape []--escape :: String -> Char -> String-escape cs c-  |    isSpace c-    || '\\' == c-    || '\'' == c-    || '"'  == c = c:'\\':cs -- n.b., our caller must reverse the result-  | otherwise    = c:cs
compiler/GHC/Stg/BcPrep.hs view
@@ -49,7 +49,7 @@  bcPrepExpr :: StgExpr -> BcPrepM StgExpr -- explicitly match all constructors so we get a warning if we miss any-bcPrepExpr (StgTick bp@(Breakpoint tick_ty _ _) rhs)+bcPrepExpr (StgTick bp@(Breakpoint tick_ty _ _ _) rhs)   | isLiftedTypeKind (typeKind tick_ty) = do       id <- newId tick_ty       rhs' <- bcPrepExpr rhs@@ -170,7 +170,7 @@  We thus must have *some* strategy for dealing with representation-polymorphic and unlifted join points. Representation-polymorphic variables are generally-not allowed (though representation -polymorphic join points *are*; see+not allowed (though representation-polymorphic join points *are*; see Note [Invariants on join points] in GHC.Core, point 6), and we don't wish to evaluate unlifted join points eagerly. The questionable join points are *not-necessarily-lifted join points*
compiler/GHC/Stg/CSE.hs view
@@ -71,6 +71,11 @@                           , Right [x] -> b}  +Note that this can revive dead case binders (e.g. "b" above), hence we zap+occurrence information on all case binders during STG CSE.+See Note [Dead-binder optimisation] in GHC.StgToCmm.Expr.++ Note [StgCse after unarisation] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -344,16 +349,20 @@     = let body' = stgCseExpr env body       in StgTick tick body' stgCseExpr env (StgCase scrut bndr ty alts)-    = mkStgCase scrut' bndr' ty alts'+    = mkStgCase scrut' bndr'' ty alts'   where     scrut' = stgCseExpr env scrut     (env1, bndr') = substBndr env bndr+    -- we must zap occurrence information on the case binder+    -- because CSE might revive it.+    -- See Note [Dead-binder optimisation] in GHC.StgToCmm.Expr+    bndr'' = zapIdOccInfo bndr'     env2 | StgApp trivial_scrut [] <- scrut'          = addTrivCaseBndr bndr trivial_scrut env1                  -- See Note [Trivial case scrutinee]          | otherwise          = env1-    alts' = map (stgCseAlt env2 ty bndr') alts+    alts' = map (stgCseAlt env2 ty bndr'') alts   -- A constructor application.
compiler/GHC/Stg/Debug.hs view
@@ -68,21 +68,25 @@     return (StgRec es)  collectStgRhs :: Id -> StgRhs -> M StgRhs-collectStgRhs bndr (StgRhsClosure ext cc us bs e t) = do-  let-    name = idName bndr-    -- If the name has a span, use that initially as the source position in-case-    -- we don't get anything better.-    with_span = case nameSrcSpan name of-                  RealSrcSpan pos _ -> withSpan (pos, LexicalFastString $ occNameFS (getOccName name))-                  _ -> id-  e' <- with_span $ collectExpr e-  recordInfo bndr e'-  return $ StgRhsClosure ext cc us bs e' t-collectStgRhs _bndr (StgRhsCon cc dc _mn ticks args typ) = do-  n' <- numberDataCon dc ticks-  return (StgRhsCon cc dc n' ticks args typ)-+collectStgRhs bndr rhs =+    case rhs of+      StgRhsClosure ext cc us bs e t -> do+        e' <- with_span $ collectExpr e+        recordInfo bndr e'+        return $ StgRhsClosure ext cc us bs e' t+      StgRhsCon cc dc _mn ticks args typ -> do+        n' <- with_span $ numberDataCon dc ticks+        return (StgRhsCon cc dc n' ticks args typ)+  where+    -- If the binder name has a span, use that initially as the source position+    -- in case we don't get anything better+    with_span :: M a -> M a+    with_span =+      let name = idName bndr in+      case nameSrcSpan name of+        RealSrcSpan pos _ ->+          withSpan (pos, LexicalFastString $ occNameFS (getOccName name))+        _ -> id  recordInfo :: Id -> StgExpr -> M () recordInfo bndr new_rhs = do
compiler/GHC/Stg/FVs.hs view
@@ -257,8 +257,8 @@       , let lcl_fvs' = unionDVarSet (tickish tick) lcl_fvs       = (StgTick tick e', imp_fvs, top_fvs, lcl_fvs')         where-          tickish (Breakpoint _ _ ids) = mkDVarSet ids-          tickish _                    = emptyDVarSet+          tickish (Breakpoint _ _ ids _) = mkDVarSet ids+          tickish _                      = emptyDVarSet      go_bind dc bind body = (dc bind' body', imp_fvs, top_fvs, lcl_fvs)       where
compiler/GHC/Stg/InferTags.hs view
@@ -19,6 +19,7 @@ import GHC.Types.Unique.Supply (mkSplitUniqSupply) import GHC.Types.RepType (dataConRuntimeRepStrictness) import GHC.Core (AltCon(..))+import GHC.Builtin.PrimOps ( PrimOp(..) ) import Data.List (mapAccumL) import GHC.Utils.Outputable import GHC.Utils.Misc( zipWithEqual, zipEqual, notNull )@@ -319,14 +320,6 @@          | otherwise          = --pprTrace "inferAppUnknown" (ppr fun) $            TagDunno--- TODO:--- If we have something like:---   let x = thunk in---   f g = case g of g' -> (# x, g' #)--- then we *do* know that g' will be properly tagged,--- so we should return TagTagged [TagDunno,TagProper] but currently we infer--- TagTagged [TagDunno,TagDunno] because of the unknown arity case in inferTagExpr.--- Seems not to matter much but should be changed eventually.  inferTagExpr env (StgConApp con cn args tys)   = (inferConTag env con args, StgConApp con cn args tys)@@ -340,9 +333,21 @@     (info, body') = inferTagExpr env body  inferTagExpr _ (StgOpApp op args ty)-  = -- Do any primops guarantee to return a properly tagged value?-    -- I think not.  Ditto foreign calls.-    (TagDunno, StgOpApp op args ty)+  | StgPrimOp SeqOp <- op+  -- Recall seq# :: a -> State# s -> (# State# s, a #)+  -- However the output State# token has been unarised away,+  -- so we now effectively have+  --    seq# :: a -> State# s -> (# a #)+  -- The key point is the result of `seq#` is guaranteed evaluated and properly+  -- tagged (because that result comes directly from evaluating the arg),+  -- and we want tag inference to reflect that knowledge (#15226).+  -- Hence `TagTuple [TagProper]`.+  -- See Note [seq# magic] in GHC.Core.Opt.ConstantFold+  = (TagTuple [TagProper], StgOpApp op args ty)+  -- Do any other primops guarantee to return a properly tagged value?+  -- Probably not, and that is the conservative assumption anyway.+  -- (And foreign calls definitely need not make promises.)+  | otherwise = (TagDunno, StgOpApp op args ty)  inferTagExpr env (StgLet ext bind body)   = (info, StgLet ext bind' body')
compiler/GHC/Stg/InferTags/Rewrite.hs view
@@ -2,20 +2,12 @@ -- Copyright (c) 2019 Andreas Klebinger -- -{-# LANGUAGE BangPatterns               #-} {-# LANGUAGE CPP                        #-} {-# LANGUAGE DataKinds                  #-}-{-# LANGUAGE FlexibleContexts           #-}-{-# LANGUAGE FlexibleInstances          #-} {-# LANGUAGE GADTs                      #-}-{-# LANGUAGE GeneralisedNewtypeDeriving #-}-{-# LANGUAGE MultiParamTypeClasses      #-}-{-# LANGUAGE RankNTypes                 #-}-{-# LANGUAGE ScopedTypeVariables        #-}-{-# LANGUAGE TupleSections              #-} {-# LANGUAGE TypeFamilies               #-} -module GHC.Stg.InferTags.Rewrite (rewriteTopBinds)+module GHC.Stg.InferTags.Rewrite (rewriteTopBinds, rewriteOpApp) where  import GHC.Prelude@@ -217,7 +209,7 @@ When compiling bytecode we call myCoreToStg to get STG code first. myCoreToStg in turn calls out to stg2stg which runs the STG to STG passes followed by free variables analysis and the tag inference pass including-it's rewriting phase at the end.+its rewriting phase at the end. Running tag inference is important as it upholds Note [Strict Field Invariant]. While code executed by GHCi doesn't take advantage of the SFI it can call into compiled code which does. So it must still make sure that the SFI is upheld.@@ -396,17 +388,15 @@     if is_tagged then return $! setIdTagSig v (TagSig TagProper)                  else return v -rewriteExpr :: InferStgExpr -> RM TgStgExpr-rewriteExpr (e@StgCase {})          = rewriteCase e-rewriteExpr (e@StgLet {})           = rewriteLet e-rewriteExpr (e@StgLetNoEscape {})   = rewriteLetNoEscape e-rewriteExpr (StgTick t e)     = StgTick t <$!> rewriteExpr e-rewriteExpr e@(StgConApp {})        = rewriteConApp e-rewriteExpr e@(StgApp {})     = rewriteApp e-rewriteExpr (StgLit lit)           = return $! (StgLit lit)-rewriteExpr (StgOpApp op@(StgPrimOp DataToTagOp) args res_ty) = do-        (StgOpApp op) <$!> rewriteArgs args <*> pure res_ty-rewriteExpr (StgOpApp op args res_ty) = return $! (StgOpApp op args res_ty)+rewriteExpr :: GenStgExpr 'InferTaggedBinders -> RM (GenStgExpr 'CodeGen)+rewriteExpr (e@StgCase {})            = rewriteCase e+rewriteExpr (e@StgLet {})             = rewriteLet e+rewriteExpr (e@StgLetNoEscape {})     = rewriteLetNoEscape e+rewriteExpr (StgTick t e)             = StgTick t <$!> rewriteExpr e+rewriteExpr e@(StgConApp {})          = rewriteConApp e+rewriteExpr e@(StgApp {})             = rewriteApp e+rewriteExpr (StgLit lit)              = return $! (StgLit lit)+rewriteExpr (StgOpApp op args res_ty) = (StgOpApp op) <$!> rewriteArgs args <*> pure res_ty   rewriteCase :: InferStgExpr -> RM TgStgExpr@@ -414,7 +404,7 @@     withBinder NotTopLevel bndr $         pure StgCase <*>             rewriteExpr scrut <*>-            pure (fst bndr) <*>+            rewriteId (fst bndr) <*>             pure alt_type <*>             mapM rewriteAlt alts @@ -487,6 +477,32 @@  rewriteApp (StgApp f args) = return $ StgApp f args rewriteApp _ = panic "Impossible"++{-+Note [Rewriting primop arguments]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Given an application `op# x y`, is it worth applying `rewriteArg` to+`x` and `y`?  All that will do will be to set the `tagSig` for that+occurrence of `x` and `y` to record whether it is evaluated and+properly tagged. For the vast majority of primops that's a waste of+time: the argument is an `Int#` or something.++But code generation for `seq#` and the `dataToTag#` ops /does/ consult that+tag, to statically avoid generating an eval.  All three do so via `cgIdApp`,+which in turn uses `getCallMethod` which looks at the `tagSig`.++So for these we should call `rewriteArgs`.++-}++rewriteOpApp :: InferStgExpr -> RM TgStgExpr+rewriteOpApp (StgOpApp op args res_ty) = case op of+  op@(StgPrimOp primOp)+    | primOp == SeqOp || primOp == DataToTagSmallOp || primOp == DataToTagLargeOp+    -- see Note [Rewriting primop arguments]+    -> (StgOpApp op) <$!> rewriteArgs args <*> pure res_ty+  _ -> pure $! StgOpApp op args res_ty+rewriteOpApp _ = panic "Impossible"  -- `mkSeq` x x' e generates `case x of x' -> e` -- We could also substitute x' for x in e but that's so rarely beneficial
compiler/GHC/Stg/Lift/Analysis.hs view
@@ -418,7 +418,7 @@ -- | The number of words a single 'Id' adds to a closure's size. -- Note that this can't handle unboxed tuples (which may still be present in -- let-no-escapes, even after Unarise), in which case--- @'GHC.StgToCmm.Closure.idPrimRep'@ will crash.+-- @'GHC.StgToCmm.ArgRep.idArgRep'@ will crash. idClosureFootprint:: Platform -> Id -> WordOff idClosureFootprint platform   = StgToCmm.ArgRep.argRepSizeW platform@@ -478,9 +478,9 @@       -- cardinality. The @body_dmd@ part of 'RhsSk' is the result of       -- 'rhsCard' and accurately captures the cardinality of the RHSs body       -- relative to its defining context.-      | isAbs n      = 0-      | cg <= 0      = if isStrict n then cg else 0-      | isUsedOnce n = cg-      | otherwise    = infinity+      | isAbs n        = 0+      | cg <= 0        = if isStrict n then cg else 0+      | isAtMostOnce n = cg+      | otherwise      = infinity       where         cg = go body
compiler/GHC/Stg/Lift/Monad.hs view
@@ -39,7 +39,6 @@ import GHC.Core.Utils import GHC.Types.Unique.Supply import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Types.Var.Env import GHC.Types.Var.Set import GHC.Core.Multiplicity
compiler/GHC/Stg/Lint.hs view
@@ -178,7 +178,7 @@ lintStgConArg :: StgArg -> LintM () lintStgConArg arg = do   unarised <- lf_unarised <$> getLintFlags-  when unarised $ case typePrimRep_maybe (stgArgType arg) of+  when unarised $ case stgArgRep_maybe arg of     -- Note [Post-unarisation invariants], invariant 4     Just [_] -> pure ()     badRep   -> addErrL $@@ -192,7 +192,7 @@ lintStgFunArg :: StgArg -> LintM () lintStgFunArg arg = do   unarised <- lf_unarised <$> getLintFlags-  when unarised $ case typePrimRep_maybe (stgArgType arg) of+  when unarised $ case stgArgRep_maybe arg of     -- Note [Post-unarisation invariants], invariant 3     Just []  -> pure ()     Just [_] -> pure ()@@ -302,13 +302,13 @@  lintStgExpr (StgLet _ binds body) = do     binders <- lintStgBinds NotTopLevel binds-    addLoc (BodyOfLetRec binders) $+    addLoc (BodyOfLet binders) $       addInScopeVars binders $         lintStgExpr body  lintStgExpr (StgLetNoEscape _ binds body) = do     binders <- lintStgBinds NotTopLevel binds-    addLoc (BodyOfLetRec binders) $+    addLoc (BodyOfLet binders) $       addInScopeVars binders $         lintStgExpr body @@ -371,22 +371,16 @@       -- and we abort kind checking.       fun_arg_tys_reps, actual_arg_reps :: [Maybe [PrimRep]]       fun_arg_tys_reps = map typePrimRep_maybe fun_arg_tys'-      actual_arg_reps = map (typePrimRep_maybe . stgArgType) args+      actual_arg_reps = map stgArgRep_maybe args        match_args :: [Maybe [PrimRep]] -> [Maybe [PrimRep]] -> LintM ()       match_args (Nothing:_) _   = return ()       match_args (_) (Nothing:_) = return ()       match_args (Just actual_rep:actual_reps_left) (Just expected_rep:expected_reps_left)-        -- Common case, reps are exactly the same+        -- Common case, reps are exactly the same (perhaps void)         | actual_rep == expected_rep         = match_args actual_reps_left expected_reps_left -        -- Check for void rep which can be either an empty list *or* [VoidRep]-           -- No, typePrimRep_maybe will never return a result containing VoidRep.-           -- We should refactor to make this obvious from the types.-        | isVoidRep actual_rep && isVoidRep expected_rep-        = match_args actual_reps_left expected_reps_left-         -- Some reps are compatible *even* if they are not the same. E.g. IntRep and WordRep.         -- We check for that here with primRepCompatible         | primRepsCompatible platform actual_rep expected_rep@@ -409,9 +403,6 @@               -- text "expected reps:" <> ppr arg_ty_reps $$               text "unarised?:" <> ppr (lf_unarised lf))         where-          isVoidRep [] = True-          isVoidRep [VoidRep] = True-          isVoidRep _ = False           -- Try to strip one non-void arg rep from the current argument type returning           -- the remaining list of arguments. We return Nothing for invalid input which           -- will result in a lint failure in match_args.@@ -438,7 +429,7 @@         (text "marks" <> ppr marks $$         text "args" <> ppr args $$         text "arity" <> ppr (idArity fun) $$-        text "join_arity" <> ppr (isJoinId_maybe fun))+        text "join_arity" <> ppr (idJoinPointHood fun)) lintAppCbvMarks _ = panic "impossible - lintAppCbvMarks"  {-@@ -469,7 +460,7 @@ data LintLocInfo   = RhsOf Id            -- The variable bound   | LambdaBodyOf [Id]   -- The lambda-binder-  | BodyOfLetRec [Id]   -- One of the binders+  | BodyOfLet [Id]      -- The binders of the let  dumpLoc :: LintLocInfo -> (SrcSpan, SDoc) dumpLoc (RhsOf v) =@@ -477,8 +468,8 @@ dumpLoc (LambdaBodyOf bs) =   (srcLocSpan (getSrcLoc (head bs)), text " [in body of lambda with binders " <> pp_binders bs <> char ']' ) -dumpLoc (BodyOfLetRec bs) =-  (srcLocSpan (getSrcLoc (head bs)), text " [in body of letrec with binders " <> pp_binders bs <> char ']' )+dumpLoc (BodyOfLet bs) =+  (srcLocSpan (getSrcLoc (head bs)), text " [in body of let with binders " <> pp_binders bs <> char ']' )   pp_binders :: [Id] -> SDoc
compiler/GHC/Stg/Pipeline.hs view
@@ -74,6 +74,7 @@         -> IO ([(CgStgTopBinding,IdSet)], StgCgInfos) -- output program stg2stg logger extra_vars opts this_mod binds   = do  { dump_when Opt_D_dump_stg_from_core "Initial STG:" binds+        ; stg_linter False "StgFromCore" binds         ; showPass logger "Stg2Stg"         -- Do the main business!         ; binds' <- runStgM 'g' $@@ -92,10 +93,12 @@         ; let (binds_sorted_with_fvs, imp_fvs) = unzip (depSortWithAnnotStgPgm this_mod binds')         -- See Note [Tag inference for interactive contexts]         ; (cg_binds, cg_infos) <- inferTags (stgPipeline_pprOpts opts) (stgPipeline_forBytecode opts) logger this_mod binds_sorted_with_fvs+        ; stg_linter False "StgCodeGen" cg_binds         ; pure (zip cg_binds imp_fvs, cg_infos)    }    where+    stg_linter :: (BinderP a ~ Id, OutputablePass a) => Bool -> String -> [GenStgTopBinding a] -> IO ()     stg_linter unarised       | Just diag_opts <- stgPipeline_lint opts       = lintStgTopBindings
compiler/GHC/Stg/Subst.hs view
@@ -55,7 +55,7 @@  -- | Substitutes an occurrence of an identifier for its counterpart recorded -- in the 'Subst'.-lookupIdSubst :: HasDebugCallStack => Id -> Subst -> Id+lookupIdSubst :: HasCallStack => Id -> Subst -> Id lookupIdSubst id (Subst in_scope env)   | not (isLocalId id) = id   | Just id' <- lookupVarEnv env id = id'@@ -65,7 +65,7 @@ -- | Substitutes an occurrence of an identifier for its counterpart recorded -- in the 'Subst'. Does not generate a debug warning if the identifier to -- to substitute wasn't in scope.-noWarnLookupIdSubst :: HasDebugCallStack => Id -> Subst -> Id+noWarnLookupIdSubst :: HasCallStack => Id -> Subst -> Id noWarnLookupIdSubst id (Subst in_scope env)   | not (isLocalId id) = id   | Just id' <- lookupVarEnv env id = id'
compiler/GHC/Stg/Unarise.hs view
@@ -166,8 +166,8 @@     way to fix what is ultimately a corner-case.  -Note [Types in StgConApp]-~~~~~~~~~~~~~~~~~~~~~~~~~+Note [Representations in StgConApp]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Suppose we have this unboxed sum term:    (# 123 | #)@@ -180,10 +180,22 @@   (# 1#, 123, rubbish, rubbish #)                          -- when type is (# Int | (# Int, Int, Int #) #) -So we pass type arguments of the DataCon's TyCon in StgConApp to decide what-layout to use. Note that unlifted values can't be let-bound, so we don't need-types in StgRhsCon.+Therefore, in StgConApp we store a list [[PrimRep]] of representations+to decide what layout to use.+Given (# T_1 | ... | T_n #), this list will be+[typePrimRep T_1, ..., typePrimRep T_n].+For example, given type+  (# Int | String #)              we will store [[LiftedRep], [LiftedRep]]+  (# Int | Float# #)              we will store [[LiftedRep], [FloatRep]]+  (# Int | (# Int, Int, Int #) #) we will store [[LiftedRep], [LiftedRep, LiftedRep, LiftedRep]]. +This field is used for unboxed sums only and it's an empty list otherwise.+Perhaps it would be more elegant to have a separate StgUnboxedSumCon,+but that would require duplication of code in cases where the logic is shared.++Note that unlifted values can't be let-bound, so we don't need+representations in StgRhsCon.+ Note [Casting slot arguments] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Consider this function which selects between Int32# and Int64# from a unboxed sum.@@ -298,7 +310,7 @@       (x' :: Int32#) -> alt_rhs   ) -We then run unarise on alt_rhs within that expression, which will replace the first occurence+We then run unarise on alt_rhs within that expression, which will replace the first occurrence of `x` with sum_slot_arg_1 giving us post-unarise:      f sum_tag sum_slot1 =@@ -361,6 +373,7 @@  2. No unboxed tuple binders. Tuples only appear in return position.   3. Binders and literals always have zero (for void arguments) or one PrimRep.+    (i.e. typePrimRep1 won't crash; see Note [VoidRep] in GHC.Types.RepType.)   4. DataCon applications (StgRhsCon and StgConApp) don't have void arguments.     This means that it's safe to wrap `StgArg`s of DataCon applications with@@ -385,7 +398,6 @@ import GHC.Utils.Monad (mapAccumLM) import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Types.RepType import GHC.Stg.Syntax import GHC.Stg.Utils@@ -447,10 +459,10 @@ -- See Note [UnariseEnv] extendRho :: UnariseEnv -> Id -> UnariseVal -> UnariseEnv extendRho env x (MultiVal args)-  = assert (all (isNvUnaryType . stgArgType) args)+  = assert (all (isNvUnaryRep . stgArgRep) args)     env { ue_rho = extendVarEnv (ue_rho env) x (MultiVal args) } extendRho env x (UnaryVal val)-  = assert (isNvUnaryType (stgArgType val))+  = assert (isNvUnaryRep (stgArgRep val))     env { ue_rho = extendVarEnv (ue_rho env) x (UnaryVal val) } -- Properly shadow things from an outer scope. -- See Note [UnariseEnv]@@ -528,7 +540,7 @@           -> return $ (mkTuple args')   | otherwise =       let args' = unariseConArgs rho args in-      return $ (StgConApp dc n args' (map stgArgType args'))+      return $ (StgConApp dc n args' [])  unariseExpr rho (StgOpApp op args ty)   = return (StgOpApp op (unariseFunArgs rho args) ty)@@ -573,7 +585,7 @@   = StgTick tick <$> unariseExpr rho e  -- Doesn't return void args.-unariseUbxSumOrTupleArgs :: UnariseEnv -> UniqSupply -> DataCon -> [InStgArg] -> [Type]+unariseUbxSumOrTupleArgs :: UnariseEnv -> UniqSupply -> DataCon -> [InStgArg] -> [[PrimRep]]                    -> ( [OutStgArg]           -- Arguments representing the unboxed sum                       , Maybe (StgExpr -> StgExpr)) -- Transformation to apply to the arguments, to bring them                                                     -- into the right Rep@@ -596,13 +608,12 @@ -- See also Note [Rubbish literals] in GHC.Types.Literal. unariseLiteral_maybe :: Literal -> Maybe [OutStgArg] unariseLiteral_maybe (LitRubbish torc rep)-  | [prep] <- preps-  , assert (not (isVoidRep prep)) True-  = Nothing   -- Single, non-void PrimRep. Nothing to do!+  | [_] <- preps+  = Nothing   -- Single PrimRep. Nothing to do! -  | otherwise -- Multiple reps, possibly with VoidRep. Eliminate via elimCase+  | otherwise -- Multiple reps, or zero. Eliminate via elimCase   = Just [ StgLitArg (LitRubbish torc (primRepToRuntimeRep prep))-         | prep <- preps, assert (not (isVoidRep prep)) True ]+         | prep <- preps ]   where     preps = runtimeRepPrimRep (text "unariseLiteral_maybe") rep @@ -746,7 +757,7 @@   -> UnariseEnv   -> UnariseEnv mapTupleIdBinders ids args0 rho0-  = assert (not (any (isZeroBitTy . stgArgType) args0)) $+  = assert (not (any (null . stgArgRep) args0)) $     let       ids_unarised :: [(Id, [PrimRep])]       ids_unarised = map (\id -> (id, typePrimRep (idType id))) ids@@ -780,13 +791,13 @@   -> UniqSM (UnariseEnv, OutStgExpr)  mapSumIdBinders alt_bndr args rhs rho0-  = assert (not (any (isZeroBitTy . stgArgType) args)) $ do+  = assert (not (any (null . stgArgRep) args)) $ do     uss <- listSplitUniqSupply <$> getUniqueSupplyM     let       fld_reps = typePrimRep (idType alt_bndr)        -- Slots representing the whole sum-      arg_slots = map primRepSlot $ concatMap (typePrimRep . stgArgType) args+      arg_slots = map primRepSlot $ concatMap stgArgRep args       -- The slots representing the field of the sum we bind.       id_slots  = map primRepSlot $ fld_reps       layout1   = layoutUbxSum arg_slots id_slots@@ -797,15 +808,13 @@       -- Select only the args which contain parts of the current field.       id_arg_exprs   = [ args !! i | i <- layout1 ]       id_vars   = [v | StgVarArg v <- id_arg_exprs]-      -- Output types for the field binders based on their rep-      id_tys    = map primRepToType fld_reps -      typed_id_arg_input = assert (equalLength id_vars id_tys) $-                           zip3 id_vars id_tys uss+      typed_id_arg_input = assert (equalLength id_vars fld_reps) $+                           zip3 id_vars fld_reps uss -      mkCastInput :: (Id,Type,UniqSupply) -> ([(PrimOp,Type,Unique)],Id,Id)-      mkCastInput (id,tar_type,bndr_us) =-        let (ops,types) = unzip $ getCasts (typePrimRep1 $ idType id) (typePrimRep1 tar_type)+      mkCastInput :: (Id,PrimRep,UniqSupply) -> ([(PrimOp,Type,Unique)],Id,Id)+      mkCastInput (id,rep,bndr_us) =+        let (ops,types) = unzip $ getCasts (typePrimRepU $ idType id) rep             cst_opts = zip3 ops types $ uniqsFromSupply bndr_us             out_id = case cst_opts of               [] -> id@@ -823,7 +832,7 @@       typed_id_args = map StgVarArg typed_ids        -- pprTrace "mapSumIdBinders"-      --           (text "id_tys" <+> ppr id_tys $$+      --           (text "fld_reps" <+> ppr fld_reps $$       --           text "id_args" <+> ppr id_arg_exprs $$       --           text "rhs" <+> ppr rhs $$       --           text "rhs_with_casts" <+> ppr rhs_with_casts@@ -851,7 +860,7 @@  mkCast :: StgArg -> PrimOp -> OutId -> Type -> StgExpr -> StgExpr mkCast arg_in cast_op out_id out_ty in_rhs =-  let r2 = typePrimRep1 out_ty+  let r2 = typePrimRepU out_ty       scrut = StgOpApp (StgPrimOp cast_op) [arg_in] out_ty       alt = GenStgAlt { alt_con = DEFAULT, alt_bndrs = [], alt_rhs = in_rhs}       alt_ty = PrimAlt r2@@ -861,7 +870,7 @@ -- -- Example, for (# x | #) :: (# (# #) | Int #) we call -----   mkUbxSum (# _ | #) [ (# #), Int ] [ voidPrimId ]+--   mkUbxSum (# _ | #) [ [], [LiftedRep] ] [ voidPrimId ] -- -- which returns --@@ -870,7 +879,7 @@ mkUbxSum   :: HasDebugCallStack   => DataCon      -- Sum data con-  -> [Type]       -- Type arguments of the sum data con+  -> [[PrimRep]]  -- Representations of type arguments of the sum data con   -> [OutStgArg]  -- Actual arguments of the alternative.   -> UniqSupply   -> ([OutStgArg] -- Final tuple arguments@@ -878,9 +887,9 @@      ) mkUbxSum dc ty_args args0 us   = let-      _ :| sum_slots = ubxSumRepType (map typePrimRep ty_args)+      _ :| sum_slots = ubxSumRepType ty_args       -- drop tag slot-      field_slots = (mapMaybe (typeSlotTy . stgArgType) args0)+      field_slots = (mapMaybe (repSlotTy . stgArgRep) args0)       tag = dataConTag dc       layout'  = layoutUbxSum sum_slots field_slots @@ -897,7 +906,7 @@       mkTupArg (arg_idx, arg_map, us, wrapper) slot          | Just stg_arg <- IM.lookup arg_idx arg_map          =  case castArg us slot stg_arg of-              -- Slot and arg type missmatched, do a cast+              -- Slot and arg type mismatched, do a cast               Just (casted_arg,us',wrapper') ->                 ( (arg_idx+1, arg_map, us', wrapper . wrapper')                 , casted_arg)@@ -913,9 +922,8 @@       castArg :: UniqSupply -> SlotTy -> StgArg -> Maybe (StgArg,UniqSupply,StgExpr -> StgExpr)       castArg us slot_ty arg         -- Cast the argument to the type of the slot if required-        | slotPrimRep slot_ty /= typePrimRep1 (stgArgType arg)-        , out_ty <- primRepToType $ slotPrimRep slot_ty-        , (ops,types) <- unzip $ getCasts (typePrimRep1 $ stgArgType arg) $ typePrimRep1 out_ty+        | slotPrimRep slot_ty /= stgArgRepU arg+        , (ops,types) <- unzip $ getCasts (stgArgRepU arg) $ slotPrimRep slot_ty         , not . null $ ops         = let (us1,us2) = splitUniqSupply us               cast_uqs = uniqsFromSupply us1@@ -964,13 +972,13 @@   - When unarising function arg binders and arguments, we don't want to remove     void binders and arguments. For example, -      f :: (# (# #), (# #) #) -> Void# -> RealWorld# -> ...+      f :: (# (# #), (# #) #) -> Void# -> State# RealWorld -> ...       f x y z = <body>      Here after unarise we should still get a function with arity 3. Similarly     in the call site we shouldn't remove void arguments: -      f (# (# #), (# #) #) void# rw+      f (# (# #), (# #) #) void# realWorld#      When unarising <body>, we extend the environment with these binders: @@ -1122,7 +1130,7 @@ isUnboxedTupleBndr = isUnboxedTupleType . idType  mkTuple :: [StgArg] -> StgExpr-mkTuple args = StgConApp (tupleDataCon Unboxed (length args)) NoNumber args (map stgArgType args)+mkTuple args = StgConApp (tupleDataCon Unboxed (length args)) NoNumber args []  tagAltTy :: AltType tagAltTy = PrimAlt IntRep@@ -1134,7 +1142,7 @@ voidArg = StgVarArg voidPrimId  mkDefaultLitAlt :: [StgAlt] -> [StgAlt]--- We have an exhauseive list of literal alternatives+-- We have an exhaustive list of literal alternatives --    1# -> e1 --    2# -> e2 -- Since they are exhaustive, we can replace one with DEFAULT, to avoid
compiler/GHC/Stg/Utils.hs view
@@ -26,7 +26,6 @@  import GHC.Utils.Outputable -import GHC.Utils.Panic.Plain import GHC.Utils.Panic  import GHC.Data.FastString
compiler/GHC/StgToByteCode.hs view
@@ -56,9 +56,10 @@ import GHC.Builtin.Uniques import GHC.Data.FastString import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Exception (evaluate)-import GHC.StgToCmm.Closure ( NonVoid(..), fromNonVoid, nonVoidIds, argPrimRep )+import GHC.StgToCmm.Closure ( NonVoid(..), fromNonVoid, idPrimRepU,+                              addIdReps, addArgReps,+                              nonVoidIds, nonVoidStgArgs ) import GHC.StgToCmm.Layout import GHC.Runtime.Heap.Layout hiding (WordOff, ByteOff, wordsToBytes) import GHC.Data.Bitmap@@ -74,19 +75,17 @@ import Data.Char  import GHC.Unit.Module+import GHC.Unit.Home.ModInfo (lookupHpt)  import Data.Array import Data.Coerce (coerce) import Data.ByteString (ByteString) import Data.Map (Map) import Data.IntMap (IntMap)-import Data.List.NonEmpty (NonEmpty(..)) import qualified Data.Map as Map import qualified Data.IntMap as IntMap-import qualified Data.List.NonEmpty as NE import qualified GHC.Data.FiniteMap as Map import Data.Ord-import GHC.Stack.CCS import Data.Either ( partitionEithers )  import GHC.Stg.Syntax@@ -297,11 +296,6 @@   | isFollowableArg rep  = False : argBits platform args   | otherwise = replicate (argRepSizeW platform rep) True ++ argBits platform args -non_void :: NonEmpty ArgRep -> [ArgRep]-non_void = NE.filter nv-  where nv V = False-        nv _ = True- -- ----------------------------------------------------------------------------- -- schemeTopBind @@ -378,7 +372,7 @@          p_init    = Map.fromList (zip all_args (mkStackOffsets 0 szsb_args))           -- make the arg bitmap-         bits = argBits platform (reverse (map (bcIdArgRep platform) all_args))+         bits = argBits platform (reverse (map (idArgRep platform) all_args))          bitmap_size = genericLength bits          bitmap = mkBitmap platform bits      body_code <- schemeER_wrk sum_szsb_args p_init body@@ -386,31 +380,73 @@      emitBc (mkProtoBCO platform nm body_code (Right original_body)                  arity bitmap_size bitmap False{-not alts-}) --- introduce break instructions for ticked expressions+-- | Introduce break instructions for ticked expressions.+-- If no breakpoint information is available, the instruction is omitted. schemeER_wrk :: StackDepth -> BCEnv -> CgStgExpr -> BcM BCInstrList-schemeER_wrk d p (StgTick (Breakpoint tick_ty tick_no fvs) rhs)-  = do  code <- schemeE d 0 p rhs-        cc_arr <- getCCArray-        platform <- profilePlatform <$> getProfile-        let idOffSets = getVarOffSets platform d p fvs-            ty_vars   = tyCoVarsOfTypesWellScoped (tick_ty:map idType fvs)-        let toWord :: Maybe (Id, WordOff) -> Maybe (Id, Word)-            toWord = fmap (\(i, wo) -> (i, fromIntegral wo))-            breakInfo  = dehydrateCgBreakInfo ty_vars (map toWord idOffSets) tick_ty-        newBreakInfo tick_no breakInfo-        hsc_env <- getHscEnv-        let cc | Just interp <- hsc_interp hsc_env-               , interpreterProfiled interp-               = cc_arr ! tick_no-               | otherwise = toRemotePtr nullPtr-        mb_mod_name <- getCurrentModuleName-        case mb_mod_name of-          Just mod_ptr -> do-            let breakInstr = BRK_FUN (fromIntegral tick_no) mod_ptr cc-            return $ breakInstr `consOL` code-          Nothing -> return code+schemeER_wrk d p (StgTick (Breakpoint tick_ty tick_no fvs mod) rhs) = do+  code <- schemeE d 0 p rhs+  hsc_env <- getHscEnv+  current_mod <- getCurrentModule+  current_mod_breaks <- getCurrentModBreaks+  case break_info hsc_env mod current_mod current_mod_breaks of+    Nothing -> pure code+    Just ModBreaks {modBreaks_flags = breaks, modBreaks_module = mod_ptr, modBreaks_ccs = cc_arr} -> do+      platform <- profilePlatform <$> getProfile+      let idOffSets = getVarOffSets platform d p fvs+          ty_vars   = tyCoVarsOfTypesWellScoped (tick_ty:map idType fvs)+          toWord :: Maybe (Id, WordOff) -> Maybe (Id, Word)+          toWord = fmap (\(i, wo) -> (i, fromIntegral wo))+          breakInfo  = dehydrateCgBreakInfo ty_vars (map toWord idOffSets) tick_ty+      newBreakInfo tick_no breakInfo+      let cc | Just interp <- hsc_interp hsc_env+            , interpreterProfiled interp+            = cc_arr ! tick_no+            | otherwise = toRemotePtr nullPtr+          breakInstr = BRK_FUN breaks (fromIntegral tick_no) mod_ptr cc+      return $ breakInstr `consOL` code schemeER_wrk d p rhs = schemeE d 0 p rhs +-- | Determine the GHCi-allocated 'BreakArray' and module pointer for the module+-- from which the breakpoint originates.+-- These are stored in 'ModBreaks' as remote pointers in order to allow the BCOs+-- to refer to pointers in GHCi's address space.+-- They are initialized in 'GHC.HsToCore.Breakpoints.mkModBreaks', called by+-- 'GHC.HsToCore.deSugar'.+--+-- Breakpoints might be disabled because we're in TH, because+-- @-fno-break-points@ was specified, or because a module was reloaded without+-- reinitializing 'ModBreaks'.+--+-- If the module stored in the breakpoint is the currently processed module, use+-- the 'ModBreaks' from the state.+-- If that is 'Nothing', consider breakpoints to be disabled and skip the+-- instruction.+--+-- If the breakpoint is inlined from another module, look it up in the home+-- package table.+-- If the module doesn't exist there, or its module pointer is null (which means+-- that the 'ModBreaks' value is uninitialized), skip the instruction.+break_info ::+  HscEnv ->+  Module ->+  Module ->+  Maybe ModBreaks ->+  Maybe ModBreaks+break_info hsc_env mod current_mod current_mod_breaks+  | mod == current_mod+  = check_mod_ptr =<< current_mod_breaks+  | Just hp <- lookupHpt (hsc_HPT hsc_env) (moduleName mod)+  = check_mod_ptr (getModBreaks hp)+  | otherwise+  = Nothing+  where+    check_mod_ptr mb+      | mod_ptr <- modBreaks_module mb+      , fromRemotePtr mod_ptr /= nullPtr+      = Just mb+      | otherwise+      = Nothing+ getVarOffSets :: Platform -> StackDepth -> BCEnv -> [Id] -> [Maybe (Id, WordOff)] getVarOffSets platform depth env = map getOffSet   where@@ -452,11 +488,9 @@     -> StgArg     -> BcM BCInstrList returnUnliftedAtom d s p e = do-    let reps = case e of-                 StgLitArg lit -> typePrimRepArgs (literalType lit)-                 StgVarArg i   -> bcIdPrimReps i+    let reps = stgArgRep e     (push, szb) <- pushAtom d p e-    ret <- returnUnliftedReps d s szb (NE.toList $! reps)+    ret <- returnUnliftedReps d s szb reps     return (push `appOL` ret)  -- return an unlifted value from the top of the stack@@ -469,9 +503,7 @@ returnUnliftedReps d s szb reps = do     profile <- getProfile     let platform = profilePlatform profile-        non_void VoidRep = False-        non_void _ = True-    ret <- case filter non_void reps of+    ret <- case reps of              -- use RETURN for nullary/unary representations              []    -> return (unitOL $ RETURN V)              [rep] -> return (unitOL $ RETURN (toArgRep platform rep))@@ -495,7 +527,7 @@ returnUnboxedTuple d s p es = do     profile <- getProfile     let platform = profilePlatform profile-        arg_ty e = primRepCmmType platform (atomPrimRep e)+        arg_ty e = primRepCmmType platform (stgArgRepU e)         (call_info, tuple_components) = layoutNativeCall profile                                                          NativeTupleReturn                                                          d@@ -506,10 +538,14 @@                                          massert (off == dd + szb)                                          go (dd + szb) (push:pushes) cs     pushes <- go d [] tuple_components+    let rep_to_maybe :: PrimOrVoidRep -> Maybe PrimRep+        rep_to_maybe VoidRep = Nothing+        rep_to_maybe (NVRep rep) = Just rep+     ret <- returnUnliftedReps d                               s                               (wordsToBytes platform $ nativeCallSize call_info)-                              (map atomPrimRep es)+                              (mapMaybe (rep_to_maybe . stgArgRep1) es)     return (mconcat pushes `appOL` ret)  -- Compile code to apply the given expression to the remaining args@@ -605,7 +641,7 @@      thunk_codes <- sequence compile_binds      return (alloc_code `appOL` concatOL thunk_codes `appOL` body_code) -schemeE _d _s _p (StgTick (Breakpoint _ bp_id _) _rhs)+schemeE _d _s _p (StgTick (Breakpoint _ bp_id _ _) _rhs)    = panic ("schemeE: Breakpoint without let binding: " ++             show bp_id ++             " forgot to run bcPrep?")@@ -710,11 +746,7 @@         let platform = profilePlatform profile              non_voids =-                [ NonVoid (prim_rep, arg)-                | arg <- args-                , let prim_rep = atomPrimRep arg-                , not (isVoidRep prim_rep)-                ]+                addArgReps (nonVoidStgArgs args)             (_, _, args_offsets) =                 mkVirtHeapOffsetsWithPadding profile StdHeader non_voids @@ -818,12 +850,12 @@         -- Are we dealing with an unboxed tuple with a tuple return frame?         --         -- 'Simple' tuples with at most one non-void component,-        -- like (# Word# #) or (# Int#, State# RealWorld# #) do not have a+        -- like (# Word# #) or (# Int#, State# RealWorld #) do not have a         -- tuple return frame. This is because (# foo #) and (# foo, Void# #)         -- have the same runtime rep. We have more efficient specialized         -- return frames for the situations with one non-void element. -        non_void_arg_reps = non_void (typeArgReps platform bndr_ty)+        non_void_arg_reps = typeArgReps platform bndr_ty         ubx_tuple_frame =           (isUnboxedTupleType bndr_ty || isUnboxedSumType bndr_ty) &&           length non_void_arg_reps > 1@@ -856,7 +888,7 @@         (bndr_size, call_info, args_offsets)            | ubx_tuple_frame =                let bndr_ty = primRepCmmType platform-                   bndr_reps = NE.filter (not.isVoidRep) (bcIdPrimReps bndr)+                   bndr_reps = typePrimRep (idType bndr)                    (call_info, args_offsets) =                        layoutNativeCall profile NativeTupleReturn 0 bndr_ty bndr_reps                in ( wordsToBytes platform (nativeCallSize call_info)@@ -896,7 +928,7 @@                 rhs_code <- schemeE d_alts s p_alts rhs                 return (my_discr alt, rhs_code)            | isUnboxedTupleType bndr_ty || isUnboxedSumType bndr_ty =-             let bndr_ty = primRepCmmType platform . bcIdPrimRep+             let bndr_ty = primRepCmmType platform . idPrimRepU                  tuple_start = d_bndr                  (call_info, args_offsets) =                    layoutNativeCall profile@@ -912,7 +944,7 @@                                 wordsToBytes platform (nativeCallSize call_info) +                                 offset)                         | (arg, offset) <- args_offsets-                        , not (isVoidRep $ bcIdPrimRep arg)]+                        , not (isZeroBitTy $ idType arg)]                         p_alts              in do                rhs_code <- schemeE stack_bot s p' rhs@@ -921,9 +953,7 @@            | otherwise =              let (tot_wds, _ptrs_wds, args_offsets) =                      mkVirtHeapOffsets profile NoHeader-                         [ NonVoid (bcIdPrimRep id, id)-                         | NonVoid id <- nonVoidIds real_bndrs-                         ]+                         (addIdReps (nonVoidIds real_bndrs))                  size = WordOff tot_wds                   stack_bot = d_alts + wordsToBytes platform size@@ -1017,7 +1047,7 @@           rel_slots = IntSet.toAscList $ IntSet.fromList $ Map.elems $ Map.mapMaybeWithKey spread p           spread id offset | isUnboxedTupleType (idType id) ||                              isUnboxedSumType (idType id) = Nothing-                           | isFollowableArg (bcIdArgRep platform id) = Just (fromIntegral rel_offset)+                           | isFollowableArg (idArgRep platform id) = Just (fromIntegral rel_offset)                            | otherwise                      = Nothing                 where rel_offset = bytesToWords platform (d - offset) @@ -1342,16 +1372,16 @@          non_void _       = True           nv_args :: [StgArg]-         nv_args = filter (non_void . argPrimRep) args+         nv_args = filter (non_void . stgArgRep1) args           (args_info, args_offsets) =               layoutNativeCall profile                                NativePrimCall                                0-                               (primRepCmmType platform . argPrimRep)+                               (primRepCmmType platform . stgArgRepU)                                nv_args -         prim_args_offsets = mapFst argPrimRep args_offsets+         prim_args_offsets = mapFst stgArgRepU args_offsets          shifted_args_offsets = mapSnd (+ d) args_offsets           push_target = PUSH_UBX (LitLabel target Nothing IsFunction) 1@@ -1427,7 +1457,7 @@          -- ArgRep of what was actually pushed.           pargs-             :: ByteOff -> [StgArg] -> BcM [(BCInstrList, PrimRep)]+             :: ByteOff -> [StgArg] -> BcM [(BCInstrList, PrimOrVoidRep)]          pargs _ [] = return []          pargs d (aa@(StgVarArg a):az)             | Just t      <- tyConAppTyCon_maybe (idType a)@@ -1440,10 +1470,10 @@                  -- The ptr points at the header.  Advance it over the                  -- header and then pretend this is an Addr#.                  let code = push_fo `snocOL` SWIZZLE 0 (fromIntegral hdr_sz)-                 return ((code, AddrRep) : rest)+                 return ((code, NVRep AddrRep) : rest)          pargs d (aa:az) =  do (code_a, sz_a) <- pushAtom d p aa                                rest <- pargs (d + sz_a) az-                               return ((code_a, atomPrimRep aa) : rest)+                               return ((code_a, stgArgRep1 aa) : rest)       code_n_reps <- pargs d0 args_r_to_l      let@@ -1453,8 +1483,7 @@          push_args    = concatOL pushs_arg          !d_after_args = d0 + wordsToBytes platform a_reps_sizeW          a_reps_pushed_RAW-            | x:xs <- a_reps_pushed_r_to_l-            , isVoidRep x+            | VoidRep:xs <- a_reps_pushed_r_to_l             = reverse xs             | otherwise             = panic "GHC.StgToByteCode.generateCCall: missing or invalid World token?"@@ -1464,10 +1493,7 @@          -- d_after_args is the stack depth once the args are on.           -- Get the result rep.-         (returns_void, r_rep)-            = case maybe_getCCallReturnRep result_ty of-                 Nothing -> (True,  VoidRep)-                 Just rr -> (False, rr)+         r_rep = maybe_getCCallReturnRep result_ty          {-          Because the Haskell stack grows down, the a_reps refer to          lowest to highest addresses in that order.  The args for the call@@ -1540,10 +1566,9 @@          -- this is a V (tag).          r_sizeW   = repSizeWords platform r_rep          d_after_r = d_after_Addr + wordsToBytes platform r_sizeW-         push_r =-             if returns_void-                then nilOL-                else unitOL (PUSH_UBX (mkDummyLiteral platform r_rep) (r_sizeW))+         push_r = case r_rep of+                    VoidRep -> nilOL+                    NVRep r -> unitOL (PUSH_UBX (mkDummyLiteral platform r) r_sizeW)           -- generate the marshalling code we're going to call @@ -1581,17 +1606,17 @@          -- slide and return          d_after_r_min_s = bytesToWords platform (d_after_r - s)          wrapup       = mkSlideW r_sizeW (d_after_r_min_s - r_sizeW)-                        `snocOL` RETURN (toArgRep platform r_rep)+                        `snocOL` RETURN (toArgRepOrV platform r_rep)          --trace (show (arg1_offW, args_offW  ,  (map argRepSizeW a_reps) )) $      return (          push_args `appOL`          push_Addr `appOL` push_r `appOL` do_call `appOL` wrapup          ) -primRepToFFIType :: Platform -> PrimRep -> FFIType-primRepToFFIType platform r+primRepToFFIType :: Platform -> PrimOrVoidRep -> FFIType+primRepToFFIType _ VoidRep = FFIVoid+primRepToFFIType platform (NVRep r)   = case r of-     VoidRep     -> FFIVoid      IntRep      -> signed_word      WordRep     -> unsigned_word      Int8Rep     -> FFISInt8@@ -1638,7 +1663,7 @@ --     GHC.Prim.Char# -> GHC.Prim.State# GHC.Prim.RealWorld --                   -> (# GHC.Prim.State# GHC.Prim.RealWorld, GHC.Prim.Int# #) ----- to  Just IntRep+-- to  NVRep IntRep -- and check that an unboxed pair is returned wherein the first arg is V'd. -- -- Alternatively, for call-targets returning nothing, convert@@ -1646,25 +1671,21 @@ --     GHC.Prim.Char# -> GHC.Prim.State# GHC.Prim.RealWorld --                   -> (# GHC.Prim.State# GHC.Prim.RealWorld #) ----- to  Nothing+-- to  VoidRep -maybe_getCCallReturnRep :: Type -> Maybe PrimRep+maybe_getCCallReturnRep :: Type -> PrimOrVoidRep maybe_getCCallReturnRep fn_ty    = let        (_a_tys, r_ty) = splitFunTys (dropForAlls fn_ty)-       r_reps = typePrimRepArgs r_ty--       blargh :: a -- Used at more than one type-       blargh = pprPanic "maybe_getCCallReturn: can't handle:"-                         (pprType fn_ty)      in-       case r_reps of-         VoidRep :| [] -> Nothing-         rep     :| [] -> Just rep+       case typePrimRep r_ty of+         [] -> VoidRep+         [rep] -> NVRep rep                   -- if it was, it would be impossible to create a                  -- valid return value placeholder on the stack-         _             -> blargh+         _ -> pprPanic "maybe_getCCallReturn: can't handle:"+                         (pprType fn_ty)  maybe_is_tagToEnum_call :: CgStgExpr -> Maybe (Id, [Name]) -- Detect and extract relevant info for the tagToEnum kludge.@@ -2095,7 +2116,7 @@ lookupBCEnv_maybe = Map.lookup  idSizeW :: Platform -> Id -> WordOff-idSizeW platform = WordOff . argRepSizeW platform . bcIdArgRep platform+idSizeW platform = WordOff . argRepSizeW platform . idArgRep platform  idSizeCon :: Platform -> Id -> ByteOff idSizeCon platform var@@ -2104,25 +2125,11 @@     isUnboxedSumType (idType var) =     wordsToBytes platform .     WordOff . sum . map (argRepSizeW platform . toArgRep platform) .-    NE.toList . bcIdPrimReps $ var-  | otherwise = ByteOff (primRepSizeB platform (bcIdPrimRep var))--bcIdArgRep :: Platform -> Id -> ArgRep-bcIdArgRep platform = toArgRep platform . bcIdPrimRep--bcIdPrimRep :: Id -> PrimRep-bcIdPrimRep id-  | rep :| [] <- typePrimRepArgs (idType id)-  = rep-  | otherwise-  = pprPanic "bcIdPrimRep" (ppr id <+> dcolon <+> ppr (idType id))---bcIdPrimReps :: Id -> NonEmpty PrimRep-bcIdPrimReps id = typePrimRepArgs (idType id)+    typePrimRep . idType $ var+  | otherwise = ByteOff (primRepSizeB platform (idPrimRepU var)) -repSizeWords :: Platform -> PrimRep -> WordOff-repSizeWords platform rep = WordOff $ argRepSizeW platform (toArgRep platform rep)+repSizeWords :: Platform -> PrimOrVoidRep -> WordOff+repSizeWords platform rep = WordOff $ argRepSizeW platform (toArgRepOrV platform rep)  isFollowableArg :: ArgRep -> Bool isFollowableArg P = True@@ -2158,12 +2165,8 @@   -atomPrimRep :: StgArg -> PrimRep-atomPrimRep (StgVarArg v) = bcIdPrimRep v-atomPrimRep (StgLitArg l) = typePrimRep1 (literalType l)- atomRep :: Platform -> StgArg -> ArgRep-atomRep platform e = toArgRep platform (atomPrimRep e)+atomRep platform e = toArgRepOrV platform (stgArgRep1 e)  -- | Let szsw be the sizes in bytes of some items pushed onto the stack, which -- has initial depth @original_depth@.  Return the values which the stack@@ -2171,8 +2174,8 @@ mkStackOffsets :: ByteOff -> [ByteOff] -> [ByteOff] mkStackOffsets original_depth szsb = tail (scanl' (+) original_depth szsb) -typeArgReps :: Platform -> Type -> NonEmpty ArgRep-typeArgReps platform = NE.map (toArgRep platform) . typePrimRepArgs+typeArgReps :: Platform -> Type -> [ArgRep]+typeArgReps platform = map (toArgRep platform) . typePrimRep  -- ----------------------------------------------------------------------------- -- The bytecode generator's monad@@ -2255,18 +2258,15 @@   = BcM $ \st -> let ctr = nextlabel st                  in return (st{nextlabel = ctr+n}, coerce [ctr .. ctr+n-1]) -getCCArray :: BcM (Array BreakIndex (RemotePtr CostCentre))-getCCArray = BcM $ \st ->-  let breaks = expectJust "GHC.StgToByteCode.getCCArray" $ modBreaks st in-  return (st, modBreaks_ccs breaks)-- newBreakInfo :: BreakIndex -> CgBreakInfo -> BcM () newBreakInfo ix info = BcM $ \st ->   return (st{breakInfo = IntMap.insert ix info (breakInfo st)}, ()) -getCurrentModuleName :: BcM (Maybe (RemotePtr ModuleName))-getCurrentModuleName = BcM $ \st -> return (st, modBreaks_module <$> modBreaks st)+getCurrentModule :: BcM Module+getCurrentModule = BcM $ \st -> return (st, thisModule st)++getCurrentModBreaks :: BcM (Maybe ModBreaks)+getCurrentModBreaks = BcM $ \st -> return (st, modBreaks st)  tickFS :: FastString tickFS = fsLit "ticked"
compiler/GHC/StgToCmm.hs view
@@ -1,6 +1,5 @@  {-# LANGUAGE DataKinds #-}-{-# LANGUAGE BangPatterns #-} {-# LANGUAGE LambdaCase #-}  -----------------------------------------------------------------------------@@ -54,7 +53,6 @@  import GHC.Utils.Error import GHC.Utils.Outputable-import GHC.Utils.Panic.Plain import GHC.Utils.Logger  import GHC.Utils.TmpFs@@ -68,7 +66,7 @@ import System.IO.Unsafe import qualified Data.ByteString as BS import Data.IORef-import GHC.Utils.Panic (assertPpr)+import GHC.Utils.Panic  codeGen :: Logger         -> TmpFs@@ -103,10 +101,6 @@                 yield cmm                 return a -               -- Note [codegen-split-init] the cmm_init block must come-               -- FIRST.  This is because when -split-objs is on we need to-               -- combine this block with its initialisation routines; see-               -- Note [pipeline-split-init].         ; cg (mkModuleInit cost_centre_info (stgToCmmThisModule cfg) hpc_info)          ; mapM_ (cg . cgTopBinding logger tmpfs cfg) stg_binds@@ -258,11 +252,11 @@              -- We're generating info tables, so we don't know and care about             -- what the actual arguments are. Using () here as the place holder.-            arg_reps :: [NonVoid PrimRep]-            arg_reps = [ NonVoid rep_ty+            arg_reps :: [PrimRep]+            arg_reps = [ rep_ty                        | ty <- dataConRepArgTys data_con                        , rep_ty <- typePrimRep (scaledThing ty)-                       , not (isVoidRep rep_ty) ]+                       ]          ; emitClosureAndInfoTable platform dyn_info_tbl NativeDirectCall [] $             -- NB: the closure pointer is assumed *untagged* on
compiler/GHC/StgToCmm/ArgRep.hs view
@@ -9,7 +9,7 @@ {-# LANGUAGE LambdaCase #-}  module GHC.StgToCmm.ArgRep (-        ArgRep(..), toArgRep, argRepSizeW,+        ArgRep(..), toArgRep, toArgRepOrV, argRepSizeW,          argRepString, isNonV, idArgRep, @@ -20,10 +20,10 @@ import GHC.Prelude import GHC.Platform -import GHC.StgToCmm.Closure    ( idPrimRep )+import GHC.StgToCmm.Closure    ( idPrimRep1 ) import GHC.Runtime.Heap.Layout ( WordOff ) import GHC.Types.Id            ( Id )-import GHC.Core.TyCon          ( PrimRep(..), primElemRepSizeB )+import GHC.Core.TyCon          ( PrimRep(..), PrimOrVoidRep(..), primElemRepSizeB ) import GHC.Types.Basic         ( RepArity ) import GHC.Settings.Constants  ( wORD64_SIZE, dOUBLE_SIZE ) @@ -68,7 +68,6 @@  toArgRep :: Platform -> PrimRep -> ArgRep toArgRep platform rep = case rep of-   VoidRep           -> V    BoxedRep _        -> P    IntRep            -> N    WordRep           -> N@@ -93,6 +92,10 @@                            64 -> V64                            _  -> error "toArgRep: bad vector primrep" +toArgRepOrV :: Platform -> PrimOrVoidRep -> ArgRep+toArgRepOrV _ VoidRep = V+toArgRepOrV platform (NVRep rep) = toArgRep platform rep+ isNonV :: ArgRep -> Bool isNonV V = False isNonV _ = True@@ -112,7 +115,7 @@    ws       = platformWordSizeInBytes platform  idArgRep :: Platform -> Id -> ArgRep-idArgRep platform = toArgRep platform . idPrimRep+idArgRep platform = toArgRepOrV platform . idPrimRep1  -- This list of argument patterns should be kept in sync with at least -- the following:
compiler/GHC/StgToCmm/Bind.hs view
@@ -123,26 +123,10 @@   -- StgStdThunks.cmm.   gen_code _ closure_label     | null args-    , StgApp f [arg] <- stripStgTicksTopE (not . tickishIsCode) body-    , Just unpack <- is_string_unpack_op f-    = do arg' <- getArgAmode (NonVoid arg)-         case arg' of-           CmmLit lit -> do-             let info = CmmInfoTable-                   { cit_lbl = unpack-                   , cit_rep = HeapRep True 0 1 Thunk-                   , cit_prof = NoProfilingInfo-                   , cit_srt = Nothing-                   , cit_clo = Nothing-                   }-             emitDecl $ CmmData (Section Data closure_label) $-                 CmmStatics closure_label info ccs [] [lit]-           _ -> panic "cgTopRhsClosure.gen_code"-    where-      is_string_unpack_op f-        | idName f == unpackCStringName     = Just mkRtsUnpackCStringLabel-        | idName f == unpackCStringUtf8Name = Just mkRtsUnpackCStringUtf8Label-        | otherwise                         = Nothing+    , Just gen <- isUnpackCStringClosure body+    = do (info, lit) <- gen+         emitDecl $ CmmData (Section Data closure_label) $+             CmmStatics closure_label info ccs [] [lit]    gen_code lf_info _closure_label    = do { profile <- getProfile@@ -168,6 +152,41 @@   unLit (CmmLit l) = l   unLit _ = panic "unLit" +isUnpackCStringClosure :: CgStgExpr -> Maybe (FCode (CmmInfoTable, CmmLit))+isUnpackCStringClosure body = case stripStgTicksTopE (not . tickishIsCode) body of+  StgApp f [arg]+    | Just unpack <- is_string_unpack_op f+    -> Just $ do+        arg' <- getArgAmode (NonVoid arg)+        case arg' of+          CmmLit lit -> do+            let info = CmmInfoTable+                  { cit_lbl = unpack+                  , cit_rep = HeapRep True 0 1 Thunk+                  , cit_prof = NoProfilingInfo+                  , cit_srt = Nothing+                  , cit_clo = Nothing+                  }+            return (info, lit)+          _ -> panic "isUnpackCStringClosure: not a lit"+  StgCase (StgLit l) b _ [alt]+    -- In -O0, we might get strings that haven't been floated to top-level, e.g.,+    --   case "undefined"# of sat {+    --     __DEFAULT -> unpackCString# sat+    --   }+    -- This case is supposed to catch that.+    | Just gen <- isUnpackCStringClosure (alt_rhs alt)+    -> Just $ do+        e <- cgLit l+        addBindC (mkCgIdInfo b mkLFStringLit e)+        gen+  _ -> Nothing+  where+    is_string_unpack_op f+      | idName f == unpackCStringName     = Just mkRtsUnpackCStringLabel+      | idName f == unpackCStringUtf8Name = Just mkRtsUnpackCStringUtf8Label+      | otherwise                         = Nothing+ ------------------------------------------------------------------------ --              Non-top-level bindings ------------------------------------------------------------------------@@ -363,7 +382,7 @@                                -- args are all distinct local variables                                -- The "-1" is for fun_id     -- Missed opportunity:   (f x x) is not detected-  , all (isGcPtrRep . idPrimRep . fromNonVoid) fvs+  , all (isGcPtrRep . idPrimRepU . fromNonVoid) fvs   , isUpdatable upd_flag   , n_fvs <= pc_MAX_SPEC_AP_SIZE (profileConstants profile)   , not (profileIsProfiling profile)@@ -744,7 +763,8 @@               lbl | bh        = mkBHUpdInfoLabel                   | otherwise = mkUpdInfoLabel -          pushUpdateFrame lbl (CmmReg (CmmLocal node)) body+          pushOrigThunkInfoFrame closure_info+            $ pushUpdateFrame lbl (CmmReg (CmmLocal node)) body    | otherwise   -- A static closure   = do  { tickyUpdateBhCaf closure_info@@ -752,7 +772,8 @@         ; if closureUpdReqd closure_info           then do       -- Blackhole the (updatable) CAF:                 { upd_closure <- link_caf node-                ; pushUpdateFrame mkBHUpdInfoLabel upd_closure body }+                ; pushOrigThunkInfoFrame closure_info+                    $ pushUpdateFrame mkBHUpdInfoLabel upd_closure body }           else do {tickyUpdateFrameOmitted; body}     } @@ -768,8 +789,7 @@   = do        updfr  <- getUpdFrameOff        profile <- getProfile-       let-           hdr         = fixedHdrSize profile+       let hdr         = fixedHdrSize profile            frame       = updfr + hdr + pc_SIZEOF_StgUpdateFrame_NoHdr (profileConstants profile)        --        emitUpdateFrame (CmmStackSlot Old frame) lbl updatee@@ -786,6 +806,47 @@   emitStore frame (mkLblExpr lbl)   emitStore (cmmOffset platform frame off_updatee) updatee   initUpdFrameProf frame++-----------------------------------------------------------------------------+-- Original thunk info table frames+--+-- Note [Original thunk info table frames]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- In some debugging scenarios (e.g. when debugging cyclic thunks) it can be very+-- useful to know which thunks the program is in the process of evaluating.+-- However, in the case of updateable thunks this can be very difficult+-- to determine since the process of blackholing overwrites the thunk's+-- info table pointer.+--+-- To help in such situations we provide the -forig-thunk-info flag. This enables+-- code generation logic which pushes a stg_orig_thunk_info_frame stack frame to+-- accompany each update frame. As the name suggests, this frame captures the+-- the original info table of the thunk being updated. The entry code for these+-- frames has no operational effects; the frames merely exist as breadcrumbs+-- for debugging.++pushOrigThunkInfoFrame :: ClosureInfo -> FCode () -> FCode ()+pushOrigThunkInfoFrame closure_info body = do+  cfg <- getStgToCmmConfig+  if stgToCmmOrigThunkInfo cfg+     then do_it+     else body+  where+    orig_itbl = mkLblExpr (closureInfoLabel closure_info)+    do_it = do+      updfr <- getUpdFrameOff+      profile <- getProfile+      let platform = profilePlatform profile+          hdr = fixedHdrSize profile+          orig_info_frame_sz =+              hdr + pc_SIZEOF_StgOrigThunkInfoFrame_NoHdr (profileConstants profile)+          off_orig_info = hdr + pc_OFFSET_StgOrigThunkInfoFrame_info_ptr (profileConstants profile)+          frame_off = updfr + orig_info_frame_sz+          frame = CmmStackSlot Old frame_off+      --+      emitStore frame (mkLblExpr mkOrigThunkInfoLabel)+      emitStore (cmmOffset platform frame off_orig_info) orig_itbl+      withUpdFrameOff frame_off body  ----------------------------------------------------------------------------- -- Entering a CAF
compiler/GHC/StgToCmm/CgUtils.hs view
@@ -1,5 +1,4 @@ {-# LANGUAGE GADTs #-}-{-# LANGUAGE BangPatterns #-}  ----------------------------------------------------------------------------- --
compiler/GHC/StgToCmm/Closure.hs view
@@ -18,8 +18,7 @@ module GHC.StgToCmm.Closure (         DynTag,  tagForCon, isSmallFamily, -        idPrimRep, isVoidRep, isGcPtrRep, addIdReps, addArgReps,-        argPrimRep,+        idPrimRep1, idPrimRepU, isGcPtrRep, addIdReps, addArgReps,          NonVoid(..), fromNonVoid, nonVoidIds, nonVoidStgArgs,         assertNonVoidIds, assertNonVoidStgArgs,@@ -94,7 +93,6 @@ import GHC.Types.Basic import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Data.Maybe (isNothing)  import Data.Coerce (coerce)@@ -161,13 +159,13 @@                        coerce ids  nonVoidStgArgs :: [StgArg] -> [NonVoid StgArg]-nonVoidStgArgs args = [NonVoid arg | arg <- args, not (isZeroBitTy (stgArgType arg))]+nonVoidStgArgs args = [NonVoid arg | arg <- args, not (null (stgArgRep arg))]  -- | Used in places where some invariant ensures that all these arguments are -- non-void; e.g. constructor arguments. -- See Note [Post-unarisation invariants] in "GHC.Stg.Unarise". assertNonVoidStgArgs :: [StgArg] -> [NonVoid StgArg]-assertNonVoidStgArgs args = assert (not (any (isZeroBitTy . stgArgType) args)) $+assertNonVoidStgArgs args = assert (not (any (null . stgArgRep) args)) $                             coerce args  @@ -177,29 +175,27 @@  -- Why are these here? --- | Assumes that there is precisely one 'PrimRep' of the type. This assumption+-- | Assumes that there is at most one 'PrimRep' of the type. This assumption -- holds after unarise.--- See Note [Post-unarisation invariants]-idPrimRep :: Id -> PrimRep-idPrimRep id = typePrimRep1 (idType id)-    -- See also Note [VoidRep] in GHC.Types.RepType+-- See Note [Post-unarisation invariants] in GHC.Stg.Unarise.+-- See Note [VoidRep] in GHC.Types.RepType.+idPrimRep1 :: Id -> PrimOrVoidRep+idPrimRep1 id = typePrimRep1 (idType id) +idPrimRepU :: Id -> PrimRep+idPrimRepU id = typePrimRepU (idType id)+ -- | Assumes that Ids have one PrimRep, which holds after unarisation.--- See Note [Post-unarisation invariants]+-- See Note [Post-unarisation invariants] in GHC.Stg.Unarise. addIdReps :: [NonVoid Id] -> [NonVoid (PrimRep, Id)] addIdReps = map (\id -> let id' = fromNonVoid id-                         in NonVoid (idPrimRep id', id'))+                         in NonVoid (idPrimRepU id', id'))  -- | Assumes that arguments have one PrimRep, which holds after unarisation.--- See Note [Post-unarisation invariants]+-- See Note [Post-unarisation invariants] in GHC.Stg.Unarise. addArgReps :: [NonVoid StgArg] -> [NonVoid (PrimRep, StgArg)] addArgReps = map (\arg -> let arg' = fromNonVoid arg-                           in NonVoid (argPrimRep arg', arg'))---- | Assumes that the argument has one PrimRep, which holds after unarisation.--- See Note [Post-unarisation invariants]-argPrimRep :: StgArg -> PrimRep-argPrimRep arg = typePrimRep1 (stgArgType arg)+                           in NonVoid (stgArgRepU arg', arg'))  ------------------------------------------------------ --                Building LambdaFormInfo
compiler/GHC/StgToCmm/DataCon.hs view
@@ -45,7 +45,6 @@ import GHC.Types.Literal import GHC.Builtin.Utils import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Misc import GHC.Utils.Monad (mapMaybeM) 
compiler/GHC/StgToCmm/Env.hs view
@@ -10,7 +10,7 @@ module GHC.StgToCmm.Env (         CgIdInfo, -        litIdInfo, lneIdInfo, rhsIdInfo, mkRhsInit,+        mkCgIdInfo, litIdInfo, lneIdInfo, rhsIdInfo, mkRhsInit,         idInfoToAmode,          addBindC, addBindsC,@@ -43,7 +43,6 @@  import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain  import GHC.Builtin.Names (getUnique) @@ -206,4 +205,4 @@ -- about accidental collision idToReg platform (NonVoid id)              = LocalReg (idUnique id)-                        (primRepCmmType platform (idPrimRep id))+                        (primRepCmmType platform (idPrimRepU id))
compiler/GHC/StgToCmm/Expr.hs view
@@ -1,5 +1,4 @@ {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}-{-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-} {-# LANGUAGE TypeFamilies #-} @@ -37,7 +36,7 @@ import GHC.Cmm.BlockId import GHC.Cmm hiding ( succ ) import GHC.Cmm.Info-import GHC.Cmm.Utils ( zeroExpr, cmmTagMask, mkWordCLit, mAX_PTR_TAG )+import GHC.Cmm.Utils ( cmmTagMask, mkWordCLit, mAX_PTR_TAG ) import GHC.Core import GHC.Core.DataCon import GHC.Types.ForeignCall@@ -53,7 +52,6 @@ import GHC.Data.FastString import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain  import Control.Monad ( unless, void ) import Control.Arrow ( first )@@ -74,55 +72,51 @@ cgExpr (StgOpApp (StgPrimOp SeqOp) [StgVarArg a, _] _res_ty) =   cgIdApp a [] --- dataToTag# :: a -> Int#--- See Note [dataToTag# magic] in GHC.Core.Opt.ConstantFold--- TODO: There are some more optimization ideas for this code path--- in #21710-cgExpr (StgOpApp (StgPrimOp DataToTagOp) [StgVarArg a] _res_ty) = do+-- dataToTagSmall# :: a_levpoly -> Int#+-- See Note [DataToTag overview] in GHC.Tc.Instance.Class,+-- particularly wrinkles H3 and DTW4+cgExpr (StgOpApp (StgPrimOp DataToTagSmallOp) [StgVarArg a] _res_ty) = do   platform <- getPlatform-  emitComment (mkFastString "dataToTag#")-  info <- getCgIdInfo a-  let amode = idInfoToAmode info-  tag_reg <- assignTemp $ cmmConstrTag1 platform amode+  emitComment (mkFastString "dataToTagSmall#")++  a_eval_reg <- newTemp (bWord platform)+  _ <- withSequel (AssignTo [a_eval_reg] False) (cgIdApp a [])+  let a_eval_expr = CmmReg (CmmLocal a_eval_reg)+      tag1 = cmmConstrTag1 platform a_eval_expr++  -- subtract 1 because we need to return a zero-indexed tag+  emitReturn [cmmSubWord platform tag1 (CmmLit $ mkWordCLit platform 1)]++-- dataToTagLarge# :: a_levpoly -> Int#+-- See Note [DataToTag overview] in GHC.Tc.Instance.Class,+-- particularly wrinkles H3 and DTW4+cgExpr (StgOpApp (StgPrimOp DataToTagLargeOp) [StgVarArg a] _res_ty) = do+  platform <- getPlatform+  emitComment (mkFastString "dataToTagLarge#")++  a_eval_reg <- newTemp (bWord platform)+  _ <- withSequel (AssignTo [a_eval_reg] False) (cgIdApp a [])+  let a_eval_expr = CmmReg (CmmLocal a_eval_reg)++  tag1_reg <- assignTemp $ cmmConstrTag1 platform a_eval_expr   result_reg <- newTemp (bWord platform)-  let tag = CmmReg $ CmmLocal tag_reg-      is_tagged = cmmNeWord platform tag (zeroExpr platform)-      is_too_big_tag = cmmEqWord platform tag (cmmTagMask platform)-  -- Here we will first check the tag bits of the pointer we were given;-  -- if this doesn't work then enter the closure and use the info table-  -- to determine the constructor. Note that all tag bits set means that-  -- the constructor index is too large to fit in the pointer and therefore-  -- we must look in the info table. See Note [Tagging big families].+  let tag1_expr = CmmReg $ CmmLocal tag1_reg+      is_too_big_tag = cmmEqWord platform tag1_expr (cmmTagMask platform) -  (fast_path :: CmmAGraph) <- getCode $ do-      -- Return the constructor index from the pointer tag-      return_ptr_tag <- getCode $ do-          emitAssign (CmmLocal result_reg)-            $ cmmSubWord platform tag (CmmLit $ mkWordCLit platform 1)-      -- Return the constructor index recorded in the info table-      return_info_tag <- getCode $ do-          profile     <- getProfile-          align_check <- stgToCmmAlignCheck <$> getStgToCmmConfig-          emitAssign (CmmLocal result_reg)-            $ getConstrTag profile align_check (cmmUntag platform amode)+  -- Return the constructor index from the pointer tag+  -- (Used if pointer tag is small enough to be unambiguous)+  return_ptr_tag <- getCode $ do+    emitAssign (CmmLocal result_reg)+      $ cmmSubWord platform tag1_expr (CmmLit $ mkWordCLit platform 1) -      emit =<< mkCmmIfThenElse' is_too_big_tag return_info_tag return_ptr_tag (Just False)-  -- If we know the argument is already tagged there is no need to generate code to evaluate it-  -- so we skip straight to the fast path. If we don't know if there is a tag we take the slow-  -- path which evaluates the argument before fetching the tag.-  case (idTagSig_maybe a) of-    Just sig-      | isTaggedSig sig-      -> emit fast_path-    _ -> do-          slow_path <- getCode $ do-              tmp <- newTemp (bWord platform)-              _ <- withSequel (AssignTo [tmp] False) (cgIdApp a [])-              profile     <- getProfile-              align_check <- stgToCmmAlignCheck <$> getStgToCmmConfig-              emitAssign (CmmLocal result_reg)-                $ getConstrTag profile align_check (cmmUntag platform (CmmReg (CmmLocal tmp)))-          emit =<< mkCmmIfThenElse' is_tagged fast_path slow_path (Just True)+  -- Return the constructor index recorded in the info table+  return_info_tag <- getCode $ do+    profile     <- getProfile+    align_check <- stgToCmmAlignCheck <$> getStgToCmmConfig+    emitAssign (CmmLocal result_reg)+      $ getConstrTag profile align_check (cmmUntag platform a_eval_expr)++  emit =<< mkCmmIfThenElse' is_too_big_tag return_info_tag return_ptr_tag (Just False)   emitReturn [CmmReg $ CmmLocal result_reg]  @@ -240,6 +234,8 @@ the case forces an evaluation, or if there is a primitive op which can trigger GC. +NB: things are not settled here: see #8326.+ A more interesting situation is this (a Plan-B situation)          !P!;@@ -447,25 +443,53 @@  Note [Dead-binder optimisation] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-A case-binder, or data-constructor argument, may be marked as dead,-because we preserve occurrence-info on binders in GHC.Core.Tidy (see+Consider:++   case x of (y, z<dead>) -> rhs++where `z` is unused in `rhs`.  When we return form the eval of `x`,+GHC.StgToCmm.DataCon.bindConArgs will generate some loads, assuming the the+value of `x` is returned in R1:+   y := R1[1]+   z := R1[2]++If `z` is never used, the load `z := R1[2]` is a waste of a memory operation.+CmmSink (which sinks loads to their usage sites, if any) will eliminate the dead+load; but+  1. CmmSink only runs with -O+  2. It would save CmmSink work if we simply did not generate the load in the+  first place.++Hence STG uses dead-binder information, in `bindConArgs` to drop dead loads.+That's why we preserve occurrence-info on binders in GHC.Core.Tidy (see GHC.Core.Tidy.tidyIdBndr). -If the binder is dead, we can sometimes eliminate a load.  While-CmmSink will eliminate that load, it's very easy to kill it at source-(giving CmmSink less work to do), and in any case CmmSink only runs-with -O. Since the majority of case binders are dead, this-optimisation probably still has a great benefit-cost ratio and we want-to keep it for -O0. See also Phab:D5358.+So it's important that deadness is accurate.  But StgCse can invalidate it+(#14895 #24233).  Here is an example: -This probably also was the reason for occurrence hack in Phab:D5339 to-exist, perhaps because the occurrence information preserved by-'GHC.Core.Tidy.tidyIdBndr' was insufficient.  But now that CmmSink does the-job we deleted the hacks.+  map_either :: (a -> b) -> Either String a -> Either String b+  map_either = \f e -> case e of b<dead> {+    Right x -> Right (f x)+    Left  x -> Left x+  }++  The case-binder "b" is dead (not used in the rhss of the alternatives).+  StgCse notices that `Left x` doesn't need to be allocated as we can reuse `b`,+  and we get:++  map_either :: (a -> b) -> Either String a -> Either String b+  map_either = \f e -> case e of b { -- b no longer dead!+    Right x -> Right (f x)+    Left  x -> b+  }++For now StgCse simply zaps occurrence information on case binders. A more+accurate update would complexify the implementation and doesn't seem worth it.+ -}  cgCase (StgApp v []) _ (PrimAlt _) alts-  | isVoidRep (idPrimRep v)  -- See Note [Scrutinising VoidRep]+  | isZeroBitTy (idType v)  -- See Note [Scrutinising VoidRep]   , [GenStgAlt{alt_con=DEFAULT, alt_bndrs=_, alt_rhs=rhs}] <- alts   = cgExpr rhs @@ -499,9 +523,9 @@        ; _ <- bindArgToReg (NonVoid bndr)        ; cgAlts (NoGcInAlts,AssignedDirectly) (NonVoid bndr) alt_type alts }   where-    reps_compatible platform = primRepCompatible platform (idPrimRep v) (idPrimRep bndr)+    reps_compatible platform = primRepCompatible platform (idPrimRepU v) (idPrimRepU bndr) -    pp_bndr id = ppr id <+> dcolon <+> ppr (idType id) <+> parens (ppr (idPrimRep id))+    pp_bndr id = ppr id <+> dcolon <+> ppr (idType id) <+> parens (ppr (idPrimRepU id))  {- Note [Dodgy unsafeCoerce 2, #3132] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -547,6 +571,58 @@     -- Use the same return convention as vanilla 'a'.     cgCase (StgApp a []) bndr alt_type alts +{-+Note [Eliminate trivial Solo# continuations]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+If we have code like this:++    case scrut of bndr {+      alt -> Solo# bndr+    }++The RHS of the only branch does nothing except wrap the case-binder+returned by 'scrut' in a unary unboxed tuple.  But unboxed tuples+don't exist at run-time, i.e. the branch is a no-op!  So we can+generate code as if we just had 'scrut' instead of a case-expression.++This situation can easily arise for IO or ST code, where the last+operation a function performs is commonly 'pure $! someExpr'.+See also #24264 and !11778.  More concretely, as of December 2023,+when building a stage2 "perf+no_profiled_libs" ghc:++ * The special case is reached 398 times.+ * Of these, 158 have scrutinees that call a function or enter a+   potential thunk, and would need to push a useless stack frame if+   not for this optimisation.++We might consider rewriting such case expressions in GHC.Stg.CSE as a+slight extension of Note [All alternatives are the binder].  But the+RuntimeReps of 'bndr' and 'Solo# bndr' are not exactly the same, and+per Note [Typing the STG language] in GHC.Stg.Lint, we do expect Stg+code to remain RuntimeRep-correct.  So we just detect the situation in+StgToCmm instead.++Crucially, the return conventions for 'ty' and '(# ty #)' are compatible:+The returned value is passed in the same register(s) or stack slot in+both conventions, and the set of allowed return values for 'ty'+is a subset of the allowed return values for '(# ty #)':++ * For a lifted type 'ty', the return convention for 'ty' promises to+   return an evaluated-properly-tagged heap pointer, while a return+   type '(# ty #)' only promises to return a heap pointer to an object+   that can be evaluated later if need be.++ * If 'ty' is unlifted, the allowed return+   values for 'ty' and '(# ty #)' are identical.+-}++cgCase scrut bndr _alt_type [GenStgAlt { alt_rhs = rhs}]+  -- see Note [Eliminate trivial Solo# continuations]+  | StgConApp dc _ [StgVarArg v] _ <- rhs+  , isUnboxedTupleDataCon dc+  , v == bndr+  = cgExpr scrut+ cgCase scrut bndr alt_type alts   = -- the general case     do { platform <- getPlatform@@ -578,20 +654,10 @@  {- Note [GC for conditionals] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-For boolean conditionals it seems that we have always done NoGcInAlts.-That is, we have always done the GC check before the conditional.-This is enshrined in the special case for-   case tagToEnum# (a>b) of ...-See Note [case on bool]--It's odd, and it's flagrantly inconsistent with the rules described-Note [Compiling case expressions].  However, after eliminating the-tagToEnum# (#13397) we will have:-   case (a>b) of ...-Rather than make it behave quite differently, I am testing for a-comparison operator here in the general case as well.--ToDo: figure out what the Right Rule should be.+For comparison operators (`is_cmp_op`) it seems that we have always done+NoGcInAlts.  It's odd, and it's flagrantly inconsistent with the rules described+Note [Compiling case expressions].  However, that's the way it has been for ages+(there was some long-gone history involving tagToEnum#; see #13397, #8317, #8326).  Note [scrut sequel] ~~~~~~~~~~~~~~~~~~~@@ -639,8 +705,10 @@ isSimpleOp :: StgOp -> [StgArg] -> FCode Bool -- True iff the op cannot block or allocate isSimpleOp (StgFCallOp (CCall (CCallSpec _ _ safe)) _) _ = return $! not (playSafe safe)--- dataToTag# evaluates its argument, see Note [dataToTag# magic] in GHC.Core.Opt.ConstantFold-isSimpleOp (StgPrimOp DataToTagOp) _ = return False+-- dataToTagSmall#/dataToTagLarge# evaluate an argument;+-- see Note [DataToTag overview] in GHC.Tc.Instance.Class+isSimpleOp (StgPrimOp DataToTagSmallOp) _ = return False+isSimpleOp (StgPrimOp DataToTagLargeOp) _ = return False isSimpleOp (StgPrimOp op) stg_args                  = do     arg_exprs <- getNonVoidArgAmodes stg_args     cfg       <- getStgToCmmConfig@@ -851,6 +919,7 @@   -- Note [alg-alt heap check]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~ -- -- In an algebraic case with more than one alternative, we will have -- code like@@ -1027,7 +1096,7 @@                       (text "TagCheck failed on entry in" <+> ppr mod <+> text "- value:" <> ppr fun_id <+> pdoc platform fun))                       fun -        EnterIt -> assert (null args) $  -- Discarding arguments+        EnterIt -> assertPpr (null args) (ppr fun_id $$ ppr args) $  -- Discarding arguments                    emitEnter fun          SlowCall -> do      -- A slow function call via the RTS apply routines
compiler/GHC/StgToCmm/InfoTableProv.hs view
@@ -6,7 +6,6 @@  #if defined(HAVE_LIBZSTD) import Foreign.C.Types-import Foreign.Marshal.Utils (copyBytes) import qualified Data.ByteString.Internal as BSI import GHC.IO (unsafePerformIO) #endif@@ -84,9 +83,11 @@         platform = stgToCmmPlatform cfg         int n    = mkIntCLit platform n -        (cg_ipes, strtab) = flip runState emptyStringTable $ do-          module_name <- lookupStringTable $ ST.pack $ renderWithContext ctx (ppr this_mod)-          mapM (toCgIPE platform ctx module_name) ents+        ((cg_ipes, unit_id, module_name), strtab) = flip runState emptyStringTable $ do+          unit_id <- lookupStringTable $ ST.pack $ renderWithContext ctx (ppr $ moduleName this_mod)+          module_name <- lookupStringTable $ ST.pack $ renderWithContext ctx (ppr $ moduleUnit this_mod)+          cg_ipes <- mapM (toCgIPE platform ctx) ents+          return (cg_ipes, unit_id, module_name)          tables :: [CmmStatic]         tables = map (CmmStaticLit . CmmLabel . ipeInfoTablePtr) cg_ipes@@ -137,6 +138,12 @@              -- 'string_table_size' field (decompressed size)           , int $ BS.length uncompressed_strings++            -- 'module_name' field+          , CmmInt (fromIntegral module_name) W32++            -- 'unit_id' field+          , CmmInt (fromIntegral unit_id) W32           ]      -- Emit the list of info table pointers@@ -174,10 +181,8 @@       , ipeClosureDesc cg_ipe       , ipeTypeDesc cg_ipe       , ipeLabel cg_ipe-      , ipeModuleName cg_ipe       , ipeSrcFile cg_ipe       , ipeSrcSpan cg_ipe-      , 0 -- padding       ]      word32Builder :: Word32 -> BSB.Builder@@ -185,8 +190,8 @@       BigEndian    -> BSB.word32BE       LittleEndian -> BSB.word32LE -toCgIPE :: Platform -> SDocContext -> StrTabOffset -> InfoProvEnt -> State StringTable CgInfoProvEnt-toCgIPE platform ctx module_name ipe = do+toCgIPE :: Platform -> SDocContext -> InfoProvEnt -> State StringTable CgInfoProvEnt+toCgIPE platform ctx ipe = do     table_name <- lookupStringTable $ ST.pack $ renderWithContext ctx (pprCLabel platform (infoTablePtr ipe))     closure_desc <- lookupStringTable $ ST.pack $ show (infoProvEntClosureType ipe)     type_desc <- lookupStringTable $ ST.pack $ infoTableType ipe@@ -206,7 +211,6 @@                            , ipeClosureDesc = closure_desc                            , ipeTypeDesc = type_desc                            , ipeLabel = label-                           , ipeModuleName = module_name                            , ipeSrcFile = src_file                            , ipeSrcSpan = src_span                            }@@ -217,7 +221,6 @@                                , ipeClosureDesc :: !StrTabOffset                                , ipeTypeDesc :: !StrTabOffset                                , ipeLabel :: !StrTabOffset-                               , ipeModuleName :: !StrTabOffset                                , ipeSrcFile :: !StrTabOffset                                , ipeSrcSpan :: !StrTabOffset                                }
compiler/GHC/StgToCmm/Layout.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE BangPatterns #-} {-# LANGUAGE CPP #-}  -----------------------------------------------------------------------------@@ -26,7 +25,7 @@         mkVirtConstrSizes,         getHpRelOffset, -        ArgRep(..), toArgRep, argRepSizeW, -- re-exported from GHC.StgToCmm.ArgRep+        ArgRep(..), toArgRep, toArgRepOrV, idArgRep, argRepSizeW, -- re-exported from GHC.StgToCmm.ArgRep         getArgAmode, getNonVoidArgAmodes   ) where @@ -50,7 +49,7 @@ import GHC.Cmm.CLabel import GHC.Stg.Syntax import GHC.Types.Id-import GHC.Core.TyCon    ( PrimRep(..), primRepSizeB )+import GHC.Core.TyCon    ( PrimRep(..), PrimOrVoidRep(..), primRepSizeB ) import GHC.Types.Basic   ( RepArity ) import GHC.Platform import GHC.Platform.Profile@@ -60,7 +59,6 @@ import Data.List (mapAccumL, partition) import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Constants (debugIsOn) import GHC.Data.FastString import Control.Monad@@ -329,10 +327,10 @@    platform <- profilePlatform <$> getProfile    mapM (getArgRepAmode platform) args   where getArgRepAmode platform arg-           | V <- rep  = return (V, Nothing)-           | otherwise = do expr <- getArgAmode (NonVoid arg)-                            return (rep, Just expr)-           where rep = toArgRep platform (argPrimRep arg)+           = case stgArgRep1 arg of+               VoidRep -> return (V, Nothing)+               NVRep rep -> do expr <- getArgAmode (NonVoid arg)+                               return (toArgRep platform rep, Just expr)  nonVArgs :: [(ArgRep, Maybe CmmExpr)] -> [CmmExpr] nonVArgs [] = []@@ -439,7 +437,6 @@ -- than the unboxed things  mkVirtHeapOffsetsWithPadding profile header things =-    assert (not (any (isVoidRep . fst . fromNonVoid) things))     ( tot_wds     , bytesToWordsRoundUp platform bytes_of_ptrs     , concat (ptrs_w_offsets ++ non_ptrs_w_offsets) ++ final_pad@@ -521,13 +518,13 @@ -- | Just like mkVirtConstrOffsets, but used when we don't have the actual -- arguments. Useful when e.g. generating info tables; we just need to know -- sizes of pointer and non-pointer fields.-mkVirtConstrSizes :: Profile -> [NonVoid PrimRep] -> (WordOff, WordOff)+mkVirtConstrSizes :: Profile -> [PrimRep] -> (WordOff, WordOff) mkVirtConstrSizes profile field_reps   = (tot_wds, ptr_wds)   where     (tot_wds, ptr_wds, _) =        mkVirtConstrOffsets profile-         (map (\nv_rep -> NonVoid (fromNonVoid nv_rep, ())) field_reps)+         (map (\nv_rep -> NonVoid (nv_rep, ())) field_reps)  ------------------------------------------------------------------------- --@@ -604,12 +601,7 @@ getNonVoidArgAmodes :: [StgArg] -> FCode [CmmExpr] -- NB: Filters out void args, --     so the result list may be shorter than the argument list-getNonVoidArgAmodes [] = return []-getNonVoidArgAmodes (arg:args)-  | isVoidRep (argPrimRep arg) = getNonVoidArgAmodes args-  | otherwise = do { amode  <- getArgAmode (NonVoid arg)-                   ; amodes <- getNonVoidArgAmodes args-                   ; return ( amode : amodes ) }+getNonVoidArgAmodes args = mapM getArgAmode (nonVoidStgArgs args)  ------------------------------------------------------------------------- --
compiler/GHC/StgToCmm/Lit.hs view
@@ -52,7 +52,6 @@  -- not unpackFS; we want the UTF-8 byte stream. cgLit (LitRubbish _ rep) =   case expectOnly "cgLit" prim_reps of -- Note [Post-unarisation invariants]-    VoidRep     -> panic "cgLit:VoidRep"   -- ditto     BoxedRep _  -> idInfoToAmode <$> getCgIdInfo unitDataConId     AddrRep     -> cgLit LitNullAddr     VecRep n elem -> do
compiler/GHC/StgToCmm/Monad.hs view
@@ -73,10 +73,10 @@ import GHC.StgToCmm.Config import GHC.StgToCmm.Closure import GHC.StgToCmm.Sequel-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Graph as CmmGraph import GHC.Cmm.BlockId import GHC.Cmm.CLabel+import GHC.Cmm.Dataflow.Label import GHC.Runtime.Heap.Layout import GHC.Unit import GHC.Types.Id
compiler/GHC/StgToCmm/Prim.hs view
@@ -45,7 +45,6 @@ import GHC.Data.FastString import GHC.Utils.Misc import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import Data.Maybe  import Control.Monad (liftM, when, unless)@@ -141,7 +140,7 @@ -- -- In more complex cases, there is a foreign call (out of line) fallback. This -- might happen e.g. if there's enough static information, such as statically--- know arguments.+-- known arguments. emitPrimOp   :: StgToCmmConfig   -> PrimOp            -- ^ The primop@@ -371,6 +370,10 @@   UnsafeFreezeByteArrayOp -> \[arg] -> opIntoRegs $ \[res] ->     emitAssign (CmmLocal res) arg +--  #define unsafeThawByteArrayzh(r,a)       r=(a)+  UnsafeThawByteArrayOp -> \[arg] -> opIntoRegs $ \[res] ->+    emitAssign (CmmLocal res) arg+ -- Reading/writing pointer arrays    ReadArrayOp -> \[obj, ix] -> opIntoRegs $ \[res] ->@@ -468,6 +471,98 @@   ReadOffAddrOp_Word64 -> \args -> opIntoRegs $ \res ->     doIndexOffAddrOp   Nothing b64 res args +-- IndexWord8OffAddrAsXXX++  IndexOffAddrOp_Word8AsChar -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   (Just (mo_u_8ToWord platform)) b8 b8 res args+  IndexOffAddrOp_Word8AsWideChar -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   (Just (mo_u_32ToWord platform)) b32 b8 res args+  IndexOffAddrOp_Word8AsInt -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing (bWord platform) b8 res args+  IndexOffAddrOp_Word8AsWord -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing (bWord platform) b8 res args+  IndexOffAddrOp_Word8AsAddr -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing (bWord platform) b8 res args+  IndexOffAddrOp_Word8AsFloat -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing f32 b8 res args+  IndexOffAddrOp_Word8AsDouble -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing f64 b8 res args+  IndexOffAddrOp_Word8AsStablePtr -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing (bWord platform) b8 res args+  IndexOffAddrOp_Word8AsInt16 -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing b16 b8 res args+  IndexOffAddrOp_Word8AsInt32 -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing b32 b8 res args+  IndexOffAddrOp_Word8AsInt64 -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing b64 b8 res args+  IndexOffAddrOp_Word8AsWord16 -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing b16 b8 res args+  IndexOffAddrOp_Word8AsWord32 -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing b32 b8 res args+  IndexOffAddrOp_Word8AsWord64 -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing b64 b8 res args++-- ReadWord8OffAddrAsXXX, identical to IndexWord8OffAddrAsXXX++  ReadOffAddrOp_Word8AsChar -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   (Just (mo_u_8ToWord platform)) b8 b8 res args+  ReadOffAddrOp_Word8AsWideChar -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   (Just (mo_u_32ToWord platform)) b32 b8 res args+  ReadOffAddrOp_Word8AsInt -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing (bWord platform) b8 res args+  ReadOffAddrOp_Word8AsWord -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing (bWord platform) b8 res args+  ReadOffAddrOp_Word8AsAddr -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing (bWord platform) b8 res args+  ReadOffAddrOp_Word8AsFloat -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing f32 b8 res args+  ReadOffAddrOp_Word8AsDouble -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing f64 b8 res args+  ReadOffAddrOp_Word8AsStablePtr -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing (bWord platform) b8 res args+  ReadOffAddrOp_Word8AsInt16 -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing b16 b8 res args+  ReadOffAddrOp_Word8AsInt32 -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing b32 b8 res args+  ReadOffAddrOp_Word8AsInt64 -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing b64 b8 res args+  ReadOffAddrOp_Word8AsWord16 -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing b16 b8 res args+  ReadOffAddrOp_Word8AsWord32 -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing b32 b8 res args+  ReadOffAddrOp_Word8AsWord64 -> \args -> opIntoRegs $ \res ->+    doIndexOffAddrOpAs   Nothing b64 b8 res args++-- WriteWord8ArrayAsXXX+  WriteOffAddrOp_Word8AsChar -> \args -> opIntoRegs $ \res ->+    doWriteOffAddrOp (Just (mo_WordTo8 platform))  b8 res args+  WriteOffAddrOp_Word8AsWideChar -> \args -> opIntoRegs $ \res ->+    doWriteOffAddrOp (Just (mo_WordTo32 platform)) b8 res args+  WriteOffAddrOp_Word8AsInt -> \args -> opIntoRegs $ \res ->+    doWriteOffAddrOp Nothing b8 res args+  WriteOffAddrOp_Word8AsWord -> \args -> opIntoRegs $ \res ->+    doWriteOffAddrOp Nothing b8 res args+  WriteOffAddrOp_Word8AsAddr -> \args -> opIntoRegs $ \res ->+    doWriteOffAddrOp Nothing b8 res args+  WriteOffAddrOp_Word8AsFloat -> \args -> opIntoRegs $ \res ->+    doWriteOffAddrOp Nothing b8 res args+  WriteOffAddrOp_Word8AsDouble -> \args -> opIntoRegs $ \res ->+    doWriteOffAddrOp Nothing b8 res args+  WriteOffAddrOp_Word8AsStablePtr -> \args -> opIntoRegs $ \res ->+    doWriteOffAddrOp Nothing b8 res args+  WriteOffAddrOp_Word8AsInt16 -> \args -> opIntoRegs $ \res ->+    doWriteOffAddrOp Nothing b8 res args+  WriteOffAddrOp_Word8AsInt32 -> \args -> opIntoRegs $ \res ->+    doWriteOffAddrOp Nothing b8 res args+  WriteOffAddrOp_Word8AsInt64 -> \args -> opIntoRegs $ \res ->+    doWriteOffAddrOp Nothing b8 res args+  WriteOffAddrOp_Word8AsWord16 -> \args -> opIntoRegs $ \res ->+    doWriteOffAddrOp Nothing b8 res args+  WriteOffAddrOp_Word8AsWord32 -> \args -> opIntoRegs $ \res ->+    doWriteOffAddrOp Nothing b8 res args+  WriteOffAddrOp_Word8AsWord64 -> \args -> opIntoRegs $ \res ->+    doWriteOffAddrOp Nothing b8 res args+ -- IndexXXXArray    IndexByteArrayOp_Char -> \args -> opIntoRegs $ \res ->@@ -1637,7 +1732,8 @@   SeqOp -> alwaysExternal   GetSparkOp -> alwaysExternal   NumSparks -> alwaysExternal-  DataToTagOp -> alwaysExternal+  DataToTagSmallOp -> alwaysExternal+  DataToTagLargeOp -> alwaysExternal   MkApUpd0_Op -> alwaysExternal   NewBCOOp -> alwaysExternal   UnpackClosureOp -> alwaysExternal@@ -1651,6 +1747,10 @@   TraceMarkerOp -> alwaysExternal   SetThreadAllocationCounter -> alwaysExternal   KeepAliveOp -> alwaysExternal+  CastWord32ToFloatOp -> alwaysExternal+  CastWord64ToDoubleOp -> alwaysExternal+  CastDoubleToWord64Op -> alwaysExternal+  CastFloatToWord32Op -> alwaysExternal   where   profile  = stgToCmmProfile  cfg@@ -1679,6 +1779,13 @@     let stmt = mkAssign (CmmLocal res) (CmmMachOp mop args)     emit stmt +  isQuottishOp :: CallishMachOp -> Bool+  isQuottishOp MO_I64_Quot = True+  isQuottishOp MO_I64_Rem = True+  isQuottishOp MO_W64_Quot = True+  isQuottishOp MO_W64_Rem = True+  isQuottishOp _ = False+   opTranslate64     :: [CmmExpr]     -> (Width -> MachOp)@@ -1687,7 +1794,8 @@   opTranslate64 args mkMop callish =     case platformWordSize platform of       -- LLVM and C `can handle larger than native size arithmetic natively.-      _ | stgToCmmAllowBigArith cfg -> opTranslate args $ mkMop W64+      _ | not (isQuottishOp callish), stgToCmmAllowBigArith cfg -> opTranslate args $ mkMop W64+        | isQuottishOp callish, stgToCmmAllowBigQuot cfg -> opTranslate args $ mkMop W64       PW4 -> opCallish args callish       PW8 -> opTranslate args $ mkMop W64 @@ -1708,16 +1816,14 @@     -> PrimopCmmEmit   opIntoRegs f = PrimopCmmEmit_Internal $ \res_ty -> do     regs <- case result_info of-      ReturnsPrim VoidRep -> pure []+      ReturnsVoid -> pure []       ReturnsPrim rep         -> do reg <- newTemp (primRepCmmType platform rep)               pure [reg] -      ReturnsAlg tycon | isUnboxedTupleTyCon tycon+      ReturnsTuple         -> do (regs, _hints) <- newUnboxedTupleRegs res_ty               pure regs--      _ -> panic "cgOpApp"     f regs     pure $ map (CmmReg . CmmLocal) regs @@ -2074,8 +2180,8 @@                    -> CmmType  -- ^ index type                    -> AlignmentSpec alignmentFromTypes ty idx_ty-  | typeWidth ty <= typeWidth idx_ty = NaturallyAligned-  | otherwise                        = Unaligned+  | typeWidth ty < typeWidth idx_ty = NaturallyAligned+  | otherwise                       = Unaligned  doIndexOffAddrOp :: Maybe MachOp                  -> CmmType
compiler/GHC/StgToCmm/Prof.hs view
@@ -23,7 +23,7 @@         saveCurrentCostCentre, restoreCurrentCostCentre,          -- Lag/drag/void stuff-        ldvEnter, ldvEnterClosure, ldvRecordCreate+        ldvEnter, ldvEnterClosure, profHeaderCreate   ) where  import GHC.Prelude@@ -88,14 +88,14 @@ -- | The profiling header words in a static closure staticProfHdr :: Profile -> CostCentreStack -> [CmmLit] staticProfHdr profile ccs-  | profileIsProfiling profile = [mkCCostCentreStack ccs, staticLdvInit platform]+  | profileIsProfiling profile = [mkCCostCentreStack ccs, staticProfHeaderInit platform]   | otherwise                  = []   where platform = profilePlatform profile  -- | Profiling header words in a dynamic closure dynProfHdr :: Profile -> CmmExpr -> [CmmExpr] dynProfHdr profile ccs-  | profileIsProfiling profile = [ccs, dynLdvInit (profilePlatform profile)]+  | profileIsProfiling profile = [ccs, dynProfInit (profilePlatform profile)]   | otherwise                  = []  -- | Initialise the profiling field of an update frame@@ -322,34 +322,63 @@  ----------------------------------------------------------------------------- -----                Lag/drag/void stuff+--                Profiling header stuff -- ----------------------------------------------------------------------------- ------ Initial value for the LDV field in a static closure----staticLdvInit :: Platform -> CmmLit-staticLdvInit = zeroCLit ------ Initial value of the LDV field in a dynamic closure---+-- Header initialisation for static objects happens to coicincide for the+-- three uses of the header+--  * LDV profiling = 0 (era = 0, LDV_STATE_CREATE)+--  * Eras profiling = 0 (user_era = 0, ignored by profiler)+--  * Retainer profiling = 0++staticProfHeaderInit :: Platform -> CmmLit+staticProfHeaderInit plat = zeroCLit plat+++-- Dynamic initialisation++dynErasInit :: Platform -> CmmExpr+dynErasInit platform = loadUserEra platform+ dynLdvInit :: Platform -> CmmExpr-dynLdvInit platform =     -- (era << LDV_SHIFT) | LDV_STATE_CREATE+dynLdvInit platform =+-- (era << LDV_SHIFT) | LDV_STATE_CREATE   CmmMachOp (mo_wordOr platform) [       CmmMachOp (mo_wordShl platform) [loadEra platform, mkIntExpr platform (pc_LDV_SHIFT (platformConstants platform))],       CmmLit (mkWordCLit platform (pc_ILDV_STATE_CREATE (platformConstants platform)))   ] ------ Initialise the LDV word of a new closure----ldvRecordCreate :: CmmExpr -> FCode ()-ldvRecordCreate closure = do++-- | If LDV profiling the user_era = 0+-- , if eras profiling then (ldv)era = 0, so we can initialise correctly by OR the two expressions.+dynProfInit :: Platform -> CmmExpr+dynProfInit platform = CmmMachOp (mo_wordOr platform) [(dynLdvInit platform), dynErasInit platform]+++-- |  Initialise the profiling word of a new dynamic closure+-- * When LDV profiling is enabled (era > 0) - Initialise to the LDV word+-- * When eras profiling is enabled (user_era > 0) - Initialise to current user_era+profHeaderCreate :: CmmExpr -> FCode ()+profHeaderCreate closure = do   platform <- getPlatform-  emit $ mkStore (ldvWord platform closure) (dynLdvInit platform)+  let prof_header_wd = profHeaderWord platform closure +  let check_ldv = mkCmmIfThenElse (CmmMachOp (mo_wordUGt platform) [loadEra platform, CmmLit (zeroCLit platform)])+  let check_eras = mkCmmIfThenElse (CmmMachOp (mo_wordUGt platform) [loadUserEra platform, CmmLit (zeroCLit platform)])+  -- Case 2: user_era > 0, eras profiling is enabled+  check_1 <- check_eras (mkStore prof_header_wd (dynErasInit platform)) mkNop+  -- Case 1: era > 0, LDV profiling is enabled+  check_2 <- check_ldv (mkStore prof_header_wd (dynLdvInit platform)) check_1+  emit check_2+++++++ -- -- | Called when a closure is entered, marks the closure as having -- been "used".  The closure is not an "inherently used" one.  The@@ -368,27 +397,35 @@     platform <- getPlatform     let constants = platformConstants platform         -- don't forget to subtract node's tag-        ldv_wd = ldvWord platform cl_ptr+        ldv_wd = profHeaderWord platform cl_ptr         new_ldv_wd = cmmOrWord platform                         (cmmAndWord platform (cmmLoadBWord platform ldv_wd)                                              (CmmLit (mkWordCLit platform (pc_ILDV_CREATE_MASK constants))))                         (cmmOrWord platform (loadEra platform) (CmmLit (mkWordCLit platform (pc_ILDV_STATE_USE constants))))-    ifProfiling $-         -- if (era > 0) {+    ifProfiling $ do+       -- if (era > 0) {          --    LDVW((c)) = (LDVW((c)) & LDV_CREATE_MASK) |          --                era | LDV_STATE_USE }         emit =<< mkCmmIfThenElse (CmmMachOp (mo_wordUGt platform) [loadEra platform, CmmLit (zeroCLit platform)])                      (mkStore ldv_wd new_ldv_wd)                      mkNop ++ loadEra :: Platform -> CmmExpr loadEra platform = CmmMachOp (MO_UU_Conv (cIntWidth platform) (wordWidth platform))     [CmmLoad (mkLblExpr (mkRtsCmmDataLabel (fsLit "era")))              (cInt platform)              NaturallyAligned] +loadUserEra :: Platform -> CmmExpr+loadUserEra platform = CmmLoad (mkLblExpr (mkRtsCmmDataLabel (fsLit "user_era")))+             (bWord platform)+             NaturallyAligned+ -- | Takes the address of a closure, and returns--- the address of the LDV word in the closure-ldvWord :: Platform -> CmmExpr -> CmmExpr-ldvWord platform closure_ptr+-- the address of the prof header word in the closure (this is used to store LDV info,+-- retainer profiling info and eras profiling info).+profHeaderWord :: Platform -> CmmExpr -> CmmExpr+profHeaderWord platform closure_ptr     = cmmOffsetB platform closure_ptr (pc_OFFSET_StgHeader_ldvw (platformConstants platform))
compiler/GHC/StgToCmm/TagCheck.hs view
@@ -31,8 +31,7 @@ import GHC.Core.DataCon import Control.Monad import GHC.StgToCmm.Types-import GHC.Utils.Panic (pprPanic)-import GHC.Utils.Panic.Plain (panic)+import GHC.Utils.Panic (pprPanic, panic) import GHC.Stg.Syntax import GHC.StgToCmm.Closure import GHC.Cmm.Switch (mkSwitchTargets)@@ -133,10 +132,10 @@ emitArgTagCheck info marks args = whenCheckTags $ do   mod <- getModuleName   let cbv_args = filter (isBoxedType . idType) $ filterByList (map isMarkedCbv marks) args-  arg_infos <- mapM getCgIdInfo cbv_args-  let arg_cmms = map idInfoToAmode arg_infos-      mk_msg arg = showPprUnsafe (text "Untagged arg:" <> (ppr mod) <> char ':' <> info <+> ppr arg)-  zipWithM_ emitTagAssertion (map mk_msg args) (arg_cmms)+  forM_ cbv_args $ \arg -> do+    cginfo <- getCgIdInfo arg+    let msg = showPprUnsafe (text "Untagged arg:" <> (ppr mod) <> char ':' <> info <+> ppr arg)+    emitTagAssertion msg (idInfoToAmode cginfo)  taggedCgInfo :: CgIdInfo -> Bool taggedCgInfo cg_info
compiler/GHC/StgToCmm/Ticky.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE BangPatterns #-} {-# LANGUAGE MultiWayIf #-}  -----------------------------------------------------------------------------@@ -118,7 +117,7 @@ import GHC.Platform import GHC.Platform.Profile -import GHC.StgToCmm.ArgRep    ( slowCallPattern , toArgRep , argRepString )+import GHC.StgToCmm.ArgRep    ( slowCallPattern, toArgRepOrV, argRepString ) import GHC.StgToCmm.Closure import GHC.StgToCmm.Config import {-# SOURCE #-} GHC.StgToCmm.Foreign   ( emitPrimCall )@@ -587,7 +586,7 @@ tickyDirectCall arity args   | args `lengthIs` arity = tickyKnownCallExact   | otherwise = do tickyKnownCallExtraArgs-                   tickySlowCallPat (map argPrimRep (drop arity args))+                   tickySlowCallPat (drop arity args)  tickyKnownCallTooFewArgs :: FCode () tickyKnownCallTooFewArgs = ifTicky $ bumpTickyCounter (fsLit "KNOWN_CALL_TOO_FEW_ARGS_ctr")@@ -610,12 +609,12 @@  if isKnownFun lf_info    then tickyKnownCallTooFewArgs    else tickyUnknownCall- tickySlowCallPat (map argPrimRep args)+ tickySlowCallPat args -tickySlowCallPat :: [PrimRep] -> FCode ()+tickySlowCallPat :: [StgArg] -> FCode () tickySlowCallPat args = ifTicky $ do   platform <- profilePlatform <$> getProfile-  let argReps = map (toArgRep platform) args+  let argReps = map (toArgRepOrV platform . stgArgRep1) args       (_, n_matched) = slowCallPattern argReps   if n_matched > 0 && args `lengthIs` n_matched      then bumpTickyLbl $ mkRtsSlowFastTickyCtrLabel $ concatMap (map Data.Char.toLower . argRepString) argReps@@ -830,25 +829,34 @@ bumpTickyLit lhs = bumpTickyLitBy lhs 1  bumpTickyLitBy :: CmmLit -> Int -> FCode ()-bumpTickyLitBy lhs n = do-  platform <- getPlatform-  emit (addToMem (bWord platform) (CmmLit lhs) n)+bumpTickyLitBy lhs n = emitAddToMem (CmmLit lhs) n  bumpTickyLitByE :: CmmLit -> CmmExpr -> FCode ()-bumpTickyLitByE lhs e = do-  platform <- getPlatform-  emit (addToMemE (bWord platform) (CmmLit lhs) e)+bumpTickyLitByE lhs e = emitAddToMemE (CmmLit lhs) e  bumpHistogram :: FastString -> Int -> FCode () bumpHistogram lbl n = do     platform <- getPlatform     let offset = n `min` (pc_TICKY_BIN_COUNT (platformConstants platform) - 1)-    emit (addToMem (bWord platform)-           (cmmIndexExpr platform+    let addr =+           cmmIndexExpr platform                 (wordWidth platform)                 (CmmLit (CmmLabel (mkRtsCmmDataLabel lbl)))-                (CmmLit (CmmInt (fromIntegral offset) (wordWidth platform))))-           1)+                (CmmLit (CmmInt (fromIntegral offset) (wordWidth platform)))+    emitAddToMem addr 1++emitAddToMem :: CmmExpr -> Int -> FCode ()+emitAddToMem lhs n = do+  platform <- getPlatform+  emitAddToMemE lhs (mkIntExpr platform n)++emitAddToMemE :: CmmExpr -> CmmExpr -> FCode ()+emitAddToMemE lhs n = do+  platform <- getPlatform+  val <- newTemp (bWord platform)+  emitAtomicRead MemOrderRelaxed val lhs+  let val' = cmmOffsetExpr platform (CmmReg (CmmLocal val)) n+  emitAtomicWrite MemOrderRelaxed lhs val'  ------------------------------------------------------------------ -- Showing the "type category" for ticky-ticky profiling
compiler/GHC/StgToCmm/Utils.hs view
@@ -39,6 +39,7 @@         cmmUntag, cmmIsTagged,          addToMem, addToMemE, addToMemLblE, addToMemLbl,+        emitAtomicRead, emitAtomicWrite,          -- * Update remembered set operations         whenUpdRemSetEnabled,@@ -62,6 +63,7 @@ import GHC.Cmm.CLabel import GHC.Cmm.Utils import GHC.Cmm.Switch+import {-# SOURCE #-} GHC.StgToCmm.Foreign (emitPrimCall) import GHC.StgToCmm.CgUtils  import GHC.Types.ForeignCall@@ -77,7 +79,6 @@ import GHC.Data.FastString import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Types.RepType import GHC.Types.CostCentre import GHC.Types.IPE@@ -123,6 +124,29 @@ addToMemE rep ptr n   = mkStore ptr (CmmMachOp (MO_Add (typeWidth rep)) [CmmLoad ptr rep NaturallyAligned, n]) +-------------------------------------------------------------------------+--      Atomic loads and stores+-------------------------------------------------------------------------++emitAtomicRead+  :: MemoryOrdering+  -> LocalReg -- ^ result register+  -> CmmExpr  -- ^ address+  -> FCode ()+emitAtomicRead mord res addr+  = void $ emitPrimCall [res] (MO_AtomicRead w mord) [addr]+  where+    w = typeWidth $ localRegType res++emitAtomicWrite+  :: MemoryOrdering+  -> CmmExpr  -- ^ address+  -> CmmExpr  -- ^ value+  -> FCode ()+emitAtomicWrite mord addr val+  = do platform <- getPlatform+       let w = typeWidth $ cmmExprType platform val+       void $ emitPrimCall [] (MO_AtomicWrite w mord) [addr, val]  ------------------------------------------------------------------------- --
compiler/GHC/StgToJS/Apply.hs view
@@ -27,7 +27,9 @@  import GHC.Prelude hiding ((.|.)) -import GHC.JS.Unsat.Syntax+import GHC.JS.JStg.Syntax+import GHC.JS.JStg.Monad+import GHC.JS.Ident import GHC.JS.Make  import GHC.StgToJS.Arg@@ -69,18 +71,18 @@  -- | Pre-generated functions for fast Apply. -- These are bundled with the RTS.-rtsApply :: StgToJSConfig -> JStat-rtsApply cfg = BlockStat $-  map (specApply cfg) applySpec-  ++ map (pap cfg) specPap-  ++ [ mkApplyArr+rtsApply :: StgToJSConfig -> JSM JStgStat+rtsApply cfg = jBlock+     [ mconcat <$> mapM (specApply cfg) applySpec+     , mconcat <$> mapM (pap cfg)       specPap+     , mkApplyArr      , genericStackApply cfg      , genericFastApply  cfg-     , zeroApply cfg-     , updates   cfg-     , papGen    cfg+     , zeroApply         cfg+     , updates           cfg+     , papGen            cfg+     , selectors         cfg      , moveRegs2-     , selectors cfg      ]  @@ -93,7 +95,7 @@   => ExprCtx   -> Id   -> [StgArg]-  -> G (JStat, ExprResult)+  -> G (JStgStat, ExprResult) genApp ctx i args      -- let-no-escape@@ -111,14 +113,14 @@     | [] <- args     , getUnique i == proxyHashKey     , [top] <- concatMap typex_expr (ctxTarget ctx)-    = return (top |= null_, ExprInline Nothing)+    = return (top |= null_, ExprInline)      -- unboxed tuple or strict type: return fields individually     | [] <- args     , isUnboxedTupleType (idType i) || isStrictType (idType i)     = do       a <- storeIdFields i (ctxTarget ctx)-      return (a, ExprInline Nothing)+      return (a, ExprInline)      -- Handle alternative heap object representation: in some cases, a heap     -- object is not represented as a JS object but directly as a number or a@@ -135,23 +137,23 @@     --  object representation     --  - returns the object directly, otherwise     | [] <- args-    , [vt] <- idVt i+    , [vt] <- idJSRep i     , isUnboxable vt-    , ctxIsEvaluated ctx i+    , ctxIsEvaluated i     = do       let c = head (concatMap typex_expr $ ctxTarget ctx)       is <- varsForId i       case is of         [i'] ->           return ( c |= if_ (isObject i') (closureField1 i') i'-                 , ExprInline Nothing+                 , ExprInline                  )         _ -> panic "genApp: invalid size"      -- case of Id without args and known to be already evaluated: return fields     -- individually     | [] <- args-    , ctxIsEvaluated ctx i || isStrictType (idType i)+    , ctxIsEvaluated i || isStrictType (idType i)     = do       a <- storeIdFields i (ctxTarget ctx)       -- optional runtime assert for detecting unexpected thunks (unevaluated)@@ -162,7 +164,7 @@                              (appS "throw" [String "unexpected thunk"]) -- yuck                              mempty                  _   -> mempty-      return (a `mappend` ww, ExprInline Nothing)+      return (a `mappend` ww, ExprInline)       -- Case: "newtype" datacon wrapper@@ -179,8 +181,8 @@               a' = case args of                 [StgVarArg a'] -> a'                 _              -> panic "genApp: unexpected arg"-          if isStrictId a' || ctxIsEvaluated ctx a'-            then return (t |= ai, ExprInline Nothing)+          if isStrictId a' || ctxIsEvaluated a'+            then return (t |= ai, ExprInline)             else return (returnS (app "h$e" [ai]), ExprCont)         _ -> panic "genApp: invalid size" @@ -237,7 +239,7 @@  -- avoid one indirection for global ids -- fixme in many cases we can also jump directly to the entry for local?-jumpToII :: Id -> [JExpr] -> JStat -> G JStat+jumpToII :: Id -> [JStgExpr] -> JStgStat -> G JStgStat jumpToII i vars load_app_in_r1   | isLocalId i = do      ii <- varForId i@@ -256,7 +258,7 @@  -- | Try to use a specialized pre-generated application function. -- If there is none, use h$ap_gen_fast instead-jumpToFast :: HasDebugCallStack => [StgArg] -> JStat -> G JStat+jumpToFast :: HasDebugCallStack => [StgArg] -> JStgStat -> G JStgStat jumpToFast args load_app_in_r1 = do   -- get JS expressions for every argument   -- Arguments may have more than one expression (e.g. Word64#)@@ -287,7 +289,7 @@   StackConv -> "h$ap_gen"  -- | Expr of the generic apply function-genericApplyExpr :: ApplyConv -> JExpr+genericApplyExpr :: ApplyConv -> JStgExpr genericApplyExpr conv = var (genericApplyName conv)  @@ -324,13 +326,13 @@ -- -- Warning: the returned function may not be generated! Use specApplyExprMaybe -- if you want to ensure that it exists.-specApplyExpr :: ApplySpec -> JExpr+specApplyExpr :: ApplySpec -> JStgExpr specApplyExpr spec = var (specApplyName spec)  -- | Return the expression of the specialized apply function for the given -- number of args, number of arg variables, and calling convention. -- Return Nothing if it isn't generated.-specApplyExprMaybe :: ApplySpec -> Maybe JExpr+specApplyExprMaybe :: ApplySpec -> Maybe JStgExpr specApplyExprMaybe spec =   if spec `elem` applySpec     then Just (specApplyExpr spec)@@ -338,7 +340,7 @@  -- | Make an ApplySpec from a calling convention, a list of Haskell args, and a -- list of corresponding JS variables-mkApplySpec :: ApplyConv -> [StgArg] -> [JExpr] -> ApplySpec+mkApplySpec :: ApplyConv -> [StgArg] -> [JStgExpr] -> ApplySpec mkApplySpec conv args vars = ApplySpec   { specConv = conv   , specArgs = length args@@ -348,7 +350,7 @@ -- | Find a specialized application function if there is one selectApply   :: ApplySpec-  -> G (Either JExpr JExpr) -- ^ the function to call (Left for generic, Right for specialized)+  -> G (Either JStgExpr JStgExpr) -- ^ the function to call (Left for generic, Right for specialized) selectApply spec =   case specApplyExprMaybe spec of     Just e  -> return (Right e)@@ -378,30 +380,34 @@ specTag spec = Bits.shiftL (specVars spec) 8 Bits..|. (specArgs spec)  -- | Generate a tag expression for the given ApplySpec-specTagExpr :: ApplySpec -> JExpr+specTagExpr :: ApplySpec -> JStgExpr specTagExpr = toJExpr . specTag  -- | Build arrays to quickly lookup apply functions -- --  h$apply[r << 8 | n] = function application for r regs, n args --  h$paps[r]           = partial application for r registers (number of args is in the object)-mkApplyArr :: JStat-mkApplyArr = mconcat-  [ TxtI "h$apply" ||= toJExpr (JList [])-  , TxtI "h$paps"  ||= toJExpr (JList [])-  , ApplStat (var "h$initStatic" .^ "push")-    [ ValExpr $ JFunc [] $ mconcat-        [ jFor (|= zero_) (.<. Int 65536) preIncrS-          (\j -> var "h$apply" .! j |= var "h$ap_gen")-        , jFor (|= zero_) (.<. Int 128) preIncrS-          (\j -> var "h$paps" .! j |= var "h$pap_gen")-        , mconcat (map assignSpec applySpec)-        , mconcat (map assignPap specPap)-        ]-    ]-  ]+mkApplyArr :: JSM JStgStat+mkApplyArr =+  do mk_ap_gens  <- jFor (|= zero_) (.<. Int 65536) preIncrS+                    \j -> var "h$apply" .! j |= var "h$ap_gen"+     mk_pap_gens <- jFor (|= zero_) (.<. Int 128) preIncrS+                    \j -> var "h$paps" .! j |= var "h$pap_gen"+     return $ mconcat+       [ global "h$apply" ||= toJExpr (JList [])+       , global "h$paps"  ||= toJExpr (JList [])+       , ApplStat (var "h$initStatic" .^ "push")+         [ jLam' $+           mconcat+           [ mk_ap_gens+           , mk_pap_gens+           , mconcat (map assignSpec applySpec)+           , mconcat (map assignPap specPap)+           ]+         ]+       ]   where-    assignSpec :: ApplySpec -> JStat+    assignSpec :: ApplySpec -> JStgStat     assignSpec spec = case specConv spec of       -- both fast/slow (regs/stack) specialized apply functions have the same       -- tags. We store the stack ones in the array because they are used as@@ -409,7 +415,7 @@       StackConv -> var "h$apply" .! specTagExpr spec |= specApplyExpr spec       RegsConv  -> mempty -    assignPap :: Int -> JStat+    assignPap :: Int -> JStgStat     assignPap p = var "h$paps" .! toJExpr p |=                       (var (mkFastString $ ("h$pap_" ++ show p))) @@ -419,7 +425,7 @@ -- possible, otherwise the generic h$ap_gen function). pushCont :: HasDebugCallStack          => [StgArg]-         -> G JStat+         -> G JStgStat pushCont args = do   vars <- concatMapM genArg args   let spec = mkApplySpec StackConv args vars@@ -438,26 +444,30 @@ -- Regs: --  R1 = applied closure ---genericStackApply :: StgToJSConfig -> JStat+genericStackApply :: StgToJSConfig -> JSM JStgStat genericStackApply cfg = closure info body   where     -- h$ap_gen body-    body = jVar \cf ->-      [ traceRts cfg (jString "h$ap_gen")-      , cf |= closureEntry r1-        -- switch on closure type-      , SwitchStat (entryClosureType cf)-        [ (toJExpr Thunk    , thunk_case cfg cf)-        , (toJExpr Fun      , fun_case cf (funArity' cf))-        , (toJExpr Pap      , fun_case cf (papArity r1))-        , (toJExpr Blackhole, blackhole_case cfg)-        ]-        (default_case cf)-      ]+    body = jVar $ \cf ->+      do fun <- fun_case cf (funArity' cf)+         pap <- fun_case cf (papArity r1)+         return $+           mconcat $+           [ traceRts cfg (jString "h$ap_gen")+           , cf |= closureEntry r1+           -- switch on closure type+           , SwitchStat (entryClosureType cf)+             [ (toJExpr Thunk    , thunk_case cfg cf)+             , (toJExpr Fun      , fun)+             , (toJExpr Pap      , pap)+             , (toJExpr Blackhole, blackhole_case cfg)+             ]+             (default_case cf)+           ]      -- info table for h$ap_gen     info = ClosureInfo-      { ciVar     = TxtI "h$ap_gen"+      { ciVar     = global "h$ap_gen"       , ciRegs    = CIRegs 0 [PtrV] -- closure to apply to       , ciName    = "h$ap_gen"       , ciLayout  = CILayoutVariable@@ -478,90 +488,98 @@       , returnS (app "h$blockOnBlackhole" [r1])       ] -    fun_case c arity = jVar \tag needed_args needed_regs given_args given_regs newTag newAp p dat ->-      [ tag         |= stack .! (sp - 1) -- tag on the stack-      , given_args  |= mask8 tag         -- indicates the number of passed args-      , given_regs  |= tag .>>. 8        -- and the number of passed values for registers-      , needed_args |= mask8 arity-      , needed_regs |= arity .>>. 8-      , traceRts cfg (jString "h$ap_gen: args: " + given_args-                    + jString " regs: " + given_regs)-      , ifBlockS (given_args .===. needed_args)-        ---------------------------------        -- exactly saturated application-        ---------------------------------        [ traceRts cfg (jString "h$ap_gen: exact")-        -- Set registers to register values on the stack-        , loop 0 (.<. given_regs) \i -> mconcat-            [ appS "h$setReg" [i+2, stack .! (sp-2-i)]-            , postIncrS i-            ]-        -- drop register values from the stack-        , sp |= sp - given_regs - 2-        -- enter closure in R1-        , returnS c-        ]-        [ ifBlockS (given_args .>. needed_args)-            -----------------------------            -- oversaturated application-            -----------------------------            [ traceRts cfg (jString "h$ap_gen: oversat: arity: " + needed_args-                          + jString " regs: " + needed_regs)-            -- load needed register values-            , loop 0 (.<. needed_regs) \i -> mconcat-                [ traceRts cfg (jString "h$ap_gen: loading register: " + i)-                , appS "h$setReg" [i+2, stack .! (sp-2-i)]-                , postIncrS i-                ]-            -- compute new tag with consumed register values and args removed-            , newTag |= ((given_regs-needed_regs).<<.8) .|. (given_args - needed_args)-            -- find application function for the remaining regs/args-            , newAp |= var "h$apply" .! newTag-            , traceRts cfg (jString "h$ap_gen: next: " + (newAp .^ "n"))+    fun_case c arity = jVars \(tag, needed_args, needed_regs, given_args, given_regs, newTag, newAp, p, dat) ->+      do build_pap_payload <- loop 0 (.<. given_regs)+                              \i -> return $ mconcat [ (dat .^ "push") `ApplStat` [stack .! (sp - i - 2)]+                                                     , postIncrS i+                                                     ]+         load_reg_values <- loop 0 (.<. needed_regs)+                            \i -> return $+                                  mconcat [ traceRts cfg (jString "h$ap_gen: loading register: " + i)+                                          , appS "h$setReg" [ i+2 , stack .! (sp-2-i)]+                                          , postIncrS i+                                          ]+         set_reg_values <- loop 0 (.<. given_regs)+           \i -> return $+                 mconcat [ appS "h$setReg" [ i+2, stack .! (sp-2-i)]+                         , postIncrS i+                         ]+         return $+           mconcat $ [ tag         |= stack .! (sp - 1) -- tag on the stack+                     , given_args  |= mask8 tag         -- indicates the number of passed args+                     , given_regs  |= tag .>>. 8        -- and the number of passed values for registers+                     , needed_args |= mask8 arity+                     , needed_regs |= arity .>>. 8+                     , traceRts cfg (jString "h$ap_gen: args: " + given_args+                                     + jString " regs: " + given_regs)+                     , ifBlockS (given_args .===. needed_args)+                       --------------------------------+                       -- exactly saturated application+                       --------------------------------+                       [ traceRts cfg (jString "h$ap_gen: exact")+                       -- Set registers to register values on the stack+                       , set_reg_values+                       -- drop register values from the stack+                       , sp |= sp - given_regs - 2+                       -- enter closure in R1+                       , returnS c+                       ]+                       [ ifBlockS (given_args .>. needed_args)+                         ----------------------------+                         -- oversaturated application+                         ----------------------------+                         [ traceRts cfg (jString "h$ap_gen: oversat: arity: " + needed_args+                                         + jString " regs: " + needed_regs) -            -- Drop used registers from the stack.-            -- Test if the application function needs a tag and push it.-            , ifS (newAp .===. var "h$ap_gen")-                   ((sp |= sp - needed_regs) <> (stack .! (sp - 1) |= newTag))-                   (sp |= sp - needed_regs - 1)+                         -- load needed register values+                         , load_reg_values -            -- Push generic application function as continuation-            , stack .! sp |= newAp+                         -- compute new tag with consumed register values and args removed+                         , newTag |= ((given_regs-needed_regs).<<.8) .|. (given_args - needed_args)+                         -- find application function for the remaining regs/args+                         , newAp |= var "h$apply" .! newTag+                         , traceRts cfg (jString "h$ap_gen: next: " + (newAp .^ "n")) -            -- Push "current thread CCS restore" function as continuation-            , profStat cfg pushRestoreCCS+                         -- Drop used registers from the stack.+                         -- Test if the application function needs a tag and push it.+                         , ifS (newAp .===. var "h$ap_gen")+                           ((sp |= sp - needed_regs) <> (stack .! (sp - 1) |= newTag))+                           (sp |= sp - needed_regs - 1) -            -- enter closure in R1-            , returnS c-            ]+                         -- Push generic application function as continuation+                         , stack .! sp |= newAp -            ------------------------------            -- undersaturated application-            ------------------------------            [ traceRts cfg (jString "h$ap_gen: undersat")-            -- find PAP entry function corresponding to given_regs count-            , p      |= var "h$paps" .! given_regs+                         -- Push "current thread CCS restore" function as continuation+                         , profStat cfg pushRestoreCCS -            -- build PAP payload: R1 + tag + given register values-            , newTag |= ((needed_regs-given_regs) .<<. 8) .|. (needed_args-given_args)-            , dat    |= toJExpr [r1, newTag]-            , loop 0 (.<. given_regs) \i -> mconcat-                [ (dat .^ "push") `ApplStat` [stack .! (sp - i - 2)]-                , postIncrS i-                ]+                         -- enter closure in R1+                         , returnS c+                         ] -            -- remove register values from the stack.-            , sp  |= sp - given_regs - 2+                         -----------------------------+                         -- undersaturated application+                         -----------------------------+                         [ traceRts cfg (jString "h$ap_gen: undersat")+                         -- find PAP entry function corresponding to given_regs count+                         , p      |= var "h$paps" .! given_regs -            -- alloc PAP closure, store reference to it in R1.-            , r1  |= initClosure cfg p dat jCurrentCCS+                         -- build PAP payload: R1 + tag + given register values+                         , newTag |= ((needed_regs-given_regs) .<<. 8) .|. (needed_args-given_args)+                         , dat    |= toJExpr [r1, newTag]+                         , build_pap_payload -            -- return to the continuation on the stack-            , returnStack-            ]-        ]-      ]+                         -- remove register values from the stack.+                         , sp  |= sp - given_regs - 2 +                         -- alloc PAP closure, store reference to it in R1.+                         , r1  |= initClosure cfg p dat jCurrentCCS++                         -- return to the continuation on the stack+                         , returnStack+                         ]+                       ]+                     ]+ -- | Generic fast apply function (h$ap_gen_fast) that can do everything, but less -- efficiently than other more specialized functions. --@@ -570,112 +588,128 @@ -- Regs: --  R1 = closure to apply to ---genericFastApply :: StgToJSConfig -> JStat+genericFastApply :: StgToJSConfig -> JSM JStgStat genericFastApply s =-   jFun (TxtI "h$ap_gen_fast") \tag -> jVar \c ->-      [traceRts s (jString "h$ap_gen_fast: " + tag)-      , c |= closureEntry r1-      , SwitchStat (entryClosureType c)-        [ (toJExpr Thunk, traceRts s (jString "h$ap_gen_fast: thunk")-           <> pushStackApply c tag-           <> returnS c)-        , (toJExpr Fun, jVar \farity ->-                               [ farity |= funArity' c-                               , traceRts s (jString "h$ap_gen_fast: fun " + farity)-                               , funCase c tag farity-                               ])-        , (toJExpr Pap, jVar \parity ->-                               [ parity |= papArity r1-                               , traceRts s (jString "h$ap_gen_fast: pap " + parity)-                               , funCase c tag parity-                               ])-        , (toJExpr Con, traceRts s (jString "h$ap_gen_fast: con")-            <> jwhenS (tag .!=. 0)-                (appS "throw" [jString "h$ap_gen_fast: invalid apply"])-                        <> returnS c)-        , (toJExpr Blackhole, traceRts s (jString "h$ap_gen_fast: blackhole")-            <> pushStackApply c tag-            <> push' s [r1, var "h$return"]-            <> returnS (app "h$blockOnBlackhole" [r1]))-        ] $ appS "throw" [jString "h$ap_gen_fast: unexpected closure type: " + entryClosureType c]-      ]+   jFunction (global "h$ap_gen_fast")+   \(MkSolo tag) -> jVar $ \c ->+     do push_stk_app <- pushStackApply c tag+        fast_fun     <- jVar \farity ->+                               do fast_fun <- funCase c tag farity+                                  return $ mconcat $+                                    [ farity |= funArity' c+                                    , traceRts s (jString "h$ap_gen_fast: fun " + farity)+                                    , fast_fun]+        fast_pap     <- jVar \parity ->+                               do fast_pap <- funCase c tag parity+                                  return $ mconcat $+                                    [ parity |= papArity r1+                                    , traceRts s (jString "h$ap_gen_fast: pap " + parity)+                                    , fast_pap+                                    ]+        return $ mconcat $+          [traceRts s (jString "h$ap_gen_fast: " + tag)+          , c |= closureEntry r1+          , SwitchStat (entryClosureType c)+            [ (toJExpr Thunk, traceRts s (jString "h$ap_gen_fast: thunk")+                <> push_stk_app+                <> returnS c)+            , (toJExpr Fun, fast_fun)+            , (toJExpr Pap, fast_pap)+            , (toJExpr Con, traceRts s (jString "h$ap_gen_fast: con")+                <> jwhenS (tag .!=. 0)+                            (appS "throw" [jString "h$ap_gen_fast: invalid apply"])+                            <> returnS c)+            , (toJExpr Blackhole, traceRts s (jString "h$ap_gen_fast: blackhole")+                <> push_stk_app+                <> push' s [r1, var "h$return"]+                <> returnS (app "h$blockOnBlackhole" [r1]))+            ] $ appS "throw" [jString "h$ap_gen_fast: unexpected closure type: " + entryClosureType c]+          ]    where      -- thunk: push everything to stack frame, enter thunk first-    pushStackApply :: JExpr -> JExpr -> JStat+    pushStackApply :: JStgExpr -> JStgExpr -> JSM JStgStat     pushStackApply _c tag =       jVar \ap ->-        [ pushAllRegs tag-        , ap |= var "h$apply" .! tag-        , ifS (ap .===. var "h$ap_gen")-                ((sp |= sp + 2) <> (stack .! (sp-1) |= tag))-                (sp |= sp + 1)-        , stack .! sp |= ap-        , profStat s pushRestoreCCS-        ]+             do push_all_regs <- pushAllRegs tag+                return $ mconcat $+                  [ push_all_regs+                  , ap |= var "h$apply" .! tag+                  , ifS (ap .===. var "h$ap_gen")+                    ((sp |= sp + 2) <> (stack .! (sp-1) |= tag))+                    (sp |= sp + 1)+                  , stack .! sp |= ap+                  , profStat s pushRestoreCCS+                  ] -    funCase :: JExpr -> JExpr -> JExpr -> JStat-    funCase c tag arity =-      jVar \ar myAr myRegs regsStart newTag newAp dat p ->-        [ ar     |= mask8 arity-        , myAr   |= mask8 tag-        , myRegs |= tag .>>. 8-        , traceRts s (jString "h$ap_gen_fast: args: " + myAr-                      + jString " regs: "             + myRegs)-        , ifS (myAr .===. ar)-        -- call the function directly-          (traceRts s (jString "h$ap_gen_fast: exact") <> returnS c)-          (ifBlockS (myAr .>. ar)-          -- push stack frame with remaining args, then call fun-           [ traceRts s (jString "h$ap_gen_fast: oversat " + sp)-           , regsStart |= (arity .>>. 8) + 1-           , sp |= sp + myRegs - regsStart + 1-           , traceRts s (jString "h$ap_gen_fast: oversat " + sp)-           , pushArgs regsStart myRegs-           , newTag |= ((myRegs-( arity.>>.8)).<<.8).|.myAr-ar-           , newAp |= var "h$apply" .! newTag-           , ifS (newAp .===. var "h$ap_gen")-                 ((sp |= sp + 2) <> (stack .! (sp - 1) |= newTag))-                 (sp |= sp + 1)-           , stack .! sp |= newAp-           , profStat s pushRestoreCCS-           , returnS c-           ]-          -- else-           [traceRts s (jString "h$ap_gen_fast: undersat: " + myRegs + jString " " + tag)-           , jwhenS (tag .!=. 0) $ mconcat-               [ p |= var "h$paps" .! myRegs-               , dat |= toJExpr [r1, ((arity .>>. 8)-myRegs)*256+ar-myAr]-               , loop 0 (.<. myRegs)-                 (\i -> (dat .^ "push")-                   `ApplStat` [app "h$getReg" [i+2]] <> postIncrS i)-               , r1 |= initClosure s p dat jCurrentCCS-               ]-           , returnStack-           ])-        ]+    funCase :: JStgExpr -> JStgExpr -> JStgExpr -> JSM JStgStat+    funCase c tag arity = jVars $+      \(ar, myAr, myRegs, regsStart, newTag, newAp, dat, p) -> +        do get_regs <- loop 0 (.<. myRegs) $+             \i -> return $+                   (dat .^ "push") `ApplStat` [app "h$getReg" [i+2]] <> postIncrS i+           push_args <- pushArgs regsStart myRegs -    pushAllRegs :: JExpr -> JStat+           return $ mconcat $+             [ ar     |= mask8 arity+             , myAr   |= mask8 tag+             , myRegs |= tag .>>. 8+             , traceRts s (jString "h$ap_gen_fast: args: " + myAr+                           + jString " regs: "             + myRegs)+             , ifS (myAr .===. ar)+             -- call the function directly+               (traceRts s (jString "h$ap_gen_fast: exact") <> returnS c)+               (ifBlockS (myAr .>. ar)+               -- push stack frame with remaining args, then call fun+                [ traceRts s (jString "h$ap_gen_fast: oversat " + sp)+                , regsStart |= (arity .>>. 8) + 1+                , sp |= sp + myRegs - regsStart + 1+                , traceRts s (jString "h$ap_gen_fast: oversat " + sp)+                , push_args+                , newTag |= ((myRegs-( arity.>>.8)).<<.8).|.myAr-ar+                , newAp |= var "h$apply" .! newTag+                , ifS (newAp .===. var "h$ap_gen")+                  ((sp |= sp + 2) <> (stack .! (sp - 1) |= newTag))+                  (sp |= sp + 1)+                , stack .! sp |= newAp+                , profStat s pushRestoreCCS+                , returnS c+                ]+               -- else+                [traceRts s (jString "h$ap_gen_fast: undersat: " + myRegs + jString " " + tag)+                , jwhenS (tag .!=. 0) $ mconcat+                  [ p |= var "h$paps" .! myRegs+                  , dat |= toJExpr [r1, ((arity .>>. 8)-myRegs)*256+ar-myAr]+                  , get_regs+                  , r1 |= initClosure s p dat jCurrentCCS+                  ]+                , returnStack+                ])+             ]++    pushAllRegs :: JStgExpr -> JSM JStgStat     pushAllRegs tag =       jVar \regs ->-        [ regs |= tag .>>. 8-        , sp |= sp + regs-        , SwitchStat regs (map pushReg [65,64..2]) mempty-        ]+             return $ mconcat $+             [ regs |= tag .>>. 8+             , sp |= sp + regs+             , SwitchStat regs (map pushReg [65,64..2]) mempty+             ]       where-        pushReg :: Int -> (JExpr, JStat)+        pushReg :: Int -> (JStgExpr, JStgStat)         pushReg r = (toJExpr (r-1),  stack .! (sp - toJExpr (r - 2)) |= jsReg r) -    pushArgs :: JExpr -> JExpr -> JStat+    pushArgs :: JStgExpr -> JStgExpr -> JSM JStgStat     pushArgs start end =-      loop end (.>=.start) (\i -> traceRts s (jString "pushing register: " + i)-                             <> (stack .! (sp + start - i) |= app "h$getReg" [i+1])-                             <> postDecrS i-                           )+      loop end (.>=.start)+      \i -> return $+            traceRts s (jString "pushing register: " + i)+            <> (stack .! (sp + start - i) |= app "h$getReg" [i+1])+            <> postDecrS i  -- | Make specialized apply function for the given ApplySpec-specApply :: StgToJSConfig -> ApplySpec -> JStat+specApply :: StgToJSConfig -> ApplySpec -> JSM JStgStat specApply cfg spec@(ApplySpec conv nargs nvars) =   let fun_name = specApplyName spec   in case conv of@@ -688,92 +722,100 @@   -> FastString   -> Int   -> Int-  -> JStat+  -> JSM JStgStat stackApply s fun_name nargs nvars =   -- special case for h$ap_0_0   if nargs == 0 && nvars == 0     then closure info0 body0     else closure info body   where-    info  = ClosureInfo (TxtI fun_name) (CIRegs 0 [PtrV]) fun_name (CILayoutUnknown nvars) CIStackFrame mempty-    info0 = ClosureInfo (TxtI fun_name) (CIRegs 0 [PtrV]) fun_name (CILayoutFixed 0 [])    CIStackFrame mempty+    info  = ClosureInfo (global fun_name) (CIRegs 0 [PtrV]) fun_name (CILayoutUnknown nvars) CIStackFrame mempty+    info0 = ClosureInfo (global fun_name) (CIRegs 0 [PtrV]) fun_name (CILayoutFixed 0 [])    CIStackFrame mempty -    body0 = adjSpN' 1 <> enter s r1+    body0 = (adjSpN' 1 <>) <$> enter s r1 -    body = jVar \c ->-             [ c |= closureEntry r1-             , traceRts s (toJExpr fun_name-                           + jString " "-                           + (c .^ "n")-                           + jString " sp: " + sp-                           + jString " a: "  + (c .^ "a"))-             , SwitchStat (entryClosureType c)-               [ (toJExpr Thunk, traceRts s (toJExpr $ fun_name <> ": thunk") <> profStat s pushRestoreCCS <> returnS c)-               , (toJExpr Fun, traceRts s (toJExpr $ fun_name <> ": fun") <> funCase c)-               , (toJExpr Pap, traceRts s (toJExpr $ fun_name <> ": pap") <> papCase c)-               , (toJExpr Blackhole, push' s [r1, var "h$return"] <> returnS (app "h$blockOnBlackhole" [r1]))-               ] (appS "throw" [toJExpr ("panic: " <> fun_name <> ", unexpected closure type: ") + (entryClosureType c)])-             ]+    body = jVar $ \c ->+      do fun_case <- funCase c+         pap_case <- papCase c+         return $ mconcat+           [ c |= closureEntry r1+           , traceRts s (toJExpr fun_name+                          + jString " "+                          + (c .^ "n")+                          + jString " sp: " + sp+                          + jString " a: "  + (c .^ "a"))+           , SwitchStat (entryClosureType c)+             [ (toJExpr Thunk, traceRts s (toJExpr $ fun_name <> ": thunk") <> profStat s pushRestoreCCS <> returnS c)+             , (toJExpr Fun, traceRts s (toJExpr $ fun_name <> ": fun") <> fun_case)+             , (toJExpr Pap, traceRts s (toJExpr $ fun_name <> ": pap") <> pap_case)+             , (toJExpr Blackhole, push' s [r1, var "h$return"] <> returnS (app "h$blockOnBlackhole" [r1]))+             ] (appS "throw" [toJExpr ("panic: " <> fun_name <> ", unexpected closure type: ") + (entryClosureType c)])+           ]      funExact c = popSkip 1 (reverse $ take nvars jsRegsFromR2) <> returnS c     stackArgs = map (\x -> stack .! (sp - toJExpr x)) [1..nvars] -    papCase :: JExpr -> JStat-    papCase c = jVar \expr arity0 arity ->-      case expr of-        ValExpr (JVar pap) -> [ arity0 |= papArity r1-                              , arity |= mask8 arity0-                              , traceRts s (toJExpr (fun_name <> ": found pap, arity: ") + arity)-                              , ifS (toJExpr nargs .===. arity)-                              --then-                                (traceRts s (toJExpr (fun_name <> ": exact")) <> funExact c)-                              -- else-                                (ifS (toJExpr nargs .>. arity)-                                  (traceRts s (toJExpr (fun_name <> ": oversat")) <> oversatCase c arity0 arity)-                                  (traceRts s (toJExpr (fun_name <> ": undersat"))-                                   <> mkPap s pap r1 (toJExpr nargs) stackArgs-                                   <> (sp |= sp - toJExpr (nvars + 1))-                                   <> (r1 |= toJExpr pap)-                                   <> returnStack))-                              ]-        _                   -> mempty+    papCase :: JStgExpr -> JSM JStgStat+    papCase c = jVars \(expr, arity0, arity) ->+      do oversat_case <- oversatCase c arity0 arity+         return $ mconcat $+           case expr of+             ValExpr (JVar pap) -> [ arity0 |= papArity r1+                                   , arity |= mask8 arity0+                                   , traceRts s (toJExpr (fun_name <> ": found pap, arity: ") + arity)+                                   , ifS (toJExpr nargs .===. arity)+                                   --then+                                     (traceRts s (toJExpr (fun_name <> ": exact")) <> funExact c)+                                   -- else+                                     (ifS (toJExpr nargs .>. arity)+                                      (traceRts s (toJExpr (fun_name <> ": oversat")) <> oversat_case)+                                      (traceRts s (toJExpr (fun_name <> ": undersat"))+                                       <> mkPap s pap r1 (toJExpr nargs) stackArgs+                                       <> (sp |= sp - toJExpr (nvars + 1))+                                       <> (r1 |= toJExpr pap)+                                       <> returnStack))+                                   ]+             _                   -> mempty  -    funCase :: JExpr -> JStat-    funCase c = jVar \expr ar0 ar ->-      case expr of-        ValExpr (JVar pap) -> [ ar0 |= funArity' c-                              , ar |= mask8 ar0-                              , ifS (toJExpr nargs .===. ar)-                                (traceRts s (toJExpr (fun_name <> ": exact")) <> funExact c)-                                (ifS (toJExpr nargs .>. ar)-                                 (traceRts s (toJExpr (fun_name <> ": oversat"))-                                  <> oversatCase c ar0 ar)-                                 (traceRts s (toJExpr (fun_name <> ": undersat"))-                                  <> mkPap s pap (toJExpr R1) (toJExpr nargs) stackArgs-                                  <> (sp |= sp - toJExpr (nvars+1))-                                  <> (r1 |= toJExpr pap)-                                  <> returnStack))-                              ]-        _                  -> mempty+    funCase :: JStgExpr -> JSM JStgStat+    funCase c = jVars \(expr, ar0, ar) ->+      do oversat_case <- oversatCase c ar0 ar+         return $ mconcat $+           case expr of+             ValExpr (JVar pap) -> [ ar0 |= funArity' c+                                   , ar |= mask8 ar0+                                   , ifS (toJExpr nargs .===. ar)+                                     (traceRts s (toJExpr (fun_name <> ": exact")) <> funExact c)+                                     (ifS (toJExpr nargs .>. ar)+                                      (traceRts s (toJExpr (fun_name <> ": oversat"))+                                       <> oversat_case)+                                      (traceRts s (toJExpr (fun_name <> ": undersat"))+                                       <> mkPap s pap (toJExpr R1) (toJExpr nargs) stackArgs+                                       <> (sp |= sp - toJExpr (nvars+1))+                                       <> (r1 |= toJExpr pap)+                                       <> returnStack))+                                   ]+             _                  -> mempty       -- oversat: call the function but keep enough on the stack for the next-    oversatCase :: JExpr -- function-                -> JExpr -- the arity tag-                -> JExpr -- real arity (arity & 0xff)-                -> JStat+    oversatCase :: JStgExpr -- function+                -> JStgExpr -- the arity tag+                -> JStgExpr -- real arity (arity & 0xff)+                -> JSM JStgStat     oversatCase c arity arity0 =-      jVar \rs newAp ->-        [ rs |= (arity .>>. 8)-        , loadRegs rs-        , sp |= sp - rs-        , newAp |= (var "h$apply" .! ((toJExpr nargs-arity0).|.((toJExpr nvars-rs).<<.8)))-        , stack .! sp |= newAp-        , profStat s pushRestoreCCS-        , traceRts s (toJExpr (fun_name <> ": new stack frame: ") + (newAp .^ "n"))-        , returnS c-        ]+      jVars \(rs, newAp) ->+             return $ mconcat $+             [ rs |= (arity .>>. 8)+             , loadRegs rs+             , sp |= sp - rs+             , newAp |= (var "h$apply" .! ((toJExpr nargs-arity0).|.((toJExpr nvars-rs).<<.8)))+             , stack .! sp |= newAp+             , profStat s pushRestoreCCS+             , traceRts s (toJExpr (fun_name <> ": new stack frame: ") + (newAp .^ "n"))+             , returnS c+             ]       where         loadRegs rs = SwitchStat rs switchAlts mempty           where@@ -783,88 +825,93 @@ -- -- h$ap_n_r_fast is entered if a function of unknown arity is called, n -- arguments are already in r registers-fastApply :: StgToJSConfig -> FastString -> Int -> Int -> JStat-fastApply s fun_name nargs nvars = body0+fastApply :: StgToJSConfig -> FastString -> Int -> Int -> JSM JStgStat+fastApply s fun_name nargs nvars = if nargs == 0 && nvars == 0+                                   -- special case for h$ap_0_0_fast+                                   then jFunction' func ap_fast+                                   -- general case+                                   else jFunction' func body   where-      -- special case for h$ap_0_0_fast-      body0 = if nargs == 0 && nvars == 0-        then jFun func (enter s r1)-        else FuncStat func myFunArgs body--      func    = TxtI fun_name--      myFunArgs = []+      func    = global fun_name+      ap_fast :: JSM JStgStat+      ap_fast = enter s r1        regArgs = take nvars jsRegsFromR2 -      mkAp :: Int -> Int -> [JExpr]+      mkAp :: Int -> Int -> [JStgExpr]       mkAp n' r' = [ specApplyExpr (ApplySpec StackConv n' r') ] -      body =-        jVar \c farity arity ->-          [ c |= closureEntry r1-          , traceRts s (toJExpr (fun_name <> ": sp ") + sp)-          , SwitchStat (entryClosureType c)-             [(toJExpr Fun, traceRts s (toJExpr (fun_name <> ": ")-                                        + clName c-                                        + jString " (arity: " + (c .^ "a") + jString ")")-                            <> (farity |= funArity' c)-                            <> funCase c farity)-             ,(toJExpr Pap, traceRts s (toJExpr (fun_name <> ": pap")) <> (arity |= papArity r1) <> funCase c arity)-             ,(toJExpr Thunk, traceRts s (toJExpr (fun_name <> ": thunk")) <> push' s (reverse regArgs ++ mkAp nargs nvars) <> profStat s pushRestoreCCS <> returnS c)-             ,(toJExpr Blackhole, traceRts s (toJExpr (fun_name <> ": blackhole")) <> push' s (reverse regArgs ++ mkAp nargs nvars) <> push' s [r1, var "h$return"] <> returnS (app "h$blockOnBlackhole" [r1]))]-             (appS "throw" [toJExpr (fun_name <> ": unexpected closure type: ") + entryClosureType c])-          ]+      body = jVars $ \(c, farity, arity)  ->+        do fun_case_fun <- funCase c farity+           fun_case_pap <- funCase c arity+           return $ mconcat $+             [ c |= closureEntry r1+             , traceRts s (toJExpr (fun_name <> ": sp ") + sp)+             , SwitchStat (entryClosureType c)+               [(toJExpr Fun, traceRts s (toJExpr (fun_name <> ": ")+                                          + clName c+                                          + jString " (arity: " + (c .^ "a") + jString ")")+                              <> (farity |= funArity' c)+                              <> fun_case_fun)+               ,(toJExpr Pap, traceRts s (toJExpr (fun_name <> ": pap")) <> (arity |= papArity r1) <> fun_case_pap)+               ,(toJExpr Thunk, traceRts s (toJExpr (fun_name <> ": thunk")) <> push' s (reverse regArgs ++ mkAp nargs nvars) <> profStat s pushRestoreCCS <> returnS c)+               ,(toJExpr Blackhole, traceRts s (toJExpr (fun_name <> ": blackhole")) <> push' s (reverse regArgs ++ mkAp nargs nvars) <> push' s [r1, var "h$return"] <> returnS (app "h$blockOnBlackhole" [r1]))]+               (appS "throw" [toJExpr (fun_name <> ": unexpected closure type: ") + entryClosureType c])+             ] -      funCase :: JExpr -> JExpr -> JStat-      funCase c arity = jVar \arg ar -> case arg of-          ValExpr (JVar pap) -> [ ar |= mask8 arity-                                ,  ifS (toJExpr nargs .===. ar)-                                  -- then-                                  (traceRts s (toJExpr (fun_name <> ": exact")) <> returnS c)-                                  -- else-                                  (ifS (toJExpr nargs .>. ar)-                                    --then-                                    (traceRts s (toJExpr (fun_name <> ": oversat")) <> oversatCase c arity)-                                    -- else-                                    (traceRts s (toJExpr (fun_name <> ": undersat"))-                                     <> mkPap s pap r1 (toJExpr nargs) regArgs-                                     <> (r1 |= toJExpr pap)-                                     <> returnStack))-                                ]-          _             -> mempty+      funCase :: JStgExpr -> JStgExpr -> JSM JStgStat+      funCase c arity = jVars \(arg, ar) ->+        do oversat_case <- oversatCase c arity+           return $ mconcat $+             case arg of+               ValExpr (JVar pap) -> [ ar |= mask8 arity+                                     ,  ifS (toJExpr nargs .===. ar)+                                     -- then+                                       (traceRts s (toJExpr (fun_name <> ": exact")) <> returnS c)+                                     -- else+                                       (ifS (toJExpr nargs .>. ar)+                                       --then+                                        (traceRts s (toJExpr (fun_name <> ": oversat")) <> oversat_case)+                                       -- else+                                        (traceRts s (toJExpr (fun_name <> ": undersat"))+                                         <> mkPap s pap r1 (toJExpr nargs) regArgs+                                         <> (r1 |= toJExpr pap)+                                         <> returnStack))+                                     ]+               _             -> mempty -      oversatCase :: JExpr -> JExpr -> JStat+      oversatCase :: JStgExpr -> JStgExpr -> JSM JStgStat       oversatCase c arity =-         jVar \rs rsRemain ->-           [ rs |= arity .>>. 8-           , rsRemain |= toJExpr nvars - rs-           , traceRts s (toJExpr-                         (fun_name <> " regs oversat ")-                          + rs-                          + jString " remain: "-                          + rsRemain)-           , saveRegs rs-           , sp |= sp + rsRemain + 1-           , stack .! sp |= var "h$apply" .! ((rsRemain.<<.8).|. (toJExpr nargs - mask8 arity))-           , profStat s pushRestoreCCS-           , returnS c-           ]-          where-            saveRegs n = SwitchStat n switchAlts mempty-              where-                switchAlts = map (\x -> (toJExpr x, stack .! (sp + toJExpr (nvars-x)) |= jsReg (x+2))) [0..nvars-1]+         jVars \(rs, rsRemain) ->+                return $ mconcat $+                [ rs |= arity .>>. 8+                , rsRemain |= toJExpr nvars - rs+                , traceRts s (toJExpr+                              (fun_name <> " regs oversat ")+                              + rs+                              + jString " remain: "+                              + rsRemain)+                , saveRegs rs+                , sp |= sp + rsRemain + 1+                , stack .! sp |= var "h$apply" .! ((rsRemain.<<.8).|. (toJExpr nargs - mask8 arity))+                , profStat s pushRestoreCCS+                , returnS c+                ]+        where+          saveRegs n = SwitchStat n switchAlts mempty+            where+              switchAlts = map (\x -> (toJExpr x, stack .! (sp + toJExpr (nvars-x)) |= jsReg (x+2))) [0..nvars-1] -zeroApply :: StgToJSConfig -> JStat-zeroApply s = mconcat-  [ jFun (TxtI "h$e") (\c -> (r1 |= c) <> enter s c)-  ]+zeroApply :: StgToJSConfig -> JSM JStgStat+zeroApply s = jFunction (global "h$e")+              $ \(MkSolo c) -> fmap ((r1 |= c) <>) $ enter s c  -- carefully enter a closure that might be a thunk or a function  -- ex may be a local var, but must've been copied to R1 before calling this-enter :: StgToJSConfig -> JExpr -> JStat+enter :: StgToJSConfig -> JStgExpr -> JSM JStgStat enter s ex = jVar \c ->+  return $ mconcat $   [ jwhenS (app "typeof" [ex] .!==. jTyObject) returnStack   , c |= closureEntry ex   , jwhenS (c .===. var "h$unbox_e") ((r1 |= closureField1 ex) <> returnStack)@@ -877,97 +924,113 @@     ] (returnS c)   ] -updates :: StgToJSConfig -> JStat-updates s = BlockStat-  [ closure-      (ClosureInfo (TxtI "h$upd_frame") (CIRegs 0 [PtrV]) "h$upd_frame" (CILayoutFixed 1 [PtrV]) CIStackFrame mempty)-      $ jVar \updatee waiters ss si sir ->-            let unbox_closure = Closure-                  { clEntry  = var "h$unbox_e"-                  , clField1 = sir-                  , clField2 = null_-                  , clMeta   = 0-                  , clCC     = Nothing-                  }-                updateCC updatee = closureCC updatee |= jCurrentCCS-            in [ updatee |= stack .! (sp - 1)-               , traceRts s (jString "h$upd_frame updatee alloc: " + updatee .^ "alloc")-               , -- wake up threads blocked on blackhole-                 waiters |= closureField2 updatee-               , jwhenS (waiters .!==. null_)-                           (loop 0 (.<. waiters .^ "length")-                              (\i -> appS "h$wakeupThread" [waiters .! i] <> postIncrS i))-               , -- update selectors-                 jwhenS ((app "typeof" [closureMeta updatee] .===. jTyObject) .&&. (closureMeta updatee .^ "sel"))-                 ((ss |= closureMeta updatee .^ "sel")-                   <> loop 0 (.<. ss .^ "length") \i -> mconcat-                        [ si |= ss .! i-                        , sir |= (closureField2 si) `ApplExpr` [r1]-                        , ifS (app "typeof" [sir] .===. jTyObject)-                            (copyClosure DontCopyCC si sir)-                            (assignClosure si unbox_closure)-                        , postIncrS i-                        ])-               , -- overwrite the object-                 ifS (app "typeof" [r1] .===. jTyObject)-                     (mconcat [ traceRts s (jString "$upd_frame: boxed: " + ((closureEntry r1) .^ "n"))-                              , copyClosure DontCopyCC updatee r1-                              ])-                     -- the heap object is represented by another type of value-                     -- (e.g. a JS number or string) so the unboxing closure-                     -- will simply return it.-                     (assignClosure updatee (unbox_closure { clField1 = r1 }))-               , profStat s (updateCC updatee)-               , adjSpN' 2-               , traceRts s (jString "h$upd_frame: updating: "-                             + updatee-                             + jString " -> "-                             + r1)-               , returnStack-               ]+updates :: StgToJSConfig -> JSM JStgStat+updates s = do+  upd_frm <- update_frame+  upd_frm_lne <- update_frame_lne+  return $ BlockStat [upd_frm, upd_frm_lne]+  where+    unbox_closure f1 = Closure { clEntry  = var "h$unbox_e"+                               , clField1 = f1+                               , clField2 = null_+                               , clMeta   = 0+                               , clCC     = Nothing+                               }+    upd_loop' ss' si' sir' = loop zero_ (.<. ss' .^ "length")+                        $ \i -> return $ mconcat+                          [ si' |= ss' .! i+                          , sir' |= (closureField2 si') `ApplExpr` [r1]+                          , ifS (app "typeof" [sir'] .===. jTyObject)+                            (copyClosure DontCopyCC si' sir')+                            (assignClosure si' $ unbox_closure sir')+                          , postIncrS i+                          ]+    update_frame = closure+                   (ClosureInfo (global "h$upd_frame") (CIRegs 0 [PtrV]) "h$upd_frame" (CILayoutFixed 1 [PtrV]) CIStackFrame mempty)+                   $ jVars \(updatee, waiters, ss, si, sir) ->+                       do upd_loop         <- upd_loop' ss si sir+                          wake_thread_loop <- loop zero_ (.<. waiters .^ "length")+                                              \i -> return $+                                                    appS "h$wakeupThread" [waiters .! i]+                                                    <> postIncrS i+                          let updateCC updatee = closureCC updatee |= jCurrentCCS -   , closure-      (ClosureInfo (TxtI "h$upd_frame_lne") (CIRegs 0 [PtrV]) "h$upd_frame_lne" (CILayoutFixed 1 [PtrV]) CIStackFrame mempty)-      $ jVar \updateePos ->-          [ updateePos |= stack .! (sp - 1)-          , (stack .! updateePos |= r1)-          , adjSpN' 2-          , traceRts s (jString "h$upd_frame_lne: updating: "-                         + updateePos-                         + jString " -> "-                         + r1)-          , returnStack-          ]-  ]+                          return $ mconcat $+                            [ updatee |= stack .! (sp - 1)+                               , traceRts s (jString "h$upd_frame updatee alloc: " + updatee .^ "alloc")+                               , -- wake up threads blocked on blackhole+                                 waiters |= closureField2 updatee+                               , jwhenS (waiters .!==. null_) wake_thread_loop+                               , -- update selectors+                                 jwhenS ((app "typeof" [closureMeta updatee] .===. jTyObject) .&&. (closureMeta updatee .^ "sel"))+                                 ((ss |= closureMeta updatee .^ "sel")+                                  <> upd_loop)+                               , -- overwrite the object+                                 ifS (app "typeof" [r1] .===. jTyObject)+                                 (mconcat [ traceRts s (jString "$upd_frame: boxed: " + ((closureEntry r1) .^ "n"))+                                          , copyClosure DontCopyCC updatee r1+                                          ])+                               -- the heap object is represented by another type of value+                               -- (e.g. a JS number or string) so the unboxing closure+                               -- will simply return it.+                                 (assignClosure updatee (unbox_closure r1))+                               , profStat s (updateCC updatee)+                               , adjSpN' 2+                               , traceRts s (jString "h$upd_frame: updating: "+                                             + updatee+                                             + jString " -> "+                                             + r1)+                               , returnStack+                               ] -selectors :: StgToJSConfig -> JStat+    update_frame_lne = closure+                     (ClosureInfo (global "h$upd_frame_lne") (CIRegs 0 [PtrV]) "h$upd_frame_lne" (CILayoutFixed 1 [PtrV]) CIStackFrame mempty)+                     $ jVar \updateePos ->+                         return $ mconcat $+                         [ updateePos |= stack .! (sp - 1)+                         , (stack .! updateePos |= r1)+                         , adjSpN' 2+                         , traceRts s (jString "h$upd_frame_lne: updating: "+                                       + updateePos+                                       + jString " -> "+                                       + r1)+                         , returnStack+                         ]++selectors :: StgToJSConfig -> JSM JStgStat selectors s =-  mkSel "1"      closureField1-  <> mkSel "2a"  closureField2-  <> mkSel "2b"  (closureField1 . closureField2)-  <> mconcat (map mkSelN [3..16])+  do+    sel_one  <- mkSel "1"      closureField1+    sel_twoA <- mkSel "2a"  closureField2+    sel_twoB <- mkSel "2b"  (closureField1 . closureField2)+    rest     <- mconcat <$> (mapM mkSelN [3..16])+    return $+      sel_one <> sel_twoA <> sel_twoB <> rest    where-    mkSelN :: Int -> JStat+    mkSelN :: Int -> JSM JStgStat     mkSelN x = mkSel (mkFastString $ show x)                      (\e -> SelExpr (closureField2 (toJExpr e))-                            (TxtI $ mkFastString ("d" ++ show (x-1))))+                            (global $ mkFastString ("d" ++ show (x-1))))  -    mkSel :: FastString -> (JExpr -> JExpr) -> JStat-    mkSel name sel = mconcat-      [jFun (TxtI createName) \r -> mconcat+    mkSel :: FastString -> (JStgExpr -> JStgExpr) -> JSM JStgStat+    mkSel name sel = mconcat <$> sequence+      [jFunction (global createName) $+       \(MkSolo r) -> return $ mconcat           [ traceRts s (toJExpr ("selector create: " <> name <> " for ") + (r .^ "alloc"))           , ifS (isThunk r .||. isBlackhole r)               (returnS (app "h$mkSelThunk" [r, toJExpr (v entryName), toJExpr (v resName)]))               (returnS (sel r))           ]-      , jFun (TxtI resName) \r -> mconcat+      , jFunction (global resName) $+        \(MkSolo r) -> return $ mconcat           [ traceRts s (toJExpr ("selector result: " <> name <> " for ") + (r .^ "alloc"))           , returnS (sel r)           ]       , closure-        (ClosureInfo (TxtI entryName) (CIRegs 0 [PtrV]) ("select " <> name) (CILayoutFixed 1 [PtrV]) CIThunk mempty)-        (jVar \tgt ->+        (ClosureInfo (global entryName) (CIRegs 0 [PtrV]) ("select " <> name) (CILayoutFixed 1 [PtrV]) CIThunk mempty)+        (jVar $ \tgt ->+          return $ mconcat $           [ tgt |= closureField1 r1           , traceRts s (toJExpr ("selector entry: " <> name <> " for ") + (tgt .^ "alloc"))           , ifS (isThunk tgt .||. isBlackhole tgt)@@ -977,15 +1040,16 @@               (returnS (app "h$e" [sel tgt]))           ])       , closure-        (ClosureInfo (TxtI frameName) (CIRegs 0 [PtrV]) ("select " <> name <> " frame") (CILayoutFixed 0 []) CIStackFrame mempty)-        $ mconcat [ traceRts s (toJExpr ("selector frame: " <> name))-                  , postDecrS sp-                  , returnS (app "h$e" [sel r1])-                  ]+        (ClosureInfo (global frameName) (CIRegs 0 [PtrV]) ("select " <> name <> " frame") (CILayoutFixed 0 []) CIStackFrame mempty)+        $ return $+        mconcat [ traceRts s (toJExpr ("selector frame: " <> name))+                , postDecrS sp+                , returnS (app "h$e" [sel r1])+                ]       ]        where-         v x   = JVar (TxtI x)+         v x   = JVar (global x)          n ext =  "h$c_sel_" <> name <> ext          createName = n ""          resName    = n "_res"@@ -996,10 +1060,10 @@ -- arity is the remaining arity after our supplied arguments are applied mkPap :: StgToJSConfig       -> Ident   -- ^ id of the pap object-      -> JExpr   -- ^ the function that's called (can be a second pap)-      -> JExpr   -- ^ number of arguments in pap-      -> [JExpr] -- ^ values for the supplied arguments-      -> JStat+      -> JStgExpr   -- ^ the function that's called (can be a second pap)+      -> JStgExpr   -- ^ number of arguments in pap+      -> [JStgExpr] -- ^ values for the supplied arguments+      -> JStgStat mkPap s tgt fun n values =       traceRts s (toJExpr $ "making pap with: " ++ show (length values) ++ " items")       `mappend`@@ -1010,7 +1074,7 @@      values' | GHC.Prelude.null values = [null_]             | otherwise   = values-    entry | length values > numSpecPap = TxtI "h$pap_gen"+    entry | length values > numSpecPap = global "h$pap_gen"           | otherwise                  = specPapIdents ! length values  -- | Number of specialized PAPs (pre-generated for a given number of args)@@ -1024,17 +1088,18 @@  -- | Cache of specialized PAP idents specPapIdents :: Array Int Ident-specPapIdents = listArray (0,numSpecPap) $ map (TxtI . mkFastString . ("h$pap_"++) . show) specPap+specPapIdents = listArray (0,numSpecPap) $ map (global . mkFastString . ("h$pap_"++) . show) specPap  pap :: StgToJSConfig     -> Int-    -> JStat+    -> JSM JStgStat pap s r = closure (ClosureInfo funcIdent CIRegsUnknown funcName (CILayoutUnknown (r+2)) CIPap mempty) body   where-    funcIdent = TxtI funcName+    funcIdent = global funcName     funcName = mkFastString ("h$pap_" ++ show r) -    body = jVar \c d f extra ->+    body = jVars $ \(c, d, f, extra) ->+             return $ mconcat $              [ c |= closureField1 r1              , d |= closureField2 r1              , f |= closureEntry  c@@ -1052,13 +1117,14 @@     moveCase m = (toJExpr m, jsReg (m+r+1) |= jsReg (m+1))     loadOwnArgs d = mconcat $ map (\r ->         jsReg (r+1) |= dField d (r+2)) [1..r]-    dField d n = SelExpr d (TxtI . mkFastString $ ('d':show (n-1)))+    dField d n = SelExpr d (global . mkFastString $ ('d':show (n-1)))  -- Construct a generic PAP-papGen :: StgToJSConfig -> JStat+papGen :: StgToJSConfig -> JSM JStgStat papGen cfg =    closure (ClosureInfo funcIdent CIRegsUnknown funcName CILayoutVariable CIPap mempty)-           (jVar \c f d pr or r ->+           (jVars $ \(c, f, d, pr, or, r) ->+              return $ mconcat               [ c |= closureField1 r1               , d |= closureField2 r1               , f |= closureEntry  c@@ -1078,7 +1144,7 @@     where-    funcIdent = TxtI funcName+    funcIdent = global funcName     funcName = "h$pap_gen"     loadOwnArgs d r =       let prop n = d .^ ("d" <> mkFastString (show $ n+1))@@ -1087,13 +1153,13 @@  -- general utilities -- move the first n registers, starting at R2, m places up (do not use with negative m)-moveRegs2 :: JStat-moveRegs2 = jFun (TxtI "h$moveRegs2") moveSwitch+moveRegs2 :: JSM JStgStat+moveRegs2 = jFunction (global "h$moveRegs2") moveSwitch   where-    moveSwitch n m = SwitchStat ((n .<<. 8) .|. m) switchCases (defaultCase n m)+    moveSwitch (n,m) = defaultCase n m >>= return . SwitchStat ((n .<<. 8) .|. m) switchCases     -- fast cases     switchCases = [switchCase n m | n <- [1..5], m <- [1..4]]-    switchCase :: Int -> Int -> (JExpr, JStat)+    switchCase :: Int -> Int -> (JStgExpr, JStgStat)     switchCase n m = (toJExpr $                       (n `Bits.shiftL` 8) Bits..|. m                      , mconcat (map (`moveRegFast` m) [n+1,n..2])@@ -1101,11 +1167,13 @@     moveRegFast n m = jsReg (n+m) |= jsReg n     -- fallback     defaultCase n m =-      loop n (.>.0) (\i -> appS "h$setReg" [i+1+m, app "h$getReg" [i+1]] `mappend` postDecrS i)+      loop n (.>.0) (\i -> return $+                           appS "h$setReg" [i+1+m, app "h$getReg" [i+1]]+                           <> postDecrS i)   -- Initalize a variable sized object from an array of values-initClosure :: StgToJSConfig -> JExpr -> JExpr -> JExpr -> JExpr+initClosure :: StgToJSConfig -> JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr initClosure cfg entry values ccs = app "h$init_closure"   [ newClosure $ Closure       { clEntry  = entry@@ -1122,7 +1190,7 @@ getIdFields i = assocIdExprs i <$> varsForId i  -- | Store fields of Id into the given target expressions-storeIdFields :: Id -> [TypedExpr] -> G JStat+storeIdFields :: Id -> [TypedExpr] -> G JStgStat storeIdFields i dst = do   fields <- getIdFields i   pure (assignCoerce1 dst fields)
compiler/GHC/StgToJS/Arg.hs view
@@ -1,4 +1,5 @@-{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE LambdaCase   #-}+{-# LANGUAGE ViewPatterns #-}  ----------------------------------------------------------------------------- -- |@@ -30,7 +31,8 @@  import GHC.Prelude -import GHC.JS.Unsat.Syntax+import GHC.JS.JStg.Syntax+import GHC.JS.Ident import GHC.JS.Make  import GHC.StgToJS.DataCon@@ -118,7 +120,7 @@       Nothing -> reg       Just expr -> unfloated expr      where-       r = uTypeVt . stgArgType $ a+       r = primOrVoidRepToJSRep $ stgArgRep1 a        reg          | isVoid r            =              return []@@ -127,23 +129,23 @@          | i == falseDataConId =              return [StaticLitArg (BoolLit False)]          | isMultiVar r        =-             map (\(TxtI t) -> StaticObjArg t) <$> mapM (identForIdN i) [1..varSize r] -- this seems wrong, not an obj?-         | otherwise           = (\(TxtI it) -> [StaticObjArg it]) <$> identForId i+             map (\(identFS -> t) -> StaticObjArg t) <$> mapM (identForIdN i) [1..varSize r] -- this seems wrong, not an obj?+         | otherwise           = (\(identFS -> it) -> [StaticObjArg it]) <$> identForId i         unfloated :: CgStgExpr -> G [StaticArg]        unfloated (StgLit l) = map StaticLitArg <$> genStaticLit l        unfloated (StgConApp dc _n args _)          | isBoolDataCon dc || isUnboxableCon dc =              (:[]) . allocUnboxedConStatic dc . concat <$> mapM genStaticArg args -- fixme what is allocunboxedcon?-         | null args = (\(TxtI t) -> [StaticObjArg t]) <$> identForId (dataConWorkId dc)+         | null args = (\(identFS -> t) -> [StaticObjArg t]) <$> identForId (dataConWorkId dc)          | otherwise = do              as       <- concat <$> mapM genStaticArg args-             (TxtI e) <- identForDataConWorker dc+             e <- identFS <$> identForDataConWorker dc              return [StaticConArg e as]        unfloated x = pprPanic "genArg: unexpected unfloated expression" (pprStgExpr panicStgPprOpts x)  -- | Generate JS code for an StgArg-genArg :: HasDebugCallStack => StgArg -> G [JExpr]+genArg :: HasDebugCallStack => StgArg -> G [JStgExpr] genArg a = case a of   StgLitArg l -> genLit l   StgVarArg i -> do@@ -159,10 +161,10 @@     where      -- if our argument is a joinid, it can be an unboxed tuple-     r :: HasDebugCallStack => VarType-     r = uTypeVt . stgArgType $ a+     r :: HasDebugCallStack => JSRep+     r = primOrVoidRepToJSRep $ stgArgRep1 a -     unfloated :: HasDebugCallStack => CgStgExpr -> G [JExpr]+     unfloated :: HasDebugCallStack => CgStgExpr -> G [JStgExpr]      unfloated = \case       StgLit l -> genLit l       StgConApp dc _n args _@@ -176,8 +178,8 @@            return [allocDynamicE inl_alloc e as Nothing]       x -> pprPanic "genArg: unexpected unfloated expression" (pprStgExpr panicStgPprOpts x) --- | Generate a Var as JExpr-genIdArg :: HasDebugCallStack => Id -> G [JExpr]+-- | Generate a Var as JStgExpr+genIdArg :: HasDebugCallStack => Id -> G [JStgExpr] genIdArg i = genArg (StgVarArg i)  -- | Generate an Id as an Ident@@ -187,7 +189,7 @@   | isMultiVar r = mapM (identForIdN i) [1..varSize r]   | otherwise    = (:[]) <$> identForId i   where-    r = uTypeVt . idType $ i+    r = unaryTypeJSRep . idType $ i  -- | Generate IDs for stack arguments. See 'StgToJS.Expr.loadRetArgs' for use case genIdStackArgI :: HasDebugCallStack => Id -> G [(Ident,StackSlot)]@@ -198,7 +200,7 @@  -- | Allocate Static Constructors allocConStatic :: HasDebugCallStack => Ident -> CostCentreStack -> DataCon -> [StgArg] -> G ()-allocConStatic (TxtI to) cc con args = do+allocConStatic (identFS -> to) cc con args = do   as <- mapM genStaticArg args   cc' <- costCentreStackLbl cc   allocConStatic' cc' (concat as)@@ -212,7 +214,7 @@       | isBoolDataCon con && dataConTag con == 2 =            emitStatic to (StaticUnboxed $ StaticUnboxedBool True) cc'       | otherwise = do-           (TxtI e) <- identForDataConWorker con+           e <- identFS <$> identForDataConWorker con            emitStatic to (StaticData e []) cc'     allocConStatic' cc' [x]       | isUnboxableCon con =@@ -231,7 +233,7 @@                 (a0:a1:_) -> flip (emitStatic to) cc' =<< allocateStaticList [a0] a1                 _         -> panic "allocConStatic: invalid args for consDataCon"               else do-                (TxtI e) <- identForDataConWorker con+                e <- identFS <$> identForDataConWorker con                 emitStatic to (StaticData e xs) cc'  -- | Allocate unboxed constructors@@ -272,14 +274,14 @@ allocateStaticList _ _ = panic "allocateStaticList: unexpected literal in list"  -- | Generate JS code corresponding to a static arg-jsStaticArg :: StaticArg -> JExpr+jsStaticArg :: StaticArg -> JStgExpr jsStaticArg = \case   StaticLitArg l      -> toJExpr l-  StaticObjArg t      -> ValExpr (JVar (TxtI t))+  StaticObjArg t      -> var t   StaticConArg c args ->-    allocDynamicE False (ValExpr . JVar . TxtI $ c) (map jsStaticArg args) Nothing+    allocDynamicE False (var c) (map jsStaticArg args) Nothing  -- | Generate JS code corresponding to a list of static args-jsStaticArgs :: [StaticArg] -> JExpr+jsStaticArgs :: [StaticArg] -> JStgExpr jsStaticArgs = ValExpr . JList . map jsStaticArg 
compiler/GHC/StgToJS/Closure.hs view
@@ -31,7 +31,9 @@ import GHC.StgToJS.Regs (stack,sp)  import GHC.JS.Make-import GHC.JS.Unsat.Syntax+import GHC.JS.JStg.Syntax+import GHC.JS.JStg.Monad+import GHC.JS.Ident  import GHC.Types.Unique.Map @@ -39,7 +41,7 @@ import Data.Monoid import qualified Data.Bits as Bits -closureInfoStat :: Bool -> ClosureInfo -> JStat+closureInfoStat :: Bool -> ClosureInfo -> JStgStat closureInfoStat debug (ClosureInfo obj rs name layout ctype srefs)   = setObjInfoL debug obj rs layout ty name tag srefs       where@@ -67,7 +69,7 @@             -> FastString  -- ^ object name, for printing             -> Int         -- ^ `a' argument, depends on type (arity, conid)             -> CIStatic    -- ^ static refs-            -> JStat+            -> JStgStat setObjInfoL debug obj rs layout t n a   = setObjInfo debug obj t n field_types a size rs       where@@ -77,8 +79,9 @@           CILayoutFixed sz _ -> sz         field_types = case layout of           CILayoutVariable     -> []-          CILayoutUnknown size -> toTypeList (replicate size ObjV)-          CILayoutFixed _ fs   -> toTypeList fs+          CILayoutUnknown size -> to_type_list (replicate size ObjV)+          CILayoutFixed _ fs   -> to_type_list fs+        to_type_list = concatMap (\x -> replicate (varSize x) (fromEnum x))  setObjInfo :: Bool        -- ^ debug: output all symbol names            -> Ident       -- ^ the thing to modify@@ -89,7 +92,7 @@            -> Int         -- ^ object size, -1 (number of vars) for unknown            -> CIRegs      -- ^ things in registers            -> CIStatic    -- ^ static refs-           -> JStat+           -> JStgStat setObjInfo debug obj t name fields a size regs static    | debug     = appS "h$setObjInfo" [ toJExpr obj                                      , toJExpr t@@ -110,29 +113,32 @@   where     regTag CIRegsUnknown       = -1     regTag (CIRegs skip types) =-      let nregs = sum $ map varSize types+      let nregs = sum $ fmap varSize types       in  skip + (nregs `Bits.shiftL` 8) -closure :: ClosureInfo -- ^ object being info'd see @ciVar@ in @ClosureInfo@-        -> JStat       -- ^ rhs-        -> JStat-closure ci body = (jFun (ciVar ci) body) `mappend` closureInfoStat False ci+-- | Special case of closures that do not need to generate any @fresh@ names+closure :: ClosureInfo    -- ^ object being info'd see @ciVar@+         -> (JSM JStgStat) -- ^ rhs+         -> JSM JStgStat+closure ci body = do f <- (jFunction' (ciVar ci) body)+                     return $ f `mappend` closureInfoStat False ci -conClosure :: Ident -> FastString -> CILayout -> Int -> JStat-conClosure symbol name layout constr =-  closure (ClosureInfo symbol (CIRegs 0 [PtrV]) name layout (CICon constr) mempty)-          (returnS (stack .! sp))+conClosure :: Ident -> FastString -> CILayout -> Int -> JSM JStgStat+conClosure symbol name layout constr = closure ci body+  where+    ci = (ClosureInfo symbol (CIRegs 0 [PtrV]) name layout (CICon constr) mempty)+    body   = pure . returnS $ stack .! sp  -- | Used to pass arguments to newClosure with some safety data Closure = Closure-  { clEntry  :: JExpr-  , clField1 :: JExpr-  , clField2 :: JExpr-  , clMeta   :: JExpr-  , clCC     :: Maybe JExpr+  { clEntry  :: JStgExpr+  , clField1 :: JStgExpr+  , clField2 :: JStgExpr+  , clMeta   :: JStgExpr+  , clCC     :: Maybe JStgExpr   } -newClosure :: Closure -> JExpr+newClosure :: Closure -> JStgExpr newClosure Closure{..} =   let xs = [ (closureEntry_ , clEntry)            , (closureField1_, clField1)@@ -145,7 +151,7 @@     Nothing -> ValExpr (jhFromList xs)     Just cc -> ValExpr (jhFromList $ (closureCC_,cc) : xs) -assignClosure :: JExpr -> Closure -> JStat+assignClosure :: JStgExpr -> Closure -> JStgStat assignClosure t Closure{..} = BlockStat   [ closureEntry  t |= clEntry   , closureField1 t |= clField1@@ -157,7 +163,7 @@  data CopyCC = CopyCC | DontCopyCC -copyClosure :: CopyCC -> JExpr -> JExpr -> JStat+copyClosure :: CopyCC -> JStgExpr -> JStgExpr -> JStgStat copyClosure copy_cc t s = BlockStat   [ closureEntry  t |= closureEntry  s   , closureField1 t |= closureField1 s@@ -167,7 +173,7 @@       DontCopyCC -> mempty       CopyCC     -> closureCC t |= closureCC s -mkClosure :: JExpr -> [JExpr] -> JExpr -> Maybe JExpr -> Closure+mkClosure :: JStgExpr -> [JStgExpr] -> JStgExpr -> Maybe JStgExpr -> Closure mkClosure entry fields meta cc = Closure   { clEntry  = entry   , clField1 = x1@@ -183,7 +189,7 @@            []     -> null_            [_]    -> null_            [_,x]  -> x-           _:x:xs -> ValExpr . JHash . listToUniqMap $ zip (map dataFieldName [1..]) (x:xs)+           _:x:xs -> ValExpr . JHash . listToUniqMap $ zip (fmap dataFieldName [1..]) (x:xs)   -------------------------------------------------------------------------------@@ -193,7 +199,7 @@  -- | Cache "dXXX" field names dataFieldCache :: Array Int FastString-dataFieldCache = listArray (0,nFieldCache) (map (mkFastString . ('d':) . show) [(0::Int)..nFieldCache])+dataFieldCache = listArray (0,nFieldCache) (fmap (mkFastString . ('d':) . show) [(0::Int)..nFieldCache])  -- | Data names are used in the AST, and logging has determined that 255 is the maximum number we see. nFieldCache :: Int@@ -211,33 +217,34 @@  -- | Cache "h$dXXX" names dataCache :: Array Int FastString-dataCache = listArray (0,jsClosureCount) (map (mkFastString . ("h$d"++) . show) [(0::Int)..jsClosureCount])+dataCache = listArray (0,jsClosureCount) (fmap (mkFastString . ("h$d"++) . show) [(0::Int)..jsClosureCount])  dataName :: Int -> FastString dataName i   | i < 0 || i > nFieldCache = mkFastString ("h$d" ++ show i)   | otherwise                = dataCache ! i -allocData :: Int -> JExpr-allocData i = toJExpr (TxtI (dataName i))+allocData :: Int -> JStgExpr+allocData i = toJExpr (global (dataName i))  -- | Cache "h$cXXX" names clsCache :: Array Int FastString-clsCache = listArray (0,jsClosureCount) (map (mkFastString . ("h$c"++) . show) [(0::Int)..jsClosureCount])+clsCache = listArray (0,jsClosureCount) (fmap (mkFastString . ("h$c"++) . show) [(0::Int)..jsClosureCount])  clsName :: Int -> FastString clsName i   | i < 0 || i > jsClosureCount = mkFastString ("h$c" ++ show i)   | otherwise                   = clsCache ! i -allocClsA :: Int -> JExpr-allocClsA i = toJExpr (TxtI (clsName i))+allocClsA :: Int -> JStgExpr+allocClsA i = toJExpr (global (clsName i))  -- | Cache "xXXX" names varCache :: Array Int Ident-varCache = listArray (0,jsClosureCount) (map (TxtI . mkFastString . ('x':) . show) [(0::Int)..jsClosureCount])+varCache = listArray (0,jsClosureCount) (fmap (global . mkFastString . ('x':) . show) [(0::Int)..jsClosureCount])  varName :: Int -> Ident varName i-  | i < 0 || i > jsClosureCount = TxtI $ mkFastString ('x' : show i)+  | i < 0 || i > jsClosureCount = global $ mkFastString ('x' : show i)   | otherwise                   = varCache ! i+
compiler/GHC/StgToJS/CodeGen.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE BlockArguments #-}-{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE LambdaCase   #-}+{-# LANGUAGE ViewPatterns #-}  -- | JavaScript code generator module GHC.StgToJS.CodeGen@@ -13,7 +14,8 @@ import GHC.Driver.Flags (DumpFlag (Opt_D_dump_js))  import GHC.JS.Ppr-import GHC.JS.Unsat.Syntax+import GHC.JS.JStg.Syntax+import GHC.JS.Ident import GHC.JS.Make import GHC.JS.Transform import GHC.JS.Optimizer@@ -133,15 +135,15 @@         glbl <- State.gets gsGlobal         staticInit <-           initStaticPtrs spt_entries-        let stat = ( jsOptimize .-                     satJStat (Just $ modulePrefix m 1)+        let stat = ( jStgStatToJS                    $ mconcat (reverse glbl) <> staticInit)+        let opt_stat = jsOptimize stat         let syms = [moduleGlobalSymbol m]         let oi = ObjBlock                   { oiSymbols  = syms                   , oiClInfo   = []                   , oiStatic   = []-                  , oiStat     = stat+                  , oiStat     = opt_stat                   , oiRaw      = mempty                   , oiFExports = []                   , oiFImports = []@@ -196,26 +198,21 @@                     => CgStgTopBinding                     -> Int                     -> G (Maybe LinkableUnit)-      generateBlock top_bind n = case top_bind of+      generateBlock top_bind _n = case top_bind of         StgTopStringLit bnd str -> do           bids <- identsForId bnd           case bids of-            [(TxtI b1t),(TxtI b2t)] -> do-              -- [e1,e2] <- genLit (MachStr str)+            [(identFS -> b1t),(identFS -> b2t)] -> do               emitStatic b1t (StaticUnboxed (StaticUnboxedString str)) Nothing               emitStatic b2t (StaticUnboxed (StaticUnboxedStringOffset str)) Nothing-              _extraTl   <- State.gets (ggsToplevelStats . gsGroup)               si        <- State.gets (ggsStatic . gsGroup)-              let body = mempty -- mconcat (reverse extraTl) <> b1 ||= e1 <> b2 ||= e2-              let stat =  jsOptimize-                          $ satJStat (Just $ modulePrefix m n) body               let ids = [bnd]-              syms <- (\(TxtI i) -> [i]) <$> identForId bnd+              syms <- (\(identFS -> i) -> [i]) <$> identForId bnd               let oi = ObjBlock                         { oiSymbols  = syms                         , oiClInfo   = []                         , oiStatic   = si-                        , oiStat     = stat+                        , oiStat     = mempty                         , oiRaw      = ""                         , oiFExports = []                         , oiFImports = []@@ -245,15 +242,15 @@           let allDeps  = collectIds unf decl               topDeps  = collectTopIds decl               required = hasExport decl-              stat     = jsOptimize-                         . satJStat (Just $ modulePrefix m n)+              stat     = jStgStatToJS                          $ mconcat (reverse extraTl) <> tl-          syms <- mapM (fmap (\(TxtI i) -> i) . identForId) topDeps+          let opt_stat = jsOptimize stat+          syms <- mapM (fmap (\(identFS -> i) -> i) . identForId) topDeps           let oi = ObjBlock                     { oiSymbols  = syms                     , oiClInfo   = ci                     , oiStatic   = si-                    , oiStat     = stat+                    , oiStat     = opt_stat                     , oiRaw      = ""                     , oiFExports = []                     , oiFImports = fRefs@@ -271,23 +268,19 @@           pure $! seqList topDeps `seq` seqList allDeps `seq` Just lu  -- | variable prefix for the nth block in module-modulePrefix :: Module -> Int -> FastString-modulePrefix m n =-  let encMod = zEncodeString . moduleNameString . moduleName $ m-  in  mkFastString $ "h$" ++ encMod ++ "_id_" ++ show n -genToplevel :: CgStgBinding -> G JStat+genToplevel :: CgStgBinding -> G JStgStat genToplevel (StgNonRec bndr rhs) = genToplevelDecl bndr rhs genToplevel (StgRec bs)          =   mconcat <$> mapM (\(bndr, rhs) -> genToplevelDecl bndr rhs) bs -genToplevelDecl :: Id -> CgStgRhs -> G JStat+genToplevelDecl :: Id -> CgStgRhs -> G JStgStat genToplevelDecl i rhs = do   s1 <- resetSlots (genToplevelConEntry i rhs)   s2 <- resetSlots (genToplevelRhs i rhs)   return (s1 <> s2) -genToplevelConEntry :: Id -> CgStgRhs -> G JStat+genToplevelConEntry :: Id -> CgStgRhs -> G JStgStat genToplevelConEntry i rhs = case rhs of    StgRhsCon _cc con _mu _ts _args _typ      | isDataConWorkId i@@ -297,14 +290,14 @@        -> genSetConInfo i dc (stgRhsLive rhs) -- srt    _ -> pure mempty -genSetConInfo :: HasDebugCallStack => Id -> DataCon -> LiveVars -> G JStat+genSetConInfo :: HasDebugCallStack => Id -> DataCon -> LiveVars -> G JStgStat genSetConInfo i d l {- srt -} = do   ei <- identForDataConEntryId i   sr <- genStaticRefs l   emitClosureInfo $ ClosureInfo ei                                 (CIRegs 0 [PtrV])                                 (mkFastString $ renderWithContext defaultSDocContext (ppr d))-                                (fixedLayout $ map uTypeVt fields)+                                (fixedLayout $ map unaryTypeJSRep fields)                                 (CICon $ dataConTag d)                                 sr   return (mkDataEntry ei)@@ -314,10 +307,10 @@                          (dataConRepArgTys d)         -- concatMap (map slotTyToType . repTypeSlots . repType) (dataConRepArgTys d) -mkDataEntry :: Ident -> JStat+mkDataEntry :: Ident -> JStgStat mkDataEntry i = FuncStat i [] returnStack -genToplevelRhs :: Id -> CgStgRhs -> G JStat+genToplevelRhs :: Id -> CgStgRhs -> G JStgStat -- general cases: genToplevelRhs i rhs = case rhs of   StgRhsCon cc con _mu _tys args _typ -> do@@ -332,10 +325,11 @@        - order by increasing use        - prepend loading lives var to body: body can stay the same     -}-    eid@(TxtI eidt) <- identForEntryId i-    (TxtI idt)   <- identForId i+    eid  <- identForEntryId i+    idt  <- identFS <$> identForId i     body <- genBody (initExprCtx i) R2 args body typ-    global_occs <- globalOccs (satJStat (Just "ghcjs_tmp_sat_") body)+    global_occs <- globalOccs body+    let eidt = identFS eid     let lidents = map global_ident global_occs     let lids    = map global_id    global_occs     let lidents' = map identFS lidents@@ -350,8 +344,8 @@           r <- updateThunk           pure (StaticThunk (Just (eidt, map StaticObjArg lidents')), CIRegs 0 [PtrV],r)         else return (StaticFun eidt (map StaticObjArg lidents'),-                    (if null lidents then CIRegs 1 (concatMap idVt args)-                                     else CIRegs 0 (PtrV : concatMap idVt args))+                    (if null lidents then CIRegs 1 (concatMap idJSRep args)+                                     else CIRegs 0 (PtrV : concatMap idJSRep args))                       , mempty)     setcc <- ifProfiling $                if et == CIThunk@@ -360,7 +354,7 @@     emitClosureInfo (ClosureInfo eid                                  regs                                  idt-                                 (fixedLayout $ map (uTypeVt . idType) lids)+                                 (fixedLayout $ map (unaryTypeJSRep . idType) lids)                                  et                                  sr)     ccId <- costCentreStackLbl cc
compiler/GHC/StgToJS/DataCon.hs view
@@ -27,9 +27,10 @@  import GHC.Prelude -import GHC.JS.Unsat.Syntax-import GHC.JS.Transform+import GHC.JS.JStg.Syntax+import GHC.JS.Ident import GHC.JS.Make+import GHC.JS.Transform  import GHC.StgToJS.Closure import GHC.StgToJS.ExprCtx@@ -49,26 +50,26 @@ import Data.Maybe  -- | Generate a data constructor. Special handling for unboxed tuples-genCon :: ExprCtx -> DataCon -> [JExpr] -> G JStat+genCon :: ExprCtx -> DataCon -> [JStgExpr] -> G JStgStat genCon ctx con args   | isUnboxedTupleDataCon con   = return $ assignToExprCtx ctx args -  | [ValExpr (JVar ctxi)] <- concatMap typex_expr (ctxTarget ctx)+  | [Var ctxi] <- concatMap (typex_expr) (ctxTarget ctx)   = allocCon ctxi con currentCCS args    | xs <- concatMap typex_expr (ctxTarget ctx)   = pprPanic "genCon: unhandled DataCon" (ppr (con-                                              , satJExpr Nothing <$> args-                                              , satJExpr Nothing <$> xs+                                              , map jStgExprToJS args+                                              , map jStgExprToJS xs                                               ))  -- | Allocate a data constructor. Allocate in this context means bind the data -- constructor to 'to'-allocCon :: Ident -> DataCon -> CostCentreStack -> [JExpr] -> G JStat+allocCon :: Ident -> DataCon -> CostCentreStack -> [JStgExpr] -> G JStgStat allocCon to con cc xs   | isBoolDataCon con || isUnboxableCon con =-      return (toJExpr to |= allocUnboxedCon con xs)+      return $ AssignStat (Var to) AssignOp (allocUnboxedCon con xs) {-  | null xs = do       i <- varForId (dataConWorkId con)       return (assignj to i) -}@@ -82,32 +83,32 @@ -- | Allocate an unboxed data constructor. If we have a bool we calculate the -- right value. If not then we expect a singleton list and unbox by converting -- ''C x' to 'x'. NB. This function may panic.-allocUnboxedCon :: DataCon -> [JExpr] -> JExpr+allocUnboxedCon :: DataCon -> [JStgExpr] -> JStgExpr allocUnboxedCon con = \case   []     | isBoolDataCon con && dataConTag con == 1 -> false_     | isBoolDataCon con && dataConTag con == 2 -> true_   [x]     | isUnboxableCon con -> x-  xs -> pprPanic "allocUnboxedCon: not an unboxed constructor" (ppr (con, satJExpr Nothing <$> xs))+  xs -> pprPanic "allocUnboxedCon: not an unboxed constructor" (ppr (con, map jStgExprToJS xs))  -- | Allocate an entry function. See 'GHC.StgToJS.hs' for the object layout. allocDynamicE :: Bool          -- ^ csInlineAlloc from StgToJSConfig-              -> JExpr-              -> [JExpr]-              -> Maybe JExpr-              -> JExpr+              -> JStgExpr+              -> [JStgExpr]+              -> Maybe JStgExpr+              -> JStgExpr allocDynamicE  inline_alloc entry free cc   | inline_alloc || length free > jsClosureCount-    = newClosure $ mkClosure entry free (ValExpr (JInt 0)) cc-  | otherwise = ApplExpr allocFun (toJExpr entry : free ++ maybeToList cc)+    = newClosure $ mkClosure entry free zero_ cc+  | otherwise = ApplExpr allocFun (entry : free ++ maybeToList cc)   where     allocFun = allocClsA (length free)  -- | Allocate a dynamic object-allocDynamic :: StgToJSConfig -> Bool -> Ident -> JExpr -> [JExpr] -> Maybe JExpr -> JStat+allocDynamic :: StgToJSConfig -> Bool -> Ident -> JStgExpr -> [JStgExpr] -> Maybe JStgExpr -> JStgStat allocDynamic s need_decl to entry free cc   | need_decl = DeclStat to (Just value)-  | otherwise = toJExpr to |= value+  | otherwise = AssignStat (Var to) AssignOp value     where       value = allocDynamicE (csInlineAlloc s) entry free cc
compiler/GHC/StgToJS/Deps.hs view
@@ -26,7 +26,7 @@ import GHC.StgToJS.Types import GHC.StgToJS.Ids -import GHC.JS.Unsat.Syntax+import GHC.JS.Ident  import GHC.Types.Id import GHC.Types.Unique@@ -48,7 +48,6 @@ import qualified GHC.Data.Word64Map as WM import GHC.Data.Word64Map (Word64Map) import Data.Array-import Data.Either import Data.Word import Control.Monad @@ -101,9 +100,9 @@              -> Int              -> StateT DependencyDataCache G (Int, BlockDeps, Bool, [ExportedFun])       oneDep (LinkableUnit _ idExports otherExports idDeps pseudoIdDeps otherDeps req _frefs) n = do-        (edi, bdi) <- partitionEithers <$> mapM (lookupIdFun n) idDeps-        (edo, bdo) <- partitionEithers <$> mapM lookupOtherFun otherDeps-        (edp, bdp) <- partitionEithers <$> mapM (lookupPseudoIdFun n) pseudoIdDeps+        (edi, bdi) <- partitionWithM (lookupIdFun n) idDeps+        (edo, bdo) <- partitionWithM lookupOtherFun otherDeps+        (edp, bdp) <- partitionWithM (lookupPseudoIdFun n) pseudoIdDeps         expi <- mapM lookupExportedId (filter isExportedId idExports)         expo <- mapM lookupExportedOther otherExports         -- fixme thin deps, remove all transitive dependencies!@@ -140,7 +139,7 @@             let k = getKey . getUnique $ i                 addEntry :: StateT DependencyDataCache G ExportedFun                 addEntry = do-                  (TxtI idTxt) <- lift (identForId i)+                  idTxt <- identFS <$> lift (identForId i)                   lookupExternalFun (Just k) (OtherSymb m idTxt)             in  if m == mod                    then pprPanic "local id not found" (ppr m)@@ -160,7 +159,7 @@        lookupExportedId :: Id -> StateT DependencyDataCache G ExportedFun       lookupExportedId i = do-        (TxtI idTxt) <- lift (identForId i)+        idTxt <- identFS <$> lift (identForId i)         lookupExternalFun (Just . getKey . getUnique $ i) (OtherSymb mod idTxt)        lookupExportedOther :: FastString -> StateT DependencyDataCache G ExportedFun
compiler/GHC/StgToJS/Expr.hs view
@@ -1,7 +1,8 @@-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE DeriveFunctor #-}+{-# LANGUAGE LambdaCase    #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE ViewPatterns  #-}  ----------------------------------------------------------------------------- -- |@@ -30,9 +31,11 @@  import GHC.Prelude -import GHC.JS.Unsat.Syntax+import GHC.JS.JStg.Syntax+import GHC.JS.JStg.Monad import GHC.JS.Transform import GHC.JS.Make+import GHC.JS.Ident  import GHC.StgToJS.Apply import GHC.StgToJS.Arg@@ -65,7 +68,7 @@ import GHC.Builtin.PrimOps import GHC.Builtin.Names -import GHC.Core+import GHC.Core hiding (Var) import GHC.Core.TyCon import GHC.Core.DataCon import GHC.Core.Opt.Arity (isOneShotBndr)@@ -78,12 +81,13 @@ import GHC.Utils.Outputable (ppr, renderWithContext, defaultSDocContext) import qualified Control.Monad.Trans.State.Strict as State import GHC.Data.FastString+import qualified GHC.Types.Unique.Map as UM+ import qualified GHC.Data.List.SetOps as ListSetOps  import Data.Monoid import Data.Maybe import Data.Function-import Data.Either import qualified Data.List as L import qualified Data.Set as S import qualified Data.Map as M@@ -91,17 +95,17 @@ import Control.Arrow ((&&&))  -- | Evaluate an expression in the given expression context (continuation)-genExpr :: HasDebugCallStack => ExprCtx -> CgStgExpr -> G (JStat, ExprResult)+genExpr :: HasDebugCallStack => ExprCtx -> CgStgExpr -> G (JStgStat, ExprResult) genExpr ctx stg = case stg of   StgApp f args -> genApp ctx f args   StgLit l      -> do     ls <- genLit l     let r = assignToExprCtx ctx ls-    pure (r,ExprInline Nothing)+    pure (r,ExprInline)   StgConApp con _n args _ -> do     as <- concatMapM genArg args     c <- genCon ctx con as-    return (c, ExprInline (Just as))+    return (c, ExprInline)   StgOpApp (StgFCallOp f _) args t     -> genForeignCall ctx f t (concatMap typex_expr $ ctxTarget ctx) args   StgOpApp (StgPrimOp op) args t@@ -131,23 +135,23 @@ genBind :: HasDebugCallStack         => ExprCtx         -> CgStgBinding-        -> G (JStat, ExprCtx)+        -> G (JStgStat, ExprCtx) genBind ctx bndr =   case bndr of     StgNonRec b r -> do        j <- assign b r >>= \case          Just ja -> return ja          Nothing -> allocCls Nothing [(b,r)]-       return (j, addEvalRhs ctx [(b,r)])+       return (j, ctx)     StgRec bs     -> do        jas <- mapM (uncurry assign) bs -- fixme these might depend on parts initialized by allocCls        let m = if null jas then Nothing else Just (mconcat $ catMaybes jas)        j <- allocCls m . map snd . filter (isNothing . fst) $ zip jas bs-       return (j, addEvalRhs ctx bs)+       return (j, ctx)    where      ctx' = ctxClearLneFrame ctx -     assign :: Id -> CgStgRhs -> G (Maybe JStat)+     assign :: Id -> CgStgRhs -> G (Maybe JStgStat)      assign b (StgRhsClosure _ _ccs {-[the_fv]-} _upd [] expr _typ)        | let strip = snd . stripStgTicksTop (not . tickishIsCode)        , StgCase (StgApp scrutinee []) _ (AlgAlt _) [GenStgAlt (DataAlt _) params sel_expr] <- strip expr@@ -169,7 +173,7 @@                (tgt ||= ApplExpr (var ("h$c_sel_" <> mkFastString sel_tag)) [the_fvj])              _ -> panic "genBind.assign: invalid size"      assign b (StgRhsClosure _ext _ccs _upd [] expr _typ)-       | snd (isInlineExpr (ctxEvaluatedIds ctx) expr) = do+       | isInlineExpr expr = do            d   <- declVarsForId b            tgt <- varsForId b            let ctx' = ctx { ctxTarget = assocIdExprs b tgt }@@ -178,16 +182,10 @@      assign _b StgRhsCon{} = return Nothing      assign  b r           = genEntry ctx' b r >> return Nothing -     addEvalRhs c [] = c-     addEvalRhs c ((b,r):xs)-       | StgRhsCon{} <- r                         = addEvalRhs (ctxAssertEvaluated b c) xs-       | (StgRhsClosure _ _ ReEntrant _ _ _) <- r = addEvalRhs (ctxAssertEvaluated b c) xs-       | otherwise                                = addEvalRhs c xs- genBindLne :: HasDebugCallStack            => ExprCtx            -> CgStgBinding-           -> G (JStat, ExprCtx)+           -> G (JStgStat, ExprCtx) genBindLne ctx bndr = do   -- compute live variables and the offsets where they will be stored in the   -- stack@@ -231,35 +229,38 @@         maybe (panic "genEntryLne: updatable binder not found in let-no-escape frame")               ((payloadSize-) . fst)               (L.find ((==i) . fst . snd) (zip [0..] vars))-      bh | isUpdatable update =-             jVar (\x -> mconcat-              [ x |= ApplExpr (var "h$bh_lne") [Sub sp (toJExpr myOffset), toJExpr (payloadSize+1)]-              , IfStat x (ReturnStat x) mempty-              ])-         | otherwise = mempty-  lvs  <- popLneFrame True payloadSize ctx-  body <- genBody ctx R1 args body typ-  ei@(TxtI eii) <- identForEntryId i+      mk_bh :: G JStgStat+      mk_bh | isUpdatable update =+              do x <- freshIdent+                 return $ mconcat+                   [ x ||= ApplExpr (var "h$bh_lne") [Sub sp (toJExpr myOffset), toJExpr (payloadSize+1)]+                   , IfStat (Var x) (ReturnStat (Var x)) mempty+                   ]+            | otherwise = pure mempty+  blk_hl <- mk_bh+  locals <- popLneFrame True payloadSize ctx+  body   <- genBody ctx R1 args body typ+  ei@(identFS -> eii) <- identForEntryId i   sr   <- genStaticRefsRhs rhs-  let f = (bh <> lvs <> body)+  let f = (blk_hl <> locals <> body)   emitClosureInfo $     ClosureInfo ei-                (CIRegs 0 $ concatMap idVt args)+                (CIRegs 0 $ concatMap idJSRep args)                 (eii <> ", " <> mkFastString (renderWithContext defaultSDocContext (ppr i)))                 (fixedLayout . reverse $                     map (stackSlotType . fst) (ctxLneFrameVars ctx))                 CIStackFrame                 sr-  emitToplevel (jFunction ei [] f)+  emitToplevel (FuncStat ei [] f) genEntryLne ctx i (StgRhsCon cc con _mu _ticks args _typ) = resetSlots $ do   let payloadSize = ctxLneFrameSize ctx-  ei@(TxtI _eii) <- identForEntryId i+  ei <- identForEntryId i   -- di <- varForDataConWorker con   ii <- freshIdent   p  <- popLneFrame True payloadSize ctx   args' <- concatMapM genArg args   ac    <- allocCon ii con cc args'-  emitToplevel (jFunction ei [] (mconcat [decl ii, p, ac, r1 |= toJExpr ii, returnStack]))+  emitToplevel (FuncStat ei [] (mconcat [decl ii, p, ac, r1 |= toJExpr ii, returnStack]))  -- | Generate the entry function for a local closure genEntry :: HasDebugCallStack => ExprCtx -> Id -> CgStgRhs -> G ()@@ -270,7 +271,7 @@   llv   <- verifyRuntimeReps live   upd   <- genUpdFrame upd_flag i   body  <- genBody entryCtx R2 args body typ-  ei@(TxtI eii) <- identForEntryId i+  ei@(identFS -> eii) <- identForEntryId i   et    <- genEntryType args   setcc <- ifProfiling $              if et == CIThunk@@ -278,25 +279,22 @@                else enterCostCentreFun cc   sr <- genStaticRefsRhs rhs   emitClosureInfo $ ClosureInfo ei-                                (CIRegs 0 $ PtrV : concatMap idVt args)+                                (CIRegs 0 $ PtrV : concatMap idJSRep args)                                 (eii <> ", " <> mkFastString (renderWithContext defaultSDocContext (ppr i)))-                                (fixedLayout $ map (uTypeVt . idType) live)+                                (fixedLayout $ map (unaryTypeJSRep . idType) live)                                 et                                 sr-  emitToplevel (jFunction ei [] (mconcat [ll, llv, upd, setcc, body]))+  emitToplevel (FuncStat ei [] (mconcat [ll, llv, upd, setcc, body]))   where     entryCtx = ctxSetTarget [] (ctxClearLneFrame ctx)  -- | Generate the entry function types for identifiers. Note that this only--- returns either 'CIThunk' or 'CIFun'. Everything else (PAP Blackhole etc.) is--- filtered as not a RuntimeRepKinded type.+-- returns either 'CIThunk' or 'CIFun'. genEntryType :: HasDebugCallStack => [Id] -> G CIType genEntryType []   = return CIThunk-genEntryType args0 = do+genEntryType args = do   args' <- mapM genIdArg args   return $ CIFun (length args) (length $ concat args')-  where-    args = filter (not . isRuntimeRepKindedTy . idType) args0  -- | Generate the body of an object genBody :: HasDebugCallStack@@ -305,7 +303,7 @@          -> [Id]          -> CgStgExpr          -> Type-         -> G JStat+         -> G JStgStat genBody ctx startReg args e typ = do   -- load arguments into local variables   la <- do@@ -352,7 +350,7 @@ -- -- Se we're left to use the applied arguments to peel the type (unwrapped) one -- arg at a time. But passed args are args after unarisation so we need to--- unarise every argument type that we peel (using typePrimRepArgs) to get the+-- unarise every argument type that we peel (using typePrimRep) to get the -- number of passed args consumed by each type arg. -- -- In case of failure to determine the type, we default to LiftedRep as it's@@ -367,7 +365,7 @@  -- | Ensure that the set of identifiers has valid 'RuntimeRep's. This function -- returns a no-op when 'csRuntimeAssert' in 'StgToJSConfig' is False.-verifyRuntimeReps :: HasDebugCallStack => [Id] -> G JStat+verifyRuntimeReps :: HasDebugCallStack => [Id] -> G JStgStat verifyRuntimeReps xs = do   runtime_assert <- csRuntimeAssert <$> getSettings   if not runtime_assert@@ -376,7 +374,7 @@   where     verifyRuntimeRep i = do       i' <- varsForId i-      pure $ go i' (idVt i)+      pure $ go i' (idJSRep i)     go js         (VoidV:vs) = go js vs     go (j1:j2:js) (LongV:vs) = v "h$verify_rep_long" [j1,j2] <> go js vs     go (j1:j2:js) (AddrV:vs) = v "h$verify_rep_addr" [j1,j2] <> go js vs@@ -394,7 +392,7 @@ -- registers. This assumes these data fields have already been populated in the -- registers. For the empty, singleton, and binary case use register 1, for any -- more use as many registers as necessary.-loadLiveFun :: [Id] -> G JStat+loadLiveFun :: [Id] -> G JStgStat loadLiveFun l = do    l' <- concat <$> mapM identsForId l    case l' of@@ -416,11 +414,11 @@                , l''                ]   where-        loadLiveVar d n v = let ident = TxtI (dataFieldName n)+        loadLiveVar d n v = let ident = global (dataFieldName n)                             in  v ||= SelExpr d ident  -- | Pop a let-no-escape frame off the stack-popLneFrame :: Bool -> Int -> ExprCtx -> G JStat+popLneFrame :: Bool -> Int -> ExprCtx -> G JStgStat popLneFrame inEntry size ctx = do   -- calculate the new stack size   let ctx' = ctxLneShrinkStack ctx size@@ -436,7 +434,7 @@   popSkipI skip is  -- | Generate an updated given an 'Id'-genUpdFrame :: UpdateFlag -> Id -> G JStat+genUpdFrame :: UpdateFlag -> Id -> G JStgStat genUpdFrame u i   | isReEntrant u   = pure mempty   | isOneShotBndr i = maybeBh@@ -456,7 +454,7 @@ -- Useful for making sure that the object is not accidentally entered multiple -- times ---bhSingleEntry :: StgToJSConfig -> JStat+bhSingleEntry :: StgToJSConfig -> JStgStat bhSingleEntry _settings = mconcat   [ r1 .^ closureEntry_  |= var "h$blackholeTrap"   , r1 .^ closureField1_ |= undefined_@@ -480,7 +478,7 @@     sv = liveStatic lv      getStaticRef :: Id -> G (Maybe FastString)-    getStaticRef = fmap (fmap itxt . listToMaybe) . identsForId+    getStaticRef = fmap (fmap identFS . listToMaybe) . identsForId  -- | Reorder the things we need to push to reuse existing stack values as much -- as possible True if already on the stack at that location@@ -494,17 +492,18 @@                        -- -- Bool: True when the slot already contains a value optimizeFree offset ids = do   -- this line goes wrong                               vvvvvvv-  let -- ids' = concat $ map (\i -> map (i,) [1..varSize . uTypeVt . idType $ i]) ids+  let -- ids' = concat $ map (\i -> map (i,) [1..varSize . unaryTypeJSRep . idType $ i]) ids       idSize :: Id -> Int-      idSize i = sum $ map varSize (typeVt . idType $ i)+      idSize i = sum $ map varSize (typeJSRep . idType $ i)       ids' = concatMap (\i -> map (i,) [1..idSize i]) ids-      -- 1..varSize] . uTypeVt . idType $ i]) (typeVt ids)+      -- 1..varSize] . unaryTypeJSRep . idType $ i]) (typeJSRep ids)       l    = length ids'   slots <- drop offset . take l . (++repeat SlotUnknown) <$> getSlots   let slm                = M.fromList (zip slots [0..])-      (remaining, fixed) = partitionEithers $-         map (\inp@(i,n) -> maybe (Left inp) (\j -> Right (i,n,j,True))-            (M.lookup (SlotId i n) slm)) ids'+      (remaining, fixed) = partitionWith (\inp@(i,n) -> maybe (Left inp)+                                                              (\j -> Right (i,n,j,True))+                                                              (M.lookup (SlotId i n) slm))+                                         ids'       takenSlots         = S.fromList (fmap (\(_,_,x,_) -> x) fixed)       freeSlots          = filter (`S.notMember` takenSlots) [0..l-1]       remaining'         = zipWith (\(i,n) j -> (i,n,j,False)) remaining freeSlots@@ -512,15 +511,15 @@   return $ map (\(i,n,_,b) -> (i,n,b)) allSlots  -- | Allocate local closures-allocCls :: Maybe JStat -> [(Id, CgStgRhs)] -> G JStat+allocCls :: Maybe JStgStat -> [(Id, CgStgRhs)] -> G JStgStat allocCls dynMiddle xs = do-   (stat, dyn) <- partitionEithers <$> mapM toCl xs-   ac <- allocDynAll True dynMiddle dyn+   (stat, dyn) <- partitionWithM toCl xs+   ac <- allocDynAll False dynMiddle dyn    pure (mconcat stat <> ac)   where     -- left = static, right = dynamic     toCl :: (Id, CgStgRhs)-         -> G (Either JStat (Ident,JExpr,[JExpr],CostCentreStack))+         -> G (Either JStgStat (Ident,JStgExpr,[JStgExpr],CostCentreStack))     -- statics     {- making zero-arg constructors static is problematic, see #646        proper candidates for this optimization should have been floated@@ -557,7 +556,7 @@         -> AltType         -> [CgStgAlt]         -> LiveVars-        -> G (JStat, ExprResult)+        -> G (JStgStat, ExprResult) genCase ctx bnd e at alts l   -- For:      unpackCStringAppend# "some string"# str   -- Generate: h$appendToHsStringA(str, "some string")@@ -586,21 +585,18 @@       let profArg = if prof then [jCafCCS] else []       a <- genArg x       return ( top |= app "h$appendToHsStringA" (toJExpr d : a ++ profArg)-             , ExprInline Nothing+             , ExprInline              ) -  | snd $ isInlineExpr (ctxEvaluatedIds ctx) e = do+  | isInlineExpr e = do       bndi <- identsForId bnd       let ctx' = ctxSetTop bnd                   $ ctxSetTarget (assocIdExprs bnd (map toJExpr bndi))                   $ ctx       (ej, r) <- genExpr ctx' e-      let d = case r of-                ExprInline d0 -> d0-                ExprCont -> pprPanic "genCase: expression was not inline"-                                     (pprStgExpr panicStgPprOpts e)+      massert (r == ExprInline) -      (aj, ar) <- genAlts (ctxAssertEvaluated bnd ctx) bnd at d alts+      (aj, ar) <- genAlts ctx bnd at alts       (saveCCS,restoreCCS) <- ifProfilingM $ do         ccsVar <- freshIdent         pure ( ccsVar ||= toJExpr jCurrentCCS@@ -616,7 +612,7 @@         , ar          )   | otherwise = do-      rj       <- genRet (ctxAssertEvaluated bnd ctx) bnd at alts l+      rj       <- genRet ctx bnd at alts l       let ctx' = ctxSetTop bnd                   $ ctxSetTarget (assocIdExprs bnd (map toJExpr [R1 ..]))                   $ ctx@@ -629,7 +625,7 @@        -> AltType        -> [CgStgAlt]        -> LiveVars-       -> G JStat+       -> G JStgStat genRet ctx e at as l = freshIdent >>= f   where     allRefs :: [Id]@@ -641,8 +637,8 @@     isLne i    = ctxIsLneBinding ctx i || ctxIsLneLiveVar ctx' i     nonLne     = filter (not . isLne) (dVarSetElems l) -    f :: Ident -> G JStat-    f r@(TxtI ri)    =  do+    f :: Ident -> G JStgStat+    f r@(identFS -> ri)    =  do       pushLne  <- pushLneFrame lneLive ctx       saveCCS  <- ifProfilingM $ push [jCurrentCCS]       free     <- optimizeFree 0 nonLne@@ -659,18 +655,18 @@                        ++ if prof then [ObjV] else map stackSlotType lneVars)                     CIStackFrame                     sr-      emitToplevel $ jFunction r [] fun'+      emitToplevel $ FuncStat r [] fun'       return (pushLne <> saveCCS <> pushRet)     fst3 ~(x,_,_)  = x -    altRegs :: HasDebugCallStack => [VarType]+    altRegs :: HasDebugCallStack => [JSRep]     altRegs = case at of-      PrimAlt ptc    -> [primRepVt ptc]-      MultiValAlt _n -> idVt e+      PrimAlt ptc    -> [primRepToJSRep ptc]+      MultiValAlt _n -> idJSRep e       _              -> [PtrV]      -- special case for popping CCS but preserving stack size-    pop_handle_CCS :: [(JExpr, StackSlot)] -> G JStat+    pop_handle_CCS :: [(JStgExpr, StackSlot)] -> G JStgStat     pop_handle_CCS [] = return mempty     pop_handle_CCS xs = do       -- grab the slots from 'xs' and push@@ -689,7 +685,7 @@       restoreCCS    <- ifProfilingM . pop_handle_CCS $ pure (jCurrentCCS, SlotUnknown)       rlne          <- popLneFrame False lneLive ctx'       rlnev         <- verifyRuntimeReps lneVars-      (alts, _altr) <- genAlts ctx' e at Nothing as+      (alts, _altr) <- genAlts ctx' e at as       return $ decs <> load <> loadv <> ras <> rasv <> restoreCCS <> rlne <> rlnev <> alts <>                returnStack @@ -700,10 +696,9 @@         => ExprCtx        -- ^ lhs to assign expression result to         -> Id             -- ^ id being matched         -> AltType        -- ^ type-        -> Maybe [JExpr]  -- ^ if known, fields in datacon from earlier expression         -> [CgStgAlt]     -- ^ the alternatives-        -> G (JStat, ExprResult)-genAlts ctx e at me alts = do+        -> G (JStgStat, ExprResult)+genAlts ctx e at alts = do   (st, er) <- case at of      PolyAlt -> case alts of@@ -723,7 +718,7 @@       -> do         ie <- varsForId e         (r, bss) <- normalizeBranches ctx <$>-           mapM (isolateSlots . mkPrimIfBranch ctx [primRepVt tc]) alts+           mapM (isolateSlots . mkPrimIfBranch ctx [primRepToJSRep tc]) alts         setSlots []         return (mkSw ie bss, r) @@ -741,15 +736,6 @@       -> panic "genAlts: unexpected unboxed tuple"      AlgAlt _tc-      | Just es <- me-      , [GenStgAlt (DataAlt dc) bs expr] <- alts-      , not (isUnboxableCon dc)-      -> do-        bsi <- mapM identsForId bs-        (ej, er) <- genExpr ctx expr-        return (declAssignAll (concat bsi) es <> ej, er)--    AlgAlt _tc       | [alt] <- alts       -> do         Branch _ s r <- mkAlgBranch ctx e alt@@ -787,7 +773,7 @@ -- | If 'StgToJSConfig.csRuntimeAssert' is set, then generate an assertion that -- asserts the pattern match is valid, e.g., the match is attempted on a -- Boolean, a Data Constructor, or some number.-verifyMatchRep :: HasDebugCallStack => Id -> AltType -> G JStat+verifyMatchRep :: HasDebugCallStack => Id -> AltType -> G JStgStat verifyMatchRep x alt = do   runtime_assert <- csRuntimeAssert <$> getSettings   if not runtime_assert@@ -802,7 +788,7 @@ -- i.e., a possible code path from an 'StgAlt' data Branch a = Branch   { branch_expr   :: a-  , branch_stat   :: JStat+  , branch_stat   :: JStgStat   , branch_result :: ExprResult   }   deriving (Eq,Functor)@@ -818,29 +804,29 @@     | branchResult (fmap branch_result brs) == ExprCont =         (ExprCont, map mkCont brs)     | otherwise =-        (ExprInline Nothing, brs)+        (ExprInline, brs)   where     mkCont b = case branch_result b of-      ExprInline{} -> b { branch_stat   = branch_stat b <> assignAll jsRegsFromR1-                                                                     (concatMap typex_expr $ ctxTarget ctx)-                        , branch_result = ExprCont-                        }+      ExprInline -> b { branch_stat   = branch_stat b <> assignAll jsRegsFromR1+                                                                   (concatMap typex_expr $ ctxTarget ctx)+                      , branch_result = ExprCont+                      }       _ -> b  -- | Load an unboxed tuple. "Loading" means getting all 'Idents' from the input -- ID's, declaring them as variables in JS land and binding them, in order, to -- 'es'.-loadUbxTup :: [JExpr] -> [Id] -> Int -> G JStat+loadUbxTup :: [JStgExpr] -> [Id] -> Int -> G JStgStat loadUbxTup es bs _n = do   bs' <- concatMapM identsForId bs   return $ declAssignAll bs' es -mkSw :: [JExpr] -> [Branch (Maybe [JExpr])] -> JStat+mkSw :: [JStgExpr] -> [Branch (Maybe [JStgExpr])] -> JStgStat mkSw [e] cases = mkSwitch e (fmap (fmap (fmap head)) cases) mkSw es cases  = mkIfElse es cases  -- | Switch for pattern matching on constructors or prims-mkSwitch :: JExpr -> [Branch (Maybe JExpr)] -> JStat+mkSwitch :: JStgExpr -> [Branch (Maybe JStgExpr)] -> JStgStat mkSwitch e cases   | [Branch (Just c1) s1 _] <- n   , [Branch _ s2 _] <- d@@ -865,7 +851,7 @@ -- | if/else for pattern matching on things that js cannot switch on -- the list of branches is expected to have the default alternative -- first, if it exists-mkIfElse :: [JExpr] -> [Branch (Maybe [JExpr])] -> JStat+mkIfElse :: [JStgExpr] -> [Branch (Maybe [JStgExpr])] -> JStgStat mkIfElse e s = go (L.reverse s)     where       go = \case@@ -874,11 +860,11 @@         [] -> panic "mkIfElse: empty expression list"         _  -> panic "mkIfElse: multiple DEFAULT cases" --- | Wrapper to contruct sequences of (===), e.g.,+-- | Wrapper to construct sequences of (===), e.g., -- -- > mkEq [l0,l1,l2] [r0,r1,r2] = (l0 === r0) && (l1 === r1) && (l2 === r2) ---mkEq :: [JExpr] -> [JExpr] -> JExpr+mkEq :: [JStgExpr] -> [JStgExpr] -> JStgExpr mkEq es1 es2   | length es1 == length es2 = foldl1 (InfixExpr LAndOp) (zipWith (InfixExpr StrictEqOp) es1 es2)   | otherwise                = panic "mkEq: incompatible expressions"@@ -886,7 +872,7 @@ mkAlgBranch :: ExprCtx   -- ^ toplevel id for the result             -> Id        -- ^ datacon to match             -> CgStgAlt  -- ^ match alternative with binders-            -> G (Branch (Maybe JExpr))+            -> G (Branch (Maybe JStgExpr)) mkAlgBranch top d alt   | DataAlt dc <- alt_con alt   , isUnboxableCon dc@@ -910,52 +896,54 @@  -- | Generate a primitive If-expression mkPrimIfBranch :: ExprCtx-               -> [VarType]+               -> [JSRep]                -> CgStgAlt-               -> G (Branch (Maybe [JExpr]))+               -> G (Branch (Maybe [JStgExpr])) mkPrimIfBranch top _vt alt =   (\ic (ej,er) -> Branch ic ej er) <$> ifCond (alt_con alt) <*> genExpr top (alt_rhs alt)  -- fixme are bool things always checked correctly here?-ifCond :: AltCon -> G (Maybe [JExpr])+ifCond :: AltCon -> G (Maybe [JStgExpr]) ifCond = \case   DataAlt da -> return $ Just [toJExpr (dataConTag da)]   LitAlt l   -> Just <$> genLit l   DEFAULT    -> return Nothing -caseCond :: AltCon -> G (Maybe JExpr)+caseCond :: AltCon -> G (Maybe JStgExpr) caseCond = \case+-- fixme use single tmp var for all branches   DEFAULT    -> return Nothing   DataAlt da -> return $ Just (toJExpr $ dataConTag da)   LitAlt l   -> genLit l >>= \case     [e] -> pure (Just e)-    es  -> pprPanic "caseCond: expected single-variable literal" (ppr $ satJExpr Nothing <$> es)+    es  -> pprPanic "caseCond: expected single-variable literal" (ppr $ jStgExprToJS <$> es) --- fixme use single tmp var for all branches -- | Load parameters from constructor-loadParams :: JExpr -> [Id] -> G JStat+loadParams :: JStgExpr -> [Id] -> G JStgStat loadParams from args = do   as <- concat <$> zipWithM (\a u -> map (,u) <$> identsForId a) args use-  return $ case as of-    []                 -> mempty-    [(x,u)]            -> loadIfUsed (from .^ closureField1_) x  u-    [(x1,u1),(x2,u2)]  -> mconcat+  case as of+    []                 -> return mempty+    [(x,u)]            -> return $ loadIfUsed (from .^ closureField1_) x  u+    [(x1,u1),(x2,u2)]  -> return $ mconcat                             [ loadIfUsed (from .^ closureField1_) x1 u1                             , loadIfUsed (from .^ closureField2_) x2 u2                             ]-    ((x,u):xs)         -> mconcat-                            [ loadIfUsed (from .^ closureField1_) x u-                            , jVar (\d -> mconcat [ d |= from .^ closureField2_-                                                  , loadConVarsIfUsed d xs-                                                  ])-                            ]+    ((x,u):xs)         -> do d <- freshIdent+                             return $ mconcat+                               [ loadIfUsed (from .^ closureField1_) x u+                               , mconcat [ d ||= from .^ closureField2_+                                         , loadConVarsIfUsed (Var d) xs+                                         ]+                               ]   where     use = repeat True -- fixme clean up+     loadIfUsed fr tgt True = tgt ||= fr     loadIfUsed  _ _   _    = mempty      loadConVarsIfUsed fr cs = mconcat $ zipWith f cs [(1::Int)..]-      where f (x,u) n = loadIfUsed (SelExpr fr (TxtI (dataFieldName n))) x u+      where f (x,u) n = loadIfUsed (SelExpr fr (global (dataFieldName n))) x u  -- | Determine if a branch will end in a continuation or not. If not the inline -- branch must be normalized. See 'normalizeBranches'@@ -967,39 +955,58 @@   (ExprCont:_)         -> ExprCont   (_:es)     | elem ExprCont es -> ExprCont-    | otherwise        -> ExprInline Nothing+    | otherwise        -> ExprInline  -- | Push return arguments onto the stack. The 'Bool' tracks whether the value -- is already on the stack or not, used in 'StgToJS.Stack.pushOptimized'.-pushRetArgs :: HasDebugCallStack => [(Id,Int,Bool)] -> JExpr -> G JStat+pushRetArgs :: HasDebugCallStack => [(Id,Int,Bool)] -> JStgExpr -> G JStgStat pushRetArgs free fun = do   rs <- mapM (\(i,n,b) -> (\es->(es!!(n-1),b)) <$> genIdArg i) free   pushOptimized (rs++[(fun,False)])  -- | Load the return arguments then pop the stack frame-loadRetArgs :: HasDebugCallStack => [(Id,Int,Bool)] -> G JStat+loadRetArgs :: HasDebugCallStack => [(Id,Int,Bool)] -> G JStgStat loadRetArgs free = do   ids <- mapM (\(i,n,_b) -> (!! (n-1)) <$> genIdStackArgI i) free   popSkipI 1 ids +-- All identifiers referenced by the expression (does not traverse into nested functions)+allVars :: JStgExpr -> [Ident]+allVars (ValExpr v) = case v of+  (JVar i) -> [i]+  (JList xs) -> concatMap allVars xs+  (JHash xs) -> concatMap (allVars . snd) (UM.nonDetUniqMapToList xs)+  (JInt {})  -> []+  (JDouble {}) -> []+  (JStr {}) -> []+  (JRegEx {}) -> []+  (JBool {}) -> []+  (JFunc is _s) -> is+allVars (InfixExpr _op lh rh) = allVars lh ++ allVars rh+allVars (ApplExpr f xs) = allVars f ++ concatMap allVars xs+allVars (IfExpr c t e) = allVars c ++ allVars t ++ allVars e+allVars (UOpExpr _op x) = allVars x+allVars (SelExpr e _) = allVars e+allVars (IdxExpr e i) = allVars e ++ allVars i+ -- | allocate multiple, possibly mutually recursive, closures-allocDynAll :: Bool -> Maybe JStat -> [(Ident,JExpr,[JExpr],CostCentreStack)] -> G JStat-{--XXX remove use of template and enable in-place init again+allocDynAll :: Bool -> Maybe JStgStat -> [(Ident,JStgExpr,[JStgExpr],CostCentreStack)] -> G JStgStat allocDynAll haveDecl middle [(to,entry,free,cc)]-  | isNothing middle && to `notElem` (free ^.. template) = do+  | isNothing middle && to `notElem` concatMap allVars free = do       ccs <- ccsVarJ cc-      return $ allocDynamic s haveDecl to entry free ccs -}+      s <- getSettings+      return $ allocDynamic s (not haveDecl) to entry free ccs allocDynAll haveDecl middle cls = do   settings <- getSettings   let+    middle' :: JStgStat     middle' = fromMaybe mempty middle      decl_maybe i e       | haveDecl  = toJExpr i |= e       | otherwise = i ||= e -    makeObjs :: G JStat+    makeObjs :: G JStgStat     makeObjs =       fmap mconcat $ forM cls $ \(i,f,_,cc) -> do       ccs <- maybeToList <$> costCentreStackLbl cc@@ -1014,7 +1021,8 @@             else ApplExpr (var "h$c") (f : fmap (ValExpr . JVar) ccs)         ] -    fillObjs = mconcat $ map fillObj cls+    fillObjs :: [JStgStat]+    fillObjs = map fillObj cls     fillObj (i,_,es,_)       | csInlineAlloc settings || length es > 24 =           case es of@@ -1040,25 +1048,29 @@                         , toJExpr i .^ closureField2_ |= fillFun es                         ] +    fillFun :: [JStgExpr] -> JStgExpr     fillFun [] = null_     fillFun es = ApplExpr (allocData (length es)) es -    checkObjs | csAssertRts settings  = mconcat $-                map (\(i,_,_,_) -> ApplStat (ValExpr (JVar (TxtI "h$checkObj"))) [toJExpr i]) cls+    checkObjs :: [JStgStat]+    checkObjs | csAssertRts settings  =+                map (\(i,_,_,_) -> ApplStat (var "h$checkObj") [Var i]) cls               | otherwise = mempty    objs <- makeObjs-  pure $ mconcat [objs, middle', fillObjs, checkObjs]+  return $ mconcat [objs, middle', mconcat fillObjs, mconcat checkObjs]  -- | Generate a primop. This function wraps around the real generator -- 'GHC.StgToJS.genPrim', handling the 'ExprCtx' and all arguments before -- generating the primop.-genPrimOp :: ExprCtx -> PrimOp -> [StgArg] -> Type -> G (JStat, ExprResult)+genPrimOp :: ExprCtx -> PrimOp -> [StgArg] -> Type -> G (JStgStat, ExprResult) genPrimOp ctx op args t = do   as <- concatMapM genArg args   prof <- csProf <$> getSettings   bound <- csBoundsCheck <$> getSettings+  let prim_gen = withTag "h$PRM" $ genPrim prof bound t op (concatMap typex_expr $ ctxTarget ctx) as   -- fixme: should we preserve/check the primreps?-  return $ case genPrim prof bound t op (concatMap typex_expr $ ctxTarget ctx) as of-             PrimInline s -> (s, ExprInline Nothing)+  jsm <- liftIO initJSM+  return $ case runJSM jsm prim_gen of+             PrimInline s -> (s, ExprInline)              PRPrimCall s -> (s, ExprCont)
compiler/GHC/StgToJS/ExprCtx.hs view
@@ -18,14 +18,12 @@ module GHC.StgToJS.ExprCtx   ( ExprCtx   , initExprCtx-  , ctxAssertEvaluated   , ctxIsEvaluated   , ctxSetSrcSpan   , ctxSrcSpan   , ctxSetTop   , ctxTarget   , ctxSetTarget-  , ctxEvaluatedIds   -- * Let-no-escape   , ctxClearLneFrame   , ctxUpdateLneFrame@@ -43,10 +41,13 @@ import GHC.StgToJS.Types  import GHC.Types.Unique.FM-import GHC.Types.Unique.Set import GHC.Types.Var import GHC.Types.SrcLoc+import GHC.Types.Id+import GHC.Types.Id.Info +import GHC.Stg.InferTags.TagSig+ import GHC.Utils.Outputable import GHC.Utils.Panic @@ -61,10 +62,6 @@   , ctxTarget     :: [TypedExpr]     -- ^ Target variables for the evaluated expression -  , ctxEvaluatedIds :: UniqSet Id-    -- ^ Ids that we know to be evaluated (e.g. case binders when the expression-    -- to evaluate is in an alternative)-   , ctxSrcSpan    :: Maybe RealSrcSpan     -- ^ Source location @@ -95,7 +92,6 @@ initExprCtx i = ExprCtx   { ctxTop          = i   , ctxTarget       = []-  , ctxEvaluatedIds = emptyUniqSet   , ctxLneFrameBs   = emptyUFM   , ctxLneFrameVars = []   , ctxLneFrameSize = 0@@ -110,10 +106,6 @@ ctxSetTop :: Id -> ExprCtx -> ExprCtx ctxSetTop i ctx = ctx { ctxTop = i } --- | Add an Id to the known-evaluated set-ctxAssertEvaluated :: Id -> ExprCtx -> ExprCtx-ctxAssertEvaluated i ctx = ctx { ctxEvaluatedIds = addOneToUniqSet (ctxEvaluatedIds ctx) i }- -- | Set source location ctxSetSrcSpan :: RealSrcSpan -> ExprCtx -> ExprCtx ctxSetSrcSpan span ctx = ctx { ctxSrcSpan = Just span }@@ -139,8 +131,39 @@     }  -- | Predicate: do we know for sure that the given Id is evaluated?-ctxIsEvaluated :: ExprCtx -> Id -> Bool-ctxIsEvaluated ctx i = i `elementOfUniqSet` ctxEvaluatedIds ctx+ctxIsEvaluated :: Id -> Bool+ctxIsEvaluated i =+  maybe False isTaggedSig (idTagSig_maybe i)+  && go (idDetails i)+  where+    go JoinId{} = False+    go _        = True+++      -- DFunId new_type -> not new_type+      --    -- DFuns terminate, unless the dict is implemented+      --    -- with a newtype in which case they may not++      -- DataConWorkId {} -> True++      -- ClassOpId {} -> False+      --   -- suppose an argument, and we don't have one++      -- PrimOpId op _ -> primop_ok op+      --   -- probably already handled by StgOpApp++      -- JoinId {} -> False+      --   -- Don't speculate join points++      -- TickBoxOpId {} -> False+      --   -- Don't speculate box ticking++      -- -- Tagged (evaluated) ids+      -- _ | Just sig <- idTagSig_maybe i+      --   , isTaggedSig sig+      --   -> True++      -- _ -> False  -- | Does the given Id correspond to a LNE binding ctxIsLneBinding :: ExprCtx -> Id -> Bool
compiler/GHC/StgToJS/FFI.hs view
@@ -5,16 +5,14 @@ module GHC.StgToJS.FFI   ( genPrimCall   , genForeignCall-  , saturateFFI   ) where  import GHC.Prelude -import GHC.JS.Unsat.Syntax+import GHC.JS.JStg.Syntax+import GHC.JS.Ident import GHC.JS.Make-import GHC.JS.Transform-import qualified GHC.JS.Syntax as Sat  import GHC.StgToJS.Arg import GHC.StgToJS.ExprCtx@@ -44,10 +42,10 @@ import Data.Monoid import qualified Data.List as L -genPrimCall :: ExprCtx -> PrimCall -> [StgArg] -> Type -> G (JStat, ExprResult)+genPrimCall :: ExprCtx -> PrimCall -> [StgArg] -> Type -> G (JStgStat, ExprResult) genPrimCall ctx (PrimCall lbl _) args t = do   j <- parseFFIPattern False False False ("h$" ++ unpackFS lbl) t (concatMap typex_expr $ ctxTarget ctx) args-  return (j, ExprInline Nothing)+  return (j, ExprInline)  -- | generate the actual call {-@@ -69,9 +67,9 @@                 -> Bool  -- ^ using javascript calling convention                 -> String                 -> Type-                -> [JExpr]+                -> [JStgExpr]                 -> [StgArg]-                -> G JStat+                -> G JStgStat parseFFIPattern catchExcep async jscc pat t es as   | catchExcep = do       c <- parseFFIPatternA async jscc pat t es as@@ -81,7 +79,7 @@       --  } catch(except) {       --    return h$throwJSException(except);       --  }-      let ex = TxtI "except"+      let ex = global "except"       return (TryStat c ex (ReturnStat (ApplExpr (var "h$throwJSException") [toJExpr ex])) mempty)   | otherwise  = parseFFIPatternA async jscc pat t es as @@ -89,9 +87,9 @@                  -> Bool  -- ^ using JavaScript calling conv                  -> String                  -> Type-                 -> [JExpr]+                 -> [JStgExpr]                  -> [StgArg]-                 -> G JStat+                 -> G JStgStat -- async calls get an extra callback argument -- call it with the result parseFFIPatternA True True pat t es as  = do@@ -122,13 +120,13 @@  -- parseFFIPatternA _ _ _ _ _ _ = error "parseFFIPattern: non-JavaScript pattern must be synchronous" -parseFFIPattern' :: Maybe JExpr -- ^ Nothing for sync, Just callback for async-                 -> Bool        -- ^ javascript calling convention used-                 -> String      -- ^ pattern called-                 -> Type        -- ^ return type-                 -> [JExpr]     -- ^ expressions to return in (may be more than necessary)-                 -> [StgArg]    -- ^ arguments-                 -> G JStat+parseFFIPattern' :: Maybe JStgExpr -- ^ Nothing for sync, Just callback for async+                 -> Bool           -- ^ javascript calling convention used+                 -> String         -- ^ pattern called+                 -> Type           -- ^ return type+                 -> [JStgExpr]     -- ^ expressions to return in (may be more than necessary)+                 -> [StgArg]       -- ^ arguments+                 -> G JStgStat parseFFIPattern' callback javascriptCc pat t ret args   | not javascriptCc = mkApply pat   | otherwise = mkApply pat@@ -153,16 +151,16 @@          (stats, as) <- unzip <$> mapM (genFFIArg javascriptCc) args          cs <- getSettings          return $ traceCall cs as <> mconcat stats <> ApplStat f' (concat as)-        where f' = toJExpr (TxtI $ mkFastString f)+        where f' = toJExpr (global $ mkFastString f)     copyResult rs = mconcat $ zipWith (\t r -> toJExpr r |= toJExpr t) (enumFrom Ret1) rs      traceCall cs as         | csTraceForeign cs = ApplStat (var "h$traceForeign") [toJExpr pat, toJExpr as]         | otherwise         = mempty --- generate arg to be passed to FFI call, with marshalling JStat to be run+-- generate arg to be passed to FFI call, with marshalling JStgStat to be run -- before the call-genFFIArg :: Bool -> StgArg -> G (JStat, [JExpr])+genFFIArg :: Bool -> StgArg -> G (JStgStat, [JStgExpr]) genFFIArg _isJavaScriptCc (StgLitArg l) = (mempty,) <$> genLit l genFFIArg isJavaScriptCc a@(StgVarArg i)     | not isJavaScriptCc &&@@ -175,18 +173,15 @@    where      tycon  = tyConAppTyCon (unwrapType arg_ty)      arg_ty = stgArgType a-     r      = uTypeVt arg_ty--saturateFFI :: Int -> JStat -> Sat.JStat-saturateFFI u = satJStat (Just . mkFastString $ "ghcjs_ffi_sat_" ++ show u)+     r      = unaryTypeJSRep arg_ty  genForeignCall :: HasDebugCallStack                => ExprCtx                -> ForeignCall                -> Type-               -> [JExpr]+               -> [JStgExpr]                -> [StgArg]-               -> G (JStat, ExprResult)+               -> G (JStgStat, ExprResult) genForeignCall _ctx                (CCall (CCallSpec (StaticTarget _ tgt Nothing True)                                    JavaScriptCallConv@@ -198,7 +193,7 @@   , Just pairs <- getObjectKeyValuePairs args = do       pairs' <- mapM (\(k,v) -> genArg v >>= \vs -> return (k, head vs)) pairs       return ( (|=) obj (ValExpr (JHash $ listToUniqMap pairs'))-             , ExprInline Nothing+             , ExprInline              )  genForeignCall ctx (CCall (CCallSpec ccTarget cconv safety)) t tgt args = do@@ -216,7 +211,7 @@         | otherwise = "h$callDynamic"      exprResult | async     = ExprCont-               | otherwise = ExprInline Nothing+               | otherwise = ExprInline      catchExcep = (cconv == JavaScriptCallConv) &&                  playSafe safety || playInterruptible safety
compiler/GHC/StgToJS/Heap.hs view
@@ -38,7 +38,7 @@  import GHC.Prelude -import GHC.JS.Unsat.Syntax+import GHC.JS.JStg.Syntax import GHC.JS.Make import GHC.StgToJS.Types import GHC.Data.FastString@@ -67,87 +67,87 @@ entryFunArity_ :: FastString entryFunArity_ = "a" -jTyObject :: JExpr+jTyObject :: JStgExpr jTyObject = jString "object" -closureType :: JExpr -> JExpr+closureType :: JStgExpr -> JStgExpr closureType = entryClosureType . closureEntry -entryClosureType :: JExpr -> JExpr+entryClosureType :: JStgExpr -> JStgExpr entryClosureType f = f .^ entryClosureType_ -isObject :: JExpr -> JExpr+isObject :: JStgExpr -> JStgExpr isObject c = typeof c .===. String "object" -isThunk :: JExpr -> JExpr+isThunk :: JStgExpr -> JStgExpr isThunk c = closureType c .===. toJExpr Thunk -isThunk' :: JExpr -> JExpr+isThunk' :: JStgExpr -> JStgExpr isThunk' f = entryClosureType f .===. toJExpr Thunk -isBlackhole :: JExpr -> JExpr+isBlackhole :: JStgExpr -> JStgExpr isBlackhole c = closureType c .===. toJExpr Blackhole -isFun :: JExpr -> JExpr+isFun :: JStgExpr -> JStgExpr isFun c = closureType c .===. toJExpr Fun -isFun' :: JExpr -> JExpr+isFun' :: JStgExpr -> JStgExpr isFun' f = entryClosureType f .===. toJExpr Fun -isPap :: JExpr -> JExpr+isPap :: JStgExpr -> JStgExpr isPap c = closureType c .===. toJExpr Pap -isPap' :: JExpr -> JExpr+isPap' :: JStgExpr -> JStgExpr isPap' f = entryClosureType f .===. toJExpr Pap -isCon :: JExpr -> JExpr+isCon :: JStgExpr -> JStgExpr isCon c = closureType c .===. toJExpr Con -isCon' :: JExpr -> JExpr+isCon' :: JStgExpr -> JStgExpr isCon' f = entryClosureType f .===. toJExpr Con -conTag :: JExpr -> JExpr+conTag :: JStgExpr -> JStgExpr conTag = conTag' . closureEntry -conTag' :: JExpr -> JExpr+conTag' :: JStgExpr -> JStgExpr conTag' f = f .^ entryConTag_  -- | Get closure entry function-closureEntry :: JExpr -> JExpr+closureEntry :: JStgExpr -> JStgExpr closureEntry p = p .^ closureEntry_  -- | Get closure metadata-closureMeta :: JExpr -> JExpr+closureMeta :: JStgExpr -> JStgExpr closureMeta p = p .^ closureMeta_  -- | Get closure cost-center-closureCC :: JExpr -> JExpr+closureCC :: JStgExpr -> JStgExpr closureCC p = p .^ closureCC_  -- | Get closure extra field 1-closureField1 :: JExpr -> JExpr+closureField1 :: JStgExpr -> JStgExpr closureField1 p = p .^ closureField1_  -- | Get closure extra field 2-closureField2 :: JExpr -> JExpr+closureField2 :: JStgExpr -> JStgExpr closureField2 p = p .^ closureField2_  -- number of  arguments (arity & 0xff = arguments, arity >> 8 = number of registers)-funArity :: JExpr -> JExpr+funArity :: JStgExpr -> JStgExpr funArity = funArity' . closureEntry  -- function arity with raw reference to the entry-funArity' :: JExpr -> JExpr+funArity' :: JStgExpr -> JStgExpr funArity' f = f .^ entryFunArity_  -- arity of a partial application-papArity :: JExpr -> JExpr+papArity :: JStgExpr -> JStgExpr papArity cp = closureField1 (closureField2 cp)  funOrPapArity-  :: JExpr       -- ^ heap object-  -> Maybe JExpr -- ^ reference to entry, if you have one already (saves a c.f lookup twice)-  -> JExpr       -- ^ arity tag (tag >> 8 = registers, tag & 0xff = arguments)+  :: JStgExpr       -- ^ heap object+  -> Maybe JStgExpr -- ^ reference to entry, if you have one already (saves a c.f lookup twice)+  -> JStgExpr       -- ^ arity tag (tag >> 8 = registers, tag & 0xff = arguments) funOrPapArity c = \case   Nothing -> ((IfExpr (toJExpr (isFun c))) (toJExpr (funArity c)))              (toJExpr (papArity c))
compiler/GHC/StgToJS/Ids.hs view
@@ -43,7 +43,8 @@ import GHC.StgToJS.Utils import GHC.StgToJS.Symbols -import GHC.JS.Unsat.Syntax+import GHC.JS.JStg.Syntax+import GHC.JS.Ident import GHC.JS.Make  import GHC.Core.DataCon@@ -72,13 +73,13 @@     writeFastMutInt id_gen (v+1)     pure v --- | Get fresh local Ident of the form: h$$unit:module_uniq+-- | Get fresh module-local Ident of the form: h$$unit:module_uniq freshIdent :: G Ident freshIdent = do   i <- freshUnique   mod <- State.gets gsModule   let !name = mkFreshJsSymbol mod i-  return (TxtI name)+  return (global name)   -- | Generate unique Ident for the given ID (uncached!)@@ -99,7 +100,7 @@ -- Int64#), Addr#, StablePtr#, unboxed tuples, etc. -- makeIdentForId :: Id -> Maybe Int -> IdType -> Module -> Ident-makeIdentForId i num id_type current_module = TxtI ident+makeIdentForId i num id_type current_module = global ident   where     exported = isExportedId i     name     = getName i@@ -197,15 +198,15 @@   -- | Retrieve default variable name for the given Id-varForId :: Id -> G JExpr+varForId :: Id -> G JStgExpr varForId i = toJExpr <$> identForId i  -- | Retrieve default variable name for the given Id with sub index-varForIdN :: Id -> Int -> G JExpr+varForIdN :: Id -> Int -> G JStgExpr varForIdN i n = toJExpr <$> identForIdN i n  -- | Retrieve all the JS vars for the given Id-varsForId :: Id -> G [JExpr]+varsForId :: Id -> G [JStgExpr] varsForId i = case typeSize (idType i) of   0 -> pure mempty   1 -> (:[]) <$> varForId i@@ -213,11 +214,11 @@   -- | Retrieve entry variable name for the given Id-varForEntryId :: Id -> G JExpr+varForEntryId :: Id -> G JStgExpr varForEntryId i = toJExpr <$> identForEntryId i  -- | Retrieve datacon entry variable name for the given Id-varForDataConEntryId :: Id -> G JExpr+varForDataConEntryId :: Id -> G JStgExpr varForDataConEntryId i = ValExpr . JVar <$> identForDataConEntryId i  @@ -226,11 +227,11 @@ identForDataConWorker d = identForDataConEntryId (dataConWorkId d)  -- | Retrieve datacon worker entry variable name for the given datacon-varForDataConWorker :: DataCon -> G JExpr+varForDataConWorker :: DataCon -> G JStgExpr varForDataConWorker d = varForDataConEntryId (dataConWorkId d)  -- | Declare all js vars for the id-declVarsForId :: Id -> G JStat+declVarsForId :: Id -> G JStgStat declVarsForId  i = case typeSize (idType i) of   0 -> return mempty   1 -> decl <$> identForId i
compiler/GHC/StgToJS/Linker/Linker.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TupleSections     #-} {-# LANGUAGE LambdaCase        #-}+{-# LANGUAGE BlockArguments    #-}  ----------------------------------------------------------------------------- -- |@@ -32,17 +33,21 @@   , LinkPlan (..)   , emptyLinkPlan   , incrementLinkPlan+  , ArchiveCache+  , newArchiveCache   ) where -import Prelude+import GHC.Prelude  import GHC.Platform.Host (hostPlatformArchOS)  import GHC.JS.Make import GHC.JS.Optimizer-import GHC.JS.Unsat.Syntax-import qualified GHC.JS.Syntax as Sat+import GHC.JS.Ident+import GHC.JS.JStg.Syntax+import GHC.JS.JStg.Monad+import qualified GHC.JS.Syntax as JS import GHC.JS.Transform  import GHC.Driver.DynFlags (DynFlags(..))@@ -52,6 +57,7 @@  import GHC.Linker.Static.Utils (exeFileName) import GHC.Linker.Types (Unlinked(..), linkableUnlinked)+import GHC.Linker.External  import GHC.StgToJS.Linker.Types import GHC.StgToJS.Linker.Utils@@ -76,7 +82,6 @@ import GHC.Utils.Logger (Logger, logVerbAtLeast) import GHC.Utils.Binary import qualified GHC.Utils.Ppr as Ppr-import GHC.Utils.Monad import GHC.Utils.TmpFs  import GHC.Types.Unique.Set@@ -103,6 +108,7 @@ import Data.Set                 (Set) import qualified Data.Set                 as S import Data.Word+import Data.Monoid  import System.IO import System.FilePath ((<.>), (</>), dropExtension, takeDirectory)@@ -123,10 +129,10 @@   , packedMetaDataSize :: !Word64              -- ^ number of bytes for metadata   } -newtype ArchiveState = ArchiveState { loadedArchives :: IORef (Map FilePath Ar.Archive) }+newtype ArchiveCache = ArchiveCache { loadedArchives :: IORef (Map FilePath Ar.Archive) } -emptyArchiveState :: IO ArchiveState-emptyArchiveState = ArchiveState <$> newIORef M.empty+newArchiveCache :: IO ArchiveCache+newArchiveCache = ArchiveCache <$> newIORef M.empty  defaultJsContext :: SDocContext defaultJsContext = defaultSDocContext{sdocStyle = PprCode}@@ -135,52 +141,70 @@   :: FinderCache   -> JSLinkConfig   -> StgToJSConfig-  -> [FilePath]   -> Logger+  -> TmpFs   -> DynFlags   -> UnitEnv   -> [FilePath]   -> [UnitId]   -> IO ()-jsLinkBinary finder_cache lc_cfg cfg js_srcs logger dflags unit_env objs dep_units+jsLinkBinary finder_cache lc_cfg cfg logger tmpfs dflags unit_env hs_objs dep_units   | lcNoJSExecutables lc_cfg = return ()   | otherwise = do+     -- additional objects to link are passed as FileOption ldInputs...     let cmdline_objs = [ f | FileOption _ f <- ldInputs dflags ]-    -- discriminate JavaScript sources from real object files.-    (cmdline_js_srcs, cmdline_js_objs) <- partitionM isJsFile cmdline_objs++    -- cmdline objects: discriminate between the 3 kinds of objects we have+    let disc hss jss ccs = \case+          []     -> pure (hss, jss, ccs)+          (o:os) -> getObjectKind o >>= \case+            Just ObjHs -> disc (o:hss) jss ccs os+            Just ObjJs -> disc hss (o:jss) ccs os+            Just ObjCc -> disc hss jss (o:ccs) os+            Nothing    -> do+              logInfo logger (vcat [text "Ignoring unexpected command-line object: ", text o])+              disc hss jss ccs os+    (cmdline_hs_objs, cmdline_js_objs, cmdline_cc_objs) <- disc [] [] [] cmdline_objs+     let-        objs'    = map ObjFile (objs ++ cmdline_js_objs)-        js_srcs' = js_srcs ++ cmdline_js_srcs-        is_root _ = True -- FIXME: we shouldn't consider every function as a root,-                         -- but only the program entry point (main), either the-                         -- generated one or coming from an object-        exe      = jsExeFileName dflags+        exe         = jsExeFileName dflags+        all_hs_objs = hs_objs ++ cmdline_hs_objs+        all_js_objs = cmdline_js_objs+        all_cc_objs = cmdline_cc_objs+        is_root _   = True+                      -- FIXME: we shouldn't consider every function as a root,+                      -- but only the program entry point (main), either the+                      -- generated one or coming from an object      -- compute dependencies     let link_spec = LinkSpec           { lks_unit_ids        = dep_units-          , lks_obj_files       = objs'           , lks_obj_root_filter = is_root           , lks_extra_roots     = mempty-          , lks_extra_js        = js_srcs'+          , lks_objs_hs         = all_hs_objs+          , lks_objs_js         = all_js_objs+          , lks_objs_cc         = all_cc_objs           }      let finder_opts = initFinderOpts dflags+    ar_cache <- newArchiveCache -    link_plan <- computeLinkDependencies cfg unit_env link_spec finder_opts finder_cache+    link_plan <- computeLinkDependencies cfg unit_env link_spec finder_opts finder_cache ar_cache -    void $ jsLink lc_cfg cfg logger exe link_plan+    void $ jsLink lc_cfg cfg logger tmpfs ar_cache exe link_plan  -- | link and write result to disk (jsexe directory) jsLink      :: JSLinkConfig      -> StgToJSConfig      -> Logger+     -> TmpFs+     -> ArchiveCache      -> FilePath               -- ^ output file/directory      -> LinkPlan      -> IO ()-jsLink lc_cfg cfg logger out link_plan = do+jsLink lc_cfg cfg logger tmpfs ar_cache out link_plan = do        -- create output directory       createDirectoryIfMissing False out@@ -192,11 +216,11 @@       -- link all Haskell code (program + dependencies) into out.js        -- retrieve code for Haskell dependencies-      mods <- collectModuleCodes link_plan+      mods <- collectModuleCodes ar_cache link_plan        -- LTO + rendering of JS code       link_stats <- withBinaryFile (out </> "out.js") WriteMode $ \h ->-        renderLinker h (csPrettyRender cfg) mods (lkp_extra_js link_plan)+        renderModules h (csPrettyRender cfg) mods        ------------------------------------------------------------- @@ -217,52 +241,135 @@        -- link generated RTS parts into rts.js       unless (lcNoRts lc_cfg) $ do+        jsm <- initJSM         withFile (out </> "rts.js") WriteMode $ \h -> do-          void $ hPutJS (csPrettyRender cfg) h (rts cfg)+          let opt = jsOptimize (runJSM jsm $ jStgStatToJS <$> rts cfg)+          void $+            hPutJS (csPrettyRender cfg) h opt -      -- link dependencies' JS files into lib.js-      withBinaryFile (out </> "lib.js") WriteMode $ \h -> do-        forM_ (lkp_archives link_plan) $ \archive_file -> do-          Ar.Archive entries <- Ar.loadAr archive_file-          forM_ entries $ \entry -> do-            case getJsArchiveEntry entry of-              Nothing -> return ()-              Just bs -> do-                B.hPut   h bs++      -- link user-provided JS files into lib.js+      (emcc_opts,lib_cc_objs) <- withBinaryFile (out </> "lib.js") WriteMode $ \h -> do++        let+            tmp_dir = linkerTempDir (csLinkerConfig cfg)++            -- JS objects from dependencies' archives (.a)+            go_archives emcc_opts cc_objs = \case+              []     -> pure (emcc_opts, cc_objs)+              (a:as) -> do+                Ar.Archive entries <- loadArchive ar_cache a+                (emcc_opts', cc_objs') <- go_entries emcc_opts cc_objs entries+                go_archives emcc_opts' cc_objs' as++            -- archive's entries+            go_entries emcc_opts cc_objs = \case+              []     -> pure (emcc_opts, cc_objs)+              (e:es) -> case getObjectKindBS (Ar.filedata e) of+                Just ObjHs -> do+                  -- Nothing to do. HS objects are collected in+                  -- collectModuleCodes+                  go_entries emcc_opts cc_objs es+                Just ObjCc -> do+                  -- extract the object file from the archive in a temporary+                  -- file and return its path+                  cc_obj_fn <- newTempName logger tmpfs tmp_dir TFL_CurrentModule "o"+                  B.writeFile cc_obj_fn (Ar.filedata e)+                  let cc_objs' = cc_obj_fn:cc_objs+                  go_entries emcc_opts cc_objs' es+                Just ObjJs -> do+                  -- extract the JS code and append it to the `lib.js` file+                  (opts,bs) <- parseJSObjectBS (Ar.filedata e)+                  B.hPut   h bs+                  hPutChar h '\n'+                  let emcc_opts' = emcc_opts <> opts+                  go_entries emcc_opts' cc_objs es+                Nothing -> do+                  logInfo logger (vcat [text "Ignoring unexpected archive entry: ", text (Ar.filename e)])+                  go_entries emcc_opts cc_objs es++            -- additional JS objects (e.g. from the command-line)+            go_extra emcc_opts = \case+              []     -> pure emcc_opts+              (e:es) -> do+                (opts,bs) <- readJSObject e+                B.hPut h bs                 hPutChar h '\n'+                let emcc_opts' = emcc_opts <> opts+                go_extra emcc_opts' es +        -- archives+        (emcc_opts0, cc_objs) <- go_archives defaultJSOptions [] (S.toList (lkp_archives link_plan))+        -- extra object files+        emcc_opts1            <- go_extra emcc_opts0 (S.toList (lkp_objs_js link_plan))+        pure (emcc_opts1,cc_objs)+++      -- Link Cc objects using emcc's linker+      --+      -- Cc objects have been extracted from archives (see above) and are listed+      -- in lib_cc_objs.+      --+      -- We don't link C sources if there are none (obviously) or if asked+      -- explicitly by the user with -ddisable-js-c-sources (mostly used for+      -- debugging purpose).+      let emcc_objs     = lib_cc_objs ++ S.toList (lkp_objs_cc link_plan)+      let has_emcc_objs = not (null emcc_objs)+      let link_c_sources = lcLinkCsources lc_cfg && has_emcc_objs++      when link_c_sources $ do++        runLink logger tmpfs (csLinkerConfig cfg) $+          [ Option "-o"+          , FileOption "" (out </> "clibs.js")+          -- Embed wasm files into a single .js file+          , Option "-sSINGLE_FILE=1"+          -- Enable support for addFunction (callbacks)+          , Option "-sALLOW_TABLE_GROWTH"+          -- keep some RTS methods and functions (otherwise removed as dead+          -- code)+          , Option ("-sEXPORTED_RUNTIME_METHODS=" ++ concat (intersperse "," (emccExportedRuntimeMethods emcc_opts)))+          , Option ("-sEXPORTED_FUNCTIONS=" ++ concat (intersperse "," (emccExportedFunctions emcc_opts)))+          ]+          -- pass extra options from JS files' pragmas+          ++ map Option (emccExtraOptions emcc_opts)+          -- link objects+          ++ map (FileOption "") emcc_objs++      -- Don't enable the Emcc rts when not needed (i.e. no Wasm module to link+      -- with) and not forced by the caller (e.g. in the future iserv may require+      -- incremental linking of Wasm modules, hence the emcc rts even building+      -- iserv itself doesn't require the emcc rts)+      let use_emcc_rts = UseEmccRts $ link_c_sources || lcForceEmccRts lc_cfg++       -- link everything together into a runnable all.js       -- only if we link a complete application,       --   no incremental linking and no skipped parts       when (lcCombineAll lc_cfg && not (lcNoRts lc_cfg)) $ do-        _ <- combineFiles lc_cfg out+        writeRunMain out use_emcc_rts+        _ <- combineFiles lc_cfg link_c_sources out         writeHtml    out-        writeRunMain out         writeRunner lc_cfg out         writeExterns out  data LinkSpec = LinkSpec   { lks_unit_ids        :: [UnitId]--  , lks_obj_files       :: [LinkedObj]--  , lks_obj_root_filter :: ExportedFun -> Bool-      -- ^ Predicate for exported functions in objects to declare as root--  , lks_extra_roots     :: Set ExportedFun-      -- ^ Extra root functions from loaded units--  , lks_extra_js        :: [FilePath]-      -- ^ Extra JS files to link+  , lks_obj_root_filter :: ExportedFun -> Bool -- ^ Predicate for exported functions in objects to declare as root+  , lks_extra_roots     :: Set ExportedFun -- ^ Extra root functions from loaded units+  , lks_objs_hs         :: [FilePath]      -- ^ HS objects to link+  , lks_objs_js         :: [FilePath]      -- ^ JS objects to link+  , lks_objs_cc         :: [FilePath]      -- ^ Cc objects to link   }  instance Outputable LinkSpec where   ppr s = hang (text "LinkSpec") 2 $ vcat             [ hcat [text "Unit ids: ", ppr (lks_unit_ids s)]-            , hcat [text "Object files:", ppr (lks_obj_files s)]+            , hcat [text "HS objects:", vcat (fmap text (lks_objs_hs s))]+            , hang (text "JS objects::") 2 (vcat (fmap text (lks_objs_js s)))+            , hang (text "Cc objects::") 2 (vcat (fmap text (lks_objs_cc s)))             , text "Object root filter: <function>"             , hcat [text "Extra roots: ", ppr (lks_extra_roots s)]-            , hang (text "Extra JS:") 2 (vcat (fmap text (lks_extra_js s)))             ]  emptyLinkPlan :: LinkPlan@@ -270,7 +377,8 @@   { lkp_block_info = mempty   , lkp_dep_blocks = mempty   , lkp_archives   = mempty-  , lkp_extra_js   = mempty+  , lkp_objs_js    = mempty+  , lkp_objs_cc    = mempty   }  -- | Given a `base` link plan (assumed to be already linked) and a `new` link@@ -285,13 +393,15 @@       { lkp_block_info = M.union (lkp_block_info base) (lkp_block_info new)       , lkp_dep_blocks = S.union (lkp_dep_blocks base) (lkp_dep_blocks new)       , lkp_archives   = S.union (lkp_archives base) (lkp_archives new)-      , lkp_extra_js   = S.union (lkp_extra_js base) (lkp_extra_js new)+      , lkp_objs_js    = S.union (lkp_objs_js base) (lkp_objs_js new)+      , lkp_objs_cc    = S.union (lkp_objs_cc base) (lkp_objs_cc new)       }     diff = LinkPlan       { lkp_block_info = lkp_block_info new -- block info from "new" contains all we need to load new blocks       , lkp_dep_blocks = S.difference (lkp_dep_blocks new) (lkp_dep_blocks base)       , lkp_archives   = S.difference (lkp_archives new)   (lkp_archives base)-      , lkp_extra_js   = S.difference (lkp_extra_js new)   (lkp_extra_js base)+      , lkp_objs_js    = S.difference (lkp_objs_js new)    (lkp_objs_js base)+      , lkp_objs_cc    = S.difference (lkp_objs_cc new)    (lkp_objs_cc base)       }  @@ -301,11 +411,14 @@   -> LinkSpec   -> FinderOpts   -> FinderCache+  -> ArchiveCache   -> IO LinkPlan-computeLinkDependencies cfg unit_env link_spec finder_opts finder_cache = do+computeLinkDependencies cfg unit_env link_spec finder_opts finder_cache ar_cache = do    let units       = lks_unit_ids        link_spec-  let obj_files   = lks_obj_files       link_spec+  let hs_objs     = lks_objs_hs         link_spec+  let js_objs     = lks_objs_js         link_spec+  let cc_objs     = lks_objs_cc         link_spec   let extra_roots = lks_extra_roots     link_spec   let obj_is_root = lks_obj_root_filter link_spec @@ -319,12 +432,12 @@   -- find/load linkable on-demand when a module is missing.  -  (objs_block_info, objs_required_blocks) <- loadObjBlockInfo obj_files+  (objs_block_info, objs_required_blocks) <- loadObjBlockInfo hs_objs    let obj_roots = S.fromList . filter obj_is_root $ concatMap (M.keys . bi_exports . lbi_info) (M.elems objs_block_info)       obj_units = map moduleUnitId $ nub (M.keys objs_block_info) -  let (rts_wired_units, rts_wired_functions) = rtsDeps units+  let (rts_wired_units, rts_wired_functions) = rtsDeps    -- all the units we want to link together, without their dependencies   let root_units = filter (/= ue_currentUnit unit_env)@@ -339,7 +452,7 @@   let all_units = fmap unitId all_units_infos    dep_archives <- getPackageArchives cfg unit_env all_units-  (archives_block_info, archives_required_blocks) <- loadArchiveBlockInfo dep_archives+  (archives_block_info, archives_required_blocks) <- loadArchiveBlockInfo ar_cache dep_archives    -- compute dependencies   let block_info      = objs_block_info `M.union` archives_block_info@@ -374,7 +487,7 @@          case linkableUnlinked linkable of               [DotO p] -> do-                  (bis, req_b) <- loadObjBlockInfo [ObjFile p]+                  (bis, req_b) <- loadObjBlockInfo [p]                   -- Store new required blocks in IORef                   modifyIORef new_required_blocks_var ((++) req_b)                   case M.lookup mod bis of@@ -401,7 +514,8 @@         { lkp_block_info = updated_block_info         , lkp_dep_blocks = all_deps         , lkp_archives   = S.fromList dep_archives-        , lkp_extra_js   = S.fromList (lks_extra_js link_spec)+        , lkp_objs_js    = S.fromList js_objs+        , lkp_objs_cc    = S.fromList cc_objs         }    return plan@@ -410,7 +524,7 @@ -- | Compiled module data ModuleCode = ModuleCode   { mc_module   :: !Module-  , mc_js_code  :: !Sat.JStat+  , mc_js_code  :: !JS.JStat   , mc_exports  :: !B.ByteString        -- ^ rendered exports   , mc_closures :: ![ClosureInfo]   , mc_statics  :: ![StaticInfo]@@ -423,14 +537,14 @@ -- up into global "metadata" for the whole link. data CompactedModuleCode = CompactedModuleCode   { cmc_module  :: !Module-  , cmc_js_code :: !Sat.JStat+  , cmc_js_code :: !JS.JStat   , cmc_exports :: !B.ByteString        -- ^ rendered exports   }  -- | Output JS statements and return the output size in bytes.-hPutJS :: Bool -> Handle -> Sat.JStat -> IO Integer+hPutJS :: Bool -> Handle -> JS.JStat -> IO Integer hPutJS render_pretty h = \case-  Sat.BlockStat [] -> pure 0+  JS.BlockStat [] -> pure 0   x                -> do     before <- hTell h     if render_pretty@@ -446,19 +560,17 @@     pure $! (after - before)  -- | Link modules and pretty-print them into the given Handle-renderLinker+renderModules   :: Handle   -> Bool         -- ^ should we render readable JS for debugging?   -> [ModuleCode] -- ^ linked code per module-  -> Set FilePath -- ^ additional JS files   -> IO LinkerStats-renderLinker h render_pretty mods js_files = do+renderModules h render_pretty mods = do    -- link modules   let (compacted_mods, meta) = linkModules mods    let-    putBS   = B.hPut h     putJS   = hPutJS render_pretty h    ---------------------------------------------------------@@ -470,21 +582,20 @@    -- modules themselves   mod_sizes <- forM compacted_mods $ \m -> do-    !mod_size <- fromIntegral <$> putJS (cmc_js_code m)++    !mod_size <- fromIntegral <$> (putJS $ cmc_js_code m)     let !mod_mod  = cmc_module m     pure (mod_mod, mod_size)    -- commoned up metadata-  !meta_length <- fromIntegral <$> putJS (jsOptimize $ satJStat Nothing meta)+  let meta_opt = jsOptimize meta+  !meta_length <- fromIntegral <$> putJS meta_opt    -- module exports-  mapM_ (putBS . cmc_exports) compacted_mods--  -- explicit additional JS files-  mapM_ (\i -> B.readFile i >>= putBS) (S.toList js_files)+  mapM_ (B.hPut h . cmc_exports) compacted_mods    -- stats-  let link_stats = LinkerStats+  let !link_stats = LinkerStats         { bytesPerModule     = M.fromList mod_sizes         , packedMetaDataSize = meta_length         }@@ -543,15 +654,20 @@ -- | Combine rts.js, lib.js, out.js to all.js that can be run -- directly with node.js or SpiderMonkey jsshell combineFiles :: JSLinkConfig+             -> Bool -- has clibs.js              -> FilePath              -> IO ()-combineFiles cfg fp = do-  let files = map (fp </>) ["rts.js", "lib.js", "out.js"]-  withBinaryFile (fp </> "all.js") WriteMode $ \h -> do-    let cpy i = B.readFile i >>= B.hPut h-    mapM_ cpy files-    unless (lcNoHsMain cfg) $ do-      B.hPut h runMainJS+combineFiles cfg has_clibs fp = do+  let files = map (fp </>) $ catMaybes+        [ Just "rts.js"+        , Just "lib.js"+        , Just "out.js"+        , if has_clibs      then Just "clibs.js" else Nothing+        , if lcNoHsMain cfg then Nothing else Just "runmain.js"+        ]+  withBinaryFile (fp </> "all.js") WriteMode $ \h ->+    forM_ files $ \i ->+      B.readFile i >>= B.hPut h  -- | write the index.html file that loads the program if it does not exit writeHtml@@ -579,16 +695,22 @@ -- index.html is loaded writeRunMain   :: FilePath -- ^ output directory+  -> UseEmccRts   -> IO ()-writeRunMain out = do+writeRunMain out use_emcc_rts = do   let runMainFile = out </> "runmain.js"-  e <- doesFileExist runMainFile-  unless e $-    B.writeFile runMainFile runMainJS+  B.writeFile runMainFile (runMainJS use_emcc_rts) -runMainJS :: B.ByteString-runMainJS = "h$main(h$mainZCZCMainzimain);\n"+newtype UseEmccRts = UseEmccRts Bool +runMainJS :: UseEmccRts -> B.ByteString+runMainJS (UseEmccRts use_emcc_rts) = if use_emcc_rts+  then "Module['onRuntimeInitialized'] = function() {\n\+       \h$initEmscriptenHeap();\n\+       \h$main(h$mainZCZCMainzimain);\n\+       \}\n"+  else "h$main(h$mainZCZCMainzimain);\n"+ writeRunner :: JSLinkConfig -- ^ Settings             -> FilePath     -- ^ Output directory             -> IO ()@@ -707,8 +829,8 @@       in  open `S.union` S.fromList (filter (not . alreadyLinked) new_blocks)  -- | collect dependencies for a set of roots-collectModuleCodes :: LinkPlan -> IO [ModuleCode]-collectModuleCodes link_plan = do+collectModuleCodes :: ArchiveCache -> LinkPlan -> IO [ModuleCode]+collectModuleCodes ar_cache link_plan = do    let block_info = lkp_block_info link_plan   let blocks     = lkp_dep_blocks link_plan@@ -734,13 +856,12 @@       sorted_module_blocks = sortBy cmp (M.toList module_blocks)    -- load blocks-  ar_state <- emptyArchiveState   forM sorted_module_blocks $ \(mod,bids) -> do     case M.lookup mod block_info of       Nothing  -> pprPanic "collectModuleCodes: couldn't find block info for module" (ppr mod)-      Just lbi -> extractBlocks ar_state lbi bids+      Just lbi -> extractBlocks ar_cache lbi bids -extractBlocks :: ArchiveState -> LocatedBlockInfo -> BlockIds -> IO ModuleCode+extractBlocks :: ArchiveCache -> LocatedBlockInfo -> BlockIds -> IO ModuleCode extractBlocks ar_state lbi blocks = do   case lbi_loc lbi of     ObjectFile fp -> do@@ -767,16 +888,22 @@                       , mc_frefs    = concatMap oiFImports l                       } -readArObject :: ArchiveState -> Module -> FilePath -> IO Object-readArObject ar_state mod ar_file = do-  loaded_ars <- readIORef (loadedArchives ar_state)-  (Ar.Archive entries) <- case M.lookup ar_file loaded_ars of+-- | Load an archive in memory and store it in the cache for future loads.+loadArchive :: ArchiveCache -> FilePath -> IO Ar.Archive+loadArchive ar_cache ar_file = do+  loaded_ars <- readIORef (loadedArchives ar_cache)+  case M.lookup ar_file loaded_ars of     Just a -> pure a     Nothing -> do       a <- Ar.loadAr ar_file-      modifyIORef (loadedArchives ar_state) (M.insert ar_file a)+      modifyIORef (loadedArchives ar_cache) (M.insert ar_file a)       pure a ++readArObject :: ArchiveCache -> Module -> FilePath -> IO Object+readArObject ar_cache mod ar_file = do+  Ar.Archive entries <- loadArchive ar_cache ar_file+   -- look for the right object in archive   let go_entries = \case         -- XXX this shouldn't be an exception probably@@ -798,49 +925,34 @@    go_entries entries ---- | A helper function to read system dependencies that are hardcoded-diffDeps-  :: [UnitId]                    -- ^ Packages that are already Linked-  -> ([UnitId], Set ExportedFun) -- ^ New units and functions to link-  -> ([UnitId], Set ExportedFun) -- ^ Diff-diffDeps pkgs (deps_pkgs,deps_funs) =-  ( filter   linked_pkg deps_pkgs-  , S.filter linked_fun deps_funs-  )-  where-    linked_fun f = moduleUnitId (funModule f) `S.member` linked_pkgs-    linked_pkg p = S.member p linked_pkgs-    linked_pkgs  = S.fromList pkgs- -- | dependencies for the RTS, these need to be always linked-rtsDeps :: [UnitId] -> ([UnitId], Set ExportedFun)-rtsDeps pkgs = diffDeps pkgs $-  ( [baseUnitId, primUnitId]+rtsDeps :: ([UnitId], Set ExportedFun)+rtsDeps =+  ( [ghcInternalUnitId, primUnitId]   , S.fromList $ concat-      [ mkBaseFuns "GHC.Conc.Sync"+      [ mkInternalFuns "GHC.Internal.Conc.Sync"           ["reportError"]-      , mkBaseFuns "Control.Exception.Base"+      , mkInternalFuns "GHC.Internal.Control.Exception.Base"           ["nonTermination"]-      , mkBaseFuns "GHC.Exception.Type"+      , mkInternalFuns "GHC.Internal.Exception.Type"           [ "SomeException"           , "underflowException"           , "overflowException"           , "divZeroException"           ]-      , mkBaseFuns "GHC.TopHandler"+      , mkInternalFuns "GHC.Internal.TopHandler"           [ "runMainIO"           , "topHandler"           ]-      , mkBaseFuns "GHC.Base"+      , mkInternalFuns "GHC.Internal.Base"           ["$fMonadIO"]-      , mkBaseFuns "GHC.Maybe"+      , mkInternalFuns "GHC.Internal.Maybe"           [ "Nothing"           , "Just"           ]-      , mkBaseFuns "GHC.Ptr"+      , mkInternalFuns "GHC.Internal.Ptr"           ["Ptr"]-      , mkBaseFuns "GHC.JS.Prim"+      , mkInternalFuns "GHC.Internal.JS.Prim"           [ "JSVal"           , "JSException"           , "$fShowJSException"@@ -849,7 +961,7 @@           , "resolveIO"           , "toIO"           ]-      , mkBaseFuns "GHC.JS.Prim.Internal"+      , mkInternalFuns "GHC.Internal.JS.Prim.Internal"           [ "wouldBlock"           , "blockedIndefinitelyOnMVar"           , "blockedIndefinitelyOnSTM"@@ -861,7 +973,7 @@           [ ":"           , "[]"           ]-      , mkPrimFuns "GHC.Tuple.Prim"+      , mkPrimFuns "GHC.Tuple"           [ "(,)"           , "(,,)"           , "(,,,)"@@ -875,9 +987,9 @@       ]   ) --- | Export the functions in base-mkBaseFuns :: FastString -> [FastString] -> [ExportedFun]-mkBaseFuns = mkExportedFuns baseUnitId+-- | Export the functions in @ghc-internal@+mkInternalFuns :: FastString -> [FastString] -> [ExportedFun]+mkInternalFuns = mkExportedFuns ghcInternalUnitId  -- | Export the Prim functions mkPrimFuns :: FastString -> [FastString] -> [ExportedFun]@@ -899,15 +1011,16 @@     mk_fun sym = ExportedFun mod (LexicalFastString sym)  -- | read all dependency data from the to-be-linked files-loadObjBlockInfo :: [LinkedObj] -- ^ object files to link-            -> IO (Map Module LocatedBlockInfo, [BlockRef])+loadObjBlockInfo+  :: [FilePath] -- ^ object files to link+  -> IO (Map Module LocatedBlockInfo, [BlockRef]) loadObjBlockInfo objs = (prepareLoadedDeps . catMaybes) <$> mapM readBlockInfoFromObj objs  -- | Load dependencies for the Linker from Ar-loadArchiveBlockInfo :: [FilePath] -> IO (Map Module LocatedBlockInfo, [BlockRef])-loadArchiveBlockInfo archives = do+loadArchiveBlockInfo :: ArchiveCache -> [FilePath] -> IO (Map Module LocatedBlockInfo, [BlockRef])+loadArchiveBlockInfo ar_cache archives = do   archDeps <- forM archives $ \file -> do-    (Ar.Archive entries) <- Ar.loadAr file+    (Ar.Archive entries) <- loadArchive ar_cache file     catMaybes <$> mapM (readEntry file) entries   return (prepareLoadedDeps $ concat archDeps)     where@@ -922,34 +1035,6 @@               let !info = objBlockInfo obj               pure $ Just (LocatedBlockInfo (ArchiveFile ar_file) info) --- | Predicate to check that an entry in Ar is a JS source--- and to return it without its header-getJsArchiveEntry :: Ar.ArchiveEntry -> Maybe B.ByteString-getJsArchiveEntry entry = getJsBS (Ar.filedata entry)---- | Predicate to check that a file is a JS source-isJsFile :: FilePath -> IO Bool-isJsFile fp = withBinaryFile fp ReadMode $ \h -> do-  bs <- B.hGet h jsHeaderLength-  pure (isJsBS bs)--isJsBS :: B.ByteString -> Bool-isJsBS bs = isJust (getJsBS bs)---- | Get JS source with its header (if it's one)-getJsBS :: B.ByteString -> Maybe B.ByteString-getJsBS bs = B.stripPrefix jsHeader bs---- Header added to JS sources to discriminate them from other object files.--- They all have .o extension but JS sources have this header.-jsHeader :: B.ByteString-jsHeader = "//JavaScript"--jsHeaderLength :: Int-jsHeaderLength = B.length jsHeader--- prepareLoadedDeps :: [LocatedBlockInfo]                   -> (Map Module LocatedBlockInfo, [BlockRef]) prepareLoadedDeps lbis = (module_blocks, must_link)@@ -967,25 +1052,21 @@  -- | read block info from an object that might have already been into memory -- pulls in all Deps from an archive-readBlockInfoFromObj :: LinkedObj -> IO (Maybe LocatedBlockInfo)-readBlockInfoFromObj = \case-  ObjLoaded name obj -> do-    let !info = objBlockInfo obj-    pure $ Just (LocatedBlockInfo (InMemory name obj) info)-  ObjFile file -> do-    readObjectBlockInfo file >>= \case-      Nothing   -> pure Nothing-      Just info -> pure $ Just (LocatedBlockInfo (ObjectFile file) info)+readBlockInfoFromObj :: FilePath -> IO (Maybe LocatedBlockInfo)+readBlockInfoFromObj file = do+  readObjectBlockInfo file >>= \case+    Nothing   -> pure Nothing+    Just info -> pure $ Just (LocatedBlockInfo (ObjectFile file) info)  --- | Embed a JS file into a .o file------ The JS file is merely copied into a .o file with an additional header--- ("//Javascript") in order to be recognized later on.+-- | Embed a JS file into a JS object .o file -- -- JS files may contain option pragmas of the form: //#OPTIONS:--- For now, only the CPP option is supported. If the CPP option is set, we--- append some common CPP definitions to the file and call cpp on it.+-- One of those is //#OPTIONS:CPP. When it is set, we append some common CPP+-- definitions to the file and call cpp on it.+--+-- Other options (e.g. EMCC additional flags for link time) are stored in the+-- JS object header. See JSOptions. embedJsFile :: Logger -> DynFlags -> TmpFs -> UnitEnv -> FilePath -> FilePath -> IO () embedJsFile logger dflags tmpfs unit_env input_fn output_fn = do   let profiling  = False -- FIXME: add support for profiling way@@ -995,12 +1076,14 @@   -- the header lets the linker recognize processed JavaScript files   -- But don't add JavaScript header to object files! -  -- header appended to JS files stored as .o to recognize them.-  let header = "//JavaScript\n"-  jsFileNeedsCpp input_fn >>= \case-    False -> copyWithHeader header input_fn output_fn-    True  -> do+  -- read pragmas from JS file+  -- we need to store them explicitly as they can be removed by CPP.+  opts <- getOptionsFromJsFile input_fn +  -- run CPP if needed+  cpp_fn <- case enableCPP opts of+    False -> pure input_fn+    True  -> do       -- append common CPP definitions to the .js file.       -- They define macros that avoid directly wiring zencoded names       -- in RTS JS files@@ -1012,7 +1095,7 @@       js_fn <- newTempName logger tmpfs (tmpDir dflags) TFL_CurrentModule "js"       let         cpp_opts = CppOpts-          { cppUseCc       = True+          { useHsCpp       = False           , cppLinePragmas = False -- LINE pragmas aren't JS compatible           }       doCpp logger@@ -1022,19 +1105,17 @@               cpp_opts               pp_fn               js_fn-      -- add header to recognize the object as a JS file-      copyWithHeader header js_fn output_fn+      pure js_fn -jsFileNeedsCpp :: FilePath -> IO Bool-jsFileNeedsCpp fn = do-  opts <- getOptionsFromJsFile fn-  pure (CPP `elem` opts)+  -- write JS object+  cpp_bs <- B.readFile cpp_fn+  writeJSObject opts cpp_bs output_fn  -- | Link module codes. -- -- Performs link time optimizations and produces one JStat per module plus some -- commoned up initialization code.-linkModules :: [ModuleCode] -> ([CompactedModuleCode], JStat)+linkModules :: [ModuleCode] -> ([CompactedModuleCode], JS.JStat) linkModules mods = (compact_mods, meta)   where     compact_mods = map compact mods@@ -1061,7 +1142,7 @@             -- render metadata as individual statements             [ mconcat (map staticDeclStat statics)             , mconcat (map staticInitStat statics)-            , mconcat (map (closureInfoStat debug) infos)+            , jStgStatToJS $ mconcat (map (closureInfoStat debug) infos)             ]  -- | Only keep a single StaticInfo with a given name@@ -1081,8 +1162,9 @@ -- | Initialize a global object. -- -- All global objects have to be declared (staticInfoDecl) first.-staticInitStat :: StaticInfo -> JStat+staticInitStat :: StaticInfo -> JS.JStat staticInitStat (StaticInfo i sv mcc) =+  jStgStatToJS $   case sv of     StaticData con args         -> appS "h$sti" $ add_cc_arg                                     [ var i@@ -1112,10 +1194,10 @@       Just cc -> as ++ [toJExpr cc]  -- | declare and do first-pass init of a global object (create JS object for heap objects)-staticDeclStat :: StaticInfo -> JStat-staticDeclStat (StaticInfo global_name static_value _) = decl+staticDeclStat :: StaticInfo -> JS.JStat+staticDeclStat (StaticInfo global_name static_value _) = jStgStatToJS decl   where-    global_ident = TxtI global_name+    global_ident = global global_name     decl_init v  = global_ident ||= v     decl_no_init = appS "h$di" [toJExpr global_ident] 
compiler/GHC/StgToJS/Linker/Opt.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MagicHash #-}+{-# LANGUAGE ViewPatterns #-}  ----------------------------------------------------------------------------- -- |@@ -59,7 +60,7 @@ hdd = SBS.pack (map (fromIntegral . ord) "h$$")  ghcjsRenderJsI :: IsLine doc => RenderJs doc -> Ident -> doc-ghcjsRenderJsI _ (TxtI fs)+ghcjsRenderJsI _ (identFS -> fs)   -- Fresh symbols are prefixed with "h$$". They aren't explicitly referred by   -- name in user code, only in compiled code. Hence we can rename them if we do   -- it consistently in all the linked code.
compiler/GHC/StgToJS/Linker/Utils.hs view
@@ -17,9 +17,7 @@ -----------------------------------------------------------------------------  module GHC.StgToJS.Linker.Utils-  ( getOptionsFromJsFile-  , JSOption(..)-  , jsExeFileName+  ( jsExeFileName   , getInstalledPackageLibDirs   , getInstalledPackageHsLibs   , commonCppDefs@@ -41,18 +39,14 @@  import           Prelude import GHC.Platform-import GHC.Utils.Misc import Data.List (isPrefixOf)-import System.IO-import Data.Char (isSpace)-import qualified Control.Exception as Exception  import GHC.Builtin.Types import Language.Haskell.Syntax.Basic import GHC.Types.Name import GHC.StgToJS.Ids+import GHC.JS.Ident import GHC.Core.DataCon-import GHC.JS.Unsat.Syntax import GHC.Data.FastString  -- | Retrieve library directories provided by the @UnitId@ in @UnitState@@@ -85,7 +79,7 @@   [ "#define MK_TUP", sn                                                          -- #define MK_TUPn   , "(", B.intercalate "," xs, ")"                                                -- (x1,x2,...)   , "(h$c", sn, "("                                                               -- (h$cn(-  , bytesFS symbol, ","                                                           -- h$ghczmprimZCGHCziTupleziPrimziZnT_con_e,                                                                        -- ,+  , bytesFS symbol, ","                                                           -- h$ghczmprimZCGHCziTupleziZnT_con_e,                                                                        -- ,   , B.intercalate "," $ map (\x -> "(" <> x <> ")") xs                            -- (x1),(x2),(...)   , if profiling then ",h$currentThread?h$currentThread.ccs:h$CCS_SYSTEM" else "" -- ,h$currentThread?h$currentThread.ccs:h$CCS_SYSTEM   , "))\n"                                                                        -- ))\n@@ -93,7 +87,7 @@   where     xs = take n $ map (("x" <>) . Char8.pack . show) ([1..] :: [Int])     sn = Char8.pack $ show n-    TxtI symbol = makeIdentForId (dataConWorkId $ tupleDataCon Boxed n) Nothing IdConEntry mod+    symbol = identFS $ makeIdentForId (dataConWorkId $ tupleDataCon Boxed n) Nothing IdConEntry mod     name = tupleDataConName Boxed n     mod = case nameModule_maybe name of       Just m -> m@@ -122,41 +116,41 @@    -- GHCJS.Prim.JSVal   , if profiling-      then "#define MK_JSVAL(x) (h$c1(h$baseZCGHCziJSziPrimziJSVal_con_e, (x), h$CCS_SYSTEM))\n"-      else "#define MK_JSVAL(x) (h$c1(h$baseZCGHCziJSziPrimziJSVal_con_e, (x)))\n"+      then "#define MK_JSVAL(x) (h$c1(h$ghczminternalZCGHCziInternalziJSziPrimziJSVal_con_e, (x), h$CCS_SYSTEM))\n"+      else "#define MK_JSVAL(x) (h$c1(h$ghczminternalZCGHCziInternalziJSziPrimziJSVal_con_e, (x)))\n"   ,  "#define JSVAL_VAL(x) ((x).d1)\n"    -- GHCJS.Prim.JSException   , if profiling-      then "#define MK_JSEXCEPTION(msg,hsMsg) (h$c2(h$baseZCGHCziJSziPrimziJSException_con_e,(msg),(hsMsg),h$CCS_SYSTEM))\n"-      else "#define MK_JSEXCEPTION(msg,hsMsg) (h$c2(h$baseZCGHCziJSziPrimziJSException_con_e,(msg),(hsMsg)))\n"+      then "#define MK_JSEXCEPTION(msg,hsMsg) (h$c2(h$ghczminternalZCGHCziInternalziJSziPrimziJSException_con_e,(msg),(hsMsg),h$CCS_SYSTEM))\n"+      else "#define MK_JSEXCEPTION(msg,hsMsg) (h$c2(h$ghczminternalZCGHCziInternalziJSziPrimziJSException_con_e,(msg),(hsMsg)))\n"    -- Exception dictionary for JSException-  , "#define HS_JSEXCEPTION_EXCEPTION h$baseZCGHCziJSziPrimzizdfExceptionJSException\n"+  , "#define HS_JSEXCEPTION_EXCEPTION h$ghczminternalZCGHCziInternalziJSziPrimzizdfExceptionJSException\n"    -- SomeException   , if profiling-      then "#define MK_SOMEEXCEPTION(dict,except) (h$c2(h$baseZCGHCziExceptionziTypeziSomeException_con_e,(dict),(except),h$CCS_SYSTEM))\n"-      else "#define MK_SOMEEXCEPTION(dict,except) (h$c2(h$baseZCGHCziExceptionziTypeziSomeException_con_e,(dict),(except)))\n"+      then "#define MK_SOMEEXCEPTION(dict,except) (h$c2(h$ghczminternalZCGHCziInternalziExceptionziTypeziSomeException_con_e,(dict),(except),h$CCS_SYSTEM))\n"+      else "#define MK_SOMEEXCEPTION(dict,except) (h$c2(h$ghczminternalZCGHCziInternalziExceptionziTypeziSomeException_con_e,(dict),(except)))\n"    -- GHC.Ptr.Ptr   , if profiling-      then "#define MK_PTR(val,offset) (h$c2(h$baseZCGHCziPtrziPtr_con_e, (val), (offset), h$CCS_SYSTEM))\n"-      else "#define MK_PTR(val,offset) (h$c2(h$baseZCGHCziPtrziPtr_con_e, (val), (offset)))\n"+      then "#define MK_PTR(val,offset) (h$c2(h$ghczminternalZCGHCziInternalziPtrziPtr_con_e, (val), (offset), h$CCS_SYSTEM))\n"+      else "#define MK_PTR(val,offset) (h$c2(h$ghczminternalZCGHCziInternalziPtrziPtr_con_e, (val), (offset)))\n"    -- Put Addr# in ByteArray# or at Addr# (same thing)   , "#define PUT_ADDR(a,o,va,vo) if (!(a).arr) (a).arr = []; (a).arr[o] = va; (a).dv.setInt32(o,vo,true);\n"   , "#define GET_ADDR(a,o,ra,ro) var ra = (((a).arr && (a).arr[o]) ? (a).arr[o] : null_); var ro = (a).dv.getInt32(o,true);\n"    -- Data.Maybe.Maybe-  , "#define HS_NOTHING h$baseZCGHCziMaybeziNothing\n"-  , "#define IS_NOTHING(cl) ((cl).f === h$baseZCGHCziMaybeziNothing_con_e)\n"-  , "#define IS_JUST(cl) ((cl).f === h$baseZCGHCziMaybeziJust_con_e)\n"+  , "#define HS_NOTHING h$ghczminternalZCGHCziInternalziMaybeziNothing\n"+  , "#define IS_NOTHING(cl) ((cl).f === h$ghczminternalZCGHCziInternalziMaybeziNothing_con_e)\n"+  , "#define IS_JUST(cl) ((cl).f === h$ghczminternalZCGHCziInternalziMaybeziJust_con_e)\n"   , "#define JUST_VAL(jj) ((jj).d1)\n"   -- "#define HS_NOTHING h$nothing\n"   , if profiling-      then "#define MK_JUST(val) (h$c1(h$baseZCGHCziMaybeziJust_con_e, (val), h$CCS_SYSTEM))\n"-      else "#define MK_JUST(val) (h$c1(h$baseZCGHCziMaybeziJust_con_e, (val)))\n"+      then "#define MK_JUST(val) (h$c1(h$ghczminternalZCGHCziInternalziMaybeziJust_con_e, (val), h$CCS_SYSTEM))\n"+      else "#define MK_JUST(val) (h$c1(h$ghczminternalZCGHCziInternalziMaybeziJust_con_e, (val)))\n"    -- Data.List   , "#define HS_NIL h$ghczmprimZCGHCziTypesziZMZN\n"@@ -197,6 +191,9 @@   -- resumable thunks   , "#define MAKE_RESUMABLE(closure,stack) { (closure).f = h$resume_e; (closure).d1 = (stack), (closure).d2 = null; }\n" +  -- making a thunk+  , "#define MK_UPD_THUNK(closure) h$c1(h$upd_thunk_e,(closure))\n"+   -- general deconstruction   , "#define IS_THUNK(x) ((x).f.t === CLOSURE_TYPE_THUNK)\n"   , "#define CONSTR_TAG(x) ((x).f.a)\n"@@ -253,6 +250,10 @@   , "#define RETURN_UBX_TUP9(x1,x2,x3,x4,x5,x6,x7,x8,x9) { h$ret1 = (x2); h$ret2 = (x3); h$ret3 = (x4); h$ret4 = (x5); h$ret5 = (x6); h$ret6 = (x7); h$ret7 = (x8); h$ret8 = (x9); return (x1); }\n"   , "#define RETURN_UBX_TUP10(x1,x2,x3,x4,x5,x6,x7,x8,x9,x10) { h$ret1 = (x2); h$ret2 = (x3); h$ret3 = (x4); h$ret4 = (x5); h$ret5 = (x6); h$ret6 = (x7); h$ret7 = (x8); h$ret8 = (x9); h$ret9 = (x10); return (x1); }\n" +  , "#define RETURN_INT64(h,l) RETURN_UBX_TUP2((h)|0,(l)>>>0)\n"+  , "#define RETURN_WORD64(h,l) RETURN_UBX_TUP2((h)>>>0,(l)>>>0)\n"+  , "#define RETURN_ADDR(a,o) RETURN_UBX_TUP2(a,o)\n"+   , "#define CALL_UBX_TUP2(r1,r2,c) { (r1) = (c); (r2) = h$ret1; }\n"   , "#define CALL_UBX_TUP3(r1,r2,r3,c) { (r1) = (c); (r2) = h$ret1; (r3) = h$ret2; }\n"   , "#define CALL_UBX_TUP4(r1,r2,r3,r4,c) { (r1) = (c); (r2) = h$ret1; (r3) = h$ret2; (r4) = h$ret3; }\n"@@ -282,38 +283,3 @@     dropPrefix prefix xs       | prefix `isPrefixOf` xs = drop (length prefix) xs       | otherwise              = xs----- | Parse option pragma in JS file-getOptionsFromJsFile :: FilePath      -- ^ Input file-                     -> IO [JSOption] -- ^ Parsed options, if any.-getOptionsFromJsFile filename-    = Exception.bracket-              (openBinaryFile filename ReadMode)-              hClose-              getJsOptions--data JSOption = CPP deriving (Eq, Ord)--getJsOptions :: Handle -> IO [JSOption]-getJsOptions handle = do-  hSetEncoding handle utf8-  prefix' <- B.hGet handle prefixLen-  if prefix == prefix'-  then parseJsOptions <$> hGetLine handle-  else pure []- where-  prefix :: B.ByteString-  prefix = "//#OPTIONS:"-  prefixLen = B.length prefix--parseJsOptions :: String -> [JSOption]-parseJsOptions xs = go xs-  where-    trim = dropWhileEndLE isSpace . dropWhile isSpace-    go [] = []-    go xs = let (tok, rest) = break (== ',') xs-                tok' = trim tok-                rest' = drop 1 rest-            in  if | tok' == "CPP" -> CPP : go rest'-                   | otherwise     -> go rest'
compiler/GHC/StgToJS/Literal.hs view
@@ -1,5 +1,6 @@ {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns      #-}  module GHC.StgToJS.Literal   ( genLit@@ -9,8 +10,9 @@  import GHC.Prelude -import GHC.JS.Unsat.Syntax+import GHC.JS.JStg.Syntax import GHC.JS.Make+import GHC.JS.Ident  import GHC.StgToJS.Types import GHC.StgToJS.Monad@@ -35,15 +37,15 @@ --  * Addr# (Null and Strings): array and offset --  * 64-bit values: high 32-bit, low 32-bit --  * labels: call to h$mkFunctionPtr and 0, or function name and 0-genLit :: HasDebugCallStack => Literal -> G [JExpr]+genLit :: HasDebugCallStack => Literal -> G [JStgExpr] genLit = \case   LitChar c     -> return [ toJExpr (ord c) ]   LitString str ->-    freshIdent >>= \strLit@(TxtI strLitT) ->-      freshIdent >>= \strOff@(TxtI strOffT) -> do+    freshIdent >>= \strLit@(identFS -> strLitT) ->+      freshIdent >>= \strOff@(identFS -> strOffT) -> do         emitStatic strLitT (StaticUnboxed (StaticUnboxedString str)) Nothing         emitStatic strOffT (StaticUnboxed (StaticUnboxedStringOffset str)) Nothing-        return [ ValExpr (JVar strLit), ValExpr (JVar strOff) ]+        return [ Var strLit, Var strOff ]   LitNullAddr              -> return [ null_, ValExpr (JInt 0) ]   LitNumber nt v           -> case nt of     LitNumInt     -> return [ toJExpr v ]@@ -64,7 +66,7 @@                                                   [var (mkRawSymbol True name)]                                        , ValExpr (JInt 0)                                        ]-    | otherwise              -> return [ toJExpr (TxtI (mkRawSymbol True name))+    | otherwise              -> return [ toJExpr (global (mkRawSymbol True name))                                        , ValExpr (JInt 0)                                        ]   LitRubbish _ rr_ty ->@@ -86,7 +88,6 @@                   Int64Rep   -> [ ValExpr (JInt 0), ValExpr (JInt 0) ]                   DoubleRep  -> [ ValExpr (JInt 0) ]                   FloatRep   -> [ ValExpr (JInt 0) ]-                  VoidRep    -> panic "GHC.StgToJS.Literal.genLit: LitRubbish(VoidRep)"                   VecRep _ _ -> panic "GHC.StgToJS.Literal.genLit: VecRep unsupported"     in return (concatMap rub reps) @@ -114,28 +115,10 @@   LitDouble r              -> return [ DoubleLit . SaneDouble . r2d $ r ]   LitLabel name _size fod  -> return [ LabelLit (fod == IsFunction) (mkRawSymbol True name)                                      , IntLit 0 ]-  LitRubbish _ rep ->-    let prim_reps = runtimeRepPrimRep (text "GHC.StgToJS.Literal.genStaticLit") rep-    in case expectOnly "GHC.StgToJS.Literal.genStaticLit" prim_reps of -- Note [Post-unarisation invariants]-        BoxedRep _  -> pure [ NullLit ]-        AddrRep     -> pure [ NullLit, IntLit 0 ]-        IntRep      -> pure [ IntLit 0 ]-        Int8Rep     -> pure [ IntLit 0 ]-        Int16Rep    -> pure [ IntLit 0 ]-        Int32Rep    -> pure [ IntLit 0 ]-        Int64Rep    -> pure [ IntLit 0, IntLit 0 ]-        WordRep     -> pure [ IntLit 0 ]-        Word8Rep    -> pure [ IntLit 0 ]-        Word16Rep   -> pure [ IntLit 0 ]-        Word32Rep   -> pure [ IntLit 0 ]-        Word64Rep   -> pure [ IntLit 0, IntLit 0 ]-        FloatRep    -> pure [ DoubleLit (SaneDouble 0) ]-        DoubleRep   -> pure [ DoubleLit (SaneDouble 0) ]-        VoidRep     -> panic "GHC.StgToJS.Literal.getStaticLit: LitRubbish(VoidRep)"-        VecRep {}   -> pprPanic "GHC.StgToJS.Literal.genStaticLit: LitRubbish(VecRep) isn't supported" (ppr rep)+  l -> pprPanic "genStaticLit" (ppr l)  -- make an unsigned 32 bit number from this unsigned one, lower 32 bits-toU32Expr :: Integer -> JExpr+toU32Expr :: Integer -> JStgExpr toU32Expr i = Int (i Bits..&. 0xFFFFFFFF) .>>>. 0  -- make an unsigned 32 bit number from this unsigned one, lower 32 bits
compiler/GHC/StgToJS/Monad.hs view
@@ -24,8 +24,8 @@  import GHC.Prelude -import GHC.JS.Unsat.Syntax-import qualified GHC.JS.Syntax as Sat+import GHC.JS.JStg.Syntax+import GHC.JS.Ident import GHC.JS.Transform  import GHC.StgToJS.Types@@ -69,7 +69,7 @@     mod_state s = s { gsGroup = f (gsGroup s) }  -- | emit a global (for the current module) toplevel statement-emitGlobal :: JStat -> G ()+emitGlobal :: JStgStat -> G () emitGlobal stat = State.modify (\s -> s { gsGlobal = stat : gsGlobal s })  -- | add a dependency on a particular symbol to the current group@@ -79,7 +79,7 @@     mod_group g = g { ggsExtraDeps = S.insert symbol (ggsExtraDeps g) }  -- | emit a top-level statement for the current binding group-emitToplevel :: JStat -> G ()+emitToplevel :: JStgStat -> G () emitToplevel s = modifyGroup mod_group   where     mod_group g = g { ggsToplevelStats = s : ggsToplevelStats g}@@ -138,7 +138,7 @@   -assertRtsStat :: G JStat -> G JStat+assertRtsStat :: G JStgStat -> G JStgStat assertRtsStat stat = do   s <- State.gets gsSettings   if csAssertRts s then stat else pure mempty@@ -159,9 +159,9 @@   , global_count :: !Word   } --- | Return number of occurrences of every global id used in the given JStat.+-- | Return number of occurrences of every global id used in the given JStgStat. -- Sort by increasing occurrence count.-globalOccs :: Sat.JStat -> G [GlobalOcc]+globalOccs :: JStgStat -> G [GlobalOcc] globalOccs jst = do   GlobalIdCache gidc <- getGlobalIdCache   -- build a map form Ident Unique to (Ident, Id, Count)
compiler/GHC/StgToJS/Prim.hs view
@@ -13,1587 +13,1672 @@  import GHC.Prelude -import GHC.JS.Unsat.Syntax hiding (JUOp (..))-import GHC.JS.Make--import GHC.StgToJS.Heap-import GHC.StgToJS.Types-import GHC.StgToJS.Profiling-import GHC.StgToJS.Regs--import GHC.Core.Type--import GHC.Builtin.PrimOps-import GHC.Tc.Utils.TcType (isBoolTy)-import GHC.Utils.Encoding (zEncodeString)--import GHC.Data.FastString-import GHC.Utils.Outputable (renderWithContext, defaultSDocContext, ppr)---genPrim :: Bool     -- ^ Profiling (cost-centres) enabled-        -> Bool     -- ^ Array bounds-checking enabled-        -> Type-        -> PrimOp   -- ^ the primitive operation-        -> [JExpr]  -- ^ where to store the result-        -> [JExpr]  -- ^ arguments-        -> PrimRes-genPrim prof bound ty op = case op of-  CharGtOp        -> \[r] [x,y] -> PrimInline $ r |= if10 (x .>. y)-  CharGeOp        -> \[r] [x,y] -> PrimInline $ r |= if10 (x .>=. y)-  CharEqOp        -> \[r] [x,y] -> PrimInline $ r |= if10 (x .===. y)-  CharNeOp        -> \[r] [x,y] -> PrimInline $ r |= if10 (x .!==. y)-  CharLtOp        -> \[r] [x,y] -> PrimInline $ r |= if10 (x .<. y)-  CharLeOp        -> \[r] [x,y] -> PrimInline $ r |= if10 (x .<=. y)-  OrdOp           -> \[r] [x]   -> PrimInline $ r |= x--  Int8ToWord8Op   -> \[r] [x]   -> PrimInline $ r |= mask8 x-  Word8ToInt8Op   -> \[r] [x]   -> PrimInline $ r |= signExtend8 x-  Int16ToWord16Op -> \[r] [x]   -> PrimInline $ r |= mask16 x-  Word16ToInt16Op -> \[r] [x]   -> PrimInline $ r |= signExtend16 x-  Int32ToWord32Op -> \[r] [x]   -> PrimInline $ r |= x .>>>. zero_-  Word32ToInt32Op -> \[r] [x]   -> PrimInline $ r |= toI32 x-------------------------------- Int -------------------------------------------------- N.B. See Note [StgToJS design] in GHC.StgToJS for details on--- number representation.--  IntAddOp        -> \[r] [x,y] -> PrimInline $ r |= toI32 (Add x y)-  IntSubOp        -> \[r] [x,y] -> PrimInline $ r |= toI32 (Sub x y)-  IntMulOp        -> \[r] [x,y] -> PrimInline $ r |= app "Math.imul" [x, y]-  IntMul2Op       -> \[c,hr,lr] [x,y] -> PrimInline $ appT [c,hr,lr] "h$hs_timesInt2" [x, y]-  IntMulMayOfloOp -> \[r] [x,y] -> PrimInline $ jVar \tmp -> mconcat-                                            [ tmp |= Mul x y-                                            , r   |= if01 (tmp .===. toI32 tmp)-                                            ]-  IntQuotOp       -> \[r]   [x,y] -> PrimInline $ r |= toI32 (Div x y)-  IntRemOp        -> \[r]   [x,y] -> PrimInline $ r |= Mod x y-  IntQuotRemOp    -> \[q,r] [x,y] -> PrimInline $ mconcat-                                            [ q |= toI32 (Div x y)-                                            , r |= x `Sub` (Mul y q)-                                            ]-  IntAndOp        -> \[r] [x,y]   -> PrimInline $ r |= BAnd x y-  IntOrOp         -> \[r] [x,y]   -> PrimInline $ r |= BOr  x y-  IntXorOp        -> \[r] [x,y]   -> PrimInline $ r |= BXor x y-  IntNotOp        -> \[r] [x]     -> PrimInline $ r |= BNot x--  IntNegOp        -> \[r] [x]   -> PrimInline $ r |= toI32 (Negate x)--- add with carry: overflow == 0 iff no overflow-  IntAddCOp       -> \[r,overf] [x,y] ->-      PrimInline $ jVar \rt -> mconcat-        [ rt    |= Add x y-        , r     |= toI32 rt-        , overf |= if10 (r .!=. rt)-        ]-  IntSubCOp       -> \[r,overf] [x,y] ->-      PrimInline $ jVar \rt -> mconcat-        [ rt    |= Sub x y-        , r     |= toI32 rt-        , overf |= if10 (r .!=. rt)-        ]-  IntGtOp           -> \[r] [x,y] -> PrimInline $ r |= if10 (x .>. y)-  IntGeOp           -> \[r] [x,y] -> PrimInline $ r |= if10 (x .>=. y)-  IntEqOp           -> \[r] [x,y] -> PrimInline $ r |= if10 (x .===. y)-  IntNeOp           -> \[r] [x,y] -> PrimInline $ r |= if10(x .!==. y)-  IntLtOp           -> \[r] [x,y] -> PrimInline $ r |= if10 (x .<. y)-  IntLeOp           -> \[r] [x,y] -> PrimInline $ r |= if10 (x .<=. y)-  ChrOp             -> \[r] [x]   -> PrimInline $ r |= x-  IntToWordOp       -> \[r] [x]   -> PrimInline $ r |= x .>>>. 0-  IntToFloatOp      -> \[r] [x]   -> PrimInline $ r |= x-  IntToDoubleOp     -> \[r] [x]   -> PrimInline $ r |= x-  IntSllOp          -> \[r] [x,y] -> PrimInline $ r |= x .<<. y-  IntSraOp          -> \[r] [x,y] -> PrimInline $ r |= x .>>. y-  IntSrlOp          -> \[r] [x,y] -> PrimInline $ r |= toI32 (x .>>>. y)-------------------------------- Int8 -----------------------------------------------  Int8ToIntOp       -> \[r] [x]       -> PrimInline $ r |= x-  IntToInt8Op       -> \[r] [x]       -> PrimInline $ r |= signExtend8 x-  Int8NegOp         -> \[r] [x]       -> PrimInline $ r |= signExtend8 (Negate x)-  Int8AddOp         -> \[r] [x,y]     -> PrimInline $ r |= signExtend8 (Add x y)-  Int8SubOp         -> \[r] [x,y]     -> PrimInline $ r |= signExtend8 (Sub x y)-  Int8MulOp         -> \[r] [x,y]     -> PrimInline $ r |= signExtend8 (Mul x y)-  Int8QuotOp        -> \[r] [x,y]     -> PrimInline $ r |= signExtend8 (quotShortInt 8 x y)-  Int8RemOp         -> \[r] [x,y]     -> PrimInline $ r |= signExtend8 (remShortInt 8 x y)-  Int8QuotRemOp     -> \[r1,r2] [x,y] -> PrimInline $ mconcat-                                                [ r1 |= signExtend8 (quotShortInt 8 x y)-                                                , r2 |= signExtend8 (remShortInt 8 x y)-                                                ]-  Int8EqOp          -> \[r] [x,y] -> PrimInline $ r |= if10 (x .===. y)-  Int8GeOp          -> \[r] [x,y] -> PrimInline $ r |= if10 ((x .<<. (Int 24)) .>=. (y .<<. (Int 24)))-  Int8GtOp          -> \[r] [x,y] -> PrimInline $ r |= if10 ((x .<<. (Int 24)) .>.  (y .<<. (Int 24)))-  Int8LeOp          -> \[r] [x,y] -> PrimInline $ r |= if10 ((x .<<. (Int 24)) .<=. (y .<<. (Int 24)))-  Int8LtOp          -> \[r] [x,y] -> PrimInline $ r |= if10 ((x .<<. (Int 24)) .<.  (y .<<. (Int 24)))-  Int8NeOp          -> \[r] [x,y] -> PrimInline $ r |= if10 (x .!==. y)--  Int8SraOp         -> \[r] [x,i]   -> PrimInline $ r |= x .>>. i-  Int8SrlOp         -> \[r] [x,i]   -> PrimInline $ r |= signExtend8 (mask8 x .>>>. i)-  Int8SllOp         -> \[r] [x,i]   -> PrimInline $ r |= signExtend8 (mask8 (x .<<. i))-------------------------------- Word8 ----------------------------------------------  Word8ToWordOp      -> \[r] [x]       -> PrimInline $ r |= mask8 x-  WordToWord8Op      -> \[r] [x]       -> PrimInline $ r |= mask8 x--  Word8AddOp         -> \[r] [x,y]     -> PrimInline $ r |= mask8 (Add x y)-  Word8SubOp         -> \[r] [x,y]     -> PrimInline $ r |= mask8 (Sub x y)-  Word8MulOp         -> \[r] [x,y]     -> PrimInline $ r |= mask8 (Mul x y)-  Word8QuotOp        -> \[r] [x,y]     -> PrimInline $ r |= mask8 (Div x y)-  Word8RemOp         -> \[r] [x,y]     -> PrimInline $ r |= Mod x y-  Word8QuotRemOp     -> \[r1,r2] [x,y] -> PrimInline $ mconcat-                                                  [ r1 |= toI32 (Div x y)-                                                  , r2 |= Mod x y-                                                  ]-  Word8EqOp          -> \[r] [x,y] -> PrimInline $ r |= if10 (x .===. y)-  Word8GeOp          -> \[r] [x,y] -> PrimInline $ r |= if10 (x .>=. y)-  Word8GtOp          -> \[r] [x,y] -> PrimInline $ r |= if10 (x .>. y)-  Word8LeOp          -> \[r] [x,y] -> PrimInline $ r |= if10 (x .<=. y)-  Word8LtOp          -> \[r] [x,y] -> PrimInline $ r |= if10 (x .<. y)-  Word8NeOp          -> \[r] [x,y] -> PrimInline $ r |= if10 (x .!==. y)--  Word8AndOp         -> \[r] [x,y]   -> PrimInline $ r |= BAnd x y-  Word8OrOp          -> \[r] [x,y]   -> PrimInline $ r |= BOr  x y-  Word8XorOp         -> \[r] [x,y]   -> PrimInline $ r |= BXor x y-  Word8NotOp         -> \[r] [x]     -> PrimInline $ r |= BXor x (Int 0xff)--  Word8SllOp         -> \[r] [x,i]   -> PrimInline $ r |= mask8 (x .<<. i)-  Word8SrlOp         -> \[r] [x,i]   -> PrimInline $ r |= x .>>>. i-------------------------------- Int16 ---------------------------------------------  Int16ToIntOp       -> \[r] [x]       -> PrimInline $ r |= x-  IntToInt16Op       -> \[r] [x]       -> PrimInline $ r |= signExtend16 x--  Int16NegOp         -> \[r] [x]       -> PrimInline $ r |= signExtend16 (Negate x)-  Int16AddOp         -> \[r] [x,y]     -> PrimInline $ r |= signExtend16 (Add x y)-  Int16SubOp         -> \[r] [x,y]     -> PrimInline $ r |= signExtend16 (Sub x y)-  Int16MulOp         -> \[r] [x,y]     -> PrimInline $ r |= signExtend16 (Mul x y)-  Int16QuotOp        -> \[r] [x,y]     -> PrimInline $ r |= signExtend16 (quotShortInt 16 x y)-  Int16RemOp         -> \[r] [x,y]     -> PrimInline $ r |= signExtend16 (remShortInt 16 x y)-  Int16QuotRemOp     -> \[r1,r2] [x,y] -> PrimInline $ mconcat-                                                [ r1 |= signExtend16 (quotShortInt 16 x y)-                                                , r2 |= signExtend16 (remShortInt 16 x y)-                                                ]-  Int16EqOp          -> \[r] [x,y] -> PrimInline $ r |= if10 (x .===. y)-  Int16GeOp          -> \[r] [x,y] -> PrimInline $ r |= if10 ((x .<<. (Int 16)) .>=. (y .<<. (Int 16)))-  Int16GtOp          -> \[r] [x,y] -> PrimInline $ r |= if10 ((x .<<. (Int 16)) .>.  (y .<<. (Int 16)))-  Int16LeOp          -> \[r] [x,y] -> PrimInline $ r |= if10 ((x .<<. (Int 16)) .<=. (y .<<. (Int 16)))-  Int16LtOp          -> \[r] [x,y] -> PrimInline $ r |= if10 ((x .<<. (Int 16)) .<.  (y .<<. (Int 16)))-  Int16NeOp          -> \[r] [x,y] -> PrimInline $ r |= if10 (x .!==. y)--  Int16SraOp         -> \[r] [x,i]   -> PrimInline $ r |= x .>>. i-  Int16SrlOp         -> \[r] [x,i]   -> PrimInline $ r |= signExtend16 (mask16 x .>>>. i)-  Int16SllOp         -> \[r] [x,i]   -> PrimInline $ r |= signExtend16 (x .<<. i)-------------------------------- Word16 --------------------------------------------  Word16ToWordOp     -> \[r] [x]   -> PrimInline $ r |= x-  WordToWord16Op     -> \[r] [x]   -> PrimInline $ r |= mask16 x--  Word16AddOp        -> \[r] [x,y] -> PrimInline $ r |= mask16 (Add x y)-  Word16SubOp        -> \[r] [x,y] -> PrimInline $ r |= mask16 (Sub x y)-  Word16MulOp        -> \[r] [x,y] -> PrimInline $ r |= mask16 (Mul x y)-  Word16QuotOp       -> \[r] [x,y] -> PrimInline $ r |= mask16 (Div x y)-  Word16RemOp        -> \[r] [x,y] -> PrimInline $ r |= Mod x y-  Word16QuotRemOp    -> \[r1,r2] [x,y] -> PrimInline $ mconcat-                                                [ r1 |= toI32 (Div x y)-                                                , r2 |= Mod x y-                                                ]-  Word16EqOp         -> \[r] [x,y] -> PrimInline $ r |= if10 (x .===. y)-  Word16GeOp         -> \[r] [x,y] -> PrimInline $ r |= if10 (x .>=. y)-  Word16GtOp         -> \[r] [x,y] -> PrimInline $ r |= if10 (x .>. y)-  Word16LeOp         -> \[r] [x,y] -> PrimInline $ r |= if10 (x .<=. y)-  Word16LtOp         -> \[r] [x,y] -> PrimInline $ r |= if10 (x .<. y)-  Word16NeOp         -> \[r] [x,y] -> PrimInline $ r |= if10 (x .!==. y)--  Word16AndOp        -> \[r] [x,y]   -> PrimInline $ r |= BAnd x y-  Word16OrOp         -> \[r] [x,y]   -> PrimInline $ r |= BOr  x y-  Word16XorOp        -> \[r] [x,y]   -> PrimInline $ r |= BXor x y-  Word16NotOp        -> \[r] [x]     -> PrimInline $ r |= BXor x (Int 0xffff)--  Word16SllOp        -> \[r] [x,i]   -> PrimInline $ r |= mask16 (x .<<. i)-  Word16SrlOp        -> \[r] [x,i]   -> PrimInline $ r |= x .>>>. i-------------------------------- Int32 ----------------------------------------------  Int32ToIntOp       -> \[r] [x]   -> PrimInline $ r |= x-  IntToInt32Op       -> \[r] [x]   -> PrimInline $ r |= x--  Int32NegOp         -> \rs  xs    -> genPrim prof bound ty IntNegOp rs xs-  Int32AddOp         -> \rs  xs    -> genPrim prof bound ty IntAddOp rs xs-  Int32SubOp         -> \rs  xs    -> genPrim prof bound ty IntSubOp rs xs-  Int32MulOp         -> \rs  xs    -> genPrim prof bound ty IntMulOp rs xs-  Int32QuotOp        -> \rs  xs    -> genPrim prof bound ty IntQuotOp rs xs-  Int32RemOp         -> \rs  xs    -> genPrim prof bound ty IntRemOp rs xs-  Int32QuotRemOp     -> \rs  xs    -> genPrim prof bound ty IntQuotRemOp rs xs--  Int32EqOp          -> \rs  xs    -> genPrim prof bound ty IntEqOp rs xs-  Int32GeOp          -> \rs  xs    -> genPrim prof bound ty IntGeOp rs xs-  Int32GtOp          -> \rs  xs    -> genPrim prof bound ty IntGtOp rs xs-  Int32LeOp          -> \rs  xs    -> genPrim prof bound ty IntLeOp rs xs-  Int32LtOp          -> \rs  xs    -> genPrim prof bound ty IntLtOp rs xs-  Int32NeOp          -> \rs  xs    -> genPrim prof bound ty IntNeOp rs xs--  Int32SraOp         -> \rs  xs    -> genPrim prof bound ty IntSraOp rs xs-  Int32SrlOp         -> \rs  xs    -> genPrim prof bound ty IntSrlOp rs xs-  Int32SllOp         -> \rs  xs    -> genPrim prof bound ty IntSllOp rs xs-------------------------------- Word32 ---------------------------------------------  Word32ToWordOp     -> \[r] [x]   -> PrimInline $ r |= x-  WordToWord32Op     -> \[r] [x]   -> PrimInline $ r |= x--  Word32AddOp        -> \rs  xs    -> genPrim prof bound ty WordAddOp rs xs-  Word32SubOp        -> \rs  xs    -> genPrim prof bound ty WordSubOp rs xs-  Word32MulOp        -> \rs  xs    -> genPrim prof bound ty WordMulOp rs xs-  Word32QuotOp       -> \rs  xs    -> genPrim prof bound ty WordQuotOp rs xs-  Word32RemOp        -> \rs  xs    -> genPrim prof bound ty WordRemOp rs xs-  Word32QuotRemOp    -> \rs  xs    -> genPrim prof bound ty WordQuotRemOp rs xs--  Word32EqOp         -> \rs  xs    -> genPrim prof bound ty WordEqOp rs xs-  Word32GeOp         -> \rs  xs    -> genPrim prof bound ty WordGeOp rs xs-  Word32GtOp         -> \rs  xs    -> genPrim prof bound ty WordGtOp rs xs-  Word32LeOp         -> \rs  xs    -> genPrim prof bound ty WordLeOp rs xs-  Word32LtOp         -> \rs  xs    -> genPrim prof bound ty WordLtOp rs xs-  Word32NeOp         -> \rs  xs    -> genPrim prof bound ty WordNeOp rs xs--  Word32AndOp        -> \rs xs     -> genPrim prof bound ty WordAndOp rs xs-  Word32OrOp         -> \rs xs     -> genPrim prof bound ty WordOrOp rs xs-  Word32XorOp        -> \rs xs     -> genPrim prof bound ty WordXorOp rs xs-  Word32NotOp        -> \rs xs     -> genPrim prof bound ty WordNotOp rs xs--  Word32SllOp        -> \rs xs     -> genPrim prof bound ty WordSllOp rs xs-  Word32SrlOp        -> \rs xs     -> genPrim prof bound ty WordSrlOp rs xs-------------------------------- Int64 ----------------------------------------------  Int64ToIntOp      -> \[r] [_h,l] -> PrimInline $ r |= toI32 l--  Int64NegOp        -> \[r_h,r_l] [h,l] ->-      PrimInline $ mconcat-        [ r_l |= toU32 (BNot l + 1)-        , r_h |= toI32 (BNot h + Not r_l)-        ]--  Int64AddOp  -> \[hr,lr] [h0,l0,h1,l1] -> PrimInline $ appT [hr,lr] "h$hs_plusInt64"  [h0,l0,h1,l1]-  Int64SubOp  -> \[hr,lr] [h0,l0,h1,l1] -> PrimInline $ appT [hr,lr] "h$hs_minusInt64" [h0,l0,h1,l1]-  Int64MulOp  -> \[hr,lr] [h0,l0,h1,l1] -> PrimInline $ appT [hr,lr] "h$hs_timesInt64" [h0,l0,h1,l1]-  Int64QuotOp -> \[hr,lr] [h0,l0,h1,l1] -> PrimInline $ appT [hr,lr] "h$hs_quotInt64"  [h0,l0,h1,l1]-  Int64RemOp  -> \[hr,lr] [h0,l0,h1,l1] -> PrimInline $ appT [hr,lr] "h$hs_remInt64"   [h0,l0,h1,l1]--  Int64SllOp  -> \[hr,lr] [h,l,n] -> PrimInline $ appT [hr,lr] "h$hs_uncheckedShiftLLInt64" [h,l,n]-  Int64SraOp  -> \[hr,lr] [h,l,n] -> PrimInline $ appT [hr,lr] "h$hs_uncheckedShiftRAInt64" [h,l,n]-  Int64SrlOp  -> \[hr,lr] [h,l,n] -> PrimInline $ appT [hr,lr] "h$hs_uncheckedShiftRLInt64" [h,l,n]--  Int64ToWord64Op   -> \[r1,r2] [x1,x2] ->-      PrimInline $ mconcat-       [ r1 |= toU32 x1-       , r2 |= x2-       ]-  IntToInt64Op      -> \[r1,r2] [x] ->-      PrimInline $ mconcat-       [ r1 |= if_ (x .<. 0) (-1) 0 -- sign-extension-       , r2 |= toU32 x-       ]--  Int64EqOp -> \[r] [h0,l0,h1,l1] -> PrimInline $ r |= if10 (LAnd (l0 .===. l1) (h0 .===. h1))-  Int64NeOp -> \[r] [h0,l0,h1,l1] -> PrimInline $ r |= if10 (LOr (l0 .!==. l1) (h0 .!==. h1))-  Int64GeOp -> \[r] [h0,l0,h1,l1] -> PrimInline $ r |= if10 (LOr (h0 .>. h1) (LAnd (h0 .===. h1) (l0 .>=. l1)))-  Int64GtOp -> \[r] [h0,l0,h1,l1] -> PrimInline $ r |= if10 (LOr (h0 .>. h1) (LAnd (h0 .===. h1) (l0 .>. l1)))-  Int64LeOp -> \[r] [h0,l0,h1,l1] -> PrimInline $ r |= if10 (LOr (h0 .<. h1) (LAnd (h0 .===. h1) (l0 .<=. l1)))-  Int64LtOp -> \[r] [h0,l0,h1,l1] -> PrimInline $ r |= if10 (LOr (h0 .<. h1) (LAnd (h0 .===. h1) (l0 .<. l1)))-------------------------------- Word64 ---------------------------------------------  Word64ToWordOp    -> \[r] [_x1,x2] -> PrimInline $ r |= x2--  WordToWord64Op    -> \[rh,rl] [x] ->-    PrimInline $ mconcat-     [ rh |= 0-     , rl |= x-     ]--  Word64ToInt64Op   -> \[r1,r2] [x1,x2] ->-    PrimInline $ mconcat-     [ r1 |= toI32 x1-     , r2 |= x2-     ]--  Word64EqOp -> \[r] [h0,l0,h1,l1] -> PrimInline $ r |= if10 (LAnd (l0 .===. l1) (h0 .===. h1))-  Word64NeOp -> \[r] [h0,l0,h1,l1] -> PrimInline $ r |= if10 (LOr (l0 .!==. l1) (h0 .!==. h1))-  Word64GeOp -> \[r] [h0,l0,h1,l1] -> PrimInline $ r |= if10 (LOr (h0 .>. h1) (LAnd (h0 .===. h1) (l0 .>=. l1)))-  Word64GtOp -> \[r] [h0,l0,h1,l1] -> PrimInline $ r |= if10 (LOr (h0 .>. h1) (LAnd (h0 .===. h1) (l0 .>. l1)))-  Word64LeOp -> \[r] [h0,l0,h1,l1] -> PrimInline $ r |= if10 (LOr (h0 .<. h1) (LAnd (h0 .===. h1) (l0 .<=. l1)))-  Word64LtOp -> \[r] [h0,l0,h1,l1] -> PrimInline $ r |= if10 (LOr (h0 .<. h1) (LAnd (h0 .===. h1) (l0 .<. l1)))--  Word64SllOp -> \[hr,lr] [h,l,n] -> PrimInline $ appT [hr,lr] "h$hs_uncheckedShiftLWord64" [h,l,n]-  Word64SrlOp -> \[hr,lr] [h,l,n] -> PrimInline $ appT [hr,lr] "h$hs_uncheckedShiftRWord64" [h,l,n]--  Word64OrOp  -> \[hr,hl] [h0, l0, h1, l1] ->-      PrimInline $ mconcat-        [ hr |= toU32 (BOr h0 h1)-        , hl |= toU32 (BOr l0 l1)-        ]--  Word64AndOp -> \[hr,hl] [h0, l0, h1, l1] ->-      PrimInline $ mconcat-        [ hr |= toU32 (BAnd h0 h1)-        , hl |= toU32 (BAnd l0 l1)-        ]--  Word64XorOp -> \[hr,hl] [h0, l0, h1, l1] ->-      PrimInline $ mconcat-        [ hr |= toU32 (BXor h0 h1)-        , hl |= toU32 (BXor l0 l1)-        ]--  Word64NotOp -> \[hr,hl] [h, l] ->-      PrimInline $ mconcat-        [ hr |= toU32 (BNot h)-        , hl |= toU32 (BNot l)-        ]--  Word64AddOp  -> \[hr,lr] [h0,l0,h1,l1] -> PrimInline $ appT [hr,lr] "h$hs_plusWord64"  [h0,l0,h1,l1]-  Word64SubOp  -> \[hr,lr] [h0,l0,h1,l1] -> PrimInline $ appT [hr,lr] "h$hs_minusWord64" [h0,l0,h1,l1]-  Word64MulOp  -> \[hr,lr] [h0,l0,h1,l1] -> PrimInline $ appT [hr,lr] "h$hs_timesWord64" [h0,l0,h1,l1]-  Word64QuotOp -> \[hr,lr] [h0,l0,h1,l1] -> PrimInline $ appT [hr,lr] "h$hs_quotWord64"  [h0,l0,h1,l1]-  Word64RemOp  -> \[hr,lr] [h0,l0,h1,l1] -> PrimInline $ appT [hr,lr] "h$hs_remWord64"   [h0,l0,h1,l1]-------------------------------- Word -----------------------------------------------  WordAddOp  -> \[r]   [x,y] -> PrimInline $ r |= (x `Add` y) .>>>. zero_-  WordAddCOp -> \[r,c] [x,y] -> PrimInline $-      jVar \t -> mconcat-        [ t |= x `Add` y-        , r |= toU32 t-        , c |= if10 (t .!==. r)-        ]-  WordSubCOp  -> \[r,c] [x,y] ->-      PrimInline $ mconcat-        [ r |= toU32 (Sub x y)-        , c |= if10 (y .>. x)-        ]-  WordAdd2Op    -> \[h,l] [x,y] -> PrimInline $ appT [h,l] "h$wordAdd2" [x,y]-  WordSubOp     -> \  [r] [x,y] -> PrimInline $ r |= toU32 (Sub x y)-  WordMulOp     -> \  [r] [x,y] -> PrimInline $ r |= toU32 (app "Math.imul" [x, y])-  WordMul2Op    -> \[h,l] [x,y] -> PrimInline $ appT [h,l] "h$mul2Word32" [x,y]-  WordQuotOp    -> \  [q] [x,y] -> PrimInline $ q |= app "h$quotWord32" [x,y]-  WordRemOp     -> \  [r] [x,y] -> PrimInline $ r |= app "h$remWord32" [x,y]-  WordQuotRemOp -> \[q,r] [x,y] -> PrimInline $ appT [q,r] "h$quotRemWord32" [x,y]-  WordQuotRem2Op   -> \[q,r] [xh,xl,y] -> PrimInline $ appT [q,r] "h$quotRem2Word32" [xh,xl,y]-  WordAndOp        -> \[r] [x,y] -> PrimInline $ r |= toU32 (BAnd x y)-  WordOrOp         -> \[r] [x,y] -> PrimInline $ r |= toU32 (BOr  x y)-  WordXorOp        -> \[r] [x,y] -> PrimInline $ r |= toU32 (BXor x y)-  WordNotOp        -> \[r] [x]   -> PrimInline $ r |= toU32 (BNot x)-  WordSllOp        -> \[r] [x,y] -> PrimInline $ r |= toU32 (x .<<. y)-  WordSrlOp        -> \[r] [x,y] -> PrimInline $ r |= x .>>>. y-  WordToIntOp      -> \[r] [x]   -> PrimInline $ r |= toI32 x-  WordGtOp         -> \[r] [x,y] -> PrimInline $ r |= if10 (x .>.  y)-  WordGeOp         -> \[r] [x,y] -> PrimInline $ r |= if10 (x .>=. y)-  WordEqOp         -> \[r] [x,y] -> PrimInline $ r |= if10 (x .===. y)-  WordNeOp         -> \[r] [x,y] -> PrimInline $ r |= if10 (x .!==. y)-  WordLtOp         -> \[r] [x,y] -> PrimInline $ r |= if10 (x .<.  y)-  WordLeOp         -> \[r] [x,y] -> PrimInline $ r |= if10 (x .<=. y)-  WordToDoubleOp   -> \[r] [x]   -> PrimInline $ r |= x-  WordToFloatOp    -> \[r] [x]   -> PrimInline $ r |= math_fround [x]-  PopCnt8Op        -> \[r] [x]   -> PrimInline $ r |= var "h$popCntTab" .! (mask8 x)-  PopCnt16Op       -> \[r] [x]   -> PrimInline $ r |= Add (var "h$popCntTab" .! (mask8 x))-                                                      (var "h$popCntTab" .! (mask8 (x .>>>. Int 8)))--  PopCnt32Op  -> \[r] [x]     -> PrimInline $ r |= app "h$popCnt32" [x]-  PopCnt64Op  -> \[r] [x1,x2] -> PrimInline $ r |= app "h$popCnt64" [x1,x2]-  PopCntOp    -> \[r] [x]     -> genPrim prof bound ty PopCnt32Op [r] [x]-  Pdep8Op     -> \[r] [s,m]   -> PrimInline $ r |= app "h$pdep8"  [s,m]-  Pdep16Op    -> \[r] [s,m]   -> PrimInline $ r |= app "h$pdep16" [s,m]-  Pdep32Op    -> \[r] [s,m]   -> PrimInline $ r |= app "h$pdep32" [s,m]-  Pdep64Op    -> \[ra,rb] [sa,sb,ma,mb] -> PrimInline $ appT [ra,rb] "h$pdep64" [sa,sb,ma,mb]-  PdepOp      -> \rs xs                 -> genPrim prof bound ty Pdep32Op rs xs-  Pext8Op     -> \[r] [s,m] -> PrimInline $ r |= app "h$pext8" [s,m]-  Pext16Op    -> \[r] [s,m] -> PrimInline $ r |= app "h$pext16" [s,m]-  Pext32Op    -> \[r] [s,m] -> PrimInline $ r |= app "h$pext32" [s,m]-  Pext64Op    -> \[ra,rb] [sa,sb,ma,mb] -> PrimInline $ appT [ra,rb] "h$pext64" [sa,sb,ma,mb]-  PextOp      -> \rs xs     -> genPrim prof bound ty Pext32Op rs xs--  ClzOp       -> \[r]   [x]     -> PrimInline $ r |= app "h$clz32" [x]-  Clz8Op      -> \[r]   [x]     -> PrimInline $ r |= app "h$clz8"  [x]-  Clz16Op     -> \[r]   [x]     -> PrimInline $ r |= app "h$clz16" [x]-  Clz32Op     -> \[r]   [x]     -> PrimInline $ r |= app "h$clz32" [x]-  Clz64Op     -> \[r]   [x1,x2] -> PrimInline $ r |= app "h$clz64" [x1,x2]-  CtzOp       -> \[r]   [x]     -> PrimInline $ r |= app "h$ctz32" [x]-  Ctz8Op      -> \[r]   [x]     -> PrimInline $ r |= app "h$ctz8"  [x]-  Ctz16Op     -> \[r]   [x]     -> PrimInline $ r |= app "h$ctz16" [x]-  Ctz32Op     -> \[r]   [x]     -> PrimInline $ r |= app "h$ctz32" [x]-  Ctz64Op     -> \[r]   [x1,x2] -> PrimInline $ r |= app "h$ctz64" [x1,x2]--  BSwap16Op   -> \[r] [x]   -> PrimInline $-      r |= BOr ((mask8 x) .<<. (Int 8))-               (mask8 (x .>>>. (Int 8)))-  BSwap32Op   -> \[r] [x]   -> PrimInline $-      r |= toU32 ((x .<<. (Int 24))-            `BOr` ((BAnd x (Int 0xFF00)) .<<. (Int 8))-            `BOr` ((BAnd x (Int 0xFF0000)) .>>. (Int 8))-            `BOr` (x .>>>. (Int 24)))-  BSwap64Op   -> \[r1,r2] [x,y] -> PrimInline $ appT [r1,r2] "h$bswap64" [x,y]-  BSwapOp     -> \[r] [x]       -> genPrim prof bound ty BSwap32Op [r] [x]--  BRevOp      -> \[r] [w] -> genPrim prof bound ty BRev32Op [r] [w]-  BRev8Op     -> \[r] [w] -> PrimInline $ r |= (app "h$reverseWord" [w] .>>>. 24)-  BRev16Op    -> \[r] [w] -> PrimInline $ r |= (app "h$reverseWord" [w] .>>>. 16)-  BRev32Op    -> \[r] [w] -> PrimInline $ r |= app "h$reverseWord" [w]-  BRev64Op    -> \[rh,rl] [h,l] -> PrimInline $ mconcat [ rl |= app "h$reverseWord" [h]-                                                        , rh |= app "h$reverseWord" [l]-                                                        ]-------------------------------- Narrow ---------------------------------------------  Narrow8IntOp    -> \[r] [x] -> PrimInline $ r |= signExtend8  x-  Narrow16IntOp   -> \[r] [x] -> PrimInline $ r |= signExtend16 x-  Narrow32IntOp   -> \[r] [x] -> PrimInline $ r |= toI32  x-  Narrow8WordOp   -> \[r] [x] -> PrimInline $ r |= mask8  x-  Narrow16WordOp  -> \[r] [x] -> PrimInline $ r |= mask16 x-  Narrow32WordOp  -> \[r] [x] -> PrimInline $ r |= toU32  x-------------------------------- Double ---------------------------------------------  DoubleGtOp        -> \[r] [x,y] -> PrimInline $ r |= if10 (x .>.   y)-  DoubleGeOp        -> \[r] [x,y] -> PrimInline $ r |= if10 (x .>=.  y)-  DoubleEqOp        -> \[r] [x,y] -> PrimInline $ r |= if10 (x .===. y)-  DoubleNeOp        -> \[r] [x,y] -> PrimInline $ r |= if10 (x .!==. y)-  DoubleLtOp        -> \[r] [x,y] -> PrimInline $ r |= if10 (x .<.   y)-  DoubleLeOp        -> \[r] [x,y] -> PrimInline $ r |= if10 (x .<=.  y)-  DoubleAddOp       -> \[r] [x,y] -> PrimInline $ r |= Add x y-  DoubleSubOp       -> \[r] [x,y] -> PrimInline $ r |= Sub x y-  DoubleMulOp       -> \[r] [x,y] -> PrimInline $ r |= Mul x y-  DoubleDivOp       -> \[r] [x,y] -> PrimInline $ r |= Div x y-  DoubleNegOp       -> \[r] [x]   -> PrimInline $ r |= Negate x-  DoubleFabsOp      -> \[r] [x]   -> PrimInline $ r |= math_abs [x]-  DoubleToIntOp     -> \[r] [x]   -> PrimInline $ r |= toI32 x-  DoubleToFloatOp   -> \[r] [x]   -> PrimInline $ r |= math_fround [x]-  DoubleExpOp       -> \[r] [x]   -> PrimInline $ r |= math_exp  [x]-  DoubleExpM1Op     -> \[r] [x]   -> PrimInline $ r |= math_expm1 [x]-  DoubleLogOp       -> \[r] [x]   -> PrimInline $ r |= math_log  [x]-  DoubleLog1POp     -> \[r] [x]   -> PrimInline $ r |= math_log1p [x]-  DoubleSqrtOp      -> \[r] [x]   -> PrimInline $ r |= math_sqrt [x]-  DoubleSinOp       -> \[r] [x]   -> PrimInline $ r |= math_sin  [x]-  DoubleCosOp       -> \[r] [x]   -> PrimInline $ r |= math_cos  [x]-  DoubleTanOp       -> \[r] [x]   -> PrimInline $ r |= math_tan  [x]-  DoubleAsinOp      -> \[r] [x]   -> PrimInline $ r |= math_asin [x]-  DoubleAcosOp      -> \[r] [x]   -> PrimInline $ r |= math_acos [x]-  DoubleAtanOp      -> \[r] [x]   -> PrimInline $ r |= math_atan [x]-  DoubleSinhOp      -> \[r] [x]   -> PrimInline $ r |= math_sinh [x]-  DoubleCoshOp      -> \[r] [x]   -> PrimInline $ r |= math_cosh [x]-  DoubleTanhOp      -> \[r] [x]   -> PrimInline $ r |= math_tanh [x]-  DoubleAsinhOp     -> \[r] [x]   -> PrimInline $ r |= math_asinh [x]-  DoubleAcoshOp     -> \[r] [x]   -> PrimInline $ r |= math_acosh [x]-  DoubleAtanhOp     -> \[r] [x]   -> PrimInline $ r |= math_atanh [x]-  DoublePowerOp     -> \[r] [x,y] -> PrimInline $ r |= math_pow [x,y]-  DoubleDecode_2IntOp  -> \[s,h,l,e] [x] -> PrimInline $ appT [s,h,l,e] "h$decodeDouble2Int" [x]-  DoubleDecode_Int64Op -> \[s1,s2,e] [d] -> PrimInline $ appT [e,s1,s2] "h$decodeDoubleInt64" [d]--  DoubleFMAdd  -> unhandledPrimop op-  DoubleFMSub  -> unhandledPrimop op-  DoubleFNMAdd -> unhandledPrimop op-  DoubleFNMSub -> unhandledPrimop op-------------------------------- Float ----------------------------------------------  FloatGtOp         -> \[r] [x,y] -> PrimInline $ r |= if10 (x .>.   y)-  FloatGeOp         -> \[r] [x,y] -> PrimInline $ r |= if10 (x .>=.  y)-  FloatEqOp         -> \[r] [x,y] -> PrimInline $ r |= if10 (x .===. y)-  FloatNeOp         -> \[r] [x,y] -> PrimInline $ r |= if10 (x .!==. y)-  FloatLtOp         -> \[r] [x,y] -> PrimInline $ r |= if10 (x .<.   y)-  FloatLeOp         -> \[r] [x,y] -> PrimInline $ r |= if10 (x .<=.  y)-  FloatAddOp        -> \[r] [x,y] -> PrimInline $ r |= math_fround [Add x y]-  FloatSubOp        -> \[r] [x,y] -> PrimInline $ r |= math_fround [Sub x y]-  FloatMulOp        -> \[r] [x,y] -> PrimInline $ r |= math_fround [Mul x y]-  FloatDivOp        -> \[r] [x,y] -> PrimInline $ r |= math_fround [Div x y]-  FloatNegOp        -> \[r] [x]   -> PrimInline $ r |= Negate x-  FloatFabsOp       -> \[r] [x]   -> PrimInline $ r |= math_abs [x]-  FloatToIntOp      -> \[r] [x]   -> PrimInline $ r |= toI32 x-  FloatExpOp        -> \[r] [x]   -> PrimInline $ r |= math_fround [math_exp [x]]-  FloatExpM1Op      -> \[r] [x]   -> PrimInline $ r |= math_fround [math_expm1 [x]]-  FloatLogOp        -> \[r] [x]   -> PrimInline $ r |= math_fround [math_log [x]]-  FloatLog1POp      -> \[r] [x]   -> PrimInline $ r |= math_fround [math_log1p [x]]-  FloatSqrtOp       -> \[r] [x]   -> PrimInline $ r |= math_fround [math_sqrt [x]]-  FloatSinOp        -> \[r] [x]   -> PrimInline $ r |= math_fround [math_sin [x]]-  FloatCosOp        -> \[r] [x]   -> PrimInline $ r |= math_fround [math_cos [x]]-  FloatTanOp        -> \[r] [x]   -> PrimInline $ r |= math_fround [math_tan [x]]-  FloatAsinOp       -> \[r] [x]   -> PrimInline $ r |= math_fround [math_asin [x]]-  FloatAcosOp       -> \[r] [x]   -> PrimInline $ r |= math_fround [math_acos [x]]-  FloatAtanOp       -> \[r] [x]   -> PrimInline $ r |= math_fround [math_atan [x]]-  FloatSinhOp       -> \[r] [x]   -> PrimInline $ r |= math_fround [math_sinh [x]]-  FloatCoshOp       -> \[r] [x]   -> PrimInline $ r |= math_fround [math_cosh [x]]-  FloatTanhOp       -> \[r] [x]   -> PrimInline $ r |= math_fround [math_tanh [x]]-  FloatAsinhOp      -> \[r] [x]   -> PrimInline $ r |= math_fround [math_asinh [x]]-  FloatAcoshOp      -> \[r] [x]   -> PrimInline $ r |= math_fround [math_acosh [x]]-  FloatAtanhOp      -> \[r] [x]   -> PrimInline $ r |= math_fround [math_atanh [x]]-  FloatPowerOp      -> \[r] [x,y] -> PrimInline $ r |= math_fround [math_pow [x,y]]-  FloatToDoubleOp   -> \[r] [x]   -> PrimInline $ r |= x-  FloatDecode_IntOp -> \[s,e] [x] -> PrimInline $ appT [s,e] "h$decodeFloatInt" [x]--  FloatFMAdd  -> unhandledPrimop op-  FloatFMSub  -> unhandledPrimop op-  FloatFNMAdd -> unhandledPrimop op-  FloatFNMSub -> unhandledPrimop op-------------------------------- Arrays ---------------------------------------------  NewArrayOp           -> \[r] [l,e]   -> PrimInline $ r |= app "h$newArray" [l,e]-  ReadArrayOp          -> \[r] [a,i]   -> PrimInline $ bnd_arr bound a i (r |= a .! i)-  WriteArrayOp         -> \[]  [a,i,v] -> PrimInline $ bnd_arr bound a i (a .! i |= v)-  SizeofArrayOp        -> \[r] [a]     -> PrimInline $ r |= a .^ "length"-  SizeofMutableArrayOp -> \[r] [a]     -> PrimInline $ r |= a .^ "length"-  IndexArrayOp         -> \[r] [a,i]   -> PrimInline $ bnd_arr bound a i (r |= a .! i)-  UnsafeFreezeArrayOp  -> \[r] [a]     -> PrimInline $ r |= a-  UnsafeThawArrayOp    -> \[r] [a]     -> PrimInline $ r |= a-  CopyArrayOp          -> \[] [a,o1,ma,o2,n] ->-    PrimInline-      $ bnd_arr_range bound a o1 n-      $ bnd_arr_range bound ma o2 n-      $ loopBlockS (Int 0) (.<. n) \i ->-      [ ma .! (Add i o2) |= a .! (Add i o1)-      , preIncrS i-      ]-  CopyMutableArrayOp  -> \[]  [a1,o1,a2,o2,n] ->-    PrimInline-      $ bnd_arr_range bound a1 o1 n-      $ bnd_arr_range bound a2 o2 n-      $ appS "h$copyMutableArray" [a1,o1,a2,o2,n]--  CloneArrayOp        -> \[r] [a,start,n]     ->-    PrimInline-      $ bnd_arr_range bound a start n-      $ r |= app "h$sliceArray" [a,start,n]--  CloneMutableArrayOp -> \[r] [a,start,n]     ->-    PrimInline-      $ bnd_arr_range bound a start n-      $ r |= app "h$sliceArray" [a,start,n]--  FreezeArrayOp       -> \[r] [a,start,n]     ->-    PrimInline-      $ bnd_arr_range bound a start n-      $ r |= app "h$sliceArray" [a,start,n]--  ThawArrayOp         -> \[r] [a,start,n]     ->-    PrimInline-      $ bnd_arr_range bound a start n-      $ r |= app "h$sliceArray" [a,start,n]--  CasArrayOp          -> \[s,o] [a,i,old,new] ->-    PrimInline-      $ bnd_arr bound a i-      $ jVar \x -> mconcat-          [ x |= a .! i-          , ifBlockS (x .===. old)-                     [ o |= new-                     , a .! i |= new-                     , s |= zero_-                     ]-                     [ s |= one_-                     , o |= x-                     ]-          ]-------------------------------- Small Arrays ---------------------------------------  NewSmallArrayOp            -> \[a]   [n,e]         -> PrimInline $ a |= app "h$newArray" [n,e]-  ReadSmallArrayOp           -> \[r]   [a,i]         -> PrimInline $ bnd_arr bound a i (r |= a .! i)-  WriteSmallArrayOp          -> \[]    [a,i,e]       -> PrimInline $ bnd_arr bound a i (a .! i |= e)-  SizeofSmallArrayOp         -> \[r]   [a]           -> PrimInline $ r |= a .^ "length"-  SizeofSmallMutableArrayOp  -> \[r]   [a]           -> PrimInline $ r |= a .^ "length"-  IndexSmallArrayOp          -> \[r]   [a,i]         -> PrimInline $ bnd_arr bound a i (r |= a .! i)-  UnsafeFreezeSmallArrayOp   -> \[r]   [a]           -> PrimInline $ r |= a-  UnsafeThawSmallArrayOp     -> \[r]   [a]           -> PrimInline $ r |= a-  CopySmallArrayOp           -> \[]    [s,si,d,di,n] ->-    PrimInline-      $ bnd_arr_range bound s si n-      $ bnd_arr_range bound d di n-      $ loopBlockS (Sub n one_) (.>=. zero_) \i ->-          [ d .! (Add di i) |= s .! (Add si i)-          , postDecrS i-          ]-  CopySmallMutableArrayOp    -> \[]    [s,si,d,di,n] ->-    PrimInline-      $ bnd_arr_range bound s si n-      $ bnd_arr_range bound d di n-      $ appS "h$copyMutableArray" [s,si,d,di,n]--  CloneSmallArrayOp          -> \[r]   [a,o,n]       -> PrimInline $ cloneArray bound r a o n-  CloneSmallMutableArrayOp   -> \[r]   [a,o,n]       -> PrimInline $ cloneArray bound r a o n-  FreezeSmallArrayOp         -> \[r]   [a,o,n]       -> PrimInline $ cloneArray bound r a o n-  ThawSmallArrayOp           -> \[r]   [a,o,n]       -> PrimInline $ cloneArray bound r a o n--  CasSmallArrayOp            -> \[s,o] [a,i,old,new] ->-    PrimInline-      $ bnd_arr bound a i-      $ jVar \x -> mconcat-        [ x |= a .! i-        , ifBlockS (x .===. old)-            [ o |= new-            , a .! i |= new-            , s |= zero_-            ]-            [ s |= one_-            , o |= x-            ]-        ]--------------------------------- Byte Arrays ---------------------------------------  NewByteArrayOp_Char               -> \[r]   [l]        -> PrimInline (newByteArray r l)-  NewPinnedByteArrayOp_Char         -> \[r]   [l]        -> PrimInline (newByteArray r l)-  NewAlignedPinnedByteArrayOp_Char  -> \[r]   [l,_align] -> PrimInline (newByteArray r l)-  MutableByteArrayIsPinnedOp        -> \[r]   [_]        -> PrimInline $ r |= one_-  ByteArrayIsPinnedOp               -> \[r]   [_]        -> PrimInline $ r |= one_-  ByteArrayContents_Char            -> \[a,o] [b]        -> PrimInline $ mconcat [a |= b, o |= zero_]-  MutableByteArrayContents_Char     -> \[a,o] [b]        -> PrimInline $ mconcat [a |= b, o |= zero_]-  ShrinkMutableByteArrayOp_Char     -> \[]    [a,n]      -> PrimInline $ appS "h$shrinkMutableByteArray" [a,n]-  ResizeMutableByteArrayOp_Char     -> \[r]   [a,n]      -> PrimInline $ r |= app "h$resizeMutableByteArray" [a,n]-  UnsafeFreezeByteArrayOp           -> \[a]   [b]        -> PrimInline $ a |= b-  SizeofByteArrayOp                 -> \[r]   [a]        -> PrimInline $ r |= a .^ "len"-  SizeofMutableByteArrayOp          -> \[r]   [a]        -> PrimInline $ r |= a .^ "len"-  GetSizeofMutableByteArrayOp       -> \[r]   [a]        -> PrimInline $ r |= a .^ "len"--  IndexByteArrayOp_Char      -> \[r]   [a,i] -> PrimInline $ bnd_ix8  bound a i $ r |= read_u8  a i-  IndexByteArrayOp_WideChar  -> \[r]   [a,i] -> PrimInline $ bnd_ix32 bound a i $ r |= read_i32 a i-  IndexByteArrayOp_Int       -> \[r]   [a,i] -> PrimInline $ bnd_ix32 bound a i $ r |= read_i32 a i-  IndexByteArrayOp_Word      -> \[r]   [a,i] -> PrimInline $ bnd_ix32 bound a i $ r |= read_u32 a i-  IndexByteArrayOp_Addr      -> \[r,o] [a,i] -> PrimInline $ bnd_ix32 bound a i $ read_addr a i r o-  IndexByteArrayOp_Float     -> \[r]   [a,i] -> PrimInline $ bnd_ix32 bound a i $ r |= read_f32 a i-  IndexByteArrayOp_Double    -> \[r]   [a,i] -> PrimInline $ bnd_ix64 bound a i $ r |= read_f64 a i-  IndexByteArrayOp_StablePtr -> \[r,o] [a,i] -> PrimInline $ bnd_ix32 bound a i $ read_stableptr a i r o-  IndexByteArrayOp_Int8      -> \[r]   [a,i] -> PrimInline $ bnd_ix8  bound a i $ r |= read_i8  a i-  IndexByteArrayOp_Int16     -> \[r]   [a,i] -> PrimInline $ bnd_ix16 bound a i $ r |= read_i16 a i-  IndexByteArrayOp_Int32     -> \[r]   [a,i] -> PrimInline $ bnd_ix32 bound a i $ r |= read_i32 a i-  IndexByteArrayOp_Int64     -> \[h,l] [a,i] -> PrimInline $ bnd_ix64 bound a i $ read_i64 a i h l-  IndexByteArrayOp_Word8     -> \[r]   [a,i] -> PrimInline $ bnd_ix8  bound a i $ r |= read_u8  a i-  IndexByteArrayOp_Word16    -> \[r]   [a,i] -> PrimInline $ bnd_ix16 bound a i $ r |= read_u16 a i-  IndexByteArrayOp_Word32    -> \[r]   [a,i] -> PrimInline $ bnd_ix32 bound a i $ r |= read_u32 a i-  IndexByteArrayOp_Word64    -> \[h,l] [a,i] -> PrimInline $ bnd_ix64 bound a i $ read_u64 a i h l--  ReadByteArrayOp_Char       -> \[r]   [a,i] -> PrimInline $ bnd_ix8 bound a i $ r |= read_u8  a i-  ReadByteArrayOp_WideChar   -> \[r]   [a,i] -> PrimInline $ bnd_ix32 bound a i $ r |= read_i32 a i-  ReadByteArrayOp_Int        -> \[r]   [a,i] -> PrimInline $ bnd_ix32 bound a i $ r |= read_i32 a i-  ReadByteArrayOp_Word       -> \[r]   [a,i] -> PrimInline $ bnd_ix32 bound a i $ r |= read_u32 a i-  ReadByteArrayOp_Addr       -> \[r,o] [a,i] -> PrimInline $ bnd_ix32 bound a i $ read_addr a i r o-  ReadByteArrayOp_Float      -> \[r]   [a,i] -> PrimInline $ bnd_ix32 bound a i $ r |= read_f32 a i-  ReadByteArrayOp_Double     -> \[r]   [a,i] -> PrimInline $ bnd_ix64 bound a i $ r |= read_f64 a i-  ReadByteArrayOp_StablePtr  -> \[r,o] [a,i] -> PrimInline $ bnd_ix32 bound a i $ read_stableptr a i r o-  ReadByteArrayOp_Int8       -> \[r]   [a,i] -> PrimInline $ bnd_ix8  bound a i $ r |= read_i8  a i-  ReadByteArrayOp_Int16      -> \[r]   [a,i] -> PrimInline $ bnd_ix16 bound a i $ r |= read_i16 a i-  ReadByteArrayOp_Int32      -> \[r]   [a,i] -> PrimInline $ bnd_ix32 bound a i $ r |= read_i32 a i-  ReadByteArrayOp_Int64      -> \[h,l] [a,i] -> PrimInline $ bnd_ix64 bound a i $ read_i64 a i h l-  ReadByteArrayOp_Word8      -> \[r]   [a,i] -> PrimInline $ bnd_ix8  bound a i $ r |= read_u8  a i-  ReadByteArrayOp_Word16     -> \[r]   [a,i] -> PrimInline $ bnd_ix16 bound a i $ r |= read_u16 a i-  ReadByteArrayOp_Word32     -> \[r]   [a,i] -> PrimInline $ bnd_ix32 bound a i $ r |= read_u32 a i-  ReadByteArrayOp_Word64     -> \[h,l] [a,i] -> PrimInline $ bnd_ix64 bound a i $ read_u64 a i h l--  WriteByteArrayOp_Char      -> \[] [a,i,e]   -> PrimInline $ bnd_ix8  bound a i $ write_u8  a i e-  WriteByteArrayOp_WideChar  -> \[] [a,i,e]   -> PrimInline $ bnd_ix32 bound a i $ write_i32 a i e-  WriteByteArrayOp_Int       -> \[] [a,i,e]   -> PrimInline $ bnd_ix32 bound a i $ write_i32 a i e-  WriteByteArrayOp_Word      -> \[] [a,i,e]   -> PrimInline $ bnd_ix32 bound a i $ write_u32 a i e-  WriteByteArrayOp_Addr      -> \[] [a,i,r,o] -> PrimInline $ bnd_ix32 bound a i $ write_addr a i r o-  WriteByteArrayOp_Float     -> \[] [a,i,e]   -> PrimInline $ bnd_ix32 bound a i $ write_f32 a i e-  WriteByteArrayOp_Double    -> \[] [a,i,e]   -> PrimInline $ bnd_ix64 bound a i $ write_f64 a i e-  WriteByteArrayOp_StablePtr -> \[] [a,i,r,o] -> PrimInline $ bnd_ix32 bound a i $ write_stableptr a i r o-  WriteByteArrayOp_Int8      -> \[] [a,i,e]   -> PrimInline $ bnd_ix8  bound a i $ write_i8  a i e-  WriteByteArrayOp_Int16     -> \[] [a,i,e]   -> PrimInline $ bnd_ix16 bound a i $ write_i16 a i e-  WriteByteArrayOp_Int32     -> \[] [a,i,e]   -> PrimInline $ bnd_ix32 bound a i $ write_i32 a i e-  WriteByteArrayOp_Int64     -> \[] [a,i,h,l] -> PrimInline $ bnd_ix64 bound a i $ write_i64 a i h l-  WriteByteArrayOp_Word8     -> \[] [a,i,e]   -> PrimInline $ bnd_ix8  bound a i $ write_u8  a i e-  WriteByteArrayOp_Word16    -> \[] [a,i,e]   -> PrimInline $ bnd_ix16 bound a i $ write_u16 a i e-  WriteByteArrayOp_Word32    -> \[] [a,i,e]   -> PrimInline $ bnd_ix32 bound a i $ write_u32 a i e-  WriteByteArrayOp_Word64    -> \[] [a,i,h,l] -> PrimInline $ bnd_ix64 bound a i $ write_u64 a i h l--  CompareByteArraysOp -> \[r] [a1,o1,a2,o2,n] ->-      PrimInline . bnd_ba_range bound a1 o1 n-                 . bnd_ba_range bound a2 o2 n-                 $ r |= app "h$compareByteArrays" [a1,o1,a2,o2,n]--  -- We assume the arrays aren't overlapping since they're of different types-  -- (ByteArray vs MutableByteArray, Addr# vs MutableByteArray#, [Mutable]ByteArray# vs Addr#)-  CopyByteArrayOp                      -> \[] [a1,o1,a2,o2,n] -> copyByteArray False bound a1 o1 a2 o2 n-  CopyAddrToByteArrayOp                -> \[] [a1,o1,a2,o2,n] -> copyByteArray False bound a1 o1 a2 o2 n-  CopyMutableByteArrayToAddrOp         -> \[] [a1,o1,a2,o2,n] -> copyByteArray False bound a1 o1 a2 o2 n-  CopyMutableByteArrayNonOverlappingOp -> \[] [a1,o1,a2,o2,n] -> copyByteArray False bound a1 o1 a2 o2 n-  CopyAddrToAddrNonOverlappingOp       -> \[] [a1,o1,a2,o2,n] -> copyByteArray False bound a1 o1 a2 o2 n-  CopyByteArrayToAddrOp                -> \[] [a1,o1,a2,o2,n] -> copyByteArray False bound a1 o1 a2 o2 n--  CopyMutableByteArrayOp               -> \[] [a1,o1,a2,o2,n] -> copyByteArray True  bound a1 o1 a2 o2 n-  CopyAddrToAddrOp                     -> \[] [a1,o1,a2,o2,n] -> copyByteArray True  bound a1 o1 a2 o2 n--  SetByteArrayOp -> \[] [a,o,n,v] ->-      PrimInline . bnd_ba_range bound a o n $ loopBlockS zero_ (.<. n) \i ->-        [ write_u8 a (Add o i) v-        , postIncrS i-        ]-  SetAddrRangeOp -> \[] xs@[_a,_o,_n,_v] -> genPrim prof bound ty SetByteArrayOp [] xs--  AtomicReadByteArrayOp_Int  -> \[r]   [a,i]   -> PrimInline $ bnd_ix32 bound a i $ r |= read_i32 a i-  AtomicWriteByteArrayOp_Int -> \[]    [a,i,v] -> PrimInline $ bnd_ix32 bound a i $ write_i32 a i v-  FetchAddByteArrayOp_Int    -> \[r]   [a,i,v] -> PrimInline $ bnd_ix32 bound a i $ fetchOpByteArray Add  r a i v-  FetchSubByteArrayOp_Int    -> \[r]   [a,i,v] -> PrimInline $ bnd_ix32 bound a i $ fetchOpByteArray Sub  r a i v-  FetchAndByteArrayOp_Int    -> \[r]   [a,i,v] -> PrimInline $ bnd_ix32 bound a i $ fetchOpByteArray BAnd r a i v-  FetchOrByteArrayOp_Int     -> \[r]   [a,i,v] -> PrimInline $ bnd_ix32 bound a i $ fetchOpByteArray BOr  r a i v-  FetchNandByteArrayOp_Int   -> \[r]   [a,i,v] -> PrimInline $ bnd_ix32 bound a i $ fetchOpByteArray (\x y -> BNot (BAnd x y)) r a i v-  FetchXorByteArrayOp_Int    -> \[r]   [a,i,v] -> PrimInline $ bnd_ix32 bound a i $ fetchOpByteArray BXor r a i v--------------------------------- Addr# --------------------------------------------  AddrAddOp   -> \[a',o'] [a,o,i]         -> PrimInline $ mconcat [a' |= a, o' |= Add o i]-  AddrSubOp   -> \[i]     [_a1,o1,_a2,o2] -> PrimInline $ i |= Sub o1 o2-  AddrRemOp   -> \[r]     [_a,o,i]        -> PrimInline $ r |= Mod o i-  AddrToIntOp -> \[i]     [_a,o]          -> PrimInline $ i |= o -- only usable for comparisons within one range-  IntToAddrOp -> \[a,o]   [i]             -> PrimInline $ mconcat [a |= null_, o |= i]-  AddrGtOp -> \[r] [a1,o1,a2,o2] -> PrimInline $ r |= if10 (app "h$comparePointer" [a1,o1,a2,o2] .>. zero_)-  AddrGeOp -> \[r] [a1,o1,a2,o2] -> PrimInline $ r |= if10 (app "h$comparePointer" [a1,o1,a2,o2] .>=. zero_)-  AddrEqOp -> \[r] [a1,o1,a2,o2] -> PrimInline $ r |= if10 (app "h$comparePointer" [a1,o1,a2,o2] .===. zero_)-  AddrNeOp -> \[r] [a1,o1,a2,o2] -> PrimInline $ r |= if10 (app "h$comparePointer" [a1,o1,a2,o2] .!==. zero_)-  AddrLtOp -> \[r] [a1,o1,a2,o2] -> PrimInline $ r |= if10 (app "h$comparePointer" [a1,o1,a2,o2] .<. zero_)-  AddrLeOp -> \[r] [a1,o1,a2,o2] -> PrimInline $ r |= if10 (app "h$comparePointer" [a1,o1,a2,o2] .<=. zero_)--------------------------------- Addr Indexing: Unboxed Arrays ---------------------  IndexOffAddrOp_Char      -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_u8  a (off8  o i)-  IndexOffAddrOp_WideChar  -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_i32 a (off32 o i)-  IndexOffAddrOp_Int       -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_i32 a (off32 o i)-  IndexOffAddrOp_Word      -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_u32 a (off32 o i)-  IndexOffAddrOp_Addr      -> \[ra,ro] [a,o,i] -> PrimInline $ read_boff_addr a (off32 o i) ra ro-  IndexOffAddrOp_Float     -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_f32 a (off32 o i)-  IndexOffAddrOp_Double    -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_f64 a (off64 o i)-  IndexOffAddrOp_StablePtr -> \[ra,ro] [a,o,i] -> PrimInline $ read_boff_stableptr a (off32 o i) ra ro-  IndexOffAddrOp_Int8      -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_i8  a (off8  o i)-  IndexOffAddrOp_Int16     -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_i16 a (off16 o i)-  IndexOffAddrOp_Int32     -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_i32 a (off32 o i)-  IndexOffAddrOp_Int64     -> \[h,l]   [a,o,i] -> PrimInline $ read_boff_i64 a (off64 o i) h l-  IndexOffAddrOp_Word8     -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_u8  a (off8  o i)-  IndexOffAddrOp_Word16    -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_u16 a (off16 o i)-  IndexOffAddrOp_Word32    -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_u32 a (off32 o i)-  IndexOffAddrOp_Word64    -> \[h,l]   [a,o,i] -> PrimInline $ read_boff_u64 a (off64 o i) h l--  ReadOffAddrOp_Char       -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_u8  a (off8  o i)-  ReadOffAddrOp_WideChar   -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_i32 a (off32 o i)-  ReadOffAddrOp_Int        -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_i32 a (off32 o i)-  ReadOffAddrOp_Word       -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_u32 a (off32 o i)-  ReadOffAddrOp_Addr       -> \[ra,ro] [a,o,i] -> PrimInline $ read_boff_addr a (off32 o i) ra ro-  ReadOffAddrOp_Float      -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_f32 a (off32 o i)-  ReadOffAddrOp_Double     -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_f64 a (off64 o i)-  ReadOffAddrOp_StablePtr  -> \[ra,ro] [a,o,i] -> PrimInline $ read_boff_stableptr a (off32 o i) ra ro-  ReadOffAddrOp_Int8       -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_i8  a (off8  o i)-  ReadOffAddrOp_Int16      -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_i16 a (off16 o i)-  ReadOffAddrOp_Int32      -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_i32 a (off32 o i)-  ReadOffAddrOp_Int64      -> \[h,l]   [a,o,i] -> PrimInline $ read_boff_i64 a (off64 o i) h l-  ReadOffAddrOp_Word8      -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_u8  a (off8  o i)-  ReadOffAddrOp_Word16     -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_u16 a (off16 o i)-  ReadOffAddrOp_Word32     -> \[r]     [a,o,i] -> PrimInline $ r |= read_boff_u32 a (off32 o i)-  ReadOffAddrOp_Word64     -> \[h,l]   [a,o,i] -> PrimInline $ read_boff_u64 a (off64 o i) h l--  WriteOffAddrOp_Char      -> \[] [a,o,i,v]     -> PrimInline $ write_boff_u8  a (off8  o i) v-  WriteOffAddrOp_WideChar  -> \[] [a,o,i,v]     -> PrimInline $ write_boff_i32 a (off32 o i) v-  WriteOffAddrOp_Int       -> \[] [a,o,i,v]     -> PrimInline $ write_boff_i32 a (off32 o i) v-  WriteOffAddrOp_Word      -> \[] [a,o,i,v]     -> PrimInline $ write_boff_u32 a (off32 o i) v-  WriteOffAddrOp_Addr      -> \[] [a,o,i,va,vo] -> PrimInline $ write_boff_addr a (off32 o i) va vo-  WriteOffAddrOp_Float     -> \[] [a,o,i,v]     -> PrimInline $ write_boff_f32 a (off32 o i) v-  WriteOffAddrOp_Double    -> \[] [a,o,i,v]     -> PrimInline $ write_boff_f64 a (off64 o i) v-  WriteOffAddrOp_StablePtr -> \[] [a,o,i,va,vo] -> PrimInline $ write_boff_stableptr a (off32 o i) va vo-  WriteOffAddrOp_Int8      -> \[] [a,o,i,v]     -> PrimInline $ write_boff_i8  a (off8  o i) v-  WriteOffAddrOp_Int16     -> \[] [a,o,i,v]     -> PrimInline $ write_boff_i16 a (off16 o i) v-  WriteOffAddrOp_Int32     -> \[] [a,o,i,v]     -> PrimInline $ write_boff_i32 a (off32 o i) v-  WriteOffAddrOp_Int64     -> \[] [a,o,i,h,l]   -> PrimInline $ write_boff_i64 a (off64 o i) h l-  WriteOffAddrOp_Word8     -> \[] [a,o,i,v]     -> PrimInline $ write_boff_u8  a (off8  o i) v-  WriteOffAddrOp_Word16    -> \[] [a,o,i,v]     -> PrimInline $ write_boff_u16 a (off16 o i) v-  WriteOffAddrOp_Word32    -> \[] [a,o,i,v]     -> PrimInline $ write_boff_u32 a (off32 o i) v-  WriteOffAddrOp_Word64    -> \[] [a,o,i,h,l]   -> PrimInline $ write_boff_u64 a (off64 o i) h l--------------------------------- Mutable varialbes ---------------------------------------  NewMutVarOp           -> \[r] [x]       -> PrimInline $ r |= New (app "h$MutVar" [x])-  ReadMutVarOp          -> \[r] [m]       -> PrimInline $ r |= m .^ "val"-  WriteMutVarOp         -> \[] [m,x]      -> PrimInline $ m .^ "val" |= x-  AtomicModifyMutVar2Op -> \[r1,r2] [m,f] -> PrimInline $ appT [r1,r2] "h$atomicModifyMutVar2" [m,f]-  AtomicModifyMutVar_Op -> \[r1,r2] [m,f] -> PrimInline $ appT [r1,r2] "h$atomicModifyMutVar" [m,f]--  AtomicSwapMutVarOp    -> \[r] [mv,v] -> PrimInline $ mconcat-                                                [ r |= mv .^ "val", mv .^ "val" |= v ]-  CasMutVarOp -> \[status,r] [mv,o,n] -> PrimInline $ ifS (mv .^ "val" .===. o)-                   (mconcat [status |= zero_, r |= n, mv .^ "val" |= n])-                   (mconcat [status |= one_ , r |= mv .^ "val"])--------------------------------- Exceptions ----------------------------------------  CatchOp -> \[_r] [a,handler] -> PRPrimCall $ returnS (app "h$catch" [a, handler])--                             -- fully ignore the result arity as it can use 1 or 2-                             -- slots, depending on the return type.-  RaiseOp                 -> \_r [a] -> PRPrimCall $ returnS (app "h$throw" [a, false_])-  RaiseIOOp               -> \_r [a] -> PRPrimCall $ returnS (app "h$throw" [a, false_])-  RaiseUnderflowOp        -> \_r []  -> PRPrimCall $ returnS (app "h$throw" [var "h$baseZCGHCziExceptionziTypeziunderflowException", false_])-  RaiseOverflowOp         -> \_r []  -> PRPrimCall $ returnS (app "h$throw" [var "h$baseZCGHCziExceptionziTypezioverflowException", false_])-  RaiseDivZeroOp          -> \_r []  -> PRPrimCall $ returnS (app "h$throw" [var "h$baseZCGHCziExceptionziTypezidivZZeroException", false_])-  MaskAsyncExceptionsOp   -> \_r [a] -> PRPrimCall $ returnS (app "h$maskAsync" [a])-  MaskUninterruptibleOp   -> \_r [a] -> PRPrimCall $ returnS (app "h$maskUnintAsync" [a])-  UnmaskAsyncExceptionsOp -> \_r [a] -> PRPrimCall $ returnS (app "h$unmaskAsync" [a])--  MaskStatus -> \[r] [] -> PrimInline $ r |= app "h$maskStatus" []--------------------------------- STM-accessible Mutable Variables  ----------------  AtomicallyOp -> \[_r] [a]   -> PRPrimCall $ returnS (app "h$atomically" [a])-  RetryOp      -> \_r   []    -> PRPrimCall $ returnS (app "h$stmRetry" [])-  CatchRetryOp -> \[_r] [a,b] -> PRPrimCall $ returnS (app "h$stmCatchRetry" [a,b])-  CatchSTMOp   -> \[_r] [a,h] -> PRPrimCall $ returnS (app "h$catchStm" [a,h])-  NewTVarOp    -> \[tv] [v]   -> PrimInline $ tv |= app "h$newTVar" [v]-  ReadTVarOp   -> \[r] [tv]   -> PrimInline $ r |= app "h$readTVar" [tv]-  ReadTVarIOOp -> \[r] [tv]   -> PrimInline $ r |= app "h$readTVarIO" [tv]-  WriteTVarOp  -> \[] [tv,v]  -> PrimInline $ appS "h$writeTVar" [tv,v]--------------------------------- Synchronized Mutable Variables --------------------  NewMVarOp     -> \[r]   []    -> PrimInline $ r |= New (app "h$MVar" [])-  TakeMVarOp    -> \[_r]  [m]   -> PRPrimCall $ returnS (app "h$takeMVar" [m])-  TryTakeMVarOp -> \[r,v] [m]   -> PrimInline $ appT [r,v] "h$tryTakeMVar" [m]-  PutMVarOp     -> \[]    [m,v] -> PRPrimCall $ returnS (app "h$putMVar" [m,v])-  TryPutMVarOp  -> \[r]   [m,v] -> PrimInline $ r |= app "h$tryPutMVar" [m,v]-  ReadMVarOp    -> \[_r]  [m]   -> PRPrimCall $ returnS (app "h$readMVar" [m])-  TryReadMVarOp -> \[r,v] [m]   -> PrimInline $ mconcat-                                                    [ v |= m .^ "val"-                                                    , r |= if01 (v .===. null_)-                                                    ]-  IsEmptyMVarOp -> \[r]   [m]   -> PrimInline $ r |= if10 (m .^ "val" .===. null_)--------------------------------- Delay/Wait Ops -----------------------------------  DelayOp     -> \[] [t]  -> PRPrimCall $ returnS (app "h$delayThread" [t])-  WaitReadOp  -> \[] [fd] -> PRPrimCall $ returnS (app "h$waidRead" [fd])-  WaitWriteOp -> \[] [fd] -> PRPrimCall $ returnS (app "h$waitWrite" [fd])--------------------------------- Concurrency Primitives ---------------------------  ForkOp                 -> \[_tid] [x]    -> PRPrimCall $ returnS (app "h$fork" [x, true_])-  ForkOnOp               -> \[_tid] [_p,x] -> PRPrimCall $ returnS (app "h$fork" [x, true_]) -- ignore processor argument-  KillThreadOp           -> \[] [tid,ex]   -> PRPrimCall $ returnS (app "h$killThread" [tid,ex])-  YieldOp                -> \[] []         -> PRPrimCall $ returnS (app "h$yield" [])-  MyThreadIdOp           -> \[r] []        -> PrimInline $ r |= var "h$currentThread"-  IsCurrentThreadBoundOp -> \[r] []        -> PrimInline $ r |= one_-  NoDuplicateOp          -> \[] []         -> PrimInline mempty -- don't need to do anything as long as we have eager blackholing-  ThreadStatusOp         -> \[stat,cap,locked] [tid] -> PrimInline $ appT [stat, cap, locked] "h$threadStatus" [tid]-  ListThreadsOp          -> \[r] [] -> PrimInline $ appT [r] "h$listThreads" []-  GetThreadLabelOp       -> \[r1, r2] [t]  -> PrimInline $ appT [r1, r2] "h$getThreadLabel" [t]-  LabelThreadOp          -> \[] [t,l]      -> PrimInline $ t .^ "label" |= l--------------------------------- Weak Pointers -------------------------------------  MkWeakOp              -> \[r] [o,b,c] -> PrimInline $ r |= app "h$makeWeak" [o,b,c]-  MkWeakNoFinalizerOp   -> \[r] [o,b]   -> PrimInline $ r |= app "h$makeWeakNoFinalizer" [o,b]-  AddCFinalizerToWeakOp -> \[r] [_a1,_a1o,_a2,_a2o,_i,_a3,_a3o,_w] -> PrimInline $ r |= one_-  DeRefWeakOp           -> \[f,v] [w] -> PrimInline $ mconcat-                                                        [ v |= w .^ "val"-                                                        , f |= if01 (v .===. null_)-                                                        ]-  FinalizeWeakOp     -> \[fl,fin] [w] -> PrimInline $ appT [fin, fl] "h$finalizeWeak" [w]-  TouchOp            -> \[] [_e]      -> PrimInline mempty-  KeepAliveOp        -> \[_r] [x, f]  -> PRPrimCall $ ReturnStat (app "h$keepAlive" [x, f])--------------------------------- Stable pointers and names --------------------------  MakeStablePtrOp -> \[s1,s2] [a] -> PrimInline $ mconcat-      [ s1 |= var "h$stablePtrBuf"-      , s2 |= app "h$makeStablePtr" [a]-      ]-  DeRefStablePtrOp -> \[r] [_s1,s2]            -> PrimInline $ r |= app "h$deRefStablePtr" [s2]-  EqStablePtrOp    -> \[r] [_sa1,sa2,_sb1,sb2] -> PrimInline $ r |= if10 (sa2 .===. sb2)--  MakeStableNameOp  -> \[r] [a] -> PrimInline $ r |= app "h$makeStableName" [a]-  StableNameToIntOp -> \[r] [s] -> PrimInline $ r |= app "h$stableNameInt" [s]-------------------------------- Compact normal form -------------------------------  CompactNewOp           -> \[c] [s]   -> PrimInline $ c |= app "h$compactNew" [s]-  CompactResizeOp        -> \[]  [c,s] -> PrimInline $ appS "h$compactResize" [c,s]-  CompactContainsOp      -> \[r] [c,v] -> PrimInline $ r |= app "h$compactContains" [c,v]-  CompactContainsAnyOp   -> \[r] [v]   -> PrimInline $ r |= app "h$compactContainsAny" [v]-  CompactGetFirstBlockOp -> \[ra,ro,s] [c] ->-    PrimInline $ appT [ra,ro,s] "h$compactGetFirstBlock" [c]-  CompactGetNextBlockOp -> \[ra,ro,s] [c,a,o] ->-    PrimInline $ appT [ra,ro,s] "h$compactGetNextBlock" [c,a,o]-  CompactAllocateBlockOp -> \[ra,ro] [size,sa,so] ->-    PrimInline $ appT [ra,ro] "h$compactAllocateBlock" [size,sa,so]-  CompactFixupPointersOp -> \[c,newroota, newrooto] [blocka,blocko,roota,rooto] ->-    PrimInline $ appT [c,newroota,newrooto] "h$compactFixupPointers" [blocka,blocko,roota,rooto]-  CompactAdd -> \[_r] [c,o] ->-    PRPrimCall $ returnS (app "h$compactAdd" [c,o])-  CompactAddWithSharing -> \[_r] [c,o] ->-    PRPrimCall $ returnS (app "h$compactAddWithSharing" [c,o])-  CompactSize -> \[s] [c] ->-    PrimInline $ s |= app "h$compactSize" [c]-------------------------------- Unsafe pointer equality ----------------------------  ReallyUnsafePtrEqualityOp -> \[r] [p1,p2] -> PrimInline $ r |= if10 (p1 .===. p2)-------------------------------- Parallelism ----------------------------------------  ParOp     -> \[r] [_a] -> PrimInline $ r |= zero_-  SparkOp   -> \[r] [a]  -> PrimInline $ r |= a-  SeqOp     -> \[_r] [e] -> PRPrimCall $ returnS (app "h$e" [e])-  NumSparks -> \[r] []   -> PrimInline $ r |= zero_-------------------------------- Tag to enum stuff ----------------------------------  DataToTagOp -> \[_r] [d] -> PRPrimCall $ mconcat-      [ stack .! PreInc sp |= var "h$dataToTag_e"-      , returnS (app "h$e" [d])-      ]-  TagToEnumOp -> \[r] [tag] -> if-    | isBoolTy ty -> PrimInline $ r |= IfExpr tag true_ false_-    | otherwise   -> PrimInline $ r |= app "h$tagToEnum" [tag]-------------------------------- Bytecode operations --------------------------------  AddrToAnyOp -> \[r] [d,_o] -> PrimInline $ r |= d-------------------------------- Profiling (CCS)  --------------------------------  GetCCSOfOp -> \[a, o] [obj] -> if-    | prof -> PrimInline $ mconcat-        [ a |= if_ (isObject obj)-                    (app "h$buildCCSPtr" [obj .^ "cc"])-                    null_-        , o |= zero_-        ]-    | otherwise -> PrimInline $ mconcat-                    [ a |= null_-                    , o |= zero_-                    ]--  GetCurrentCCSOp -> \[a, o] [_dummy_arg] ->-    let ptr = if prof then app "h$buildCCSPtr" [jCurrentCCS]-                      else null_-    in PrimInline $ mconcat-        [ a |= ptr-        , o |= zero_-        ]--  ClearCCSOp -> \[_r] [x] -> PRPrimCall $ ReturnStat (app "h$clearCCS" [x])-------------------------------- Eventlog ---------------------  TraceEventOp       -> \[] [ed,eo]     -> PrimInline $ appS "h$traceEvent" [ed,eo]-  TraceEventBinaryOp -> \[] [ed,eo,len] -> PrimInline $ appS "h$traceEventBinary" [ed,eo,len]-  TraceMarkerOp      -> \[] [ed,eo]     -> PrimInline $ appS "h$traceMarker" [ed,eo]-------------------------------- ByteArray ---------------------  IndexByteArrayOp_Word8AsChar      -> \[r]   [a,i] -> PrimInline $ bnd_ba8  bound a i $ r |= read_boff_u8  a i-  IndexByteArrayOp_Word8AsWideChar  -> \[r]   [a,i] -> PrimInline $ bnd_ba32 bound a i $ r |= read_boff_i32 a i-  IndexByteArrayOp_Word8AsAddr      -> \[r,o] [a,i] -> PrimInline $ bnd_ba32 bound a i $ read_boff_addr a i r o-  IndexByteArrayOp_Word8AsFloat     -> \[r]   [a,i] -> PrimInline $ bnd_ba32 bound a i $ r |= read_boff_f32 a i-  IndexByteArrayOp_Word8AsDouble    -> \[r]   [a,i] -> PrimInline $ bnd_ba64 bound a i $ r |= read_boff_f64 a i-  IndexByteArrayOp_Word8AsStablePtr -> \[r,o] [a,i] -> PrimInline $ bnd_ba32 bound a i $ read_boff_stableptr a i r o-  IndexByteArrayOp_Word8AsInt16     -> \[r]   [a,i] -> PrimInline $ bnd_ba16 bound a i $ r |= read_boff_i16 a i-  IndexByteArrayOp_Word8AsInt32     -> \[r]   [a,i] -> PrimInline $ bnd_ba32 bound a i $ r |= read_boff_i32 a i-  IndexByteArrayOp_Word8AsInt64     -> \[h,l] [a,i] -> PrimInline $ bnd_ba64 bound a i $ read_boff_i64 a i h l-  IndexByteArrayOp_Word8AsInt       -> \[r]   [a,i] -> PrimInline $ bnd_ba32 bound a i $ r |= read_boff_i32  a i-  IndexByteArrayOp_Word8AsWord16    -> \[r]   [a,i] -> PrimInline $ bnd_ba16 bound a i $ r |= read_boff_u16  a i-  IndexByteArrayOp_Word8AsWord32    -> \[r]   [a,i] -> PrimInline $ bnd_ba32 bound a i $ r |= read_boff_u32  a i-  IndexByteArrayOp_Word8AsWord64    -> \[h,l] [a,i] -> PrimInline $ bnd_ba64 bound a i $ read_boff_u64 a i h l-  IndexByteArrayOp_Word8AsWord      -> \[r]   [a,i] -> PrimInline $ bnd_ba32 bound a i $ r |= read_boff_u32  a i--  ReadByteArrayOp_Word8AsChar       -> \[r]   [a,i] -> PrimInline $ bnd_ba8  bound a i $ r |= read_boff_u8  a i-  ReadByteArrayOp_Word8AsWideChar   -> \[r]   [a,i] -> PrimInline $ bnd_ba32 bound a i $ r |= read_boff_i32 a i-  ReadByteArrayOp_Word8AsAddr       -> \[r,o] [a,i] -> PrimInline $ bnd_ba32 bound a i $ read_boff_addr a i r o-  ReadByteArrayOp_Word8AsFloat      -> \[r]   [a,i] -> PrimInline $ bnd_ba32 bound a i $ r |= read_boff_f32 a i-  ReadByteArrayOp_Word8AsDouble     -> \[r]   [a,i] -> PrimInline $ bnd_ba64 bound a i $ r |= read_boff_f64 a i-  ReadByteArrayOp_Word8AsStablePtr  -> \[r,o] [a,i] -> PrimInline $ bnd_ba32 bound a i $ read_boff_stableptr a i r o-  ReadByteArrayOp_Word8AsInt16      -> \[r]   [a,i] -> PrimInline $ bnd_ba16 bound a i $ r |= read_boff_i16 a i-  ReadByteArrayOp_Word8AsInt32      -> \[r]   [a,i] -> PrimInline $ bnd_ba32 bound a i $ r |= read_boff_i32 a i-  ReadByteArrayOp_Word8AsInt64      -> \[h,l] [a,i] -> PrimInline $ bnd_ba64 bound a i $ read_boff_i64 a i h l-  ReadByteArrayOp_Word8AsInt        -> \[r]   [a,i] -> PrimInline $ bnd_ba32 bound a i $ r |= read_boff_i32  a i-  ReadByteArrayOp_Word8AsWord16     -> \[r]   [a,i] -> PrimInline $ bnd_ba16 bound a i $ r |= read_boff_u16  a i-  ReadByteArrayOp_Word8AsWord32     -> \[r]   [a,i] -> PrimInline $ bnd_ba32 bound a i $ r |= read_boff_u32  a i-  ReadByteArrayOp_Word8AsWord64     -> \[h,l] [a,i] -> PrimInline $ bnd_ba64 bound a i $ read_boff_u64 a i h l-  ReadByteArrayOp_Word8AsWord       -> \[r]   [a,i] -> PrimInline $ bnd_ba32 bound a i $ r |= read_boff_u32  a i--  WriteByteArrayOp_Word8AsChar      -> \[] [a,i,e]   -> PrimInline $ bnd_ba8  bound a i $ write_boff_i8  a i e-  WriteByteArrayOp_Word8AsWideChar  -> \[] [a,i,e]   -> PrimInline $ bnd_ba32 bound a i $ write_boff_i32 a i e-  WriteByteArrayOp_Word8AsAddr      -> \[] [a,i,r,o] -> PrimInline $ bnd_ba32 bound a i $ write_boff_addr a i r o-  WriteByteArrayOp_Word8AsFloat     -> \[] [a,i,e]   -> PrimInline $ bnd_ba32 bound a i $ write_boff_f32 a i e-  WriteByteArrayOp_Word8AsDouble    -> \[] [a,i,e]   -> PrimInline $ bnd_ba64 bound a i $ write_boff_f64 a i e-  WriteByteArrayOp_Word8AsStablePtr -> \[] [a,i,_,o] -> PrimInline $ bnd_ba32 bound a i $ write_boff_i32 a i o-  WriteByteArrayOp_Word8AsInt16     -> \[] [a,i,e]   -> PrimInline $ bnd_ba16 bound a i $ write_boff_i16 a i e-  WriteByteArrayOp_Word8AsInt32     -> \[] [a,i,e]   -> PrimInline $ bnd_ba32 bound a i $ write_boff_i32 a i e-  WriteByteArrayOp_Word8AsInt64     -> \[] [a,i,h,l] -> PrimInline $ bnd_ba64 bound a i $ write_boff_i64 a i h l-  WriteByteArrayOp_Word8AsInt       -> \[] [a,i,e]   -> PrimInline $ bnd_ba32 bound a i $ write_boff_i32 a i e-  WriteByteArrayOp_Word8AsWord16    -> \[] [a,i,e]   -> PrimInline $ bnd_ba16 bound a i $ write_boff_u16 a i e-  WriteByteArrayOp_Word8AsWord32    -> \[] [a,i,e]   -> PrimInline $ bnd_ba32 bound a i $ write_boff_u32 a i e-  WriteByteArrayOp_Word8AsWord64    -> \[] [a,i,h,l] -> PrimInline $ bnd_ba64 bound a i $ write_boff_u64 a i h l-  WriteByteArrayOp_Word8AsWord      -> \[] [a,i,e]   -> PrimInline $ bnd_ba32 bound a i $ write_boff_u32 a i e--  CasByteArrayOp_Int                -> \[r] [a,i,o,n] -> PrimInline $ bnd_ix32 bound a i $ casOp read_i32 write_i32 r a i o n-  CasByteArrayOp_Int8               -> \[r] [a,i,o,n] -> PrimInline $ bnd_ix8  bound a i $ casOp read_i8  write_i8  r a i o n-  CasByteArrayOp_Int16              -> \[r] [a,i,o,n] -> PrimInline $ bnd_ix16 bound a i $ casOp read_i16 write_i16 r a i o n-  CasByteArrayOp_Int32              -> \[r] [a,i,o,n] -> PrimInline $ bnd_ix32 bound a i $ casOp read_i32 write_i32 r a i o n--  CasByteArrayOp_Int64              -> \[rh,rl] [a,i,oh,ol,nh,nl] -> PrimInline $ bnd_ix64 bound a i $ casOp2 read_i64 write_i64 (rh,rl) a i (oh,ol) (nh,nl)--  CasAddrOp_Addr                    -> \[ra,ro] [a,o,oa,oo,na,no] -> PrimInline $ casOp2 read_boff_addr write_boff_addr (ra,ro) a o (oa,oo) (na,no)-  CasAddrOp_Word                    -> \[r] [a,o,old,new] -> PrimInline $ casOp read_u32 write_u32 r a o old new-  CasAddrOp_Word8                   -> \[r] [a,o,old,new] -> PrimInline $ casOp read_u8  write_u8  r a o old new-  CasAddrOp_Word16                  -> \[r] [a,o,old,new] -> PrimInline $ casOp read_u16 write_u16 r a o old new-  CasAddrOp_Word32                  -> \[r] [a,o,old,new] -> PrimInline $ casOp read_u32 write_u32 r a o old new-  CasAddrOp_Word64                  -> \[rh,rl] [a,o,oh,ol,nh,nl] -> PrimInline $ casOp2 read_u64 write_u64 (rh,rl) a o (oh,ol) (nh,nl)--  FetchAddAddrOp_Word               -> \[r] [a,o,v] -> PrimInline $ fetchOpAddr Add   r a o v-  FetchSubAddrOp_Word               -> \[r] [a,o,v] -> PrimInline $ fetchOpAddr Sub   r a o v-  FetchAndAddrOp_Word               -> \[r] [a,o,v] -> PrimInline $ fetchOpAddr BAnd  r a o v-  FetchNandAddrOp_Word              -> \[r] [a,o,v] -> PrimInline $ fetchOpAddr ((BNot .) . BAnd) r a o v-  FetchOrAddrOp_Word                -> \[r] [a,o,v] -> PrimInline $ fetchOpAddr BOr   r a o v-  FetchXorAddrOp_Word               -> \[r] [a,o,v] -> PrimInline $ fetchOpAddr BXor  r a o v--  InterlockedExchange_Addr          -> \[ra,ro] [a1,o1,a2,o2] -> PrimInline $ mconcat-                                          [ read_boff_addr a1 o1 ra ro-                                          , write_boff_addr a1 o1 a2 o2-                                          ]-  InterlockedExchange_Word          -> \[r] [a,o,w] -> PrimInline $ mconcat-                                          [ r |= read_boff_u32 a o-                                          , write_boff_u32 a o w-                                          ]--  ShrinkSmallMutableArrayOp_Char    -> \[]  [a,n] -> PrimInline $ appS "h$shrinkMutableCharArray" [a,n]-  GetSizeofSmallMutableArrayOp      -> \[r] [a]   -> PrimInline $ r |= a .^ "length"--  AtomicReadAddrOp_Word             -> \[r] [a,o]   -> PrimInline $ r |= read_boff_u32 a o-  AtomicWriteAddrOp_Word            -> \[]  [a,o,w] -> PrimInline $ write_boff_u32 a o w--------------------------------- Unhandled primops ---------------------  NewPromptTagOp                    -> unhandledPrimop op-  PromptOp                          -> unhandledPrimop op-  Control0Op                        -> unhandledPrimop op--  NewIOPortOp                       -> unhandledPrimop op-  ReadIOPortOp                      -> unhandledPrimop op-  WriteIOPortOp                     -> unhandledPrimop op--  GetSparkOp                        -> unhandledPrimop op-  AnyToAddrOp                       -> unhandledPrimop op-  MkApUpd0_Op                       -> unhandledPrimop op-  NewBCOOp                          -> unhandledPrimop op-  UnpackClosureOp                   -> unhandledPrimop op-  ClosureSizeOp                     -> unhandledPrimop op-  GetApStackValOp                   -> unhandledPrimop op-  WhereFromOp                       -> unhandledPrimop op -- should be easily implementable with o.f.n--  SetThreadAllocationCounter        -> unhandledPrimop op--------------------------------- Vector -------------------------------------------- For now, vectors are unsupported on the JS backend. Simply put, they do not--- make much sense to support given support for arrays and lack of SIMD support--- in JS. We could try to roll something special but we would not be able to--- give any performance guarentees to the user and so we leave these has--- unhandled for now.-  VecBroadcastOp _ _ _              -> unhandledPrimop op-  VecPackOp _ _ _                   -> unhandledPrimop op-  VecUnpackOp _ _ _                 -> unhandledPrimop op-  VecInsertOp _ _ _                 -> unhandledPrimop op-  VecAddOp _ _ _                    -> unhandledPrimop op-  VecSubOp _ _ _                    -> unhandledPrimop op-  VecMulOp _ _ _                    -> unhandledPrimop op-  VecDivOp _ _ _                    -> unhandledPrimop op-  VecQuotOp _ _ _                   -> unhandledPrimop op-  VecRemOp _ _ _                    -> unhandledPrimop op-  VecNegOp _ _ _                    -> unhandledPrimop op-  VecIndexByteArrayOp _ _ _         -> unhandledPrimop op-  VecReadByteArrayOp _ _ _          -> unhandledPrimop op-  VecWriteByteArrayOp _ _ _         -> unhandledPrimop op-  VecIndexOffAddrOp _ _ _           -> unhandledPrimop op-  VecReadOffAddrOp _ _ _            -> unhandledPrimop op-  VecWriteOffAddrOp _ _ _           -> unhandledPrimop op--  VecIndexScalarByteArrayOp _ _ _   -> unhandledPrimop op-  VecReadScalarByteArrayOp _ _ _    -> unhandledPrimop op-  VecWriteScalarByteArrayOp _ _ _   -> unhandledPrimop op-  VecIndexScalarOffAddrOp _ _ _     -> unhandledPrimop op-  VecReadScalarOffAddrOp _ _ _      -> unhandledPrimop op-  VecWriteScalarOffAddrOp _ _ _     -> unhandledPrimop op--  PrefetchByteArrayOp3              -> noOp-  PrefetchMutableByteArrayOp3       -> noOp-  PrefetchAddrOp3                   -> noOp-  PrefetchValueOp3                  -> noOp-  PrefetchByteArrayOp2              -> noOp-  PrefetchMutableByteArrayOp2       -> noOp-  PrefetchAddrOp2                   -> noOp-  PrefetchValueOp2                  -> noOp-  PrefetchByteArrayOp1              -> noOp-  PrefetchMutableByteArrayOp1       -> noOp-  PrefetchAddrOp1                   -> noOp-  PrefetchValueOp1                  -> noOp-  PrefetchByteArrayOp0              -> noOp-  PrefetchMutableByteArrayOp0       -> noOp-  PrefetchAddrOp0                   -> noOp-  PrefetchValueOp0                  -> noOp--unhandledPrimop :: PrimOp -> [JExpr] -> [JExpr] -> PrimRes-unhandledPrimop op rs as = PrimInline $ mconcat-  [ appS "h$log" [toJExpr $ mconcat-      [ "warning, unhandled primop: "-      , renderWithContext defaultSDocContext (ppr op)-      , " "-      , show (length rs, length as)-      ]]-  , appS (mkFastString $ "h$primop_" ++ zEncodeString (renderWithContext defaultSDocContext (ppr op))) as-    -- copyRes-  , mconcat $ zipWith (\r reg -> r |= toJExpr reg) rs (enumFrom Ret1)-  ]---- | A No Op, used for primops the JS platform cannot or do not support. For--- example, the prefetching primops do not make sense on the JS platform because--- we do not have enough control over memory to provide any kind of prefetching--- mechanism. Hence, these are NoOps.-noOp :: Foldable f => f a -> f a -> PrimRes-noOp = const . const $ PrimInline mempty---- tuple returns-appT :: [JExpr] -> FastString -> [JExpr] -> JStat-appT []     f xs = appS f xs-appT (r:rs) f xs = mconcat-  [ r |= app f xs-  , mconcat (zipWith (\r ret -> r |= toJExpr ret) rs (enumFrom Ret1))-  ]------------------------------------------------- ByteArray indexing------------------------------------------------- For every ByteArray, the RTS creates the following views:---  i3: Int32 view---  u8: Word8 view---  u1: Word16 view---  f3: Float32 view---  f6: Float64 view---  dv: generic DataView--- It seems a bit weird to mix Int and Word views like this, but perhaps they--- are the more common.------ See 'h$newByteArray' in 'ghc/rts/js/mem.js' for details.------ Note that *byte* indexing can only be done with the generic DataView. Use--- read_boff_* and write_boff_* for this.------ Other read_* and write_* helpers directly use the more specific views.--- Prefer using them over idx_* to make your intent clearer.--idx_i32, idx_u8, idx_u16, idx_f64, idx_f32 :: JExpr -> JExpr -> JExpr-idx_i32 a i = IdxExpr (a .^ "i3") i-idx_u8  a i = IdxExpr (a .^ "u8") i-idx_u16 a i = IdxExpr (a .^ "u1") i-idx_f64 a i = IdxExpr (a .^ "f6") i-idx_f32 a i = IdxExpr (a .^ "f3") i--read_u8 :: JExpr -> JExpr -> JExpr-read_u8 a i = idx_u8 a i--read_u16 :: JExpr -> JExpr -> JExpr-read_u16 a i = idx_u16 a i--read_u32 :: JExpr -> JExpr -> JExpr-read_u32 a i = toU32 (idx_i32 a i)--read_i8 :: JExpr -> JExpr -> JExpr-read_i8 a i = signExtend8 (idx_u8 a i)--read_i16 :: JExpr -> JExpr -> JExpr-read_i16 a i = signExtend16 (idx_u16 a i)--read_i32 :: JExpr -> JExpr -> JExpr-read_i32 a i = idx_i32 a i--read_f32 :: JExpr -> JExpr -> JExpr-read_f32 a i = idx_f32 a i--read_f64 :: JExpr -> JExpr -> JExpr-read_f64 a i = idx_f64 a i--read_u64 :: JExpr -> JExpr -> JExpr -> JExpr -> JStat-read_u64 a i rh rl = mconcat-  [ rl |= read_u32 a (i .<<. 1)-  , rh |= read_u32 a (Add 1 (i .<<. 1))-  ]--read_i64 :: JExpr -> JExpr -> JExpr -> JExpr -> JStat-read_i64 a i rh rl = mconcat-  [ rl |= read_u32 a (i .<<. 1)-  , rh |= read_i32 a (Add 1 (i .<<. 1))-  ]------------------------------------------- Addr#-----------------------------------------write_addr :: JExpr -> JExpr -> JExpr -> JExpr -> JStat-write_addr a i r o = mconcat-  [ write_i32 a i o-    -- create the hidden array for arrays if it doesn't exist-  , ifS (Not (a .^ "arr")) (a .^ "arr" |= ValExpr (JList [])) mempty-  , a .^ "arr" .! (i .<<. 2) |= r-  ]--read_addr :: JExpr -> JExpr -> JExpr -> JExpr -> JStat-read_addr a i r o = mconcat-  [ o |= read_i32 a i-  , r |= if_ ((a .^ "arr") .&&. (a .^ "arr" .! (i .<<. 2)))-            (a .^ "arr" .! (i .<<. 2))-            null_-  ]--read_boff_addr :: JExpr -> JExpr -> JExpr -> JExpr -> JStat-read_boff_addr a i r o = mconcat-  [ o |= read_boff_i32 a i-  , r |= if_ ((a .^ "arr") .&&. (a .^ "arr" .! i))-            (a .^ "arr" .! i)-            null_-  ]--write_boff_addr :: JExpr -> JExpr -> JExpr -> JExpr -> JStat-write_boff_addr a i r o = mconcat-  [ write_boff_i32 a i o-    -- create the hidden array for arrays if it doesn't exist-  , ifS (Not (a .^ "arr")) (a .^ "arr" |= ValExpr (JList [])) mempty-  , a .^ "arr" .! i |= r-  ]-------------------------------------------- StablePtr-----------------------------------------read_stableptr :: JExpr -> JExpr -> JExpr -> JExpr -> JStat-read_stableptr a i r o = mconcat-  [ r |= var "h$stablePtrBuf" -- stable pointers are always in this array-  , o |= read_i32 a i-  ]--read_boff_stableptr :: JExpr -> JExpr -> JExpr -> JExpr -> JStat-read_boff_stableptr a i r o = mconcat-  [ r |= var "h$stablePtrBuf" -- stable pointers are always in this array-  , o |= read_boff_i32 a i-  ]--write_stableptr :: JExpr -> JExpr -> JExpr -> JExpr -> JStat-write_stableptr a i _r o = write_i32 a i o-  -- don't store "r" as it must be h$stablePtrBuf--write_boff_stableptr :: JExpr -> JExpr -> JExpr -> JExpr -> JStat-write_boff_stableptr a i _r o = write_boff_i32 a i o-  -- don't store "r" as it must be h$stablePtrBuf--write_u8 :: JExpr -> JExpr -> JExpr -> JStat-write_u8 a i v = idx_u8 a i |= v--write_u16 :: JExpr -> JExpr -> JExpr -> JStat-write_u16 a i v = idx_u16 a i |= v--write_u32 :: JExpr -> JExpr -> JExpr -> JStat-write_u32 a i v = idx_i32 a i |= v--write_i8 :: JExpr -> JExpr -> JExpr -> JStat-write_i8 a i v = idx_u8 a i |= v--write_i16 :: JExpr -> JExpr -> JExpr -> JStat-write_i16 a i v = idx_u16 a i |= v--write_i32 :: JExpr -> JExpr -> JExpr -> JStat-write_i32 a i v = idx_i32 a i |= v--write_f32 :: JExpr -> JExpr -> JExpr -> JStat-write_f32 a i v = idx_f32 a i |= v--write_f64 :: JExpr -> JExpr -> JExpr -> JStat-write_f64 a i v = idx_f64 a i |= v--write_u64 :: JExpr -> JExpr -> JExpr -> JExpr -> JStat-write_u64 a i h l = mconcat-  [ write_u32 a (i .<<. 1)         l-  , write_u32 a (Add 1 (i .<<. 1)) h-  ]--write_i64 :: JExpr -> JExpr -> JExpr -> JExpr -> JStat-write_i64 a i h l = mconcat-  [ write_u32 a (i .<<. 1)         l-  , write_i32 a (Add 1 (i .<<. 1)) h-  ]---- Data View helper functions: byte indexed!------ The argument list consists of the array @a@, the index @i@, and the new value--- to set (in the case of a setter) @v@.--write_boff_i8, write_boff_u8, write_boff_i16, write_boff_u16, write_boff_i32, write_boff_u32, write_boff_f32, write_boff_f64 :: JExpr -> JExpr -> JExpr -> JStat-write_boff_i8  a i v = write_i8 a i v-write_boff_u8  a i v = write_u8 a i v-write_boff_i16 a i v = ApplStat (a .^ "dv" .^ "setInt16"  ) [i, v, true_]-write_boff_u16 a i v = ApplStat (a .^ "dv" .^ "setUint16" ) [i, v, true_]-write_boff_i32 a i v = ApplStat (a .^ "dv" .^ "setInt32"  ) [i, v, true_]-write_boff_u32 a i v = ApplStat (a .^ "dv" .^ "setUint32" ) [i, v, true_]-write_boff_f32 a i v = ApplStat (a .^ "dv" .^ "setFloat32") [i, v, true_]-write_boff_f64 a i v = ApplStat (a .^ "dv" .^ "setFloat64") [i, v, true_]--write_boff_i64, write_boff_u64 :: JExpr -> JExpr -> JExpr -> JExpr -> JStat-write_boff_i64 a i h l = mconcat-  [ write_boff_i32 a (Add i (Int 4)) h-  , write_boff_u32 a i l-  ]-write_boff_u64 a i h l = mconcat-  [ write_boff_u32 a (Add i (Int 4)) h-  , write_boff_u32 a i l-  ]--read_boff_i8, read_boff_u8, read_boff_i16, read_boff_u16, read_boff_i32, read_boff_u32, read_boff_f32, read_boff_f64 :: JExpr -> JExpr -> JExpr-read_boff_i8  a i = read_i8 a i-read_boff_u8  a i = read_u8 a i-read_boff_i16 a i = ApplExpr (a .^ "dv" .^ "getInt16"  ) [i, true_]-read_boff_u16 a i = ApplExpr (a .^ "dv" .^ "getUint16" ) [i, true_]-read_boff_i32 a i = ApplExpr (a .^ "dv" .^ "getInt32"  ) [i, true_]-read_boff_u32 a i = ApplExpr (a .^ "dv" .^ "getUint32" ) [i, true_]-read_boff_f32 a i = ApplExpr (a .^ "dv" .^ "getFloat32") [i, true_]-read_boff_f64 a i = ApplExpr (a .^ "dv" .^ "getFloat64") [i, true_]--read_boff_i64 :: JExpr -> JExpr -> JExpr -> JExpr -> JStat-read_boff_i64 a i rh rl = mconcat-  [ rh |= read_boff_i32 a (Add i (Int 4))-  , rl |= read_boff_u32 a i-  ]--read_boff_u64 :: JExpr -> JExpr -> JExpr -> JExpr -> JStat-read_boff_u64 a i rh rl = mconcat-  [ rh |= read_boff_u32 a (Add i (Int 4))-  , rl |= read_boff_u32 a i-  ]--fetchOpByteArray :: (JExpr -> JExpr -> JExpr) -> JExpr -> JExpr -> JExpr -> JExpr -> JStat-fetchOpByteArray op tgt src i v = mconcat-  [ tgt |= read_i32 src i-  , write_i32 src i (op tgt v)-  ]--fetchOpAddr :: (JExpr -> JExpr -> JExpr) -> JExpr -> JExpr -> JExpr -> JExpr -> JStat-fetchOpAddr op tgt src i v = mconcat-  [ tgt |= read_boff_u32 src i-  , write_boff_u32 src i (op tgt v)-  ]--casOp-  :: (JExpr -> JExpr -> JExpr)          -- read-  -> (JExpr -> JExpr -> JExpr -> JStat) -- write-  -> JExpr                     -- target register to store result-  -> JExpr                     -- source array-  -> JExpr                     -- index-  -> JExpr                     -- old value to compare-  -> JExpr                     -- new value to write-  -> JStat-casOp read write tgt src i old new = mconcat-  [ tgt |= read src i-  , ifS (tgt .===. old)-        (write src i new)-         mempty-  ]--casOp2-  :: (JExpr -> JExpr -> JExpr -> JExpr -> JStat) -- read-  -> (JExpr -> JExpr -> JExpr -> JExpr -> JStat) -- write-  -> (JExpr,JExpr)             -- target registers to store result-  -> JExpr                     -- source array-  -> JExpr                     -- index-  -> (JExpr,JExpr)             -- old value to compare-  -> (JExpr,JExpr)             -- new value to write-  -> JStat-casOp2 read write (tgt1,tgt2) src i (old1,old2) (new1,new2) = mconcat-  [ read src i tgt1 tgt2-  , ifS ((tgt2 .===. old2) .&&. (tgt1 .===. old1))-        (write src i new1 new2)-         mempty-  ]-------------------------------------------------------------------------------------                            Lifted Arrays------------------------------------------------------------------------------------ | lifted arrays-cloneArray :: Bool -> JExpr -> JExpr -> JExpr -> JExpr -> JStat-cloneArray bound_check tgt src start len =-  bnd_arr_range bound_check src start len-  $ mconcat-      [ tgt |= ApplExpr (src .^ "slice") [start, Add len start]-      , tgt .^ closureMeta_   |= zero_-      , tgt .^ "__ghcjsArray" |= true_-      ]--newByteArray :: JExpr -> JExpr -> JStat-newByteArray tgt len =-  tgt |= app "h$newByteArray" [len]---- | Check that index is positive and below a max value. Halt the process with--- error code 134 otherwise. This is used to implement -fcheck-prim-bounds-check_bound-  :: JExpr -- ^ Max index expression-  -> Bool  -- ^ Should we do bounds checking?-  -> JExpr -- ^ Index-  -> JStat -- ^ Result-  -> JStat-check_bound _         False _ r = r-check_bound max_index True  i r = mconcat-  [ jwhenS ((i .<. zero_) .||. (i .>=. max_index)) $-      returnS (app "h$exitProcess" [Int 134])-  , r-  ]---- | Bounds checking using ".length" property (Arrays)-bnd_arr-  :: Bool  -- ^ Should we do bounds checking?-  -> JExpr -- ^ Array-  -> JExpr -- ^ Index-  -> JStat -- ^ Result-  -> JStat-bnd_arr do_check arr = check_bound (arr .^ "length") do_check---- | Range bounds checking using ".length" property (Arrays)------ Empty ranges trivially pass the check-bnd_arr_range-  :: Bool  -- ^ Should we do bounds checking?-  -> JExpr -- ^ Array-  -> JExpr -- ^ Index-  -> JExpr -- ^ Range size-  -> JStat -- ^ Result-  -> JStat-bnd_arr_range False _arr _i _n r = r-bnd_arr_range True   arr  i  n r =-  ifS (n .<. zero_) (returnS $ app "h$exitProcess" [Int 134]) $-  -- Empty ranges trivially pass the check-  ifS (n .===. zero_)-      r-      (bnd_arr True arr i $ bnd_arr True arr (Add i (Sub n 1)) r)---- | Bounds checking using ".len" property (ByteArrays)-bnd_ba-  :: Bool  -- ^ Should we do bounds checking?-  -> JExpr -- ^ Array-  -> JExpr -- ^ Index-  -> JStat -- ^ Result-  -> JStat-bnd_ba do_check arr = check_bound (arr .^ "len") do_check---- | ByteArray bounds checking (byte offset, 8-bit value)-bnd_ba8 :: Bool -> JExpr -> JExpr -> JStat -> JStat-bnd_ba8 = bnd_ba---- | ByteArray bounds checking (byte offset, 16-bit value)-bnd_ba16 :: Bool -> JExpr -> JExpr -> JStat -> JStat-bnd_ba16 do_check arr idx r =-  -- check that idx non incremented is in range:-  -- (idx + 1) may be in range while idx isn't-  bnd_ba do_check arr idx-  $ bnd_ba do_check arr (Add idx 1) r---- | ByteArray bounds checking (byte offset, 32-bit value)-bnd_ba32 :: Bool -> JExpr -> JExpr -> JStat -> JStat-bnd_ba32 do_check arr idx r =-  -- check that idx non incremented is in range:-  -- (idx + 3) may be in range while idx isn't-  bnd_ba do_check arr idx-  $ bnd_ba do_check arr (Add idx 3) r---- | ByteArray bounds checking (byte offset, 64-bit value)-bnd_ba64 :: Bool -> JExpr -> JExpr -> JStat -> JStat-bnd_ba64 do_check arr idx r =-  -- check that idx non incremented is in range:-  -- (idx + 7) may be in range while idx isn't-  bnd_ba do_check arr idx-  $ bnd_ba do_check arr (Add idx 7) r---- | ByteArray bounds checking (8-bit offset, 8-bit value)-bnd_ix8 :: Bool -> JExpr -> JExpr -> JStat -> JStat-bnd_ix8 = bnd_ba8---- | ByteArray bounds checking (16-bit offset, 16-bit value)-bnd_ix16 :: Bool -> JExpr -> JExpr -> JStat -> JStat-bnd_ix16 do_check arr idx r = bnd_ba16 do_check arr (idx .<<. 1) r---- | ByteArray bounds checking (32-bit offset, 32-bit value)-bnd_ix32 :: Bool -> JExpr -> JExpr -> JStat -> JStat-bnd_ix32 do_check arr idx r = bnd_ba32 do_check arr (idx .<<. 2) r---- | ByteArray bounds checking (64-bit offset, 64-bit value)-bnd_ix64 :: Bool -> JExpr -> JExpr -> JStat -> JStat-bnd_ix64 do_check arr idx r = bnd_ba64 do_check arr (idx .<<. 3) r---- | Bounds checking on a range and using ".len" property (ByteArrays)------ Empty ranges trivially pass the check-bnd_ba_range-  :: Bool  -- ^ Should we do bounds checking?-  -> JExpr -- ^ Array-  -> JExpr -- ^ Index-  -> JExpr -- ^ Range size-  -> JStat -- ^ Result-  -> JStat-bnd_ba_range False _  _ _ r = r-bnd_ba_range True  xs i n r =-  ifS (n .<. zero_) (returnS $ app "h$exitProcess" [Int 134]) $-  -- Empty ranges trivially pass the check-  ifS (n .===. zero_)-      r-      (bnd_ba True xs (Add i (Sub n 1)) (bnd_ba True xs i r))--checkOverlapByteArray-  :: Bool  -- ^ Should we do bounds checking?-  -> JExpr -- ^ First array-  -> JExpr -- ^ First offset-  -> JExpr -- ^ Second array-  -> JExpr -- ^ Second offset-  -> JExpr -- ^ Range size-  -> JStat -- ^ Result-  -> JStat-checkOverlapByteArray False _ _ _ _ _ r    = r-checkOverlapByteArray True a1 o1 a2 o2 n r =-  ifS (app "h$checkOverlapByteArray" [a1, o1, a2, o2, n])-    r-    (returnS $ app "h$exitProcess" [Int 134])--copyByteArray :: Bool -> Bool -> JExpr -> JExpr -> JExpr -> JExpr -> JExpr -> PrimRes-copyByteArray allow_overlap bound a1 o1 a2 o2 n = PrimInline $ check $ appS "h$copyMutableByteArray" [a1,o1,a2,o2,n]-  where-      check = bnd_ba_range bound a1 o1 n-              . bnd_ba_range bound a2 o2 n-              . (if not allow_overlap then checkOverlapByteArray bound a1 o1 a2 o2 n else id)---- e|0 (32 bit signed integer truncation) required because of JS numbers. e|0--- converts e to an Int32. Note that e|0 _is still a Double_ because JavaScript.--- So (x|0) * (y|0) can still return values outside of the Int32 range. You have--- been warned!-toI32 :: JExpr -> JExpr-toI32 e = BOr e zero_---- e>>>0  (32 bit unsigned integer truncation)--- required because of JS numbers. e>>>0 converts e to a Word32--- so  (-2147483648)       >>> 0  = 2147483648--- and ((-2147483648) >>>0) | 0   = -2147483648-toU32 :: JExpr -> JExpr-toU32 e = e .>>>. zero_--quotShortInt :: Int -> JExpr -> JExpr -> JExpr-quotShortInt bits x y = BAnd (signed x `Div` signed y) mask-  where-    signed z = (z .<<. shift) .>>. shift-    shift    = toJExpr (32 - bits)-    mask     = toJExpr (((2::Integer) ^ bits) - 1)--remShortInt :: Int -> JExpr -> JExpr -> JExpr-remShortInt bits x y = BAnd (signed x `Mod` signed y) mask-  where-    signed z = (z .<<. shift) .>>. shift-    shift    = toJExpr (32 - bits)-    mask     = toJExpr (((2::Integer) ^ bits) - 1)+import GHC.JS.JStg.Syntax hiding (YieldOp)+import GHC.JS.JStg.Monad+import GHC.JS.Make+import GHC.JS.Ident++import GHC.StgToJS.Heap+import GHC.StgToJS.Types+import GHC.StgToJS.Profiling+import GHC.StgToJS.Regs++import GHC.Core.Type++import GHC.Builtin.PrimOps+import GHC.Tc.Utils.TcType (isBoolTy)+import GHC.Utils.Encoding (zEncodeString)++import GHC.Data.FastString+import GHC.Utils.Outputable (renderWithContext, defaultSDocContext, ppr)++genPrim :: Bool     -- ^ Profiling (cost-centres) enabled+        -> Bool     -- ^ Array bounds-checking enabled+        -> Type+        -> PrimOp   -- ^ the primitive operation+        -> [JStgExpr]  -- ^ where to store the result+        -> [JStgExpr]  -- ^ arguments+        -> JSM PrimRes+genPrim prof bound ty op = case op of+  CharGtOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .>. y)+  CharGeOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .>=. y)+  CharEqOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .===. y)+  CharNeOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .!==. y)+  CharLtOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .<. y)+  CharLeOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .<=. y)+  OrdOp           -> \[r] [x]   -> pure $ PrimInline $ r |= x++  Int8ToWord8Op   -> \[r] [x]   -> pure $ PrimInline $ r |= mask8 x+  Word8ToInt8Op   -> \[r] [x]   -> pure $ PrimInline $ r |= signExtend8 x+  Int16ToWord16Op -> \[r] [x]   -> pure $ PrimInline $ r |= mask16 x+  Word16ToInt16Op -> \[r] [x]   -> pure $ PrimInline $ r |= signExtend16 x+  Int32ToWord32Op -> \[r] [x]   -> pure $ PrimInline $ r |= x .>>>. zero_+  Word32ToInt32Op -> \[r] [x]   -> pure $ PrimInline $ r |= toI32 x++------------------------------ Int ----------------------------------------------++  IntAddOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= toI32 (Add x y)+  IntSubOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= toI32 (Sub x y)+  IntMulOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= app "Math.imul" [x, y]+  IntMul2Op       -> \[c,hr,lr] [x,y] -> pure $ PrimInline $ appT [c,hr,lr] "h$hs_timesInt2" [x, y]+  IntMulMayOfloOp -> \[r] [x,y] -> do+    PrimInline <$>+      jVar \tmp ->+             pure $ mconcat+             [ tmp |= Mul x y+             , r   |= if01 (tmp .===. toI32 tmp)+             ]+  IntQuotOp       -> \[r]   [x,y] -> pure $ PrimInline $ r |= toI32 (Div x y)+  IntRemOp        -> \[r]   [x,y] -> pure $ PrimInline $ r |= Mod x y+  IntQuotRemOp    -> \[q,r] [x,y] -> pure $ PrimInline $ mconcat+                                     [ q |= toI32 (Div x y)+                                     , r |= x `Sub` (Mul y q)+                                     ]+  IntAndOp        -> \[r] [x,y]   -> pure $ PrimInline $ r |= BAnd x y+  IntOrOp         -> \[r] [x,y]   -> pure $ PrimInline $ r |= BOr  x y+  IntXorOp        -> \[r] [x,y]   -> pure $ PrimInline $ r |= BXor x y+  IntNotOp        -> \[r] [x]     -> pure $ PrimInline $ r |= BNot x++  IntNegOp        -> \[r] [x]   -> pure $ PrimInline $ r |= toI32 (Negate x)+-- add with carry: overflow == 0 iff no overflow+  IntAddCOp       -> \[r,overf] [x,y] ->+    PrimInline <$>+    jVar \tmp ->+           pure $ mconcat+           [ tmp   |= Add x y+           , r     |= toI32 tmp+           , overf |= if10 (r .!=. tmp)+           ]+  IntSubCOp       -> \[r,overf] [x,y] ->+    PrimInline <$>+    jVar \tmp ->+           pure $ mconcat+           [ tmp   |= Sub x y+           , r     |= toI32 tmp+           , overf |= if10 (r .!=. tmp)+           ]+  IntGtOp           -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .>. y)+  IntGeOp           -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .>=. y)+  IntEqOp           -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .===. y)+  IntNeOp           -> \[r] [x,y] -> pure $ PrimInline $ r |= if10(x .!==. y)+  IntLtOp           -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .<. y)+  IntLeOp           -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .<=. y)+  ChrOp             -> \[r] [x]   -> pure $ PrimInline $ r |= x+  IntToWordOp       -> \[r] [x]   -> pure $ PrimInline $ r |= x .>>>. zero_+  IntToFloatOp      -> \[r] [x]   -> pure $ PrimInline $ r |= x+  IntToDoubleOp     -> \[r] [x]   -> pure $ PrimInline $ r |= x+  IntSllOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= x .<<. y+  IntSraOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= x .>>. y+  IntSrlOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= toI32 (x .>>>. y)++------------------------------ Int8 ---------------------------------------------++  Int8ToIntOp       -> \[r] [x]       -> pure $ PrimInline $ r |= x+  IntToInt8Op       -> \[r] [x]       -> pure $ PrimInline $ r |= signExtend8 x+  Int8NegOp         -> \[r] [x]       -> pure $ PrimInline $ r |= signExtend8 (Negate x)+  Int8AddOp         -> \[r] [x,y]     -> pure $ PrimInline $ r |= signExtend8 (Add x y)+  Int8SubOp         -> \[r] [x,y]     -> pure $ PrimInline $ r |= signExtend8 (Sub x y)+  Int8MulOp         -> \[r] [x,y]     -> pure $ PrimInline $ r |= signExtend8 (Mul x y)+  Int8QuotOp        -> \[r] [x,y]     -> pure $ PrimInline $ r |= signExtend8 (quotShortInt 8 x y)+  Int8RemOp         -> \[r] [x,y]     -> pure $ PrimInline $ r |= signExtend8 (remShortInt 8 x y)+  Int8QuotRemOp     -> \[r1,r2] [x,y] -> pure $ PrimInline $ mconcat+                                         [ r1 |= signExtend8 (quotShortInt 8 x y)+                                         , r2 |= signExtend8 (remShortInt 8 x y)+                                         ]+  Int8EqOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .===. y)+  Int8GeOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 ((x .<<. (Int 24)) .>=. (y .<<. (Int 24)))+  Int8GtOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 ((x .<<. (Int 24)) .>.  (y .<<. (Int 24)))+  Int8LeOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 ((x .<<. (Int 24)) .<=. (y .<<. (Int 24)))+  Int8LtOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 ((x .<<. (Int 24)) .<.  (y .<<. (Int 24)))+  Int8NeOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .!==. y)++  Int8SraOp         -> \[r] [x,i]   -> pure $ PrimInline $ r |= x .>>. i+  Int8SrlOp         -> \[r] [x,i]   -> pure $ PrimInline $ r |= signExtend8 (mask8 x .>>>. i)+  Int8SllOp         -> \[r] [x,i]   -> pure $ PrimInline $ r |= signExtend8 (mask8 (x .<<. i))++------------------------------ Word8 --------------------------------------------++  Word8ToWordOp      -> \[r] [x]       -> pure $ PrimInline $ r |= mask8 x+  WordToWord8Op      -> \[r] [x]       -> pure $ PrimInline $ r |= mask8 x++  Word8AddOp         -> \[r] [x,y]     -> pure $ PrimInline $ r |= mask8 (Add x y)+  Word8SubOp         -> \[r] [x,y]     -> pure $ PrimInline $ r |= mask8 (Sub x y)+  Word8MulOp         -> \[r] [x,y]     -> pure $ PrimInline $ r |= mask8 (Mul x y)+  Word8QuotOp        -> \[r] [x,y]     -> pure $ PrimInline $ r |= mask8 (Div x y)+  Word8RemOp         -> \[r] [x,y]     -> pure $ PrimInline $ r |= Mod x y+  Word8QuotRemOp     -> \[r1,r2] [x,y] -> pure $ PrimInline $ mconcat+                                          [ r1 |= toI32 (Div x y)+                                          , r2 |= Mod x y+                                          ]+  Word8EqOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .===. y)+  Word8GeOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .>=. y)+  Word8GtOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .>. y)+  Word8LeOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .<=. y)+  Word8LtOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .<. y)+  Word8NeOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .!==. y)++  Word8AndOp         -> \[r] [x,y]   -> pure $ PrimInline $ r |= BAnd x y+  Word8OrOp          -> \[r] [x,y]   -> pure $ PrimInline $ r |= BOr  x y+  Word8XorOp         -> \[r] [x,y]   -> pure $ PrimInline $ r |= BXor x y+  Word8NotOp         -> \[r] [x]     -> pure $ PrimInline $ r |= BXor x (Int 0xff)++  Word8SllOp         -> \[r] [x,i]   -> pure $ PrimInline $ r |= mask8 (x .<<. i)+  Word8SrlOp         -> \[r] [x,i]   -> pure $ PrimInline $ r |= x .>>>. i++------------------------------ Int16 -------------------------------------------++  Int16ToIntOp       -> \[r] [x]       -> pure $ PrimInline $ r |= x+  IntToInt16Op       -> \[r] [x]       -> pure $ PrimInline $ r |= signExtend16 x++  Int16NegOp         -> \[r] [x]       -> pure $ PrimInline $ r |= signExtend16 (Negate x)+  Int16AddOp         -> \[r] [x,y]     -> pure $ PrimInline $ r |= signExtend16 (Add x y)+  Int16SubOp         -> \[r] [x,y]     -> pure $ PrimInline $ r |= signExtend16 (Sub x y)+  Int16MulOp         -> \[r] [x,y]     -> pure $ PrimInline $ r |= signExtend16 (Mul x y)+  Int16QuotOp        -> \[r] [x,y]     -> pure $ PrimInline $ r |= signExtend16 (quotShortInt 16 x y)+  Int16RemOp         -> \[r] [x,y]     -> pure $ PrimInline $ r |= signExtend16 (remShortInt 16 x y)+  Int16QuotRemOp     -> \[r1,r2] [x,y] -> pure $ PrimInline $ mconcat+                                          [ r1 |= signExtend16 (quotShortInt 16 x y)+                                          , r2 |= signExtend16 (remShortInt 16 x y)+                                          ]+  Int16EqOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .===. y)+  Int16GeOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 ((x .<<. (Int 16)) .>=. (y .<<. (Int 16)))+  Int16GtOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 ((x .<<. (Int 16)) .>.  (y .<<. (Int 16)))+  Int16LeOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 ((x .<<. (Int 16)) .<=. (y .<<. (Int 16)))+  Int16LtOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 ((x .<<. (Int 16)) .<.  (y .<<. (Int 16)))+  Int16NeOp          -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .!==. y)++  Int16SraOp         -> \[r] [x,i]   -> pure $ PrimInline $ r |= x .>>. i+  Int16SrlOp         -> \[r] [x,i]   -> pure $ PrimInline $ r |= signExtend16 (mask16 x .>>>. i)+  Int16SllOp         -> \[r] [x,i]   -> pure $ PrimInline $ r |= signExtend16 (x .<<. i)++------------------------------ Word16 ------------------------------------------++  Word16ToWordOp     -> \[r] [x]   -> pure $ PrimInline $ r |= x+  WordToWord16Op     -> \[r] [x]   -> pure $ PrimInline $ r |= mask16 x++  Word16AddOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= mask16 (Add x y)+  Word16SubOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= mask16 (Sub x y)+  Word16MulOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= mask16 (Mul x y)+  Word16QuotOp       -> \[r] [x,y] -> pure $ PrimInline $ r |= mask16 (Div x y)+  Word16RemOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= Mod x y+  Word16QuotRemOp    -> \[r1,r2] [x,y] -> pure $ PrimInline $ mconcat+                                          [ r1 |= toI32 (Div x y)+                                          , r2 |= Mod x y+                                          ]+  Word16EqOp         -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .===. y)+  Word16GeOp         -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .>=. y)+  Word16GtOp         -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .>. y)+  Word16LeOp         -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .<=. y)+  Word16LtOp         -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .<. y)+  Word16NeOp         -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .!==. y)++  Word16AndOp        -> \[r] [x,y]   -> pure $ PrimInline $ r |= BAnd x y+  Word16OrOp         -> \[r] [x,y]   -> pure $ PrimInline $ r |= BOr  x y+  Word16XorOp        -> \[r] [x,y]   -> pure $ PrimInline $ r |= BXor x y+  Word16NotOp        -> \[r] [x]     -> pure $ PrimInline $ r |= BXor x (Int 0xffff)++  Word16SllOp        -> \[r] [x,i]   -> pure $ PrimInline $ r |= mask16 (x .<<. i)+  Word16SrlOp        -> \[r] [x,i]   -> pure $ PrimInline $ r |= x .>>>. i++------------------------------ Int32 --------------------------------------------++  Int32ToIntOp       -> \[r] [x]   -> pure $ PrimInline $ r |= x+  IntToInt32Op       -> \[r] [x]   -> pure $ PrimInline $ r |= x++  Int32NegOp         -> \rs  xs    -> genPrim prof bound ty IntNegOp rs xs+  Int32AddOp         -> \rs  xs    -> genPrim prof bound ty IntAddOp rs xs+  Int32SubOp         -> \rs  xs    -> genPrim prof bound ty IntSubOp rs xs+  Int32MulOp         -> \rs  xs    -> genPrim prof bound ty IntMulOp rs xs+  Int32QuotOp        -> \rs  xs    -> genPrim prof bound ty IntQuotOp rs xs+  Int32RemOp         -> \rs  xs    -> genPrim prof bound ty IntRemOp rs xs+  Int32QuotRemOp     -> \rs  xs    -> genPrim prof bound ty IntQuotRemOp rs xs++  Int32EqOp          -> \rs  xs    -> genPrim prof bound ty IntEqOp rs xs+  Int32GeOp          -> \rs  xs    -> genPrim prof bound ty IntGeOp rs xs+  Int32GtOp          -> \rs  xs    -> genPrim prof bound ty IntGtOp rs xs+  Int32LeOp          -> \rs  xs    -> genPrim prof bound ty IntLeOp rs xs+  Int32LtOp          -> \rs  xs    -> genPrim prof bound ty IntLtOp rs xs+  Int32NeOp          -> \rs  xs    -> genPrim prof bound ty IntNeOp rs xs++  Int32SraOp         -> \rs  xs    -> genPrim prof bound ty IntSraOp rs xs+  Int32SrlOp         -> \rs  xs    -> genPrim prof bound ty IntSrlOp rs xs+  Int32SllOp         -> \rs  xs    -> genPrim prof bound ty IntSllOp rs xs++------------------------------ Word32 -------------------------------------------++  Word32ToWordOp     -> \[r] [x]   -> pure $ PrimInline $ r |= x+  WordToWord32Op     -> \[r] [x]   -> pure $ PrimInline $ r |= x++  Word32AddOp        -> \rs  xs    -> genPrim prof bound ty WordAddOp rs xs+  Word32SubOp        -> \rs  xs    -> genPrim prof bound ty WordSubOp rs xs+  Word32MulOp        -> \rs  xs    -> genPrim prof bound ty WordMulOp rs xs+  Word32QuotOp       -> \rs  xs    -> genPrim prof bound ty WordQuotOp rs xs+  Word32RemOp        -> \rs  xs    -> genPrim prof bound ty WordRemOp rs xs+  Word32QuotRemOp    -> \rs  xs    -> genPrim prof bound ty WordQuotRemOp rs xs++  Word32EqOp         -> \rs  xs    -> genPrim prof bound ty WordEqOp rs xs+  Word32GeOp         -> \rs  xs    -> genPrim prof bound ty WordGeOp rs xs+  Word32GtOp         -> \rs  xs    -> genPrim prof bound ty WordGtOp rs xs+  Word32LeOp         -> \rs  xs    -> genPrim prof bound ty WordLeOp rs xs+  Word32LtOp         -> \rs  xs    -> genPrim prof bound ty WordLtOp rs xs+  Word32NeOp         -> \rs  xs    -> genPrim prof bound ty WordNeOp rs xs++  Word32AndOp        -> \rs xs     -> genPrim prof bound ty WordAndOp rs xs+  Word32OrOp         -> \rs xs     -> genPrim prof bound ty WordOrOp rs xs+  Word32XorOp        -> \rs xs     -> genPrim prof bound ty WordXorOp rs xs+  Word32NotOp        -> \rs xs     -> genPrim prof bound ty WordNotOp rs xs++  Word32SllOp        -> \rs xs     -> genPrim prof bound ty WordSllOp rs xs+  Word32SrlOp        -> \rs xs     -> genPrim prof bound ty WordSrlOp rs xs++------------------------------ Int64 --------------------------------------------++  Int64ToIntOp      -> \[r] [_h,l] -> pure $ PrimInline $ r |= toI32 l++  Int64NegOp        -> \[r_h,r_l] [h,l] ->+      pure $ PrimInline $ mconcat+        [ r_l |= toU32 (Add (BNot l) one_)+        , r_h |= toI32 (Add (BNot h) (Not r_l))+        ]++  Int64AddOp  -> \[hr,lr] [h0,l0,h1,l1] -> pure $ PrimInline $ appT [hr,lr] "h$hs_plusInt64"  [h0,l0,h1,l1]+  Int64SubOp  -> \[hr,lr] [h0,l0,h1,l1] -> pure $ PrimInline $ appT [hr,lr] "h$hs_minusInt64" [h0,l0,h1,l1]+  Int64MulOp  -> \[hr,lr] [h0,l0,h1,l1] -> pure $ PrimInline $ appT [hr,lr] "h$hs_timesInt64" [h0,l0,h1,l1]+  Int64QuotOp -> \[hr,lr] [h0,l0,h1,l1] -> pure $ PrimInline $ appT [hr,lr] "h$hs_quotInt64"  [h0,l0,h1,l1]+  Int64RemOp  -> \[hr,lr] [h0,l0,h1,l1] -> pure $ PrimInline $ appT [hr,lr] "h$hs_remInt64"   [h0,l0,h1,l1]++  Int64SllOp  -> \[hr,lr] [h,l,n] -> pure $ PrimInline $ appT [hr,lr] "h$hs_uncheckedShiftLLInt64" [h,l,n]+  Int64SraOp  -> \[hr,lr] [h,l,n] -> pure $ PrimInline $ appT [hr,lr] "h$hs_uncheckedShiftRAInt64" [h,l,n]+  Int64SrlOp  -> \[hr,lr] [h,l,n] -> pure $ PrimInline $ appT [hr,lr] "h$hs_uncheckedShiftRLInt64" [h,l,n]++  Int64ToWord64Op   -> \[r1,r2] [x1,x2] ->+      pure $ PrimInline $ mconcat+       [ r1 |= toU32 x1+       , r2 |= x2+       ]+  IntToInt64Op      -> \[r1,r2] [x] ->+      pure $ PrimInline $ mconcat+       [ r1 |= if_ (x .<. zero_) (Negate one_) zero_ -- sign-extension+       , r2 |= toU32 x+       ]++  Int64EqOp -> \[r] [h0,l0,h1,l1] -> pure $ PrimInline $ r |= if10 (LAnd (l0 .===. l1) (h0 .===. h1))+  Int64NeOp -> \[r] [h0,l0,h1,l1] -> pure $ PrimInline $ r |= if10 (LOr (l0 .!==. l1) (h0 .!==. h1))+  Int64GeOp -> \[r] [h0,l0,h1,l1] -> pure $ PrimInline $ r |= if10 (LOr (h0 .>. h1) (LAnd (h0 .===. h1) (l0 .>=. l1)))+  Int64GtOp -> \[r] [h0,l0,h1,l1] -> pure $ PrimInline $ r |= if10 (LOr (h0 .>. h1) (LAnd (h0 .===. h1) (l0 .>. l1)))+  Int64LeOp -> \[r] [h0,l0,h1,l1] -> pure $ PrimInline $ r |= if10 (LOr (h0 .<. h1) (LAnd (h0 .===. h1) (l0 .<=. l1)))+  Int64LtOp -> \[r] [h0,l0,h1,l1] -> pure $ PrimInline $ r |= if10 (LOr (h0 .<. h1) (LAnd (h0 .===. h1) (l0 .<. l1)))++------------------------------ Word64 -------------------------------------------++  Word64ToWordOp    -> \[r] [_x1,x2] -> pure $ PrimInline $ r |= x2++  WordToWord64Op    -> \[rh,rl] [x] ->+    pure $ PrimInline $ mconcat+     [ rh |= zero_+     , rl |= x+     ]++  Word64ToInt64Op   -> \[r1,r2] [x1,x2] ->+    pure $ PrimInline $ mconcat+     [ r1 |= toI32 x1+     , r2 |= x2+     ]++  Word64EqOp -> \[r] [h0,l0,h1,l1] -> pure $ PrimInline $ r |= if10 (LAnd (l0 .===. l1) (h0 .===. h1))+  Word64NeOp -> \[r] [h0,l0,h1,l1] -> pure $ PrimInline $ r |= if10 (LOr (l0 .!==. l1) (h0 .!==. h1))+  Word64GeOp -> \[r] [h0,l0,h1,l1] -> pure $ PrimInline $ r |= if10 (LOr (h0 .>. h1) (LAnd (h0 .===. h1) (l0 .>=. l1)))+  Word64GtOp -> \[r] [h0,l0,h1,l1] -> pure $ PrimInline $ r |= if10 (LOr (h0 .>. h1) (LAnd (h0 .===. h1) (l0 .>. l1)))+  Word64LeOp -> \[r] [h0,l0,h1,l1] -> pure $ PrimInline $ r |= if10 (LOr (h0 .<. h1) (LAnd (h0 .===. h1) (l0 .<=. l1)))+  Word64LtOp -> \[r] [h0,l0,h1,l1] -> pure $ PrimInline $ r |= if10 (LOr (h0 .<. h1) (LAnd (h0 .===. h1) (l0 .<. l1)))++  Word64SllOp -> \[hr,lr] [h,l,n] -> pure $ PrimInline $ appT [hr,lr] "h$hs_uncheckedShiftLWord64" [h,l,n]+  Word64SrlOp -> \[hr,lr] [h,l,n] -> pure $ PrimInline $ appT [hr,lr] "h$hs_uncheckedShiftRWord64" [h,l,n]++  Word64OrOp  -> \[hr,hl] [h0, l0, h1, l1] ->+      pure $ PrimInline $ mconcat+        [ hr |= toU32 (BOr h0 h1)+        , hl |= toU32 (BOr l0 l1)+        ]++  Word64AndOp -> \[hr,hl] [h0, l0, h1, l1] ->+      pure $ PrimInline $ mconcat+        [ hr |= toU32 (BAnd h0 h1)+        , hl |= toU32 (BAnd l0 l1)+        ]++  Word64XorOp -> \[hr,hl] [h0, l0, h1, l1] ->+      pure $ PrimInline $ mconcat+        [ hr |= toU32 (BXor h0 h1)+        , hl |= toU32 (BXor l0 l1)+        ]++  Word64NotOp -> \[hr,hl] [h, l] ->+      pure $ PrimInline $ mconcat+        [ hr |= toU32 (BNot h)+        , hl |= toU32 (BNot l)+        ]++  Word64AddOp  -> \[hr,lr] [h0,l0,h1,l1] -> pure $ PrimInline $ appT [hr,lr] "h$hs_plusWord64"  [h0,l0,h1,l1]+  Word64SubOp  -> \[hr,lr] [h0,l0,h1,l1] -> pure $ PrimInline $ appT [hr,lr] "h$hs_minusWord64" [h0,l0,h1,l1]+  Word64MulOp  -> \[hr,lr] [h0,l0,h1,l1] -> pure $ PrimInline $ appT [hr,lr] "h$hs_timesWord64" [h0,l0,h1,l1]+  Word64QuotOp -> \[hr,lr] [h0,l0,h1,l1] -> pure $ PrimInline $ appT [hr,lr] "h$hs_quotWord64"  [h0,l0,h1,l1]+  Word64RemOp  -> \[hr,lr] [h0,l0,h1,l1] -> pure $ PrimInline $ appT [hr,lr] "h$hs_remWord64"   [h0,l0,h1,l1]++------------------------------ Word ---------------------------------------------++  WordAddOp  -> \[r]   [x,y] -> pure $ PrimInline $ r |= (x `Add` y) .>>>. zero_+  WordAddCOp -> \[r,c] [x,y] ->+      PrimInline <$>+      jVar \tmp ->+             pure $ mconcat+             [ tmp |= x `Add` y+             , r   |= toU32 tmp+             , c   |= if10 (tmp .!==. r)+             ]+  WordSubCOp  -> \[r,c] [x,y] ->+      pure $ PrimInline $ mconcat+        [ r |= toU32 (Sub x y)+        , c |= if10 (y .>. x)+        ]+  WordAdd2Op    -> \[h,l] [x,y] -> pure $ PrimInline $ appT [h,l] "h$wordAdd2" [x,y]+  WordSubOp     -> \  [r] [x,y] -> pure $ PrimInline $ r |= toU32 (Sub x y)+  WordMulOp     -> \  [r] [x,y] -> pure $ PrimInline $ r |= toU32 (app "Math.imul" [x, y])+  WordMul2Op    -> \[h,l] [x,y] -> pure $ PrimInline $ appT [h,l] "h$mul2Word32" [x,y]+  WordQuotOp    -> \  [q] [x,y] -> pure $ PrimInline $ q |= app "h$quotWord32" [x,y]+  WordRemOp     -> \  [r] [x,y] -> pure $ PrimInline $ r |= app "h$remWord32" [x,y]+  WordQuotRemOp -> \[q,r] [x,y] -> pure $ PrimInline $ appT [q,r] "h$quotRemWord32" [x,y]+  WordQuotRem2Op   -> \[q,r] [xh,xl,y] -> pure $ PrimInline $ appT [q,r] "h$quotRem2Word32" [xh,xl,y]+  WordAndOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= toU32 (BAnd x y)+  WordOrOp         -> \[r] [x,y] -> pure $ PrimInline $ r |= toU32 (BOr  x y)+  WordXorOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= toU32 (BXor x y)+  WordNotOp        -> \[r] [x]   -> pure $ PrimInline $ r |= toU32 (BNot x)+  WordSllOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= toU32 (x .<<. y)+  WordSrlOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= x .>>>. y+  WordToIntOp      -> \[r] [x]   -> pure $ PrimInline $ r |= toI32 x+  WordGtOp         -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .>.  y)+  WordGeOp         -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .>=. y)+  WordEqOp         -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .===. y)+  WordNeOp         -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .!==. y)+  WordLtOp         -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .<.  y)+  WordLeOp         -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .<=. y)+  WordToDoubleOp   -> \[r] [x]   -> pure $ PrimInline $ r |= x+  WordToFloatOp    -> \[r] [x]   -> pure $ PrimInline $ r |= math_fround [x]+  PopCnt8Op        -> \[r] [x]   -> pure $ PrimInline $ r |= var "h$popCntTab" .! (mask8 x)+  PopCnt16Op       -> \[r] [x]   -> pure $ PrimInline $ r |= Add (var "h$popCntTab" .! (mask8 x))+                                                      (var "h$popCntTab" .! (mask8 (x .>>>. Int 8)))++  PopCnt32Op  -> \[r] [x]     -> pure $ PrimInline $ r |= app "h$popCnt32" [x]+  PopCnt64Op  -> \[r] [x1,x2] -> pure $ PrimInline $ r |= app "h$popCnt64" [x1,x2]+  PopCntOp    -> \[r] [x]     -> genPrim prof bound ty PopCnt32Op [r] [x]+  Pdep8Op     -> \[r] [s,m]   -> pure $ PrimInline $ r |= app "h$pdep8"  [s,m]+  Pdep16Op    -> \[r] [s,m]   -> pure $ PrimInline $ r |= app "h$pdep16" [s,m]+  Pdep32Op    -> \[r] [s,m]   -> pure $ PrimInline $ r |= app "h$pdep32" [s,m]+  Pdep64Op    -> \[ra,rb] [sa,sb,ma,mb] -> pure $ PrimInline $ appT [ra,rb] "h$pdep64" [sa,sb,ma,mb]+  PdepOp      -> \rs xs                 -> genPrim prof bound ty Pdep32Op rs xs+  Pext8Op     -> \[r] [s,m] -> pure $ PrimInline $ r |= app "h$pext8" [s,m]+  Pext16Op    -> \[r] [s,m] -> pure $ PrimInline $ r |= app "h$pext16" [s,m]+  Pext32Op    -> \[r] [s,m] -> pure $ PrimInline $ r |= app "h$pext32" [s,m]+  Pext64Op    -> \[ra,rb] [sa,sb,ma,mb] -> pure $ PrimInline $ appT [ra,rb] "h$pext64" [sa,sb,ma,mb]+  PextOp      -> \rs xs     -> genPrim prof bound ty Pext32Op rs xs++  ClzOp       -> \[r]   [x]     -> pure $ PrimInline $ r |= app "h$clz32" [x]+  Clz8Op      -> \[r]   [x]     -> pure $ PrimInline $ r |= app "h$clz8"  [x]+  Clz16Op     -> \[r]   [x]     -> pure $ PrimInline $ r |= app "h$clz16" [x]+  Clz32Op     -> \[r]   [x]     -> pure $ PrimInline $ r |= app "h$clz32" [x]+  Clz64Op     -> \[r]   [x1,x2] -> pure $ PrimInline $ r |= app "h$clz64" [x1,x2]+  CtzOp       -> \[r]   [x]     -> pure $ PrimInline $ r |= app "h$ctz32" [x]+  Ctz8Op      -> \[r]   [x]     -> pure $ PrimInline $ r |= app "h$ctz8"  [x]+  Ctz16Op     -> \[r]   [x]     -> pure $ PrimInline $ r |= app "h$ctz16" [x]+  Ctz32Op     -> \[r]   [x]     -> pure $ PrimInline $ r |= app "h$ctz32" [x]+  Ctz64Op     -> \[r]   [x1,x2] -> pure $ PrimInline $ r |= app "h$ctz64" [x1,x2]++  BSwap16Op   -> \[r] [x]   -> pure $ PrimInline $+      r |= BOr ((mask8 x) .<<. (Int 8))+               (mask8 (x .>>>. (Int 8)))+  BSwap32Op   -> \[r] [x]   -> pure $ PrimInline $+      r |= toU32 ((x .<<. (Int 24))+            `BOr` ((BAnd x (Int 0xFF00)) .<<. (Int 8))+            `BOr` ((BAnd x (Int 0xFF0000)) .>>. (Int 8))+            `BOr` (x .>>>. (Int 24)))+  BSwap64Op   -> \[r1,r2] [x,y] -> pure $ PrimInline $ appT [r1,r2] "h$bswap64" [x,y]+  BSwapOp     -> \[r] [x]       -> genPrim prof bound ty BSwap32Op [r] [x]++  BRevOp      -> \[r] [w] -> genPrim prof bound ty BRev32Op [r] [w]+  BRev8Op     -> \[r] [w] -> pure $ PrimInline $ r |= (app "h$reverseWord" [w] .>>>. Int 24)+  BRev16Op    -> \[r] [w] -> pure $ PrimInline $ r |= (app "h$reverseWord" [w] .>>>. Int 16)+  BRev32Op    -> \[r] [w] -> pure $ PrimInline $ r |= app "h$reverseWord" [w]+  BRev64Op    -> \[rh,rl] [h,l] -> pure $ PrimInline $ mconcat+                           [ rl |= app "h$reverseWord" [h]+                           , rh |= app "h$reverseWord" [l]+                           ]++------------------------------ Narrow -------------------------------------------++  Narrow8IntOp    -> \[r] [x] -> pure $ PrimInline $ r |= signExtend8  x+  Narrow16IntOp   -> \[r] [x] -> pure $ PrimInline $ r |= signExtend16 x+  Narrow32IntOp   -> \[r] [x] -> pure $ PrimInline $ r |= toI32  x+  Narrow8WordOp   -> \[r] [x] -> pure $ PrimInline $ r |= mask8  x+  Narrow16WordOp  -> \[r] [x] -> pure $ PrimInline $ r |= mask16 x+  Narrow32WordOp  -> \[r] [x] -> pure $ PrimInline $ r |= toU32  x++------------------------------ Double -------------------------------------------++  DoubleGtOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .>.   y)+  DoubleGeOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .>=.  y)+  DoubleEqOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .===. y)+  DoubleNeOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .!==. y)+  DoubleLtOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .<.   y)+  DoubleLeOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .<=.  y)+  DoubleAddOp       -> \[r] [x,y] -> pure $ PrimInline $ r |= Add x y+  DoubleSubOp       -> \[r] [x,y] -> pure $ PrimInline $ r |= Sub x y+  DoubleMulOp       -> \[r] [x,y] -> pure $ PrimInline $ r |= Mul x y+  DoubleDivOp       -> \[r] [x,y] -> pure $ PrimInline $ r |= Div x y+  DoubleNegOp       -> \[r] [x]   -> pure $ PrimInline $ r |= Negate x+  DoubleFabsOp      -> \[r] [x]   -> pure $ PrimInline $ r |= math_abs [x]+  DoubleToIntOp     -> \[r] [x]   -> pure $ PrimInline $ r |= toI32 x+  DoubleToFloatOp   -> \[r] [x]   -> pure $ PrimInline $ r |= math_fround [x]+  DoubleExpOp       -> \[r] [x]   -> pure $ PrimInline $ r |= math_exp  [x]+  DoubleExpM1Op     -> \[r] [x]   -> pure $ PrimInline $ r |= math_expm1 [x]+  DoubleLogOp       -> \[r] [x]   -> pure $ PrimInline $ r |= math_log  [x]+  DoubleLog1POp     -> \[r] [x]   -> pure $ PrimInline $ r |= math_log1p [x]+  DoubleSqrtOp      -> \[r] [x]   -> pure $ PrimInline $ r |= math_sqrt [x]+  DoubleSinOp       -> \[r] [x]   -> pure $ PrimInline $ r |= math_sin  [x]+  DoubleCosOp       -> \[r] [x]   -> pure $ PrimInline $ r |= math_cos  [x]+  DoubleTanOp       -> \[r] [x]   -> pure $ PrimInline $ r |= math_tan  [x]+  DoubleAsinOp      -> \[r] [x]   -> pure $ PrimInline $ r |= math_asin [x]+  DoubleAcosOp      -> \[r] [x]   -> pure $ PrimInline $ r |= math_acos [x]+  DoubleAtanOp      -> \[r] [x]   -> pure $ PrimInline $ r |= math_atan [x]+  DoubleSinhOp      -> \[r] [x]   -> pure $ PrimInline $ r |= math_sinh [x]+  DoubleCoshOp      -> \[r] [x]   -> pure $ PrimInline $ r |= math_cosh [x]+  DoubleTanhOp      -> \[r] [x]   -> pure $ PrimInline $ r |= math_tanh [x]+  DoubleAsinhOp     -> \[r] [x]   -> pure $ PrimInline $ r |= math_asinh [x]+  DoubleAcoshOp     -> \[r] [x]   -> pure $ PrimInline $ r |= math_acosh [x]+  DoubleAtanhOp     -> \[r] [x]   -> pure $ PrimInline $ r |= math_atanh [x]+  DoublePowerOp     -> \[r] [x,y] -> pure $ PrimInline $ r |= math_pow [x,y]+  DoubleDecode_2IntOp  -> \[s,h,l,e] [x] -> pure $ PrimInline $ appT [s,h,l,e] "h$decodeDouble2Int" [x]+  DoubleDecode_Int64Op -> \[s1,s2,e] [d] -> pure $ PrimInline $ appT [e,s1,s2] "h$decodeDoubleInt64" [d]+  CastDoubleToWord64Op -> \[rh,rl] [x]   -> pure $ PrimInline $ appT [rh,rl]   "h$castDoubleToWord64" [x]+  CastWord64ToDoubleOp -> \[r]     [h,l] -> pure $ PrimInline $ appT [r]       "h$castWord64ToDouble" [h,l]++  DoubleFMAdd  -> unhandledPrimop op+  DoubleFMSub  -> unhandledPrimop op+  DoubleFNMAdd -> unhandledPrimop op+  DoubleFNMSub -> unhandledPrimop op++------------------------------ Float --------------------------------------------++  FloatGtOp         -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .>.   y)+  FloatGeOp         -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .>=.  y)+  FloatEqOp         -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .===. y)+  FloatNeOp         -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .!==. y)+  FloatLtOp         -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .<.   y)+  FloatLeOp         -> \[r] [x,y] -> pure $ PrimInline $ r |= if10 (x .<=.  y)+  FloatAddOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= math_fround [Add x y]+  FloatSubOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= math_fround [Sub x y]+  FloatMulOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= math_fround [Mul x y]+  FloatDivOp        -> \[r] [x,y] -> pure $ PrimInline $ r |= math_fround [Div x y]+  FloatNegOp        -> \[r] [x]   -> pure $ PrimInline $ r |= Negate x+  FloatFabsOp       -> \[r] [x]   -> pure $ PrimInline $ r |= math_abs [x]+  FloatToIntOp      -> \[r] [x]   -> pure $ PrimInline $ r |= toI32 x+  FloatExpOp        -> \[r] [x]   -> pure $ PrimInline $ r |= math_fround [math_exp [x]]+  FloatExpM1Op      -> \[r] [x]   -> pure $ PrimInline $ r |= math_fround [math_expm1 [x]]+  FloatLogOp        -> \[r] [x]   -> pure $ PrimInline $ r |= math_fround [math_log [x]]+  FloatLog1POp      -> \[r] [x]   -> pure $ PrimInline $ r |= math_fround [math_log1p [x]]+  FloatSqrtOp       -> \[r] [x]   -> pure $ PrimInline $ r |= math_fround [math_sqrt [x]]+  FloatSinOp        -> \[r] [x]   -> pure $ PrimInline $ r |= math_fround [math_sin [x]]+  FloatCosOp        -> \[r] [x]   -> pure $ PrimInline $ r |= math_fround [math_cos [x]]+  FloatTanOp        -> \[r] [x]   -> pure $ PrimInline $ r |= math_fround [math_tan [x]]+  FloatAsinOp       -> \[r] [x]   -> pure $ PrimInline $ r |= math_fround [math_asin [x]]+  FloatAcosOp       -> \[r] [x]   -> pure $ PrimInline $ r |= math_fround [math_acos [x]]+  FloatAtanOp       -> \[r] [x]   -> pure $ PrimInline $ r |= math_fround [math_atan [x]]+  FloatSinhOp       -> \[r] [x]   -> pure $ PrimInline $ r |= math_fround [math_sinh [x]]+  FloatCoshOp       -> \[r] [x]   -> pure $ PrimInline $ r |= math_fround [math_cosh [x]]+  FloatTanhOp       -> \[r] [x]   -> pure $ PrimInline $ r |= math_fround [math_tanh [x]]+  FloatAsinhOp      -> \[r] [x]   -> pure $ PrimInline $ r |= math_fround [math_asinh [x]]+  FloatAcoshOp      -> \[r] [x]   -> pure $ PrimInline $ r |= math_fround [math_acosh [x]]+  FloatAtanhOp      -> \[r] [x]   -> pure $ PrimInline $ r |= math_fround [math_atanh [x]]+  FloatPowerOp      -> \[r] [x,y] -> pure $ PrimInline $ r |= math_fround [math_pow [x,y]]+  FloatToDoubleOp   -> \[r] [x]   -> pure $ PrimInline $ r |= x+  FloatDecode_IntOp -> \[s,e] [x] -> pure $ PrimInline $ appT [s,e] "h$decodeFloatInt" [x]+  CastFloatToWord32Op -> \[r] [x] -> pure $ PrimInline $ appT [r] "h$castFloatToWord32" [x]+  CastWord32ToFloatOp -> \[r] [x] -> pure $ PrimInline $ appT [r] "h$castWord32ToFloat" [x]+++  FloatFMAdd  -> unhandledPrimop op+  FloatFMSub  -> unhandledPrimop op+  FloatFNMAdd -> unhandledPrimop op+  FloatFNMSub -> unhandledPrimop op++------------------------------ Arrays -------------------------------------------++  NewArrayOp           -> \[r] [l,e]   -> pure $ PrimInline $ r |= app "h$newArray" [l,e]+  ReadArrayOp          -> \[r] [a,i]   -> pure $ PrimInline $ bnd_arr bound a i (r |= a .! i)+  WriteArrayOp         -> \[]  [a,i,v] -> pure $ PrimInline $ bnd_arr bound a i (a .! i |= v)+  SizeofArrayOp        -> \[r] [a]     -> pure $ PrimInline $ r |= a .^ "length"+  SizeofMutableArrayOp -> \[r] [a]     -> pure $ PrimInline $ r |= a .^ "length"+  IndexArrayOp         -> \[r] [a,i]   -> pure $ PrimInline $ bnd_arr bound a i (r |= a .! i)+  UnsafeFreezeArrayOp  -> \[r] [a]     -> pure $ PrimInline $ r |= a+  UnsafeThawArrayOp    -> \[r] [a]     -> pure $ PrimInline $ r |= a+  CopyArrayOp          -> \[] [a,o1,ma,o2,n] ->+    PrimInline <$>+    jVar \tmp ->+      pure $ bnd_arr_range bound a o1 n+      $ bnd_arr_range bound ma o2 n+      $ mconcat [ tmp |= Int 0+                , WhileStat False (tmp .<. n) $+                  mconcat [ ma .! (Add tmp o2) |= a .! (Add tmp o1)+                          , preIncrS tmp+                          ]++                ]+  CopyMutableArrayOp  -> \[]  [a1,o1,a2,o2,n] ->+    pure $ PrimInline+      $ bnd_arr_range bound a1 o1 n+      $ bnd_arr_range bound a2 o2 n+      $ appS "h$copyMutableArray" [a1,o1,a2,o2,n]++  CloneArrayOp        -> \[r] [a,start,n]     ->+    pure $ PrimInline+      $ bnd_arr_range bound a start n+      $ r |= app "h$sliceArray" [a,start,n]++  CloneMutableArrayOp -> \[r] [a,start,n]     ->+    pure $ PrimInline+      $ bnd_arr_range bound a start n+      $ r |= app "h$sliceArray" [a,start,n]++  FreezeArrayOp       -> \[r] [a,start,n]     ->+    pure $ PrimInline+      $ bnd_arr_range bound a start n+      $ r |= app "h$sliceArray" [a,start,n]++  ThawArrayOp         -> \[r] [a,start,n]     ->+    pure $ PrimInline+      $ bnd_arr_range bound a start n+      $ r |= app "h$sliceArray" [a,start,n]++  CasArrayOp          -> \[s,o] [a,i,old,new] ->+    PrimInline <$>+    jVar \tmp ->+      pure $ bnd_arr bound a i+      $ mconcat+          [ tmp |= a .! i+          , ifBlockS (tmp .===. old)+                     [ o |= new+                     , a .! i |= new+                     , s |= zero_+                     ]+                     [ s |= one_+                     , o |= tmp+                     ]+          ]++------------------------------ Small Arrays -------------------------------------++  NewSmallArrayOp            -> \[a]   [n,e]         -> pure $ PrimInline $ a |= app "h$newArray" [n,e]+  ReadSmallArrayOp           -> \[r]   [a,i]         -> pure $ PrimInline $ bnd_arr bound a i (r |= a .! i)+  WriteSmallArrayOp          -> \[]    [a,i,e]       -> pure $ PrimInline $ bnd_arr bound a i (a .! i |= e)+  SizeofSmallArrayOp         -> \[r]   [a]           -> pure $ PrimInline $ r |= a .^ "length"+  SizeofSmallMutableArrayOp  -> \[r]   [a]           -> pure $ PrimInline $ r |= a .^ "length"+  IndexSmallArrayOp          -> \[r]   [a,i]         -> pure $ PrimInline $ bnd_arr bound a i (r |= a .! i)+  UnsafeFreezeSmallArrayOp   -> \[r]   [a]           -> pure $ PrimInline $ r |= a+  UnsafeThawSmallArrayOp     -> \[r]   [a]           -> pure $ PrimInline $ r |= a+  CopySmallArrayOp           -> \[]    [s,si,d,di,n] ->+    PrimInline <$>+    jVar \tmp ->+      pure $ bnd_arr_range bound s si n+      $ bnd_arr_range bound d di n+      $ mconcat [ tmp |= Sub n one_+                , WhileStat False (tmp .>=. zero_)+                  $ mconcat [ d .! (Add di tmp) |= s .! (Add si tmp)+                          , postDecrS tmp+                          ]+                ]+  CopySmallMutableArrayOp    -> \[]    [s,si,d,di,n] ->+    pure $ PrimInline+      $ bnd_arr_range bound s si n+      $ bnd_arr_range bound d di n+      $ appS "h$copyMutableArray" [s,si,d,di,n]++  CloneSmallArrayOp          -> \[r]   [a,o,n]       -> pure $ PrimInline $ cloneArray bound r a o n+  CloneSmallMutableArrayOp   -> \[r]   [a,o,n]       -> pure $ PrimInline $ cloneArray bound r a o n+  FreezeSmallArrayOp         -> \[r]   [a,o,n]       -> pure $ PrimInline $ cloneArray bound r a o n+  ThawSmallArrayOp           -> \[r]   [a,o,n]       -> pure $ PrimInline $ cloneArray bound r a o n++  CasSmallArrayOp            -> \[s,o] [a,i,old,new] ->+    PrimInline <$>+    jVar \tmp ->+      pure $ bnd_arr bound a i+      $ mconcat+        [ tmp |= a .! i+        , ifBlockS (tmp .===. old)+            [ o |= new+            , a .! i |= new+            , s |= zero_+            ]+            [ s |= one_+            , o |= tmp+            ]+        ]++------------------------------- Byte Arrays -------------------------------------++  NewByteArrayOp_Char               -> \[r]   [l]        -> pure $ PrimInline (newByteArray r l)+  NewPinnedByteArrayOp_Char         -> \[r]   [l]        -> pure $ PrimInline (newByteArray r l)+  NewAlignedPinnedByteArrayOp_Char  -> \[r]   [l,_align] -> pure $ PrimInline (newByteArray r l)+  MutableByteArrayIsPinnedOp        -> \[r]   [_]        -> pure $ PrimInline $ r |= one_+  ByteArrayIsPinnedOp               -> \[r]   [_]        -> pure $ PrimInline $ r |= one_+  ByteArrayContents_Char            -> \[a,o] [b]        -> pure $ PrimInline $ mconcat [a |= b, o |= zero_]+  MutableByteArrayContents_Char     -> \[a,o] [b]        -> pure $ PrimInline $ mconcat [a |= b, o |= zero_]+  ShrinkMutableByteArrayOp_Char     -> \[]    [a,n]      -> pure $ PrimInline $ appS "h$shrinkMutableByteArray" [a,n]+  ResizeMutableByteArrayOp_Char     -> \[r]   [a,n]      -> pure $ PrimInline $ r |= app "h$resizeMutableByteArray" [a,n]+  UnsafeFreezeByteArrayOp           -> \[a]   [b]        -> pure $ PrimInline $ a |= b+  UnsafeThawByteArrayOp             -> \[a]   [b]        -> pure $ PrimInline $ a |= b+  SizeofByteArrayOp                 -> \[r]   [a]        -> pure $ PrimInline $ r |= a .^ "len"+  SizeofMutableByteArrayOp          -> \[r]   [a]        -> pure $ PrimInline $ r |= a .^ "len"+  GetSizeofMutableByteArrayOp       -> \[r]   [a]        -> pure $ PrimInline $ r |= a .^ "len"++  IndexByteArrayOp_Char      -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix8  bound a i $ r |= read_u8  a i+  IndexByteArrayOp_WideChar  -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix32 bound a i $ r |= read_i32 a i+  IndexByteArrayOp_Int       -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix32 bound a i $ r |= read_i32 a i+  IndexByteArrayOp_Word      -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix32 bound a i $ r |= read_u32 a i+  IndexByteArrayOp_Addr      -> \[r,o] [a,i] -> pure $ PrimInline $ bnd_ix32 bound a i $ read_addr a i r o+  IndexByteArrayOp_Float     -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix32 bound a i $ r |= read_f32 a i+  IndexByteArrayOp_Double    -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix64 bound a i $ r |= read_f64 a i+  IndexByteArrayOp_StablePtr -> \[r,o] [a,i] -> pure $ PrimInline $ bnd_ix32 bound a i $ read_stableptr a i r o+  IndexByteArrayOp_Int8      -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix8  bound a i $ r |= read_i8  a i+  IndexByteArrayOp_Int16     -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix16 bound a i $ r |= read_i16 a i+  IndexByteArrayOp_Int32     -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix32 bound a i $ r |= read_i32 a i+  IndexByteArrayOp_Int64     -> \[h,l] [a,i] -> pure $ PrimInline $ bnd_ix64 bound a i $ read_i64 a i h l+  IndexByteArrayOp_Word8     -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix8  bound a i $ r |= read_u8  a i+  IndexByteArrayOp_Word16    -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix16 bound a i $ r |= read_u16 a i+  IndexByteArrayOp_Word32    -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix32 bound a i $ r |= read_u32 a i+  IndexByteArrayOp_Word64    -> \[h,l] [a,i] -> pure $ PrimInline $ bnd_ix64 bound a i $ read_u64 a i h l++  ReadByteArrayOp_Char       -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix8 bound a i $ r |= read_u8  a i+  ReadByteArrayOp_WideChar   -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix32 bound a i $ r |= read_i32 a i+  ReadByteArrayOp_Int        -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix32 bound a i $ r |= read_i32 a i+  ReadByteArrayOp_Word       -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix32 bound a i $ r |= read_u32 a i+  ReadByteArrayOp_Addr       -> \[r,o] [a,i] -> pure $ PrimInline $ bnd_ix32 bound a i $ read_addr a i r o+  ReadByteArrayOp_Float      -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix32 bound a i $ r |= read_f32 a i+  ReadByteArrayOp_Double     -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix64 bound a i $ r |= read_f64 a i+  ReadByteArrayOp_StablePtr  -> \[r,o] [a,i] -> pure $ PrimInline $ bnd_ix32 bound a i $ read_stableptr a i r o+  ReadByteArrayOp_Int8       -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix8  bound a i $ r |= read_i8  a i+  ReadByteArrayOp_Int16      -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix16 bound a i $ r |= read_i16 a i+  ReadByteArrayOp_Int32      -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix32 bound a i $ r |= read_i32 a i+  ReadByteArrayOp_Int64      -> \[h,l] [a,i] -> pure $ PrimInline $ bnd_ix64 bound a i $ read_i64 a i h l+  ReadByteArrayOp_Word8      -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix8  bound a i $ r |= read_u8  a i+  ReadByteArrayOp_Word16     -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix16 bound a i $ r |= read_u16 a i+  ReadByteArrayOp_Word32     -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ix32 bound a i $ r |= read_u32 a i+  ReadByteArrayOp_Word64     -> \[h,l] [a,i] -> pure $ PrimInline $ bnd_ix64 bound a i $ read_u64 a i h l++  WriteByteArrayOp_Char      -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ix8  bound a i $ write_u8  a i e+  WriteByteArrayOp_WideChar  -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ix32 bound a i $ write_i32 a i e+  WriteByteArrayOp_Int       -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ix32 bound a i $ write_i32 a i e+  WriteByteArrayOp_Word      -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ix32 bound a i $ write_u32 a i e+  WriteByteArrayOp_Addr      -> \[] [a,i,r,o] -> pure $ PrimInline $ bnd_ix32 bound a i $ write_addr a i r o+  WriteByteArrayOp_Float     -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ix32 bound a i $ write_f32 a i e+  WriteByteArrayOp_Double    -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ix64 bound a i $ write_f64 a i e+  WriteByteArrayOp_StablePtr -> \[] [a,i,r,o] -> pure $ PrimInline $ bnd_ix32 bound a i $ write_stableptr a i r o+  WriteByteArrayOp_Int8      -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ix8  bound a i $ write_i8  a i e+  WriteByteArrayOp_Int16     -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ix16 bound a i $ write_i16 a i e+  WriteByteArrayOp_Int32     -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ix32 bound a i $ write_i32 a i e+  WriteByteArrayOp_Int64     -> \[] [a,i,h,l] -> pure $ PrimInline $ bnd_ix64 bound a i $ write_i64 a i h l+  WriteByteArrayOp_Word8     -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ix8  bound a i $ write_u8  a i e+  WriteByteArrayOp_Word16    -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ix16 bound a i $ write_u16 a i e+  WriteByteArrayOp_Word32    -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ix32 bound a i $ write_u32 a i e+  WriteByteArrayOp_Word64    -> \[] [a,i,h,l] -> pure $ PrimInline $ bnd_ix64 bound a i $ write_u64 a i h l++  CompareByteArraysOp -> \[r] [a1,o1,a2,o2,n] ->+      pure . PrimInline+      . bnd_ba_range bound a1 o1 n+      . bnd_ba_range bound a2 o2 n+      $ r |= app "h$compareByteArrays" [a1,o1,a2,o2,n]++  -- We assume the arrays aren't overlapping since they're of different types+  -- (ByteArray vs MutableByteArray, Addr# vs MutableByteArray#, [Mutable]ByteArray# vs Addr#)+  CopyByteArrayOp                      -> \[] [a1,o1,a2,o2,n] -> pure $ copyByteArray False bound a1 o1 a2 o2 n+  CopyAddrToByteArrayOp                -> \[] [a1,o1,a2,o2,n] -> pure $ copyByteArray False bound a1 o1 a2 o2 n+  CopyMutableByteArrayToAddrOp         -> \[] [a1,o1,a2,o2,n] -> pure $ copyByteArray False bound a1 o1 a2 o2 n+  CopyMutableByteArrayNonOverlappingOp -> \[] [a1,o1,a2,o2,n] -> pure $ copyByteArray False bound a1 o1 a2 o2 n+  CopyAddrToAddrNonOverlappingOp       -> \[] [a1,o1,a2,o2,n] -> pure $ copyByteArray False bound a1 o1 a2 o2 n+  CopyByteArrayToAddrOp                -> \[] [a1,o1,a2,o2,n] -> pure $ copyByteArray False bound a1 o1 a2 o2 n++  CopyMutableByteArrayOp               -> \[] [a1,o1,a2,o2,n] -> pure $ copyByteArray True  bound a1 o1 a2 o2 n+  CopyAddrToAddrOp                     -> \[] [a1,o1,a2,o2,n] -> pure $ copyByteArray True  bound a1 o1 a2 o2 n++  SetByteArrayOp -> \[] [a,o,n,v] ->+    PrimInline <$> jVar \tmpIdent ->+    do+      let tmp = var $ identFS tmpIdent+      pure . bnd_ba_range bound a o n $+        mconcat [ tmpIdent ||= zero_+                , WhileStat False (tmp .<. n) $+                  mconcat [ write_u8 a (Add o tmp) v+                          , postIncrS tmp+                          ]+                ]+  SetAddrRangeOp -> \[] xs@[_a,_o,_n,_v] -> genPrim prof bound ty SetByteArrayOp [] xs++  AtomicReadByteArrayOp_Int  -> \[r]   [a,i]   -> pure $ PrimInline $ bnd_ix32 bound a i $ r |= read_i32 a i+  AtomicWriteByteArrayOp_Int -> \[]    [a,i,v] -> pure $ PrimInline $ bnd_ix32 bound a i $ write_i32 a i v+  FetchAddByteArrayOp_Int    -> \[r]   [a,i,v] -> pure $ PrimInline $ bnd_ix32 bound a i $ fetchOpByteArray Add  r a i v+  FetchSubByteArrayOp_Int    -> \[r]   [a,i,v] -> pure $ PrimInline $ bnd_ix32 bound a i $ fetchOpByteArray Sub  r a i v+  FetchAndByteArrayOp_Int    -> \[r]   [a,i,v] -> pure $ PrimInline $ bnd_ix32 bound a i $ fetchOpByteArray BAnd r a i v+  FetchOrByteArrayOp_Int     -> \[r]   [a,i,v] -> pure $ PrimInline $ bnd_ix32 bound a i $ fetchOpByteArray BOr  r a i v+  FetchNandByteArrayOp_Int   -> \[r]   [a,i,v] -> pure $ PrimInline $ bnd_ix32 bound a i $ fetchOpByteArray (\x y -> BNot (BAnd x y)) r a i v+  FetchXorByteArrayOp_Int    -> \[r]   [a,i,v] -> pure $ PrimInline $ bnd_ix32 bound a i $ fetchOpByteArray BXor r a i v++------------------------------- Addr# ------------------------------------------++  AddrAddOp   -> \[a',o'] [a,o,i]         -> pure $ PrimInline $ mconcat [a' |= a, o' |= Add o i]+  AddrSubOp   -> \[i]     [_a1,o1,_a2,o2] -> pure $ PrimInline $ i |= Sub o1 o2+  AddrRemOp   -> \[r]     [_a,o,i]        -> pure $ PrimInline $ r |= Mod o i+  AddrToIntOp -> \[i]     [_a,o]          -> pure $ PrimInline $ i |= o -- only usable for comparisons within one range+  IntToAddrOp -> \[a,o]   [i]             -> pure $ PrimInline $ mconcat [a |= null_, o |= i]+  AddrGtOp -> \[r] [a1,o1,a2,o2] -> pure $ PrimInline $ r |= if10 (app "h$comparePointer" [a1,o1,a2,o2] .>. zero_)+  AddrGeOp -> \[r] [a1,o1,a2,o2] -> pure $ PrimInline $ r |= if10 (app "h$comparePointer" [a1,o1,a2,o2] .>=. zero_)+  AddrEqOp -> \[r] [a1,o1,a2,o2] -> pure $ PrimInline $ r |= if10 (app "h$comparePointer" [a1,o1,a2,o2] .===. zero_)+  AddrNeOp -> \[r] [a1,o1,a2,o2] -> pure $ PrimInline $ r |= if10 (app "h$comparePointer" [a1,o1,a2,o2] .!==. zero_)+  AddrLtOp -> \[r] [a1,o1,a2,o2] -> pure $ PrimInline $ r |= if10 (app "h$comparePointer" [a1,o1,a2,o2] .<. zero_)+  AddrLeOp -> \[r] [a1,o1,a2,o2] -> pure $ PrimInline $ r |= if10 (app "h$comparePointer" [a1,o1,a2,o2] .<=. zero_)++------------------------------- Addr Indexing: Unboxed Arrays -------------------++  IndexOffAddrOp_Char      -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_u8  a (off8  o i)+  IndexOffAddrOp_WideChar  -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_i32 a (off32 o i)+  IndexOffAddrOp_Int       -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_i32 a (off32 o i)+  IndexOffAddrOp_Word      -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_u32 a (off32 o i)+  IndexOffAddrOp_Addr      -> \[ra,ro] [a,o,i] -> pure $ PrimInline $ read_boff_addr a (off32 o i) ra ro+  IndexOffAddrOp_Float     -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_f32 a (off32 o i)+  IndexOffAddrOp_Double    -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_f64 a (off64 o i)+  IndexOffAddrOp_StablePtr -> \[ra,ro] [a,o,i] -> pure $ PrimInline $ read_boff_stableptr a (off32 o i) ra ro+  IndexOffAddrOp_Int8      -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_i8  a (off8  o i)+  IndexOffAddrOp_Int16     -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_i16 a (off16 o i)+  IndexOffAddrOp_Int32     -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_i32 a (off32 o i)+  IndexOffAddrOp_Int64     -> \[h,l]   [a,o,i] -> pure $ PrimInline $ read_boff_i64 a (off64 o i) h l+  IndexOffAddrOp_Word8     -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_u8  a (off8  o i)+  IndexOffAddrOp_Word16    -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_u16 a (off16 o i)+  IndexOffAddrOp_Word32    -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_u32 a (off32 o i)+  IndexOffAddrOp_Word64    -> \[h,l]   [a,o,i] -> pure $ PrimInline $ read_boff_u64 a (off64 o i) h l++  ReadOffAddrOp_Char       -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_u8  a (off8  o i)+  ReadOffAddrOp_WideChar   -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_i32 a (off32 o i)+  ReadOffAddrOp_Int        -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_i32 a (off32 o i)+  ReadOffAddrOp_Word       -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_u32 a (off32 o i)+  ReadOffAddrOp_Addr       -> \[ra,ro] [a,o,i] -> pure $ PrimInline $ read_boff_addr a (off32 o i) ra ro+  ReadOffAddrOp_Float      -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_f32 a (off32 o i)+  ReadOffAddrOp_Double     -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_f64 a (off64 o i)+  ReadOffAddrOp_StablePtr  -> \[ra,ro] [a,o,i] -> pure $ PrimInline $ read_boff_stableptr a (off32 o i) ra ro+  ReadOffAddrOp_Int8       -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_i8  a (off8  o i)+  ReadOffAddrOp_Int16      -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_i16 a (off16 o i)+  ReadOffAddrOp_Int32      -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_i32 a (off32 o i)+  ReadOffAddrOp_Int64      -> \[h,l]   [a,o,i] -> pure $ PrimInline $ read_boff_i64 a (off64 o i) h l+  ReadOffAddrOp_Word8      -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_u8  a (off8  o i)+  ReadOffAddrOp_Word16     -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_u16 a (off16 o i)+  ReadOffAddrOp_Word32     -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_u32 a (off32 o i)+  ReadOffAddrOp_Word64     -> \[h,l]   [a,o,i] -> pure $ PrimInline $ read_boff_u64 a (off64 o i) h l++  WriteOffAddrOp_Char      -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_u8  a (off8  o i) v+  WriteOffAddrOp_WideChar  -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_i32 a (off32 o i) v+  WriteOffAddrOp_Int       -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_i32 a (off32 o i) v+  WriteOffAddrOp_Word      -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_u32 a (off32 o i) v+  WriteOffAddrOp_Addr      -> \[] [a,o,i,va,vo] -> pure $ PrimInline $ write_boff_addr a (off32 o i) va vo+  WriteOffAddrOp_Float     -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_f32 a (off32 o i) v+  WriteOffAddrOp_Double    -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_f64 a (off64 o i) v+  WriteOffAddrOp_StablePtr -> \[] [a,o,i,va,vo] -> pure $ PrimInline $ write_boff_stableptr a (off32 o i) va vo+  WriteOffAddrOp_Int8      -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_i8  a (off8  o i) v+  WriteOffAddrOp_Int16     -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_i16 a (off16 o i) v+  WriteOffAddrOp_Int32     -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_i32 a (off32 o i) v+  WriteOffAddrOp_Int64     -> \[] [a,o,i,h,l]   -> pure $ PrimInline $ write_boff_i64 a (off64 o i) h l+  WriteOffAddrOp_Word8     -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_u8  a (off8  o i) v+  WriteOffAddrOp_Word16    -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_u16 a (off16 o i) v+  WriteOffAddrOp_Word32    -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_u32 a (off32 o i) v+  WriteOffAddrOp_Word64    -> \[] [a,o,i,h,l]   -> pure $ PrimInline $ write_boff_u64 a (off64 o i) h l++  IndexOffAddrOp_Word8AsChar      -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_u8  a (off8  o i)+  IndexOffAddrOp_Word8AsWideChar  -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_i32 a (off8 o i)+  IndexOffAddrOp_Word8AsInt       -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_i32 a (off8 o i)+  IndexOffAddrOp_Word8AsWord      -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_u32 a (off8 o i)+  IndexOffAddrOp_Word8AsAddr      -> \[ra,ro] [a,o,i] -> pure $ PrimInline $ read_boff_addr a (off8 o i) ra ro+  IndexOffAddrOp_Word8AsFloat     -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_f32 a (off8 o i)+  IndexOffAddrOp_Word8AsDouble    -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_f64 a (off8 o i)+  IndexOffAddrOp_Word8AsStablePtr -> \[ra,ro] [a,o,i] -> pure $ PrimInline $ read_boff_stableptr a (off8 o i) ra ro+  IndexOffAddrOp_Word8AsInt16     -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_i16 a (off8 o i)+  IndexOffAddrOp_Word8AsInt32     -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_i32 a (off8 o i)+  IndexOffAddrOp_Word8AsInt64     -> \[h,l]   [a,o,i] -> pure $ PrimInline $ read_boff_i64 a (off8 o i) h l+  IndexOffAddrOp_Word8AsWord16    -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_u16 a (off8 o i)+  IndexOffAddrOp_Word8AsWord32    -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_u32 a (off8 o i)+  IndexOffAddrOp_Word8AsWord64    -> \[h,l]   [a,o,i] -> pure $ PrimInline $ read_boff_u64 a (off8 o i) h l++  ReadOffAddrOp_Word8AsChar       -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_u8  a (off8  o i)+  ReadOffAddrOp_Word8AsWideChar   -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_i32 a (off8 o i)+  ReadOffAddrOp_Word8AsInt        -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_i32 a (off8 o i)+  ReadOffAddrOp_Word8AsWord       -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_u32 a (off8 o i)+  ReadOffAddrOp_Word8AsAddr       -> \[ra,ro] [a,o,i] -> pure $ PrimInline $ read_boff_addr a (off8 o i) ra ro+  ReadOffAddrOp_Word8AsFloat      -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_f32 a (off8 o i)+  ReadOffAddrOp_Word8AsDouble     -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_f64 a (off8 o i)+  ReadOffAddrOp_Word8AsStablePtr  -> \[ra,ro] [a,o,i] -> pure $ PrimInline $ read_boff_stableptr a (off8 o i) ra ro+  ReadOffAddrOp_Word8AsInt16      -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_i16 a (off8 o i)+  ReadOffAddrOp_Word8AsInt32      -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_i32 a (off8 o i)+  ReadOffAddrOp_Word8AsInt64      -> \[h,l]   [a,o,i] -> pure $ PrimInline $ read_boff_i64 a (off8 o i) h l+  ReadOffAddrOp_Word8AsWord16     -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_u16 a (off8 o i)+  ReadOffAddrOp_Word8AsWord32     -> \[r]     [a,o,i] -> pure $ PrimInline $ r |= read_boff_u32 a (off8 o i)+  ReadOffAddrOp_Word8AsWord64     -> \[h,l]   [a,o,i] -> pure $ PrimInline $ read_boff_u64 a (off8 o i) h l++  WriteOffAddrOp_Word8AsChar      -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_u8  a (off8  o i) v+  WriteOffAddrOp_Word8AsWideChar  -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_i32 a (off8 o i) v+  WriteOffAddrOp_Word8AsInt       -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_i32 a (off8 o i) v+  WriteOffAddrOp_Word8AsWord      -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_u32 a (off8 o i) v+  WriteOffAddrOp_Word8AsAddr      -> \[] [a,o,i,va,vo] -> pure $ PrimInline $ write_boff_addr a (off8 o i) va vo+  WriteOffAddrOp_Word8AsFloat     -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_f32 a (off8 o i) v+  WriteOffAddrOp_Word8AsDouble    -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_f64 a (off8 o i) v+  WriteOffAddrOp_Word8AsStablePtr -> \[] [a,o,i,va,vo] -> pure $ PrimInline $ write_boff_stableptr a (off8 o i) va vo+  WriteOffAddrOp_Word8AsInt16     -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_i16 a (off8 o i) v+  WriteOffAddrOp_Word8AsInt32     -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_i32 a (off8 o i) v+  WriteOffAddrOp_Word8AsInt64     -> \[] [a,o,i,h,l]   -> pure $ PrimInline $ write_boff_i64 a (off8 o i) h l+  WriteOffAddrOp_Word8AsWord16    -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_u16 a (off8 o i) v+  WriteOffAddrOp_Word8AsWord32    -> \[] [a,o,i,v]     -> pure $ PrimInline $ write_boff_u32 a (off8 o i) v+  WriteOffAddrOp_Word8AsWord64    -> \[] [a,o,i,h,l]   -> pure $ PrimInline $ write_boff_u64 a (off8 o i) h l++------------------------------- Mutable variables --------------------------------------+  NewMutVarOp           -> \[r] [x]       -> pure $ PrimInline $ r |= New (app "h$MutVar" [x])+  ReadMutVarOp          -> \[r] [m]       -> pure $ PrimInline $ r |= m .^ "val"+  WriteMutVarOp         -> \[] [m,x]      -> pure $ PrimInline $ m .^ "val" |= x+  AtomicModifyMutVar2Op -> \[r1,r2] [m,f] -> pure $ PrimInline $ appT [r1,r2] "h$atomicModifyMutVar2" [m,f]+  AtomicModifyMutVar_Op -> \[r1,r2] [m,f] -> pure $ PrimInline $ appT [r1,r2] "h$atomicModifyMutVar" [m,f]++  AtomicSwapMutVarOp    -> \[r] [mv,v] -> pure $ PrimInline $ mconcat+                                          [ r |= mv .^ "val", mv .^ "val" |= v ]+  CasMutVarOp -> \[status,r] [mv,o,n] -> pure $ PrimInline $ ifS (mv .^ "val" .===. o)+                   (mconcat [status |= zero_, r |= n, mv .^ "val" |= n])+                   (mconcat [status |= one_ , r |= mv .^ "val"])++------------------------------- Exceptions --------------------------------------++  CatchOp -> \[_r] [a,handler] -> pure $ PRPrimCall $ returnS (app "h$catch" [a, handler])++                             -- fully ignore the result arity as it can use 1 or 2+                             -- slots, depending on the return type.+  RaiseOp                 -> \_r [a] -> pure $ PRPrimCall $ returnS (app "h$throw" [a, false_])+  RaiseIOOp               -> \_r [a] -> pure $ PRPrimCall $ returnS (app "h$throw" [a, false_])+  RaiseUnderflowOp        -> \_r []  -> pure $ PRPrimCall $ returnS (app "h$throw" [var "h$ghczminternalZCGHCziInternalziExceptionziTypeziunderflowException", false_])+  RaiseOverflowOp         -> \_r []  -> pure $ PRPrimCall $ returnS (app "h$throw" [var "h$ghczminternalZCGHCziInternalziExceptionziTypezioverflowException", false_])+  RaiseDivZeroOp          -> \_r []  -> pure $ PRPrimCall $ returnS (app "h$throw" [var "h$ghczminternalZCGHCziInternalziExceptionziTypezidivZZeroException", false_])+  MaskAsyncExceptionsOp   -> \_r [a] -> pure $ PRPrimCall $ returnS (app "h$maskAsync" [a])+  MaskUninterruptibleOp   -> \_r [a] -> pure $ PRPrimCall $ returnS (app "h$maskUnintAsync" [a])+  UnmaskAsyncExceptionsOp -> \_r [a] -> pure $ PRPrimCall $ returnS (app "h$unmaskAsync" [a])++  MaskStatus -> \[r] [] -> pure $ PrimInline $ r |= app "h$maskStatus" []++------------------------------- STM-accessible Mutable Variables  --------------++  AtomicallyOp -> \[_r] [a]   -> pure $ PRPrimCall $ returnS (app "h$atomically" [a])+  RetryOp      -> \_r   []    -> pure $ PRPrimCall $ returnS (app "h$stmRetry" [])+  CatchRetryOp -> \[_r] [a,b] -> pure $ PRPrimCall $ returnS (app "h$stmCatchRetry" [a,b])+  CatchSTMOp   -> \[_r] [a,h] -> pure $ PRPrimCall $ returnS (app "h$catchStm" [a,h])+  NewTVarOp    -> \[tv] [v]   -> pure $ PrimInline $ tv |= app "h$newTVar" [v]+  ReadTVarOp   -> \[r] [tv]   -> pure $ PrimInline $ r |= app "h$readTVar" [tv]+  ReadTVarIOOp -> \[r] [tv]   -> pure $ PrimInline $ r |= app "h$readTVarIO" [tv]+  WriteTVarOp  -> \[] [tv,v]  -> pure $ PrimInline $ appS "h$writeTVar" [tv,v]++------------------------------- Synchronized Mutable Variables ------------------++  NewMVarOp     -> \[r]   []    -> pure $ PrimInline $ r |= New (app "h$MVar" [])+  TakeMVarOp    -> \[_r]  [m]   -> pure $ PRPrimCall $ returnS (app "h$takeMVar" [m])+  TryTakeMVarOp -> \[r,v] [m]   -> pure $ PrimInline $ appT [r,v] "h$tryTakeMVar" [m]+  PutMVarOp     -> \[]    [m,v] -> pure $ PRPrimCall $ returnS (app "h$putMVar" [m,v])+  TryPutMVarOp  -> \[r]   [m,v] -> pure $ PrimInline $ r |= app "h$tryPutMVar" [m,v]+  ReadMVarOp    -> \[_r]  [m]   -> pure $ PRPrimCall $ returnS (app "h$readMVar" [m])+  TryReadMVarOp -> \[r,v] [m]   -> pure $ PrimInline $ mconcat+                                   [ v |= m .^ "val"+                                   , r |= if01 (v .===. null_)+                                   ]+  IsEmptyMVarOp -> \[r]   [m]   -> pure $ PrimInline $ r |= if10 (m .^ "val" .===. null_)++------------------------------- Delay/Wait Ops ---------------------------------++  DelayOp     -> \[] [t]  -> pure $ PRPrimCall $ returnS (app "h$delayThread" [t])+  WaitReadOp  -> \[] [fd] -> pure $ PRPrimCall $ returnS (app "h$waidRead" [fd])+  WaitWriteOp -> \[] [fd] -> pure $ PRPrimCall $ returnS (app "h$waitWrite" [fd])++------------------------------- Concurrency Primitives -------------------------++  ForkOp                 -> \[_tid] [x]    -> pure $ PRPrimCall $ returnS (app "h$fork" [x, true_])+  ForkOnOp               -> \[_tid] [_p,x] -> pure $ PRPrimCall $ returnS (app "h$fork" [x, true_]) -- ignore processor argument+  KillThreadOp           -> \[] [tid,ex]   -> pure $ PRPrimCall $ returnS (app "h$killThread" [tid,ex])+  YieldOp                -> \[] []         -> pure $ PRPrimCall $ returnS (app "h$yield" [])+  MyThreadIdOp           -> \[r] []        -> pure $ PrimInline $ r |= var "h$currentThread"+  IsCurrentThreadBoundOp -> \[r] []        -> pure $ PrimInline $ r |= one_+  NoDuplicateOp          -> \[] []         -> pure $ PrimInline mempty -- don't need to do anything as long as we have eager blackholing+  ThreadStatusOp         -> \[stat,cap,locked] [tid] -> pure $ PrimInline $ appT [stat, cap, locked] "h$threadStatus" [tid]+  ListThreadsOp          -> \[r] [] -> pure $ PrimInline $ appT [r] "h$listThreads" []+  GetThreadLabelOp       -> \[r1, r2] [t]  -> pure $ PrimInline $ appT [r1, r2] "h$getThreadLabel" [t]+  LabelThreadOp          -> \[] [t,l]      -> pure $ PrimInline $ t .^ "label" |= l++------------------------------- Weak Pointers -----------------------------------++  MkWeakOp              -> \[r] [o,b,c] -> pure $ PrimInline $ r |= app "h$makeWeak" [o,b,c]+  MkWeakNoFinalizerOp   -> \[r] [o,b]   -> pure $ PrimInline $ r |= app "h$makeWeakNoFinalizer" [o,b]+  AddCFinalizerToWeakOp -> \[r] [_a1,_a1o,_a2,_a2o,_i,_a3,_a3o,_w] -> pure $ PrimInline $ r |= one_+  DeRefWeakOp           -> \[f,v] [w] -> pure $ PrimInline $ mconcat+                                         [ v |= w .^ "val"+                                         , f |= if01 (v .===. null_)+                                         ]+  FinalizeWeakOp     -> \[fl,fin] [w] -> pure $ PrimInline $ appT [fin, fl] "h$finalizeWeak" [w]+  TouchOp            -> \[] [_e]      -> pure $ PrimInline mempty+  KeepAliveOp        -> \[_r] [x, f]  -> pure $ PRPrimCall $ ReturnStat (app "h$keepAlive" [x, f])+++------------------------------ Stable pointers and names ------------------------++  MakeStablePtrOp -> \[s1,s2] [a] -> pure $ PrimInline $ mconcat+      [ s1 |= var "h$stablePtrBuf"+      , s2 |= app "h$makeStablePtr" [a]+      ]+  DeRefStablePtrOp -> \[r] [_s1,s2]            -> pure $ PrimInline $ r |= app "h$deRefStablePtr" [s2]+  EqStablePtrOp    -> \[r] [_sa1,sa2,_sb1,sb2] -> pure $ PrimInline $ r |= if10 (sa2 .===. sb2)++  MakeStableNameOp  -> \[r] [a] -> pure $ PrimInline $ r |= app "h$makeStableName" [a]+  StableNameToIntOp -> \[r] [s] -> pure $ PrimInline $ r |= app "h$stableNameInt" [s]++------------------------------ Compact normal form -----------------------------++  CompactNewOp           -> \[c] [s]   -> pure $ PrimInline $ c |= app "h$compactNew" [s]+  CompactResizeOp        -> \[]  [c,s] -> pure $ PrimInline $ appS "h$compactResize" [c,s]+  CompactContainsOp      -> \[r] [c,v] -> pure $ PrimInline $ r |= app "h$compactContains" [c,v]+  CompactContainsAnyOp   -> \[r] [v]   -> pure $ PrimInline $ r |= app "h$compactContainsAny" [v]+  CompactGetFirstBlockOp -> \[ra,ro,s] [c] ->+    pure $ PrimInline $ appT [ra,ro,s] "h$compactGetFirstBlock" [c]+  CompactGetNextBlockOp -> \[ra,ro,s] [c,a,o] ->+    pure $ PrimInline $ appT [ra,ro,s] "h$compactGetNextBlock" [c,a,o]+  CompactAllocateBlockOp -> \[ra,ro] [size,sa,so] ->+    pure $ PrimInline $ appT [ra,ro] "h$compactAllocateBlock" [size,sa,so]+  CompactFixupPointersOp -> \[c,newroota, newrooto] [blocka,blocko,roota,rooto] ->+    pure $ PrimInline $ appT [c,newroota,newrooto] "h$compactFixupPointers" [blocka,blocko,roota,rooto]+  CompactAdd -> \[_r] [c,o] ->+    pure $ PRPrimCall $ returnS (app "h$compactAdd" [c,o])+  CompactAddWithSharing -> \[_r] [c,o] ->+    pure $ PRPrimCall $ returnS (app "h$compactAddWithSharing" [c,o])+  CompactSize -> \[s] [c] ->+    pure $ PrimInline $ s |= app "h$compactSize" [c]++------------------------------ Unsafe pointer equality --------------------------++  ReallyUnsafePtrEqualityOp -> \[r] [p1,p2] -> pure $ PrimInline $ r |= if10 (p1 .===. p2)++------------------------------ Parallelism --------------------------------------++  ParOp     -> \[r] [_a] -> pure $ PrimInline $ r |= zero_+  SparkOp   -> \[r] [a]  -> pure $ PrimInline $ r |= a+  SeqOp     -> \[_r] [e] -> pure $ PRPrimCall $ returnS (app "h$e" [e])+  NumSparks -> \[r] []   -> pure $ PrimInline $ r |= zero_++------------------------------ Tag to enum stuff --------------------------------++  DataToTagSmallOp -> \[_r] [d] -> pure $ PRPrimCall $ mconcat+      [ stack .! PreInc sp |= var "h$dataToTag_e"+      , returnS (app "h$e" [d])+      ]+  DataToTagLargeOp -> \[_r] [d] -> pure $ PRPrimCall $ mconcat+      [ stack .! PreInc sp |= var "h$dataToTag_e"+      , returnS (app "h$e" [d])+      ]+  TagToEnumOp -> \[r] [tag] -> pure $ PrimInline $+    if isBoolTy ty+    then r |= IfExpr tag true_ false_+    else r |= app "h$tagToEnum" [tag]++------------------------------ Bytecode operations ------------------------------++  AddrToAnyOp -> \[r] [d,_o] -> pure $ PrimInline $ r |= d++------------------------------ Profiling (CCS)  ------------------------------++  GetCCSOfOp -> \[a, o] [obj] -> pure $ PrimInline $ mconcat+    if prof+    then [ a |= if_ (isObject obj)+           (app "h$buildCCSPtr" [obj .^ "cc"])+           null_+         , o |= zero_+         ]+    else [ a |= null_+         , o |= zero_+         ]++  GetCurrentCCSOp -> \[a, o] [_dummy_arg] ->+    let ptr = if prof then app "h$buildCCSPtr" [jCurrentCCS]+                      else null_+    in pure $ PrimInline $ mconcat+        [ a |= ptr+        , o |= zero_+        ]++  ClearCCSOp -> \[_r] [x] -> pure $ PRPrimCall $ ReturnStat (app "h$clearCCS" [x])++------------------------------ Eventlog -------------------++  TraceEventOp       -> \[] [ed,eo]     -> pure $ PrimInline $ appS "h$traceEvent" [ed,eo]+  TraceEventBinaryOp -> \[] [ed,eo,len] -> pure $ PrimInline $ appS "h$traceEventBinary" [ed,eo,len]+  TraceMarkerOp      -> \[] [ed,eo]     -> pure $ PrimInline $ appS "h$traceMarker" [ed,eo]++------------------------------ ByteArray -------------------++  IndexByteArrayOp_Word8AsChar      -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba8  bound a i $ r |= read_boff_u8  a i+  IndexByteArrayOp_Word8AsWideChar  -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba32 bound a i $ r |= read_boff_i32 a i+  IndexByteArrayOp_Word8AsAddr      -> \[r,o] [a,i] -> pure $ PrimInline $ bnd_ba32 bound a i $ read_boff_addr a i r o+  IndexByteArrayOp_Word8AsFloat     -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba32 bound a i $ r |= read_boff_f32 a i+  IndexByteArrayOp_Word8AsDouble    -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba64 bound a i $ r |= read_boff_f64 a i+  IndexByteArrayOp_Word8AsStablePtr -> \[r,o] [a,i] -> pure $ PrimInline $ bnd_ba32 bound a i $ read_boff_stableptr a i r o+  IndexByteArrayOp_Word8AsInt16     -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba16 bound a i $ r |= read_boff_i16 a i+  IndexByteArrayOp_Word8AsInt32     -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba32 bound a i $ r |= read_boff_i32 a i+  IndexByteArrayOp_Word8AsInt64     -> \[h,l] [a,i] -> pure $ PrimInline $ bnd_ba64 bound a i $ read_boff_i64 a i h l+  IndexByteArrayOp_Word8AsInt       -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba32 bound a i $ r |= read_boff_i32  a i+  IndexByteArrayOp_Word8AsWord16    -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba16 bound a i $ r |= read_boff_u16  a i+  IndexByteArrayOp_Word8AsWord32    -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba32 bound a i $ r |= read_boff_u32  a i+  IndexByteArrayOp_Word8AsWord64    -> \[h,l] [a,i] -> pure $ PrimInline $ bnd_ba64 bound a i $ read_boff_u64 a i h l+  IndexByteArrayOp_Word8AsWord      -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba32 bound a i $ r |= read_boff_u32  a i++  ReadByteArrayOp_Word8AsChar       -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba8  bound a i $ r |= read_boff_u8  a i+  ReadByteArrayOp_Word8AsWideChar   -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba32 bound a i $ r |= read_boff_i32 a i+  ReadByteArrayOp_Word8AsAddr       -> \[r,o] [a,i] -> pure $ PrimInline $ bnd_ba32 bound a i $ read_boff_addr a i r o+  ReadByteArrayOp_Word8AsFloat      -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba32 bound a i $ r |= read_boff_f32 a i+  ReadByteArrayOp_Word8AsDouble     -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba64 bound a i $ r |= read_boff_f64 a i+  ReadByteArrayOp_Word8AsStablePtr  -> \[r,o] [a,i] -> pure $ PrimInline $ bnd_ba32 bound a i $ read_boff_stableptr a i r o+  ReadByteArrayOp_Word8AsInt16      -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba16 bound a i $ r |= read_boff_i16 a i+  ReadByteArrayOp_Word8AsInt32      -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba32 bound a i $ r |= read_boff_i32 a i+  ReadByteArrayOp_Word8AsInt64      -> \[h,l] [a,i] -> pure $ PrimInline $ bnd_ba64 bound a i $ read_boff_i64 a i h l+  ReadByteArrayOp_Word8AsInt        -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba32 bound a i $ r |= read_boff_i32  a i+  ReadByteArrayOp_Word8AsWord16     -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba16 bound a i $ r |= read_boff_u16  a i+  ReadByteArrayOp_Word8AsWord32     -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba32 bound a i $ r |= read_boff_u32  a i+  ReadByteArrayOp_Word8AsWord64     -> \[h,l] [a,i] -> pure $ PrimInline $ bnd_ba64 bound a i $ read_boff_u64 a i h l+  ReadByteArrayOp_Word8AsWord       -> \[r]   [a,i] -> pure $ PrimInline $ bnd_ba32 bound a i $ r |= read_boff_u32  a i++  WriteByteArrayOp_Word8AsChar      -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ba8  bound a i $ write_boff_i8  a i e+  WriteByteArrayOp_Word8AsWideChar  -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ba32 bound a i $ write_boff_i32 a i e+  WriteByteArrayOp_Word8AsAddr      -> \[] [a,i,r,o] -> pure $ PrimInline $ bnd_ba32 bound a i $ write_boff_addr a i r o+  WriteByteArrayOp_Word8AsFloat     -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ba32 bound a i $ write_boff_f32 a i e+  WriteByteArrayOp_Word8AsDouble    -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ba64 bound a i $ write_boff_f64 a i e+  WriteByteArrayOp_Word8AsStablePtr -> \[] [a,i,_,o] -> pure $ PrimInline $ bnd_ba32 bound a i $ write_boff_i32 a i o+  WriteByteArrayOp_Word8AsInt16     -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ba16 bound a i $ write_boff_i16 a i e+  WriteByteArrayOp_Word8AsInt32     -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ba32 bound a i $ write_boff_i32 a i e+  WriteByteArrayOp_Word8AsInt64     -> \[] [a,i,h,l] -> pure $ PrimInline $ bnd_ba64 bound a i $ write_boff_i64 a i h l+  WriteByteArrayOp_Word8AsInt       -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ba32 bound a i $ write_boff_i32 a i e+  WriteByteArrayOp_Word8AsWord16    -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ba16 bound a i $ write_boff_u16 a i e+  WriteByteArrayOp_Word8AsWord32    -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ba32 bound a i $ write_boff_u32 a i e+  WriteByteArrayOp_Word8AsWord64    -> \[] [a,i,h,l] -> pure $ PrimInline $ bnd_ba64 bound a i $ write_boff_u64 a i h l+  WriteByteArrayOp_Word8AsWord      -> \[] [a,i,e]   -> pure $ PrimInline $ bnd_ba32 bound a i $ write_boff_u32 a i e++  CasByteArrayOp_Int                -> \[r] [a,i,o,n] -> pure $ PrimInline $ bnd_ix32 bound a i $ casOp read_i32 write_i32 r a i o n+  CasByteArrayOp_Int8               -> \[r] [a,i,o,n] -> pure $ PrimInline $ bnd_ix8  bound a i $ casOp read_i8  write_i8  r a i o n+  CasByteArrayOp_Int16              -> \[r] [a,i,o,n] -> pure $ PrimInline $ bnd_ix16 bound a i $ casOp read_i16 write_i16 r a i o n+  CasByteArrayOp_Int32              -> \[r] [a,i,o,n] -> pure $ PrimInline $ bnd_ix32 bound a i $ casOp read_i32 write_i32 r a i o n++  CasByteArrayOp_Int64              -> \[rh,rl] [a,i,oh,ol,nh,nl] -> pure $ PrimInline $ bnd_ix64 bound a i $ casOp2 read_i64 write_i64 (rh,rl) a i (oh,ol) (nh,nl)++  CasAddrOp_Addr                    -> \[ra,ro] [a,o,oa,oo,na,no] -> pure $ PrimInline $ casOp2 read_boff_addr write_boff_addr (ra,ro) a o (oa,oo) (na,no)+  CasAddrOp_Word                    -> \[r] [a,o,old,new] -> pure $ PrimInline $ casOp read_u32 write_u32 r a o old new+  CasAddrOp_Word8                   -> \[r] [a,o,old,new] -> pure $ PrimInline $ casOp read_u8  write_u8  r a o old new+  CasAddrOp_Word16                  -> \[r] [a,o,old,new] -> pure $ PrimInline $ casOp read_u16 write_u16 r a o old new+  CasAddrOp_Word32                  -> \[r] [a,o,old,new] -> pure $ PrimInline $ casOp read_u32 write_u32 r a o old new+  CasAddrOp_Word64                  -> \[rh,rl] [a,o,oh,ol,nh,nl] -> pure $ PrimInline $ casOp2 read_u64 write_u64 (rh,rl) a o (oh,ol) (nh,nl)++  FetchAddAddrOp_Word               -> \[r] [a,o,v] -> pure $ PrimInline $ fetchOpAddr Add   r a o v+  FetchSubAddrOp_Word               -> \[r] [a,o,v] -> pure $ PrimInline $ fetchOpAddr Sub   r a o v+  FetchAndAddrOp_Word               -> \[r] [a,o,v] -> pure $ PrimInline $ fetchOpAddr BAnd  r a o v+  FetchNandAddrOp_Word              -> \[r] [a,o,v] -> pure $ PrimInline $ fetchOpAddr ((BNot .) . BAnd) r a o v+  FetchOrAddrOp_Word                -> \[r] [a,o,v] -> pure $ PrimInline $ fetchOpAddr BOr   r a o v+  FetchXorAddrOp_Word               -> \[r] [a,o,v] -> pure $ PrimInline $ fetchOpAddr BXor  r a o v++  InterlockedExchange_Addr          -> \[ra,ro] [a1,o1,a2,o2] -> pure $ PrimInline $ mconcat+                                          [ read_boff_addr a1 o1 ra ro+                                          , write_boff_addr a1 o1 a2 o2+                                          ]+  InterlockedExchange_Word          -> \[r] [a,o,w] -> pure $ PrimInline $ mconcat+                                          [ r |= read_boff_u32 a o+                                          , write_boff_u32 a o w+                                          ]++  ShrinkSmallMutableArrayOp_Char    -> \[]  [a,n] -> pure $ PrimInline $ appS "h$shrinkMutableCharArray" [a,n]+  GetSizeofSmallMutableArrayOp      -> \[r] [a]   -> pure $ PrimInline $ r |= a .^ "length"++  AtomicReadAddrOp_Word             -> \[r] [a,o]   -> pure $ PrimInline $ r |= read_boff_u32 a o+  AtomicWriteAddrOp_Word            -> \[]  [a,o,w] -> pure $ PrimInline $ write_boff_u32 a o w+++------------------------------ Unhandled primops -------------------++  NewPromptTagOp                    -> unhandledPrimop op+  PromptOp                          -> unhandledPrimop op+  Control0Op                        -> unhandledPrimop op++  NewIOPortOp                       -> unhandledPrimop op+  ReadIOPortOp                      -> unhandledPrimop op+  WriteIOPortOp                     -> unhandledPrimop op++  GetSparkOp                        -> unhandledPrimop op+  AnyToAddrOp                       -> unhandledPrimop op+  MkApUpd0_Op                       -> unhandledPrimop op+  NewBCOOp                          -> unhandledPrimop op+  UnpackClosureOp                   -> unhandledPrimop op+  ClosureSizeOp                     -> unhandledPrimop op+  GetApStackValOp                   -> unhandledPrimop op+  WhereFromOp                       -> unhandledPrimop op -- should be easily implementable with o.f.n++  SetThreadAllocationCounter        -> unhandledPrimop op++------------------------------- Vector -----------------------------------------+-- For now, vectors are unsupported on the JS backend. Simply put, they do not+-- make much sense to support given support for arrays and lack of SIMD support+-- in JS. We could try to roll something special but we would not be able to+-- give any performance guarentees to the user and so we leave these has+-- unhandled for now.+  VecBroadcastOp _ _ _              -> unhandledPrimop op+  VecPackOp _ _ _                   -> unhandledPrimop op+  VecUnpackOp _ _ _                 -> unhandledPrimop op+  VecInsertOp _ _ _                 -> unhandledPrimop op+  VecAddOp _ _ _                    -> unhandledPrimop op+  VecSubOp _ _ _                    -> unhandledPrimop op+  VecMulOp _ _ _                    -> unhandledPrimop op+  VecDivOp _ _ _                    -> unhandledPrimop op+  VecQuotOp _ _ _                   -> unhandledPrimop op+  VecRemOp _ _ _                    -> unhandledPrimop op+  VecNegOp _ _ _                    -> unhandledPrimop op+  VecIndexByteArrayOp _ _ _         -> unhandledPrimop op+  VecReadByteArrayOp _ _ _          -> unhandledPrimop op+  VecWriteByteArrayOp _ _ _         -> unhandledPrimop op+  VecIndexOffAddrOp _ _ _           -> unhandledPrimop op+  VecReadOffAddrOp _ _ _            -> unhandledPrimop op+  VecWriteOffAddrOp _ _ _           -> unhandledPrimop op++  VecIndexScalarByteArrayOp _ _ _   -> unhandledPrimop op+  VecReadScalarByteArrayOp _ _ _    -> unhandledPrimop op+  VecWriteScalarByteArrayOp _ _ _   -> unhandledPrimop op+  VecIndexScalarOffAddrOp _ _ _     -> unhandledPrimop op+  VecReadScalarOffAddrOp _ _ _      -> unhandledPrimop op+  VecWriteScalarOffAddrOp _ _ _     -> unhandledPrimop op++  PrefetchByteArrayOp3              -> noOp+  PrefetchMutableByteArrayOp3       -> noOp+  PrefetchAddrOp3                   -> noOp+  PrefetchValueOp3                  -> noOp+  PrefetchByteArrayOp2              -> noOp+  PrefetchMutableByteArrayOp2       -> noOp+  PrefetchAddrOp2                   -> noOp+  PrefetchValueOp2                  -> noOp+  PrefetchByteArrayOp1              -> noOp+  PrefetchMutableByteArrayOp1       -> noOp+  PrefetchAddrOp1                   -> noOp+  PrefetchValueOp1                  -> noOp+  PrefetchByteArrayOp0              -> noOp+  PrefetchMutableByteArrayOp0       -> noOp+  PrefetchAddrOp0                   -> noOp+  PrefetchValueOp0                  -> noOp++unhandledPrimop :: PrimOp -> [JStgExpr] -> [JStgExpr] -> JSM PrimRes+unhandledPrimop op rs as = pure $ PrimInline $ mconcat+  [ appS "h$log" $ pure $ String $+    fsLit $ mconcat+           [ "warning, unhandled primop: "+           , renderWithContext defaultSDocContext (ppr op)+           , " "+           , show (length rs, length as)+           ]+  , appS (mkFastString $ "h$primop_" ++ zEncodeString (renderWithContext defaultSDocContext (ppr op))) as+    -- copyRes+  , mconcat $ zipWith (\r reg -> r |= (foreignRegister reg)) rs (enumFrom Ret1)+  ]++-- | A No Op, used for primops the JS platform cannot or do not support. For+-- example, the prefetching primops do not make sense on the JS platform because+-- we do not have enough control over memory to provide any kind of prefetching+-- mechanism. Hence, these are NoOps.+noOp :: Foldable f => f a -> f a -> JSM PrimRes+noOp = const . const . pure $ PrimInline mempty++-- tuple returns+appT :: [JStgExpr] -> FastString -> [JStgExpr] -> JStgStat+appT []     f xs = appS f xs+appT (r:rs) f xs = mconcat+  [ r |= app f xs+  , mconcat (zipWith (\r ret -> r |= (foreignRegister ret)) rs (enumFrom Ret1))+  ]++--------------------------------------------+-- ByteArray indexing+--------------------------------------------++-- For every ByteArray, the RTS creates the following views:+--  i3: Int32 view+--  u8: Word8 view+--  u1: Word16 view+--  f3: Float32 view+--  f6: Float64 view+--  dv: generic DataView+-- It seems a bit weird to mix Int and Word views like this, but perhaps they+-- are the more common.+--+-- See 'h$newByteArray' in 'ghc/rts/js/mem.js' for details.+--+-- Note that *byte* indexing can only be done with the generic DataView. Use+-- read_boff_* and write_boff_* for this.+--+-- Other read_* and write_* helpers directly use the more specific views.+-- Prefer using them over idx_* to make your intent clearer.++idx_i32, idx_u8, idx_u16, idx_f64, idx_f32 :: JStgExpr -> JStgExpr -> JStgExpr+idx_i32 a i = IdxExpr (a .^ "i3") i+idx_u8  a i = IdxExpr (a .^ "u8") i+idx_u16 a i = IdxExpr (a .^ "u1") i+idx_f64 a i = IdxExpr (a .^ "f6") i+idx_f32 a i = IdxExpr (a .^ "f3") i++read_u8 :: JStgExpr -> JStgExpr -> JStgExpr+read_u8 a i = idx_u8 a i++read_u16 :: JStgExpr -> JStgExpr -> JStgExpr+read_u16 a i = idx_u16 a i++read_u32 :: JStgExpr -> JStgExpr -> JStgExpr+read_u32 a i = toU32 (idx_i32 a i)++read_i8 :: JStgExpr -> JStgExpr -> JStgExpr+read_i8 a i = signExtend8 (idx_u8 a i)++read_i16 :: JStgExpr -> JStgExpr -> JStgExpr+read_i16 a i = signExtend16 (idx_u16 a i)++read_i32 :: JStgExpr -> JStgExpr -> JStgExpr+read_i32 a i = idx_i32 a i++read_f32 :: JStgExpr -> JStgExpr -> JStgExpr+read_f32 a i = idx_f32 a i++read_f64 :: JStgExpr -> JStgExpr -> JStgExpr+read_f64 a i = idx_f64 a i++read_u64 :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+read_u64 a i rh rl = mconcat+  [ rl |= read_u32 a (i .<<. one_)+  , rh |= read_u32 a (Add one_ (i .<<. one_))+  ]++read_i64 :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+read_i64 a i rh rl = mconcat+  [ rl |= read_u32 a (i .<<. one_)+  , rh |= read_i32 a (Add one_ (i .<<. one_))+  ]++--------------------------------------+-- Addr#+--------------------------------------++write_addr :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+write_addr a i r o = mconcat+  [ write_i32 a i o+    -- create the hidden array for arrays if it doesn't exist+  , ifS (Not (a .^ "arr")) (a .^ "arr" |= ValExpr (JList [])) mempty+  , a .^ "arr" .! (i .<<. two_) |= r+  ]++read_addr :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+read_addr a i r o = mconcat+  [ o |= read_i32 a i+  , r |= if_ ((a .^ "arr") .&&. (a .^ "arr" .! (i .<<. two_)))+            (a .^ "arr" .! (i .<<. two_))+            null_+  ]++read_boff_addr :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+read_boff_addr a i r o = mconcat+  [ o |= read_boff_i32 a i+  , r |= if_ ((a .^ "arr") .&&. (a .^ "arr" .! i))+            (a .^ "arr" .! i)+            null_+  ]++write_boff_addr :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+write_boff_addr a i r o = mconcat+  [ write_boff_i32 a i o+    -- create the hidden array for arrays if it doesn't exist+  , ifS (Not (a .^ "arr")) (a .^ "arr" |= ValExpr (JList [])) mempty+  , a .^ "arr" .! i |= r+  ]+++--------------------------------------+-- StablePtr+--------------------------------------++read_stableptr :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+read_stableptr a i r o = mconcat+  [ o |= read_i32 a i+  , ifS (o .===. zero_)+      (r |= null_)+      (r |= var "h$stablePtrBuf")+  ]++read_boff_stableptr :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+read_boff_stableptr a i r o = mconcat+  [ o |= read_boff_i32 a i+  , ifS (o .===. zero_)+      (r |= null_)+      (r |= var "h$stablePtrBuf")+  ]++write_stableptr :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+write_stableptr a i _r o = write_i32 a i o+  -- don't store "r" as it must be h$stablePtrBuf or null++write_boff_stableptr :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+write_boff_stableptr a i _r o = write_boff_i32 a i o+  -- don't store "r" as it must be h$stablePtrBuf or null++write_u8 :: JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+write_u8 a i v = idx_u8 a i |= v++write_u16 :: JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+write_u16 a i v = idx_u16 a i |= v++write_u32 :: JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+write_u32 a i v = idx_i32 a i |= v++write_i8 :: JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+write_i8 a i v = idx_u8 a i |= v++write_i16 :: JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+write_i16 a i v = idx_u16 a i |= v++write_i32 :: JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+write_i32 a i v = idx_i32 a i |= v++write_f32 :: JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+write_f32 a i v = idx_f32 a i |= v++write_f64 :: JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+write_f64 a i v = idx_f64 a i |= v++write_u64 :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+write_u64 a i h l = mconcat+  [ write_u32 a (i .<<. one_)         l+  , write_u32 a (Add one_ (i .<<. one_)) h+  ]++write_i64 :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+write_i64 a i h l = mconcat+  [ write_u32 a (i .<<. one_)         l+  , write_i32 a (Add one_ (i .<<. one_)) h+  ]++-- Data View helper functions: byte indexed!+--+-- The argument list consists of the array @a@, the index @i@, and the new value+-- to set (in the case of a setter) @v@.++write_boff_i8, write_boff_u8, write_boff_i16, write_boff_u16, write_boff_i32, write_boff_u32, write_boff_f32, write_boff_f64 :: JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+write_boff_i8  a i v = write_i8 a i v+write_boff_u8  a i v = write_u8 a i v+write_boff_i16 a i v = ApplStat (a .^ "dv" .^ "setInt16"  ) [i, v, true_]+write_boff_u16 a i v = ApplStat (a .^ "dv" .^ "setUint16" ) [i, v, true_]+write_boff_i32 a i v = ApplStat (a .^ "dv" .^ "setInt32"  ) [i, v, true_]+write_boff_u32 a i v = ApplStat (a .^ "dv" .^ "setUint32" ) [i, v, true_]+write_boff_f32 a i v = ApplStat (a .^ "dv" .^ "setFloat32") [i, v, true_]+write_boff_f64 a i v = ApplStat (a .^ "dv" .^ "setFloat64") [i, v, true_]++write_boff_i64, write_boff_u64 :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+write_boff_i64 a i h l = mconcat+  [ write_boff_i32 a (Add i (Int 4)) h+  , write_boff_u32 a i l+  ]+write_boff_u64 a i h l = mconcat+  [ write_boff_u32 a (Add i (Int 4)) h+  , write_boff_u32 a i l+  ]++read_boff_i8, read_boff_u8, read_boff_i16, read_boff_u16, read_boff_i32, read_boff_u32, read_boff_f32, read_boff_f64 :: JStgExpr -> JStgExpr -> JStgExpr+read_boff_i8  a i = read_i8 a i+read_boff_u8  a i = read_u8 a i+read_boff_i16 a i = ApplExpr (a .^ "dv" .^ "getInt16"  ) [i, true_]+read_boff_u16 a i = ApplExpr (a .^ "dv" .^ "getUint16" ) [i, true_]+read_boff_i32 a i = ApplExpr (a .^ "dv" .^ "getInt32"  ) [i, true_]+read_boff_u32 a i = ApplExpr (a .^ "dv" .^ "getUint32" ) [i, true_]+read_boff_f32 a i = ApplExpr (a .^ "dv" .^ "getFloat32") [i, true_]+read_boff_f64 a i = ApplExpr (a .^ "dv" .^ "getFloat64") [i, true_]++read_boff_i64 :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+read_boff_i64 a i rh rl = mconcat+  [ rh |= read_boff_i32 a (Add i (Int 4))+  , rl |= read_boff_u32 a i+  ]++read_boff_u64 :: JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+read_boff_u64 a i rh rl = mconcat+  [ rh |= read_boff_u32 a (Add i (Int 4))+  , rl |= read_boff_u32 a i+  ]++fetchOpByteArray :: (JStgExpr -> JStgExpr -> JStgExpr) -> JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+fetchOpByteArray op tgt src i v = mconcat+  [ tgt |= read_i32 src i+  , write_i32 src i (op tgt v)+  ]++fetchOpAddr :: (JStgExpr -> JStgExpr -> JStgExpr) -> JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+fetchOpAddr op tgt src i v = mconcat+  [ tgt |= read_boff_u32 src i+  , write_boff_u32 src i (op tgt v)+  ]++casOp+  :: (JStgExpr -> JStgExpr -> JStgExpr)          -- read+  -> (JStgExpr -> JStgExpr -> JStgExpr -> JStgStat) -- write+  -> JStgExpr                     -- target register to store result+  -> JStgExpr                     -- source array+  -> JStgExpr                     -- index+  -> JStgExpr                     -- old value to compare+  -> JStgExpr                     -- new value to write+  -> JStgStat+casOp read write tgt src i old new = mconcat+  [ tgt |= read src i+  , ifS (tgt .===. old)+        (write src i new)+         mempty+  ]++casOp2+  :: (JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat) -- read+  -> (JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat) -- write+  -> (JStgExpr,JStgExpr)             -- target registers to store result+  -> JStgExpr                     -- source array+  -> JStgExpr                     -- index+  -> (JStgExpr,JStgExpr)             -- old value to compare+  -> (JStgExpr,JStgExpr)             -- new value to write+  -> JStgStat+casOp2 read write (tgt1,tgt2) src i (old1,old2) (new1,new2) = mconcat+  [ read src i tgt1 tgt2+  , ifS ((tgt2 .===. old2) .&&. (tgt1 .===. old1))+        (write src i new1 new2)+         mempty+  ]++--------------------------------------------------------------------------------+--                            Lifted Arrays+--------------------------------------------------------------------------------+-- | lifted arrays+cloneArray :: Bool -> JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgStat+cloneArray bound_check tgt src start len =+  bnd_arr_range bound_check src start len+  $ mconcat+      [ tgt |= ApplExpr (src .^ "slice") [start, Add len start]+      , tgt .^ closureMeta_   |= zero_+      , tgt .^ "__ghcjsArray" |= true_+      ]++newByteArray :: JStgExpr -> JStgExpr -> JStgStat+newByteArray tgt len =+  tgt |= app "h$newByteArray" [len]++-- | Check that index is positive and below a max value. Halt the process with+-- error code 134 otherwise. This is used to implement -fcheck-prim-bounds+check_bound+  :: JStgExpr -- ^ Max index expression+  -> Bool  -- ^ Should we do bounds checking?+  -> JStgExpr -- ^ Index+  -> JStgStat -- ^ Result+  -> JStgStat+check_bound _         False _ r = r+check_bound max_index True  i r = mconcat+  [ jwhenS ((i .<. zero_) .||. (i .>=. max_index)) $+      returnS (app "h$exitProcess" [Int 134])+  , r+  ]++-- | Bounds checking using ".length" property (Arrays)+bnd_arr+  :: Bool  -- ^ Should we do bounds checking?+  -> JStgExpr -- ^ Array+  -> JStgExpr -- ^ Index+  -> JStgStat -- ^ Result+  -> JStgStat+bnd_arr do_check arr = check_bound (arr .^ "length") do_check++-- | Range bounds checking using ".length" property (Arrays)+--+-- Empty ranges trivially pass the check+bnd_arr_range+  :: Bool  -- ^ Should we do bounds checking?+  -> JStgExpr -- ^ Array+  -> JStgExpr -- ^ Index+  -> JStgExpr -- ^ Range size+  -> JStgStat -- ^ Result+  -> JStgStat+bnd_arr_range False _arr _i _n r = r+bnd_arr_range True   arr  i  n r =+  ifS (n .<. zero_) (returnS $ app "h$exitProcess" [Int 134]) $+  -- Empty ranges trivially pass the check+  ifS (n .===. zero_)+      r+      (bnd_arr True arr i $ bnd_arr True arr (Add i (Sub n one_)) r)++-- | Bounds checking using ".len" property (ByteArrays)+bnd_ba+  :: Bool  -- ^ Should we do bounds checking?+  -> JStgExpr -- ^ Array+  -> JStgExpr -- ^ Index+  -> JStgStat -- ^ Result+  -> JStgStat+bnd_ba do_check arr = check_bound (arr .^ "len") do_check++-- | ByteArray bounds checking (byte offset, 8-bit value)+bnd_ba8 :: Bool -> JStgExpr -> JStgExpr -> JStgStat -> JStgStat+bnd_ba8 = bnd_ba++-- | ByteArray bounds checking (byte offset, 16-bit value)+bnd_ba16 :: Bool -> JStgExpr -> JStgExpr -> JStgStat -> JStgStat+bnd_ba16 do_check arr idx r =+  -- check that idx non incremented is in range:+  -- (idx + 1) may be in range while idx isn't+  bnd_ba do_check arr idx+  $ bnd_ba do_check arr (Add idx one_) r++-- | ByteArray bounds checking (byte offset, 32-bit value)+bnd_ba32 :: Bool -> JStgExpr -> JStgExpr -> JStgStat -> JStgStat+bnd_ba32 do_check arr idx r =+  -- check that idx non incremented is in range:+  -- (idx + 3) may be in range while idx isn't+  bnd_ba do_check arr idx+  $ bnd_ba do_check arr (Add idx three_) r++-- | ByteArray bounds checking (byte offset, 64-bit value)+bnd_ba64 :: Bool -> JStgExpr -> JStgExpr -> JStgStat -> JStgStat+bnd_ba64 do_check arr idx r =+  -- check that idx non incremented is in range:+  -- (idx + 7) may be in range while idx isn't+  bnd_ba do_check arr idx+  $ bnd_ba do_check arr (Add idx (Int 7)) r++-- | ByteArray bounds checking (8-bit offset, 8-bit value)+bnd_ix8 :: Bool -> JStgExpr -> JStgExpr -> JStgStat -> JStgStat+bnd_ix8 = bnd_ba8++-- | ByteArray bounds checking (16-bit offset, 16-bit value)+bnd_ix16 :: Bool -> JStgExpr -> JStgExpr -> JStgStat -> JStgStat+bnd_ix16 do_check arr idx r = bnd_ba16 do_check arr (idx .<<. one_) r++-- | ByteArray bounds checking (32-bit offset, 32-bit value)+bnd_ix32 :: Bool -> JStgExpr -> JStgExpr -> JStgStat -> JStgStat+bnd_ix32 do_check arr idx r = bnd_ba32 do_check arr (idx .<<. two_) r++-- | ByteArray bounds checking (64-bit offset, 64-bit value)+bnd_ix64 :: Bool -> JStgExpr -> JStgExpr -> JStgStat -> JStgStat+bnd_ix64 do_check arr idx r = bnd_ba64 do_check arr (idx .<<. three_) r++-- | Bounds checking on a range and using ".len" property (ByteArrays)+--+-- Empty ranges trivially pass the check+bnd_ba_range+  :: Bool  -- ^ Should we do bounds checking?+  -> JStgExpr -- ^ Array+  -> JStgExpr -- ^ Index+  -> JStgExpr -- ^ Range size+  -> JStgStat -- ^ Result+  -> JStgStat+bnd_ba_range False _  _ _ r = r+bnd_ba_range True  xs i n r =+  ifS (n .<. zero_) (returnS $ app "h$exitProcess" [Int 134]) $+  -- Empty ranges trivially pass the check+  ifS (n .===. zero_)+      r+      (bnd_ba True xs (Add i (Sub n one_)) (bnd_ba True xs i r))++checkOverlapByteArray+  :: Bool  -- ^ Should we do bounds checking?+  -> JStgExpr -- ^ First array+  -> JStgExpr -- ^ First offset+  -> JStgExpr -- ^ Second array+  -> JStgExpr -- ^ Second offset+  -> JStgExpr -- ^ Range size+  -> JStgStat -- ^ Result+  -> JStgStat+checkOverlapByteArray False _ _ _ _ _ r    = r+checkOverlapByteArray True a1 o1 a2 o2 n r =+  ifS (app "h$checkOverlapByteArray" [a1, o1, a2, o2, n])+    r+    (returnS $ app "h$exitProcess" [Int 134])++copyByteArray :: Bool -> Bool -> JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> JStgExpr -> PrimRes+copyByteArray allow_overlap bound a1 o1 a2 o2 n = PrimInline $+  check $ appS "h$copyMutableByteArray" [a1,o1,a2,o2,n]+  where+      check = bnd_ba_range bound a1 o1 n+              . bnd_ba_range bound a2 o2 n+              . (if not allow_overlap then checkOverlapByteArray bound a1 o1 a2 o2 n else id)++-- e|0 (32 bit signed integer truncation) required because of JS numbers. e|0+-- converts e to an Int32. Note that e|0 _is still a Double_ because JavaScript.+-- So (x|0) * (y|0) can still return values outside of the Int32 range. You have+-- been warned!+toI32 :: JStgExpr -> JStgExpr+toI32 e = BOr e zero_++-- e>>>0  (32 bit unsigned integer truncation)+-- required because of JS numbers. e>>>0 converts e to a Word32+-- so  (-2147483648)       >>> 0  = 2147483648+-- and ((-2147483648) >>>0) | 0   = -2147483648+toU32 :: JStgExpr -> JStgExpr+toU32 e = e .>>>. zero_++quotShortInt :: Int -> JStgExpr -> JStgExpr -> JStgExpr+quotShortInt bits x y = BAnd (signed x `Div` signed y) mask+  where+    signed z = (z .<<. shift) .>>. shift+    shift    = Int (32 - toInteger bits)+    mask     = Int (((2::Integer) ^ toInteger bits) - 1)++remShortInt :: Int -> JStgExpr -> JStgExpr -> JStgExpr+remShortInt bits x y = BAnd (signed x `Mod` signed y) mask+  where+    signed z = (z .<<. shift) .>>. shift+    shift    = Int (32 - toInteger bits)+    mask     = Int (((2::Integer) ^ toInteger bits) - 1)
compiler/GHC/StgToJS/Profiling.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE ViewPatterns      #-}  module GHC.StgToJS.Profiling   ( initCostCentres@@ -26,8 +27,10 @@  import GHC.Prelude -import GHC.JS.Unsat.Syntax+import GHC.JS.Syntax+import qualified GHC.JS.JStg.Syntax as JStg import GHC.JS.Make+import GHC.JS.Ident  import GHC.StgToJS.Regs import GHC.StgToJS.Types@@ -58,12 +61,13 @@       label  = costCentreUserName cc       modl   = moduleNameString $ moduleName $ cc_mod cc       loc    = renderWithContext defaultSDocContext (ppr (costCentreSrcSpan cc))-      js     = ccsLbl ||= UOpExpr NewOp (ApplExpr (var "h$CC")-                                                  [ toJExpr label-                                                  , toJExpr modl-                                                  , toJExpr loc-                                                  , toJExpr is_caf-                                                  ])+      js     = JStg.DeclStat ccsLbl+        (Just (JStg.UOpExpr JStg.NewOp (JStg.ApplExpr (JStg.var "h$CC")+                               [ toJExpr label+                               , toJExpr modl+                               , toJExpr loc+                               , toJExpr is_caf+                               ])))   emitGlobal js  emitCostCentreStackDecl :: CostCentreStack -> G ()@@ -72,43 +76,49 @@       Just cc -> do         ccsLbl <- singletonCCSLbl cc         ccLbl  <- costCentreLbl cc-        let js = ccsLbl ||= UOpExpr NewOp (ApplExpr (var "h$CCS") [null_, toJExpr ccLbl])+        let js =+              JStg.DeclStat ccsLbl+              (Just (JStg.UOpExpr JStg.NewOp+                     (JStg.ApplExpr (JStg.var "h$CCS") [null_, toJExpr ccLbl])))         emitGlobal js       Nothing -> pprPanic "emitCostCentreStackDecl" (ppr ccs)  -------------------------------------------------------------------------------- -- Entering to cost-centres -enterCostCentreFun :: CostCentreStack -> JStat+enterCostCentreFun :: CostCentreStack -> JStg.JStgStat enterCostCentreFun ccs-  | isCurrentCCS ccs = ApplStat (var "h$enterFunCCS") [jCurrentCCS, r1 .^ "cc"]+  | isCurrentCCS ccs = JStg.ApplStat (JStg.var "h$enterFunCCS")+                       [jCurrentCCS, JStg.SelExpr r1 (global "cc")]   | otherwise = mempty -- top-level function, nothing to do -enterCostCentreThunk :: JStat-enterCostCentreThunk = ApplStat (var "h$enterThunkCCS") [r1 .^ "cc"]+enterCostCentreThunk :: JStg.JStgStat+enterCostCentreThunk = JStg.ApplStat (JStg.var "h$enterThunkCCS") [JStg.SelExpr r1 (global "cc")] -setCC :: CostCentre -> Bool -> Bool -> G JStat+setCC :: CostCentre -> Bool -> Bool -> G JStg.JStgStat setCC cc _tick True = do-  ccI@(TxtI _ccLbl) <- costCentreLbl cc+  ccI@(identFS -> _ccLbl) <- costCentreLbl cc   addDependency $ OtherSymb (cc_mod cc)                             (moduleGlobalSymbol $ cc_mod cc)-  return $ jCurrentCCS |= ApplExpr (var "h$pushCostCentre") [jCurrentCCS, toJExpr ccI]+  return $ jCurrentCCS |= JStg.ApplExpr (JStg.var "h$pushCostCentre") [ jCurrentCCS+                                                                      , JStg.Var ccI+                                                                      ] setCC _cc _tick _push = return mempty -pushRestoreCCS :: JStat-pushRestoreCCS = ApplStat (var "h$pushRestoreCCS") []+pushRestoreCCS :: JStg.JStgStat+pushRestoreCCS = JStg.ApplStat (JStg.var "h$pushRestoreCCS") []  -------------------------------------------------------------------------------- -- Some cost-centre stacks to be used in generator -jCurrentCCS :: JExpr-jCurrentCCS = var "h$currentThread" .^ "ccs"+jCurrentCCS :: JStg.JStgExpr+jCurrentCCS = JStg.SelExpr (JStg.var "h$currentThread") (global "ccs") -jCafCCS :: JExpr-jCafCCS = var "h$CAF"+jCafCCS :: JStg.JStgExpr+jCafCCS = JStg.var "h$CAF" -jSystemCCS :: JExpr-jSystemCCS = var "h$CCS_SYSTEM"+jSystemCCS :: JStg.JStgExpr+jSystemCCS = JStg.var "h$CCS_SYSTEM" -------------------------------------------------------------------------------- -- Helpers for generating profiling related things @@ -125,8 +135,8 @@     prof <- profiling     if prof then m else return mempty --- | If profiling is enabled, then use input JStat, else ignore-profStat :: StgToJSConfig -> JStat -> JStat+-- | If profiling is enabled, then use input JStgStat, else ignore+profStat :: StgToJSConfig -> JStg.JStgStat -> JStg.JStgStat profStat cfg e = if csProf cfg then e else mempty -------------------------------------------------------------------------------- -- Generating cost-centre and cost-centre stack variables@@ -140,7 +150,7 @@     moduleNameColons (moduleName curModl) ++ "_" ++ if isCafCC cc then "CAF_ccs" else lbl  costCentreLbl :: CostCentre -> G Ident-costCentreLbl cc = TxtI . mkFastString <$> costCentreLbl' cc+costCentreLbl cc = global . mkFastString <$> costCentreLbl' cc  costCentreStackLbl' :: CostCentreStack -> G (Maybe String) costCentreStackLbl' ccs = do@@ -154,7 +164,7 @@             Nothing -> pure Nothing  costCentreStackLbl :: CostCentreStack -> G (Maybe Ident)-costCentreStackLbl ccs = fmap (TxtI . mkFastString) <$> costCentreStackLbl' ccs+costCentreStackLbl ccs = fmap (global . mkFastString) <$> costCentreStackLbl' ccs  singletonCCSLbl' :: CostCentre -> G String singletonCCSLbl' cc = do@@ -168,11 +178,11 @@               ]  singletonCCSLbl :: CostCentre -> G Ident-singletonCCSLbl cc = TxtI . mkFastString <$> singletonCCSLbl' cc+singletonCCSLbl cc = global . mkFastString <$> singletonCCSLbl' cc -ccsVarJ :: CostCentreStack -> G (Maybe JExpr)+ccsVarJ :: CostCentreStack -> G (Maybe JStg.JStgExpr) ccsVarJ ccs = do   prof <- profiling   if prof-    then fmap (ValExpr . JVar) <$> costCentreStackLbl ccs+    then fmap (JStg.ValExpr . JStg.JVar) <$> costCentreStackLbl ccs     else pure Nothing
compiler/GHC/StgToJS/Regs.hs view
@@ -16,12 +16,14 @@   , jsReg   , maxReg   , minReg+  , register+  , foreignRegister   ) where  import GHC.Prelude -import GHC.JS.Unsat.Syntax+import GHC.JS.JStg.Syntax import GHC.JS.Make  import GHC.Data.FastString@@ -78,13 +80,13 @@ -- helpers --------------------------------------------------- -sp :: JExpr+sp :: JStgExpr sp = toJExpr Sp -stack :: JExpr+stack :: JStgExpr stack = toJExpr Stack -r1, r2, r3, r4 :: JExpr+r1, r2, r3, r4 :: JStgExpr r1 = toJExpr R1 r2 = toJExpr R2 r3 = toJExpr R3@@ -97,7 +99,7 @@ intToJSReg :: Int -> StgReg intToJSReg r = toEnum (r - 1) -jsReg :: Int -> JExpr+jsReg :: Int -> JStgExpr jsReg r = toJExpr (intToJSReg r)  maxReg :: Int@@ -114,12 +116,12 @@ regsFromR2 :: [StgReg] regsFromR2 = tail regsFromR1 --- | List of registers, starting from R1 as JExpr-jsRegsFromR1 :: [JExpr]+-- | List of registers, starting from R1 as JStgExpr+jsRegsFromR1 :: [JStgExpr] jsRegsFromR1 = fmap toJExpr regsFromR1  -- | List of registers, starting from R2 as JExpr-jsRegsFromR2 :: [JExpr]+jsRegsFromR2 :: [JStgExpr] jsRegsFromR2 = tail jsRegsFromR1  ---------------------------------------------------@@ -127,7 +129,7 @@ ---------------------------------------------------  -- cache JExpr representing StgReg-registers :: Array StgReg JExpr+registers :: Array StgReg JStgExpr registers = listArray (minBound, maxBound) (map regN regsFromR1)   where     regN r@@ -136,7 +138,15 @@                             (toJExpr ((fromEnum r) - 32))  -- cache JExpr representing StgRet-rets :: Array StgRet JExpr+rets :: Array StgRet JStgExpr rets = listArray (minBound, maxBound) (map retN (enumFrom Ret1))   where     retN = var . mkFastString . ("h$"++) . map toLower . show++-- | Given a register, return the JS syntax object representing that register+register :: StgReg -> JStgExpr+register i = registers ! i++-- | Given a register, return the JS syntax object representing that register+foreignRegister :: StgRet -> JStgExpr+foreignRegister i = rets ! i
compiler/GHC/StgToJS/Rts/Rts.hs view
@@ -31,11 +31,10 @@  import GHC.Prelude -import GHC.JS.Unsat.Syntax-import GHC.JS.Make-import GHC.JS.Transform-import GHC.JS.Optimizer-import qualified GHC.JS.Syntax as Sat+import GHC.JS.JStg.Syntax+import GHC.JS.JStg.Monad+import GHC.JS.Make hiding (trace)+import GHC.JS.Ident  import GHC.StgToJS.Apply import GHC.StgToJS.Closure@@ -54,22 +53,22 @@ import qualified Data.Bits          as Bits  -- | The garbageCollector resets registers and result variables.-garbageCollector :: JStat-garbageCollector =-  mconcat [ jFun (TxtI "h$resetRegisters")  (mconcat $ map resetRegister [minBound..maxBound])-          , jFun (TxtI "h$resetResultVars") (mconcat $ map resetResultVar [minBound..maxBound])-          ]+garbageCollector :: JSM JStgStat+garbageCollector = jBlock+    [ jFunction' (global "h$resetRegisters")  (return $ mconcat $ map resetRegister [minBound..maxBound])+    , jFunction' (global "h$resetResultVars") (return $ mconcat $ map resetResultVar [minBound..maxBound])+    ]  -- | Reset the register 'r' in JS Land. Note that this "resets" by setting the -- register to a dummy variable called "null", /not/ by setting to JS's nil -- value.-resetRegister :: StgReg -> JStat+resetRegister :: StgReg -> JStgStat resetRegister r = toJExpr r |= null_  -- | Reset the return variable 'r' in JS Land. Note that this "resets" by -- setting the register to a dummy variable called "null", /not/ by setting to -- JS's nil value.-resetResultVar :: StgRet -> JStat+resetResultVar :: StgRet -> JStgStat resetResultVar r = toJExpr r |= null_  -- | Define closures based on size, these functions are syntactic sugar, e.g., a@@ -84,17 +83,19 @@ -- implications; you should use h$c1, h$c2, h$c3, ... h$c24 instead of making -- objects manually so layouts and fields can be changed more easily and so the -- JIT can optimize better.-closureConstructors :: StgToJSConfig -> JStat-closureConstructors s = BlockStat-  [ mconcat (map mkClosureCon (Nothing : map Just [0..jsClosureCount]))-  , mconcat (map mkDataFill [1..jsClosureCount])-  ]+closureConstructors :: StgToJSConfig -> JSM JStgStat+closureConstructors s = do+ closures <- mapM mkClosureCon (Nothing : map Just [0..jsClosureCount])+ fillers  <- mapM mkDataFill [1..jsClosureCount]+ return $ BlockStat $ closures ++ fillers+   where     prof = csProf s     (ccArg,ccVal)       -- the cc argument happens to be named just like the cc field...-      | prof      = ([TxtI closureCC_], Just (var closureCC_))+      | prof      = ([Var $ global closureCC_], Just (var closureCC_))       | otherwise = ([], Nothing)+     addCCArg' as = as ++ ccArg      traceAlloc x | csTraceRts s = appS "h$traceAlloc" [x]@@ -107,22 +108,22 @@     -- although it's possible (and legal) to make other Haskell types     -- to contain JS refs directly     -- this can cause false positives here-    checkC :: JStat+    checkC :: JSM JStgStat     checkC | csAssertRts s =       jVar $ \msg ->-      jwhenS (var "arguments" .! 0 .!==. jString "h$baseZCGHCziJSziPrimziJSVal_con_e")-                                  (loop 1 (.<. var "arguments" .^ "length")-                                          (\i ->-                                             mconcat [msg |= jString "warning: undefined or null in argument: "-                                                       + i-                                                       + jString " allocating closure: " + (var "arguments" .! 0 .^ "n")-                                                     , appS "h$log" [msg]-                                                     , jwhenS (var "console" .&&. (var "console" .^ "trace")) ((var "console" .^ "trace") `ApplStat` [msg])-                                                     , postIncrS i-                                                     ])--                                  )-           | otherwise = mempty+        jwhenS (var "arguments" .! 0 .!==. jString "h$ghczminternalZCGHCziInternalziJSziPrimziJSVal_con_e")+        <$>+        (loop 1 (.<. var "arguments" .^ "length")+          (\i ->+              return $+              mconcat [msg |= jString "warning: undefined or null in argument: "+                        + i+                        + jString " allocating closure: " + (var "arguments" .! 0 .^ "n")+                      , appS "h$log" [msg]+                      , jwhenS (var "console" .&&. (var "console" .^ "trace")) ((var "console" .^ "trace") `ApplStat` [msg])+                      , postIncrS i+                      ]))+           | otherwise = pure mempty      -- h$d is never used for JSVal (since it's only for constructors with     -- at least three fields, so we always warn here@@ -130,69 +131,94 @@                      loop 0 (.<. var "arguments" .^ "length")                      (\i -> jwhenS ((var "arguments" .! i .===. null_)                                     .||. (var "arguments" .! i .===. undefined_))-                            (jVar $ \msg ->+                            <$>+                            (jVar \msg->+                                return $                                 mconcat [ msg |= jString "warning: undefined or null in argument: " + i + jString " allocating fields"                                         , jwhenS (var "console" .&&. (var "console" .^ "trace"))                                                 ((var "console" .^ "trace") `ApplStat` [msg])                                         ])) -           | otherwise = mempty+           | otherwise = pure mempty -    mkClosureCon :: Maybe Int -> JStat-    mkClosureCon n0 = jFunction funName args funBod+    -- special case handler, the key difference is a call to @jFunction@ instead+    -- of @jFunctionSized@+    singleton_closure_con name = jFunction (global $ mkFastString name) $+      \(MkSolo f) -> do+        chk_c <- checkC+        jVar $ \x ->+          return $ mconcat $+          [ chk_c+          , x |= newClosure (mkClosure f mempty 0 ccVal)+          , notifyAlloc x+          , traceAlloc x+          , returnS x+          ]++    mkClosureCon :: Maybe Int -> JSM JStgStat+    -- the h$c special case+    mkClosureCon Nothing  = singleton_closure_con "h$c"+    -- the h$c0 special case+    mkClosureCon (Just 0) = singleton_closure_con "h$c0"+    -- the rest h$c1 .. h$c24. Note that h$c1 takes 2 arguments, one for the+    -- entry function 'f' and another for the data field 'd1'. Thus the 1 in+    -- h$c1 means 1 data field argument, not just one argument+    mkClosureCon (Just n) = jFunctionSized funName (n + 1) funBod       where-        n | Just n' <- n0 = n'-          | Nothing <- n0 = 0-        funName | Just n' <- n0 = TxtI $ clsName n'-                | Nothing <- n0 = TxtI $ mkFastString "h$c"-        -- args are: f x1 x2 .. xn [cc]-        args   = TxtI "f" : addCCArg' (map varName [1..n])-        -- x1 goes into closureField1. All the other args are bundled into an-        -- object in closureField2: { d1 = x2, d2 = x3, ... }-        ---        vars   = map (toJExpr . varName) [1..n]+        funName = global $ clsName n -        funBod = jVar $ \x ->-            [ checkC-            , x |= newClosure (mkClosure (var "f") vars 0 ccVal)+        funBod [] = pure mempty -- impossible+        funBod (f:vars') = do+          let vars = addCCArg' vars'+          chk_c <- checkC+          jVar $ \x ->+            return $ mconcat $+            [ chk_c+            , x |= newClosure (mkClosure f vars 0 ccVal)             , notifyAlloc x             , traceAlloc x             , returnS x             ] -    mkDataFill :: Int -> JStat-    mkDataFill n = jFunction funName (map TxtI ds) body+    mkDataFill :: Int -> JSM JStgStat+    mkDataFill n = jFunctionSized funName n body       where-        funName    = TxtI $ dataName n+        funName    = global $ dataName n         ds         = map dataFieldName [1..n]-        extra_args = ValExpr . JHash . listToUniqMap . zip ds $ map (toJExpr . TxtI) ds-        body       = (checkD <> returnS extra_args)+        extra_args as = ValExpr . JHash+                        . listToUniqMap+                        $ zip ds as+        body :: [JStgExpr] -> JSM JStgStat+        body ids = do+          c <- checkD+          return (c <> returnS (extra_args ids))  -- | JS Payload to perform stack manipulation in the RTS-stackManip :: JStat-stackManip = mconcat (map mkPush [1..32]) <>-             mconcat (map mkPpush [1..255])+stackManip :: JSM JStgStat+stackManip = do+  pushes  <- mapM mkPush [1..32]+  ppushes <- mapM mkPpush [1..255]+  return $ mconcat $ pushes ++ ppushes   where-    mkPush :: Int -> JStat-    mkPush n = let funName = TxtI $ mkFastString ("h$p" ++ show n)-                   as      = map varName [1..n]-                   body    = ((sp |= sp + toJExpr n)-                               <> mconcat (zipWith (\i a -> stack .! (sp - toJExpr (n-i)) |= toJExpr a)+    mkPush :: Int -> JSM JStgStat+    mkPush n = let funName = global $ mkFastString ("h$p" ++ show n)+                   body as = return $+                     ((sp |= sp + toJExpr n)+                       <> mconcat (zipWith (\i a -> stack .! (sp - toJExpr (n-i)) |= a)                                             [1..] as))-               in jFunction funName as body+               in jFunctionSized funName n body      -- partial pushes, based on bitmap, increases Sp by highest bit-    mkPpush :: Integer -> JStat-    mkPpush sig | sig Bits..&. (sig+1) == 0 = mempty -- already handled by h$p-    mkPpush sig = let funName = TxtI $ mkFastString ("h$pp" ++ show sig)+    mkPpush :: Integer -> JSM JStgStat+    mkPpush sig | sig Bits..&. (sig+1) == 0 = pure mempty -- already handled by h$p+    mkPpush sig = let funName = global $ mkFastString ("h$pp" ++ show sig)                       bits    = bitsIdx sig-                      n       = length bits                       h       = last bits-                      args    = map varName [1..n]-                      body    = mconcat [ sp |= sp + toJExpr (h+1)-                                        , mconcat (zipWith (\b a -> stack .! (sp - toJExpr (h-b)) |= toJExpr a) bits args)-                                        ]-                   in jFunction funName args body+                      body args = return $+                        mconcat [ sp |= sp + toJExpr (h+1)+                                , mconcat (zipWith (\b a -> stack .! (sp - toJExpr (h-b)) |= a) bits args)+                                ]+                   in jFunctionSized funName (length bits) body  bitsIdx :: Integer -> [Int] bitsIdx n | n < 0 = error "bitsIdx: negative"@@ -202,66 +228,69 @@     go m b | Bits.testBit m b = b : go (Bits.clearBit m b) (b+1)            | otherwise   = go (Bits.clearBit m b) (b+1) -bhLneStats :: StgToJSConfig -> JExpr -> JExpr -> JStat-bhLneStats _s p frameSize =-   jVar $ \v ->-            mconcat [ v |= stack .! p-                    , ifS v-                      ((sp |= sp - frameSize)-                       <> ifS (v .===. var "h$blackhole")-                                (returnS $ app "h$throw" [var "h$baseZCControlziExceptionziBasezinonTermination", false_])-                                (mconcat [r1 |= v-                                         , sp |= sp - frameSize-                                         , returnStack-                                         ]))-                      ((stack .! p |= var "h$blackhole") <> returnS null_)-                    ]+bhLneStats :: StgToJSConfig -> JStgExpr -> JStgExpr -> JSM JStgStat+bhLneStats _s p frameSize = jVar $ \v ->+  return $ mconcat+  [ v |= stack .! p+  , ifS v+    ((sp |= sp - frameSize)+      <> ifS (v .===. var "h$blackhole")+      (returnS $ app "h$throw" [var "h$ghczminternalZCGHCziInternalziControlziExceptionziBasezinonTermination", false_])+      (mconcat [r1 |= v+               , sp |= sp - frameSize+               , returnStack+               ]))+    ((stack .! p |= var "h$blackhole") <> returnS null_)+  ]   -- | JS payload to declare the registers-declRegs :: JStat-declRegs =-  mconcat [ TxtI "h$regs" ||= toJExpr (JList [])-          , mconcat (map declReg (enumFromTo R1 R32))-          , regGettersSetters-          , loadRegs-          ]+declRegs :: JSM JStgStat+declRegs = do+    getters_setters <- regGettersSetters+    loaders         <- loadRegs+    return $+      mconcat [ global "h$regs" ||= toJExpr (JList [])+              , mconcat (map declReg (enumFromTo R1 R32))+              , getters_setters+              , loaders+              ]     where-      declReg r = (decl . TxtI . mkFastString . ("h$"++) . map toLower . show) r-                  <> BlockStat [AssignStat (toJExpr r) (ValExpr (JInt 0))] -- [j| `r` = 0; |]+      declReg r = (decl . global . mkFastString . ("h$"++) . map toLower . show) r+                  <> BlockStat [toJExpr r |= zero_]  -- | JS payload to define getters and setters on the registers.-regGettersSetters :: JStat+regGettersSetters :: JSM JStgStat regGettersSetters =-  mconcat [ jFun (TxtI "h$getReg") (\n   -> SwitchStat n getRegCases mempty)-          , jFun (TxtI "h$setReg") (\n v -> SwitchStat n (setRegCases v) mempty)-          ]+  do setters <- jFunction (global "h$getReg") (\(MkSolo n) -> return $ SwitchStat n getRegCases mempty)+     getters <- jFunction (global "h$setReg") (\(n,v)    -> return $ SwitchStat n (setRegCases v) mempty)+     return $ setters <> getters   where     getRegCases =       map (\r -> (toJExpr (jsRegToInt r) , returnS (toJExpr r))) regsFromR1+    setRegCases :: JStgExpr -> [(JStgExpr,JStgStat)]     setRegCases v =       map (\r -> (toJExpr (jsRegToInt r), (toJExpr r |= toJExpr v) <> returnS undefined_)) regsFromR1  -- | JS payload that defines the functions to load each register-loadRegs :: JStat-loadRegs = mconcat $ map mkLoad [1..32]+loadRegs :: JSM JStgStat+loadRegs = mconcat <$> mapM mkLoad [1..32]   where-    mkLoad :: Int -> JStat-    mkLoad n = let args  = map varName [1..n]-                   body  = mconcat $-                           zipWith (\a r -> toJExpr r |= toJExpr a)+    mkLoad :: Int -> JSM JStgStat+    mkLoad n = let body  = \args -> return $ mconcat $+                           zipWith (\a r -> toJExpr r |= a)                            args (reverse $ take n regsFromR1)-                   fname = TxtI $ mkFastString ("h$l" ++ show n)-               in jFunction fname args body+                   fname = global $ mkFastString ("h$l" ++ show n)+               in jFunctionSized fname n body  -- | Assign registers R1 ... Rn in descending order, that is assign Rn first. -- This function uses the 'assignRegs'' array to construct functions which set -- the registers.-assignRegs :: StgToJSConfig -> [JExpr] -> JStat+assignRegs :: StgToJSConfig -> [JStgExpr] -> JStgStat assignRegs _ [] = mempty assignRegs s xs   | l <= 32 && not (csInlineLoadRegs s)-      = ApplStat (ValExpr (JVar $ assignRegs'!l)) (reverse xs)+      = ApplStat (ValExpr (JVar $ assignRegs' ! l)) (reverse xs)   | otherwise = mconcat . reverse $       zipWith (\r ex -> toJExpr r |= ex) (take l regsFromR1) xs   where@@ -278,161 +307,153 @@ --    }; -- @ assignRegs' :: Array Int Ident-assignRegs' = listArray (1,32) (map (TxtI . mkFastString . ("h$l"++) . show) [(1::Int)..32])+assignRegs' = listArray (1,32) (map (global . mkFastString . ("h$l"++) . show) [(1::Int)..32])  -- | JS payload to declare return variables.-declRets :: JStat-declRets = mconcat $ map (decl . TxtI . mkFastString . ("h$"++) . map toLower . show) (enumFrom Ret1)+declRets :: JStgStat+declRets = mconcat $ map (decl . global . mkFastString . ("h$"++) . map toLower . show) (enumFrom Ret1)  -- | JS payload defining the types closures.-closureTypes :: JStat-closureTypes = mconcat (map mkClosureType (enumFromTo minBound maxBound)) <> closureTypeName+closureTypes :: JSM JStgStat+closureTypes = do+  cls_typ_nm <- closureTypeName+  return $+    mconcat (map mkClosureType (enumFromTo minBound maxBound))+    <> cls_typ_nm   where-    mkClosureType :: ClosureType -> JStat-    mkClosureType c = let s = TxtI . mkFastString $ "h$" ++ map toUpper (show c) ++ "_CLOSURE"+    mkClosureType :: ClosureType -> JStgStat+    mkClosureType c = let s = global . mkFastString $ "h$" ++ map toUpper (show c) ++ "_CLOSURE"                       in  s ||= toJExpr c-    closureTypeName :: JStat-    closureTypeName = jFun (TxtI "h$closureTypeName") \c ->-                        mconcat (map (ifCT c) [minBound..maxBound])-                        <> returnS (jString "InvalidClosureType")+    closureTypeName :: JSM JStgStat+    closureTypeName = jFunction (global "h$closureTypeName")+                      \(MkSolo c) -> return $+                              mconcat (map (ifCT c) [minBound..maxBound])+                              <> returnS (jString "InvalidClosureType") -    ifCT :: JExpr -> ClosureType -> JStat+    ifCT :: JStgExpr -> ClosureType -> JStgStat     ifCT arg ct = jwhenS (arg .===. toJExpr ct) (returnS (toJExpr (show ct)))  -- | JS payload declaring the RTS functions.-rtsDecls :: JStat-rtsDecls =-  mconcat [ TxtI "h$currentThread"   ||= null_                   -- thread state object for current thread-          , TxtI "h$stack"           ||= null_                   -- stack for the current thread-          , TxtI "h$sp"              ||= 0                       -- stack pointer for the current thread-          , TxtI "h$initStatic"      ||= toJExpr (JList [])      -- we need delayed initialization for static objects, push functions here to be initialized just before haskell runs-          , TxtI "h$staticThunks"    ||= toJExpr (jhFromList []) --  funcName -> heapidx map for srefs-          , TxtI "h$staticThunksArr" ||= toJExpr (JList [])      -- indices of updatable thunks in static heap-          , TxtI "h$CAFs"            ||= toJExpr (JList [])-          , TxtI "h$CAFsReset"       ||= toJExpr (JList [])-          -- stg registers-          , declRegs-          , declRets]+rtsDecls :: JSM JStgStat+rtsDecls = do+  decl_stg_regs <- declRegs+  return $+    mconcat [ global "h$currentThread"   ||= null_                   -- thread state object for current thread+            , global "h$stack"           ||= null_                   -- stack for the current thread+            , global "h$sp"              ||= 0                       -- stack pointer for the current thread+            , global "h$initStatic"      ||= toJExpr (JList [])      -- we need delayed initialization for static objects, push functions here to be initialized just before haskell runs+            , global "h$staticThunks"    ||= toJExpr (jhFromList []) --  funcName -> heapidx map for srefs+            , global "h$staticThunksArr" ||= toJExpr (JList [])      -- indices of updatable thunks in static heap+            , global "h$CAFs"            ||= toJExpr (JList [])+            , global "h$CAFsReset"       ||= toJExpr (JList [])+            -- stg registers+            , decl_stg_regs+            , declRets]  -- | Generated RTS code-rts :: StgToJSConfig -> Sat.JStat-rts cfg = jsOptimize $ satJStat (Just "h$RTS") $ mconcat-  [ rtsDecls-  , rts' cfg-  ]+rts :: StgToJSConfig -> JSM JStgStat+rts cfg = withTag "h$RTS" $+  do+  rts_      <- rts_gen cfg+  rts_decls <- rtsDecls+  return $  rts_decls <> rts_  -- | JS Payload which defines the embedded RTS.-rts' :: StgToJSConfig -> JStat-rts' s =-  mconcat [ closureConstructors s-          , garbageCollector-          , stackManip-          , TxtI "h$rts_traceForeign" ||= toJExpr (csTraceForeign s)-          , TxtI "h$rts_profiling"    ||= toJExpr (csProf s)-          , TxtI "h$ct_fun"        ||= toJExpr Fun-          , TxtI "h$ct_con"        ||= toJExpr Con-          , TxtI "h$ct_thunk"      ||= toJExpr Thunk-          , TxtI "h$ct_pap"        ||= toJExpr Pap-          , TxtI "h$ct_blackhole"  ||= toJExpr Blackhole-          , TxtI "h$ct_stackframe" ||= toJExpr StackFrame-          , TxtI "h$vt_ptr"    ||= toJExpr PtrV-          , TxtI "h$vt_void"   ||= toJExpr VoidV-          , TxtI "h$vt_double" ||= toJExpr IntV-          , TxtI "h$vt_long"   ||= toJExpr LongV-          , TxtI "h$vt_addr"   ||= toJExpr AddrV-          , TxtI "h$vt_obj"    ||= toJExpr ObjV-          , TxtI "h$vt_arr"    ||= toJExpr ArrV-          , jFun (TxtI "h$bh")     (bhStats s True)-          , jFun (TxtI "h$bh_lne") (\x frameSize -> bhLneStats s x frameSize)-          , closure (ClosureInfo (TxtI "h$blackhole") (CIRegs 0 []) "blackhole" (CILayoutUnknown 2) CIBlackhole mempty)-               (appS "throw" [jString "oops: entered black hole"])-          , closure (ClosureInfo (TxtI "h$blackholeTrap") (CIRegs 0 []) "blackhole" (CILayoutUnknown 2) CIThunk mempty)-               (appS "throw" [jString "oops: entered multiple times"])-          , closure (ClosureInfo (TxtI "h$done") (CIRegs 0 [PtrV]) "done" (CILayoutUnknown 0) CIStackFrame mempty)-               (appS "h$finishThread" [var "h$currentThread"] <> returnS (var "h$reschedule"))-          , closure (ClosureInfo (TxtI "h$doneMain_e") (CIRegs 0 [PtrV]) "doneMain" (CILayoutUnknown 0) CIStackFrame mempty)-               (returnS (var "h$doneMain"))-          , conClosure (TxtI "h$false_e") "GHC.Types.False" (CILayoutFixed 0 []) 1-          , conClosure (TxtI "h$true_e" ) "GHC.Types.True"  (CILayoutFixed 0 []) 2-          -- generic data constructor with 1 non-heapobj field-          , conClosure (TxtI "h$data1_e") "data1" (CILayoutFixed 1 [ObjV]) 1-          -- generic data constructor with 2 non-heapobj fields-          , conClosure (TxtI "h$data2_e") "data2" (CILayoutFixed 2 [ObjV,ObjV]) 1-          , closure (ClosureInfo (TxtI "h$noop_e") (CIRegs 1 [PtrV]) "no-op IO ()" (CILayoutFixed 0 []) (CIFun 1 0) mempty)-               (returnS (stack .! sp))-            <> (TxtI "h$noop" ||= ApplExpr (var "h$c0") (var "h$noop_e" : [jSystemCCS | csProf s]))-          , closure (ClosureInfo (TxtI "h$catch_e") (CIRegs 0 [PtrV]) "exception handler" (CILayoutFixed 2 [PtrV,IntV]) CIStackFrame mempty)-               (adjSpN' 3 <> returnS (stack .! sp))-          , closure (ClosureInfo (TxtI "h$dataToTag_e") (CIRegs 0 [PtrV]) "data to tag" (CILayoutFixed 0 []) CIStackFrame mempty)-                $ mconcat [ r1 |= if_ (r1 .===. true_) 1 (if_ (typeof r1 .===. jTyObject) (r1 .^ "f" .^ "a" - 1) 0)-                          , adjSpN' 1-                          , returnS (stack .! sp)-                          ]-          -- function application to one argument-          , closure (ClosureInfo (TxtI "h$ap1_e") (CIRegs 0 [PtrV]) "apply1" (CILayoutFixed 2 [PtrV, PtrV]) CIThunk mempty)-               (jVar $ \d1 d2 ->-                   mconcat [ d1 |= closureField1 r1-                           , d2 |= closureField2 r1-                           , appS "h$bh" []-                           , profStat s enterCostCentreThunk-                           , r1 |= d1-                           , r2 |= d2-                           , returnS (app "h$ap_1_1_fast" [])-                           ])-          -- function application to two arguments-          , closure (ClosureInfo (TxtI "h$ap2_e") (CIRegs 0 [PtrV]) "apply2" (CILayoutFixed 3 [PtrV, PtrV, PtrV]) CIThunk mempty)-               (jVar $ \d1 d2 d3 ->-                   mconcat [ d1 |= closureField1 r1-                           , d2 |= closureField2 r1 .^ "d1"-                           , d3 |= closureField2 r1 .^ "d2"-                           , appS "h$bh" []-                           , profStat s enterCostCentreThunk-                           , r1 |= d1-                           , r2 |= d2-                           , r3 |= d3-                           , returnS (app "h$ap_2_2_fast" [])-                           ])-          -- function application to three arguments-          , closure (ClosureInfo (TxtI "h$ap3_e") (CIRegs 0 [PtrV]) "apply3" (CILayoutFixed 4 [PtrV, PtrV, PtrV, PtrV]) CIThunk mempty)-               (jVar $ \d1 d2 d3 d4 ->-                   mconcat [ d1 |= closureField1 r1-                           , d2 |= closureField2 r1 .^ "d1"-                           , d3 |= closureField2 r1 .^ "d2"-                           , d4 |= closureField2 r1 .^ "d3"-                           , appS "h$bh" []-                           , r1 |= d1-                           , r2 |= d2-                           , r3 |= d3-                           , r4 |= d4-                           , returnS (app "h$ap_3_3_fast" [])-                           ])-          -- select first field-          , closure (ClosureInfo (TxtI "h$select1_e") (CIRegs 0 [PtrV]) "select1" (CILayoutFixed 1 [PtrV]) CIThunk mempty)-               (jVar $ \t ->-                   mconcat [ t |= closureField1 r1-                           , adjSp' 3-                           , stack .! (sp - 2) |= r1-                           , stack .! (sp - 1) |= var "h$upd_frame"-                           , stack .! sp |= var "h$select1_ret"-                           , closureEntry  r1 |= var "h$blackhole"-                           , closureField1 r1 |= var "h$currentThread"-                           , closureField2 r1 |= null_-                           , r1 |= t-                           , returnS (app "h$ap_0_0_fast" [])-                           ])-          , closure (ClosureInfo (TxtI "h$select1_ret") (CIRegs 0 [PtrV]) "select1ret" (CILayoutFixed 0 []) CIStackFrame mempty)-               ((r1 |= closureField1 r1)-                <> adjSpN' 1-                <> returnS (app "h$ap_0_0_fast" [])-               )-          -- select second field of a two-field constructor-          , closure (ClosureInfo (TxtI "h$select2_e") (CIRegs 0 [PtrV]) "select2" (CILayoutFixed 1 [PtrV]) CIThunk mempty)-               (jVar $ \t ->+rts_gen :: StgToJSConfig -> JSM JStgStat+rts_gen s = do+  let decls = [ global "h$rts_traceForeign" ||= toJExpr (csTraceForeign s)+              , global "h$rts_profiling"    ||= toJExpr (csProf s)+              , global "h$ct_fun"        ||= toJExpr Fun+              , global "h$ct_con"        ||= toJExpr Con+              , global "h$ct_thunk"      ||= toJExpr Thunk+              , global "h$ct_pap"        ||= toJExpr Pap+              , global "h$ct_blackhole"  ||= toJExpr Blackhole+              , global "h$ct_stackframe" ||= toJExpr StackFrame+              , global "h$vt_ptr"    ||= toJExpr PtrV+              , global "h$vt_void"   ||= toJExpr VoidV+              , global "h$vt_double" ||= toJExpr IntV+              , global "h$vt_long"   ||= toJExpr LongV+              , global "h$vt_addr"   ||= toJExpr AddrV+              , global "h$vt_obj"    ||= toJExpr ObjV+              , global "h$vt_arr"    ||= toJExpr ArrV+              ]+  gc           <- garbageCollector+  closure_cons <- closureConstructors s+  stk_manip    <- stackManip+  rest         <- impure+  return $ mconcat $ pure gc <> decls <> [closure_cons, stk_manip] <> rest+  where+    impure = sequence+             [ jFunction' (global "h$bh")     (return $ bhStats s True)+             , jFunction (global "h$bh_lne") (\(x, frameSize) -> bhLneStats s x frameSize)+             , closure (ClosureInfo (global "h$blackhole") (CIRegs 0 []) "blackhole" (CILayoutUnknown 2) CIBlackhole mempty)+               (return $ appS "throw" [jString "oops: entered black hole"])+             , closure (ClosureInfo (global "h$blackholeTrap") (CIRegs 0 []) "blackhole" (CILayoutUnknown 2) CIThunk mempty)+               (return $ appS "throw" [jString "oops: entered multiple times"])+             , closure (ClosureInfo (global "h$done") (CIRegs 0 [PtrV]) "done" (CILayoutUnknown 0) CIStackFrame mempty)+               (return $ appS "h$finishThread" [var "h$currentThread"] <> returnS (var "h$reschedule"))+             , closure (ClosureInfo (global "h$doneMain_e") (CIRegs 0 [PtrV]) "doneMain" (CILayoutUnknown 0) CIStackFrame mempty)+               (return $ returnS (var "h$doneMain"))+             , conClosure (global "h$false_e") "GHC.Types.False" (CILayoutFixed 0 []) 1+             , conClosure (global "h$true_e" ) "GHC.Types.True"  (CILayoutFixed 0 []) 2+             -- generic data constructor with 1 non-heapobj field+             , conClosure (global "h$data1_e") "data1" (CILayoutFixed 1 [ObjV]) 1+             -- generic data constructor with 2 non-heapobj fields+             , conClosure (global "h$data2_e") "data2" (CILayoutFixed 2 [ObjV,ObjV]) 1+             , closure (ClosureInfo (global "h$noop_e") (CIRegs 1 [PtrV]) "no-op IO ()" (CILayoutFixed 0 []) (CIFun 1 0) mempty)+               $ return (returnS (stack .! sp))+             , pure (global "h$noop" ||= ApplExpr (var "h$c0") (var "h$noop_e" : [jSystemCCS | csProf s]))+             , closure (ClosureInfo (global "h$catch_e") (CIRegs 0 [PtrV]) "exception handler" (CILayoutFixed 2 [PtrV,IntV]) CIStackFrame mempty)+                  (return $ adjSpN' 3 <> returnS (stack .! sp))+             , closure (ClosureInfo (global "h$dataToTag_e") (CIRegs 0 [PtrV]) "data to tag" (CILayoutFixed 0 []) CIStackFrame mempty)+                   $ return $ mconcat [ r1 |= if_ (r1 .===. true_) 1 (if_ (typeof r1 .===. jTyObject) (r1 .^ "f" .^ "a" - 1) 0)+                                      , adjSpN' 1+                                      , returnS (stack .! sp)+                                      ]+             -- function application to one argument+             , closure (ClosureInfo (global "h$ap1_e") (CIRegs 0 [PtrV]) "apply1" (CILayoutFixed 2 [PtrV, PtrV]) CIThunk mempty)+                  (jVars \(d1, d2) -> return $+                                mconcat [ d1 |= closureField1 r1+                                        , d2 |= closureField2 r1+                                        , appS "h$bh" []+                                        , profStat s enterCostCentreThunk+                                        , r1 |= d1+                                        , r2 |= d2+                                        , returnS (app "h$ap_1_1_fast" [])+                                        ])+             -- function application to two arguments+             , closure (ClosureInfo (global "h$ap2_e") (CIRegs 0 [PtrV]) "apply2" (CILayoutFixed 3 [PtrV, PtrV, PtrV]) CIThunk mempty)+                  (jVars \(d1, d2, d3) -> return $+                                    mconcat [ d1 |= closureField1 r1+                                            , d2 |= closureField2 r1 .^ "d1"+                                            , d3 |= closureField2 r1 .^ "d2"+                                            , appS "h$bh" []+                                            , profStat s enterCostCentreThunk+                                            , r1 |= d1+                                            , r2 |= d2+                                            , r3 |= d3+                                            , returnS (app "h$ap_2_2_fast" [])+                                            ])+             -- function application to three arguments+             , closure (ClosureInfo (global "h$ap3_e") (CIRegs 0 [PtrV]) "apply3" (CILayoutFixed 4 [PtrV, PtrV, PtrV, PtrV]) CIThunk mempty)+                  (jVars \(d1, d2, d3, d4) -> return $+                                        mconcat [ d1 |= closureField1 r1+                                                , d2 |= closureField2 r1 .^ "d1"+                                                , d3 |= closureField2 r1 .^ "d2"+                                                , d4 |= closureField2 r1 .^ "d3"+                                                , appS "h$bh" []+                                                , r1 |= d1+                                                , r2 |= d2+                                                , r3 |= d3+                                                , r4 |= d4+                                                , returnS (app "h$ap_3_3_fast" [])+                                                ])+             , closure (ClosureInfo (TxtI "h$upd_thunk_e") (CIRegs 0 [PtrV]) "updatable thunk" (CILayoutFixed 1 [PtrV]) CIThunk mempty)+               (jVar $ \t -> return $                    mconcat [t |= closureField1 r1-                           , adjSp' 3-                           , stack .! (sp - 2) |= r1-                           , stack .! (sp - 1) |= var "h$upd_frame"-                           , stack .! sp |= var "h$select2_ret"+                           , adjSp' 2+                           , stack .! (sp - 1) |= r1+                           , stack .! sp       |= var "h$upd_frame"                            , closureEntry  r1 |= var "h$blackhole"                            , closureField1 r1 |= var "h$currentThread"                            , closureField2 r1 |= null_@@ -440,174 +461,218 @@                            , returnS (app "h$ap_0_0_fast" [])                            ]                   )-          , closure (ClosureInfo (TxtI "h$select2_ret") (CIRegs 0 [PtrV]) "select2ret" (CILayoutFixed 0 []) CIStackFrame mempty)-                        $ mconcat [ r1 |= closureField2 r1-                                  , adjSpN' 1-                                  , returnS (app "h$ap_0_0_fast" [])-                                  ]-          , closure (ClosureInfo (TxtI "h$keepAlive_e") (CIRegs 0 [PtrV]) "keepAlive" (CILayoutFixed 1 [PtrV]) CIStackFrame mempty)-                    (mconcat [ adjSpN' 2-                             , returnS (stack .! sp)-                             ]-                    )-          -- a thunk that just raises a synchronous exception-          , closure (ClosureInfo (TxtI "h$raise_e") (CIRegs 0 [PtrV]) "h$raise_e" (CILayoutFixed 0 []) CIThunk mempty)-               (returnS (app "h$throw" [closureField1 r1, false_]))-          , closure (ClosureInfo (TxtI "h$raiseAsync_e") (CIRegs 0 [PtrV]) "h$raiseAsync_e" (CILayoutFixed 0 []) CIThunk mempty)-               (returnS  (app "h$throw" [closureField1 r1, true_]))-          , closure (ClosureInfo (TxtI "h$raiseAsync_frame") (CIRegs 0 []) "h$raiseAsync_frame" (CILayoutFixed 1 []) CIStackFrame mempty)-               (jVar $ \ex ->-                   mconcat [ ex |= stack .! (sp - 1)-                           , adjSpN' 2-                           , returnS (app "h$throw" [ex, true_])-                           ])-          {- reduce result if it's a thunk, follow if it's an ind-             add this to the stack if you want the outermost result-             to always be reduced to whnf, and not an ind-          -}-          , closure (ClosureInfo (TxtI "h$reduce") (CIRegs 0 [PtrV]) "h$reduce" (CILayoutFixed 0 []) CIStackFrame mempty)-               (ifS (isThunk r1)-                    (returnS (r1 .^ "f"))-                    (adjSpN' 1 <> returnS (stack .! sp))-               )-          , rtsApply s-          , closureTypes-          , closure (ClosureInfo (TxtI "h$runio_e") (CIRegs 0 [PtrV]) "runio" (CILayoutFixed 1 [PtrV]) CIThunk mempty)-                        $ mconcat [ r1 |= closureField1 r1-                                  , stack .! PreInc sp |= var "h$ap_1_0"-                                  , returnS (var "h$ap_1_0")-                                  ]-          , closure (ClosureInfo (TxtI "h$flushStdout_e") (CIRegs 0 []) "flushStdout" (CILayoutFixed 0 []) CIThunk mempty)-                        $ mconcat [ r1 |= var "h$baseZCGHCziIOziHandlezihFlush"-                                  , r2 |= var "h$baseZCGHCziIOziHandleziFDzistdout"+             -- select first field+             , closure (ClosureInfo (global "h$select1_e") (CIRegs 0 [PtrV]) "select1" (CILayoutFixed 1 [PtrV]) CIThunk mempty)+                  (jVar \t -> return $+                           mconcat [ t |= closureField1 r1+                                   , adjSp' 3+                                   , stack .! (sp - 2) |= r1+                                   , stack .! (sp - 1) |= var "h$upd_frame"+                                   , stack .! sp |= var "h$select1_ret"+                                   , closureEntry  r1 |= var "h$blackhole"+                                   , closureField1 r1 |= var "h$currentThread"+                                   , closureField2 r1 |= null_+                                   , r1 |= t+                                   , returnS (app "h$ap_0_0_fast" [])+                                   ])+             , closure (ClosureInfo (global "h$select1_ret") (CIRegs 0 [PtrV]) "select1ret" (CILayoutFixed 0 []) CIStackFrame mempty)+                  (return $+                    (r1 |= closureField1 r1)+                    <> adjSpN' 1+                    <> returnS (app "h$ap_0_0_fast" [])+                  )+             -- select second field of a two-field constructor+             , closure (ClosureInfo (global "h$select2_e") (CIRegs 0 [PtrV]) "select2" (CILayoutFixed 1 [PtrV]) CIThunk mempty)+                  (jVar \t -> return $+                           mconcat [t |= closureField1 r1+                                   , adjSp' 3+                                   , stack .! (sp - 2) |= r1+                                   , stack .! (sp - 1) |= var "h$upd_frame"+                                   , stack .! sp |= var "h$select2_ret"+                                   , closureEntry  r1 |= var "h$blackhole"+                                   , closureField1 r1 |= var "h$currentThread"+                                   , closureField2 r1 |= null_+                                   , r1 |= t+                                   , returnS (app "h$ap_0_0_fast" [])+                                   ]+                  )+             , closure (ClosureInfo (global "h$select2_ret") (CIRegs 0 [PtrV]) "select2ret" (CILayoutFixed 0 []) CIStackFrame mempty)+                           $ return $ mconcat [ r1 |= closureField2 r1+                                              , adjSpN' 1+                                              , returnS (app "h$ap_0_0_fast" [])+                                              ]+             , closure (ClosureInfo (global "h$keepAlive_e") (CIRegs 0 [PtrV]) "keepAlive" (CILayoutFixed 1 [PtrV]) CIStackFrame mempty)+                       (return $ mconcat [ adjSpN' 2+                                         , returnS (stack .! sp)+                                         ]+                       )+             -- a thunk that just raises a synchronous exception+             , closure (ClosureInfo (global "h$raise_e") (CIRegs 0 [PtrV]) "h$raise_e" (CILayoutFixed 0 []) CIThunk mempty)+                  (return $ returnS (app "h$throw" [closureField1 r1, false_]))+             , closure (ClosureInfo (global "h$raiseAsync_e") (CIRegs 0 [PtrV]) "h$raiseAsync_e" (CILayoutFixed 0 []) CIThunk mempty)+                  (return $ returnS  (app "h$throw" [closureField1 r1, true_]))+             , closure (ClosureInfo (global "h$raiseAsync_frame") (CIRegs 0 []) "h$raiseAsync_frame" (CILayoutFixed 1 []) CIStackFrame mempty)+                  (jVar \ex -> return $ mconcat [ ex |= stack .! (sp - 1)+                                                , adjSpN' 2+                                                , returnS (app "h$throw" [ex, true_])+                                                ])+             {- reduce result if it's a thunk, follow if it's an ind+                add this to the stack if you want the outermost result+                to always be reduced to whnf, and not an ind+             -}+             , closure (ClosureInfo (global "h$reduce") (CIRegs 0 [PtrV]) "h$reduce" (CILayoutFixed 0 []) CIStackFrame mempty)+                  (return $+                    ifS (isThunk r1)+                       (returnS (r1 .^ "f"))+                       (adjSpN' 1 <> returnS (stack .! sp))+                  )+             , rtsApply s+             , closureTypes+             , closure (ClosureInfo (global "h$runio_e") (CIRegs 0 [PtrV]) "runio" (CILayoutFixed 1 [PtrV]) CIThunk mempty)+                           $ return $ mconcat [ r1 |= closureField1 r1+                                              , stack .! PreInc sp |= var "h$ap_1_0"+                                              , returnS (var "h$ap_1_0")+                                              ]+             , closure (ClosureInfo (global "h$flushStdout_e") (CIRegs 0 []) "flushStdout" (CILayoutFixed 0 []) CIThunk mempty)+               $ return $ mconcat [ r1 |= var "h$ghczminternalZCGHCziInternalziIOziHandlezihFlush"+                                  , r2 |= var "h$ghczminternalZCGHCziInternalziIOziHandleziFDzistdout"                                   , returnS (app "h$ap_1_1_fast" [])                                   ]-          , TxtI "h$flushStdout" ||= app "h$static_thunk" [var "h$flushStdout_e"]-          -- the scheduler pushes this frame when suspending a thread that-          -- has not called h$reschedule explicitly-          , closure (ClosureInfo (TxtI "h$restoreThread") (CIRegs 0 []) "restoreThread" CILayoutVariable CIStackFrame mempty)-                (jVar $ \f frameSize nregs ->-                    mconcat [f |= stack .! (sp - 2)-                            , frameSize |= stack .! (sp - 1)-                            , nregs |= frameSize - 3-                            , loop 1 (.<=. nregs)-                                     (\i -> appS "h$setReg" [i, stack .! (sp - 2 - i)] <> postIncrS i)-                            , sp |= sp - frameSize-                            , returnS f-                            ])-          -- return a closure in the stack frame to the next thing on the stack-          , closure (ClosureInfo (TxtI "h$return") (CIRegs 0 []) "return" (CILayoutFixed 1 [PtrV]) CIStackFrame mempty)-                ((r1 |= stack .! (sp - 1))-                 <> adjSpN' 2-                 <> returnS (stack .! sp))-          --  return a function in the stack frame for the next call-          , closure (ClosureInfo (TxtI "h$returnf") (CIRegs 0 [PtrV]) "returnf" (CILayoutFixed 1 [ObjV]) CIStackFrame mempty)-                (jVar $ \r ->-                    mconcat [ r |= stack .! (sp - 1)-                            , adjSpN' 2-                            , returnS r-                            ])-          -- return this function when the scheduler needs to come into action-          -- (yield, delay etc), returning thread needs to push all relevant-          -- registers to stack frame, thread will be resumed by calling the stack top-          , closure (ClosureInfo (TxtI "h$reschedule") (CIRegs 0 []) "reschedule" (CILayoutFixed 0 []) CIThunk mempty)-                (returnS $ var "h$reschedule")-          -- debug thing, insert on stack to dump current result, should be boxed-          , closure (ClosureInfo (TxtI "h$dumpRes") (CIRegs 0 [PtrV]) "dumpRes" (CILayoutFixed 1 [ObjV]) CIThunk mempty)-                (jVar $ \re ->-                    mconcat [ appS "h$log" [jString "h$dumpRes result: " + stack .! (sp-1)]-                            , appS "h$log" [r1]-                            , appS "h$log" [app "h$collectProps" [r1]]-                            , jwhenS ((r1 .^ "f") .&&. (r1 .^ "f" .^ "n"))-                                        (appS "h$log" [jString "name: " + r1 .^ "f" .^ "n"])-                            , jwhenS (ApplExpr (r1 .^ "hasOwnProperty") [jString closureField1_])-                                        (appS "h$log" [jString "d1: " + closureField1 r1])-                            , jwhenS (ApplExpr (r1 .^ "hasOwnProperty") [jString closureField2_])-                                        (appS "h$log" [jString "d2: " + closureField2 r1])-                            , jwhenS (r1 .^ "f") $ mconcat-                                [ re |= New (app "RegExp" [jString "([^\\n]+)\\n(.|\\n)*"])-                                , appS "h$log" [jString "function"+             , pure $ global "h$flushStdout" ||= app "h$static_thunk" [var "h$flushStdout_e"]+             -- the scheduler pushes this frame when suspending a thread that+             -- has not called h$reschedule explicitly+             , closure (ClosureInfo (global "h$restoreThread") (CIRegs 0 []) "restoreThread" CILayoutVariable CIStackFrame mempty)+               (jVars \(f,frameSize,nregs) ->+                      do set_regs <- loop 1 (.<=. nregs)+                                     (\i -> return $ appS "h$setReg" [i, stack .! (sp - 2 - i)] <> postIncrS i)+                         return $ mconcat [f |= stack .! (sp - 2)+                                          , frameSize |= stack .! (sp - 1)+                                          , nregs |= frameSize - 3+                                          , set_regs+                                          , sp |= sp - frameSize+                                          , returnS f+                                          ])+             -- return a closure in the stack frame to the next thing on the stack+             , closure (ClosureInfo (global "h$return") (CIRegs 0 []) "return" (CILayoutFixed 1 [PtrV]) CIStackFrame mempty)+                   (return $+                     (r1 |= stack .! (sp - 1))+                     <> adjSpN' 2+                     <> returnS (stack .! sp))+             --  return a function in the stack frame for the next call+             , closure (ClosureInfo (global "h$returnf") (CIRegs 0 [PtrV]) "returnf" (CILayoutFixed 1 [ObjV]) CIStackFrame mempty)+                   (jVar \r -> return $+                               mconcat [ r |= stack .! (sp - 1)+                                       , adjSpN' 2+                                       , returnS r+                                       ])+             -- return this function when the scheduler needs to come into action+             -- (yield, delay etc), returning thread needs to push all relevant+             -- registers to stack frame, thread will be resumed by calling the stack top+             , closure (ClosureInfo (global "h$reschedule") (CIRegs 0 []) "reschedule" (CILayoutFixed 0 []) CIThunk mempty)+                   (return $ returnS $ var "h$reschedule")+             -- debug thing, insert on stack to dump current result, should be boxed+             , closure (ClosureInfo (global "h$dumpRes") (CIRegs 0 [PtrV]) "dumpRes" (CILayoutFixed 1 [ObjV]) CIThunk mempty)+                (jVar \re -> return $+                     mconcat [ appS "h$log" [jString "h$dumpRes result: " + stack .! (sp-1)]+                             , appS "h$log" [r1]+                             , appS "h$log" [app "h$collectProps" [r1]]+                             , jwhenS ((r1 .^ "f") .&&. (r1 .^ "f" .^ "n"))+                               (appS "h$log" [jString "name: " + r1 .^ "f" .^ "n"])+                             , jwhenS (ApplExpr (r1 .^ "hasOwnProperty") [jString closureField1_])+                               (appS "h$log" [jString "d1: " + closureField1 r1])+                             , jwhenS (ApplExpr (r1 .^ "hasOwnProperty") [jString closureField2_])+                               (appS "h$log" [jString "d2: " + closureField2 r1])+                             , jwhenS (r1 .^ "f") $ mconcat+                               [ re |= New (app "RegExp" [jString "([^\\n]+)\\n(.|\\n)*"])+                               , appS "h$log" [jString "function"                                                 + ApplExpr (ApplExpr ((jString "" + r1 .^ "f") .^ "substring") [0, 50] .^ "replace") [r1, jString "$1"]]-                                ]-                            , adjSpN' 2-                            , r1 |= null_-                            , returnS (stack .! sp)-                            ])-          , closure (ClosureInfo (TxtI "h$resume_e") (CIRegs 0 [PtrV]) "resume" (CILayoutFixed 0 []) CIThunk mempty)-                  (jVar $ \ss ->-                      mconcat [ss |= closureField1 r1-                              , updateThunk' s-                              , loop 0 (.<. ss .^ "length") (\i -> (stack .! (sp+1+i) |= ss .! i)-                                                                   <> postIncrS i)-                              , sp |= sp + ss .^ "length"-                              , r1 |= null_-                              , returnS (stack .! sp)-                              ])-          , closure (ClosureInfo (TxtI "h$unmaskFrame") (CIRegs 0 [PtrV]) "unmask" (CILayoutFixed 0 []) CIStackFrame mempty)-               ((var "h$currentThread" .^ "mask" |= 0)-                <> adjSpN' 1-                -- back to scheduler to give us async exception if pending-                <> ifS (var "h$currentThread" .^ "excep" .^ "length" .>. 0)+                               ]+                             , adjSpN' 2+                             , r1 |= null_+                             , returnS (stack .! sp)+                             ])+             , closure (ClosureInfo (global "h$resume_e") (CIRegs 0 [PtrV]) "resume" (CILayoutFixed 0 []) CIThunk mempty)+                     (jVar \ss ->+                        do update_stk <- loop 0 (.<. ss .^ "length") (\i -> return $ (stack .! (sp+1+i) |= ss .! i) <> postIncrS i)+                           return $ mconcat [ss |= closureField1 r1+                                            , updateThunk' s+                                            , update_stk+                                            , sp |= sp + ss .^ "length"+                                            , r1 |= null_+                                            , returnS (stack .! sp)+                                            ])+             , closure (ClosureInfo (global "h$unmaskFrame") (CIRegs 0 [PtrV]) "unmask" (CILayoutFixed 0 []) CIStackFrame mempty)+                  (return $+                    (var "h$currentThread" .^ "mask" |= 0)+                    <> adjSpN' 1+                    -- back to scheduler to give us async exception if pending+                    <> ifS (var "h$currentThread" .^ "excep" .^ "length" .>. 0)                     (push' s [r1, var "h$return"] <> returnS (var "h$reschedule"))                     (returnS (stack .! sp)))-          , closure (ClosureInfo (TxtI "h$maskFrame") (CIRegs 0 [PtrV]) "mask" (CILayoutFixed 0 []) CIStackFrame mempty)-                ((var "h$currentThread" .^ "mask" |= 2)+             , closure (ClosureInfo (global "h$maskFrame") (CIRegs 0 [PtrV]) "mask" (CILayoutFixed 0 []) CIStackFrame mempty)+               (return $+                 (var "h$currentThread" .^ "mask" |= 2)                  <> adjSpN' 1                  <> returnS (stack .! sp))-          , closure (ClosureInfo (TxtI "h$maskUnintFrame") (CIRegs 0 [PtrV]) "maskUnint" (CILayoutFixed 0 []) CIStackFrame mempty)-                ((var "h$currentThread" .^ "mask" |= 1)+             , closure (ClosureInfo (global "h$maskUnintFrame") (CIRegs 0 [PtrV]) "maskUnint" (CILayoutFixed 0 []) CIStackFrame mempty)+               (return $+                 (var "h$currentThread" .^ "mask" |= 1)                  <> adjSpN' 1                  <> returnS (stack .! sp))-          , closure (ClosureInfo (TxtI "h$unboxFFIResult") (CIRegs 0 [PtrV]) "unboxFFI" (CILayoutFixed 0 []) CIStackFrame mempty)-               (jVar $ \d ->-                   mconcat [d |= closureField1 r1-                           , loop 0 (.<. d .^ "length") (\i -> appS "h$setReg" [i + 1, d .! i] <> postIncrS i)-                           , adjSpN' 1-                           , returnS (stack .! sp)-                           ])-          , closure (ClosureInfo (TxtI "h$unbox_e") (CIRegs 0 [PtrV]) "unboxed value" (CILayoutFixed 1 [DoubleV]) CIThunk mempty)-               ((r1 |= closureField1 r1) <> returnS (stack .! sp))-          , closure (ClosureInfo (TxtI "h$retryInterrupted") (CIRegs 0 [ObjV]) "retry interrupted operation" (CILayoutFixed 1 [ObjV]) CIStackFrame mempty)-               (jVar $ \a ->-                   mconcat [ a |= stack .! (sp - 1)-                           , adjSpN' 2-                           , returnS (ApplExpr (a .! 0 .^ "apply") [var "this", ApplExpr (a .^ "slice") [1]])-                           ])-          , closure (ClosureInfo (TxtI "h$atomically_e") (CIRegs 0 [PtrV]) "atomic operation" (CILayoutFixed 1 [PtrV]) CIStackFrame mempty)-               (ifS (app "h$stmValidateTransaction" [])-                    (appS "h$stmCommitTransaction" []-                     <> adjSpN' 2-                     <> returnS (stack .! sp))-                    (returnS (app "h$stmStartTransaction" [stack .! (sp - 1)])))+             , closure (ClosureInfo (global "h$unboxFFIResult") (CIRegs 0 [PtrV]) "unboxFFI" (CILayoutFixed 0 []) CIStackFrame mempty)+                  (jVar \d -> do set_regs <- loop 0 (.<. d .^ "length") (\i -> return $ appS "h$setReg" [i + 1, d .! i] <> postIncrS i)+                                 return $ mconcat [ d |= closureField1 r1+                                                  , set_regs+                                                  , adjSpN' 1+                                                  , returnS (stack .! sp)+                                                  ])+             , closure (ClosureInfo (global "h$unbox_e") (CIRegs 0 [PtrV]) "unboxed value" (CILayoutFixed 1 [DoubleV]) CIThunk mempty)+                  (return $ (r1 |= closureField1 r1) <> returnS (stack .! sp))+             , closure (ClosureInfo (global "h$retryInterrupted") (CIRegs 0 [ObjV]) "retry interrupted operation" (CILayoutFixed 1 [ObjV]) CIStackFrame mempty)+                  (jVar \a -> return $ mconcat [ a |= stack .! (sp - 1)+                                               , adjSpN' 2+                                               , returnS (ApplExpr (a .! 0 .^ "apply") [var "this", ApplExpr (a .^ "slice") [1]])+                                               ])+             , closure (ClosureInfo (global "h$atomically_e") (CIRegs 0 [PtrV]) "atomic operation" (CILayoutFixed 1 [PtrV]) CIStackFrame mempty)+                  (return $ ifS (app "h$stmValidateTransaction" [])+               (appS "h$stmCommitTransaction" []+                        <> adjSpN' 2+                        <> returnS (stack .! sp))+                       (returnS (app "h$stmStartTransaction" [stack .! (sp - 1)]))) -          , closure (ClosureInfo (TxtI "h$stmCatchRetry_e") (CIRegs 0 [PtrV]) "catch retry" (CILayoutFixed 1 [PtrV]) CIStackFrame mempty)-                        (adjSpN' 2-                         <> appS "h$stmCommitTransaction" []-                         <> returnS (stack .! sp))-          , closure (ClosureInfo (TxtI "h$catchStm_e") (CIRegs 0 [PtrV]) "STM catch" (CILayoutFixed 3 [ObjV,PtrV,ObjV]) CIStackFrame mempty)-                       (adjSpN' 4-                       <> appS "h$stmCommitTransaction" []-                       <> returnS (stack .! sp))-          , closure (ClosureInfo (TxtI "h$stmResumeRetry_e") (CIRegs 0 [PtrV]) "resume retry" (CILayoutFixed 0 []) CIStackFrame mempty)-                        (jVar $ \blocked ->-                            mconcat [ jwhenS (stack .! (sp - 2) .!==. var "h$atomically_e")-                                                 (appS "throw" [jString "h$stmResumeRetry_e: unexpected value on stack"])-                                    , blocked |= stack .! (sp - 1)-                                    , adjSpN' 2-                                    , appS "h$stmRemoveBlockedThread" [blocked, var "h$currentThread"]-                                    , returnS (app "h$stmStartTransaction" [stack .! (sp - 1)])-                                    ])-          , closure (ClosureInfo (TxtI "h$lazy_e") (CIRegs 0 [PtrV]) "generic lazy value" (CILayoutFixed 0 []) CIThunk mempty)-                        (jVar $ \x ->-                            mconcat [x |= ApplExpr (closureField1 r1) []-                                    , appS "h$bh" []-                                    , profStat s enterCostCentreThunk-                                    , r1 |= x-                                    , returnS (stack .! sp)-                                    ])-          -- Top-level statements to generate only in profiling mode-          , profStat s (closure (ClosureInfo (TxtI "h$setCcs_e") (CIRegs 0 [PtrV]) "set cost centre stack" (CILayoutFixed 1 [ObjV]) CIStackFrame mempty)-                        (appS "h$restoreCCS" [ stack .! (sp - 1)]-                         <> adjSpN' 2-                         <> returnS (stack .! sp)))-          ]+             , closure (ClosureInfo (global "h$stmCatchRetry_e") (CIRegs 0 [PtrV]) "catch retry" (CILayoutFixed 1 [PtrV]) CIStackFrame mempty)+                           (return $+                             adjSpN' 2+                             <> appS "h$stmCommitTransaction" []+                             <> returnS (stack .! sp))+             , closure (ClosureInfo (global "h$catchStm_e") (CIRegs 0 [PtrV]) "STM catch" (CILayoutFixed 3 [ObjV,PtrV,ObjV]) CIStackFrame mempty)+               (return $+                 adjSpN' 4+                 <> appS "h$stmCommitTransaction" []+                 <> returnS (stack .! sp))+             , closure (ClosureInfo (global "h$stmResumeRetry_e") (CIRegs 0 [PtrV]) "resume retry" (CILayoutFixed 0 []) CIStackFrame mempty)+                           (jVar \blocked ->+                              return $+                               mconcat [ jwhenS (stack .! (sp - 2) .!==. var "h$atomically_e")+                                                    (appS "throw" [jString "h$stmResumeRetry_e: unexpected value on stack"])+                                       , blocked |= stack .! (sp - 1)+                                       , adjSpN' 2+                                       , appS "h$stmRemoveBlockedThread" [blocked, var "h$currentThread"]+                                       , returnS (app "h$stmStartTransaction" [stack .! (sp - 1)])+                                       ])+             , closure (ClosureInfo (global "h$lazy_e") (CIRegs 0 [PtrV]) "generic lazy value" (CILayoutFixed 0 []) CIThunk mempty)+                           (jVar \x ->+                              return $+                               mconcat [x |= ApplExpr (closureField1 r1) []+                                       , appS "h$bh" []+                                       , profStat s enterCostCentreThunk+                                       , r1 |= x+                                       , returnS (stack .! sp)+                                       ])+             -- Top-level statements to generate only in profiling mode+             , fmap (profStat s) $ (closure (ClosureInfo (global "h$setCcs_e") (CIRegs 0 [PtrV]) "set cost centre stack" (CILayoutFixed 1 [ObjV]) CIStackFrame mempty)+                           (return $+                             appS "h$restoreCCS" [ stack .! (sp - 1)]+                             <> adjSpN' 2+                             <> returnS (stack .! sp)))+             ]
compiler/GHC/StgToJS/Rts/Types.hs view
@@ -22,7 +22,8 @@ import GHC.Prelude  import GHC.JS.Make-import GHC.JS.Unsat.Syntax+import GHC.JS.JStg.Syntax+import GHC.JS.JStg.Monad import GHC.StgToJS.Regs import GHC.StgToJS.Types @@ -31,48 +32,48 @@ --------------------------------------------------------------------------------  -- | Syntactic sugar, i.e., a Haskell function which generates useful JS code.--- Given a @JExpr@, 'ex', inject a trace statement on 'ex' in the compiled JS+-- Given a @JStgExpr@, 'ex', inject a trace statement on 'ex' in the compiled JS -- program-traceRts :: StgToJSConfig -> JExpr -> JStat+traceRts :: StgToJSConfig -> JStgExpr -> JStgStat traceRts s ex | (csTraceRts s)  = appS "h$log" [ex]               | otherwise       = mempty --- | Syntactic sugar. Given a @JExpr@, 'ex' which is assumed to be a predicate,+-- | Syntactic sugar. Given a @JStgExpr@, 'ex' which is assumed to be a predicate, -- and a message 'm', assert that 'not ex' is True, if not throw an exception in -- JS land with message 'm'.-assertRts :: ToJExpr a => StgToJSConfig -> JExpr -> a -> JStat+assertRts :: ToJExpr a => StgToJSConfig -> JStgExpr -> a -> JStgStat assertRts s ex m | csAssertRts s = jwhenS (UOpExpr NotOp ex) (appS "throw" [toJExpr m])                  | otherwise     = mempty  -- | name of the closure 'c'-clName :: JExpr -> JExpr+clName :: JStgExpr -> JStgExpr clName c = c .^ "n"  -- | Type name of the closure 'c'-clTypeName :: JExpr -> JExpr+clTypeName :: JStgExpr -> JStgExpr clTypeName c = app "h$closureTypeName" [c .^ "t"]  -- number of  arguments (arity & 0xff = arguments, arity >> 8 = number of registers)-stackFrameSize :: JExpr -- ^ assign frame size to this-               -> JExpr -- ^ stack frame header function-               -> JStat -- ^ size of the frame, including header+stackFrameSize :: JStgExpr -- ^ assign frame size to this+               -> JStgExpr -- ^ stack frame header function+               -> JSM JStgStat -- ^ size of the frame, including header stackFrameSize tgt f =-  ifS (f .===. var "h$ap_gen") -- h$ap_gen is special-      (tgt |= (stack .! (sp - 1) .>>. 8) + 2)-      (jVar (\tag ->-               mconcat-               [tag |= f .^ "size"-               , ifS (tag .<. 0)              -- if tag is less than 0-                 (tgt |= stack .! (sp - 1))   -- set target to stack pointer - 1-                 (tgt |= mask8 tag + 1)       -- else set to mask'd tag + 1-               ]-        ))+  jIf (f .===. var "h$ap_gen") -- h$ap_gen is special+    (pure $ tgt |= (stack .! (sp - 1) .>>. 8) + 2)+    (jVar (\tag ->+              return $ mconcat+              [tag |= f .^ "size"+              , ifS (tag .<. 0)              -- if tag is less than 0+                (tgt |= stack .! (sp - 1))   -- set target to stack pointer - 1+                (tgt |= mask8 tag + 1)       -- else set to mask'd tag + 1+              ]+          )) ---------------------------------------------------------------------------------+  -------------------------------------------------------------------------------- -- Register utilities --------------------------------------------------------------------------------  -- | Perform the computation 'f', on the range of registers bounded by 'start' -- and 'end'.-withRegs :: StgReg -> StgReg -> (StgReg -> JStat) -> JStat+withRegs :: StgReg -> StgReg -> (StgReg -> JStgStat) -> JStgStat withRegs start end f = mconcat $ fmap f [start..end]
compiler/GHC/StgToJS/Sinker.hs view
@@ -15,10 +15,10 @@ import GHC.Types.Literal import GHC.Data.Graph.Directed +import GHC.Utils.Misc (partitionWith) import GHC.StgToJS.Utils  import Data.Char-import Data.Either import Data.List (partition) import Data.Maybe @@ -38,7 +38,7 @@   where     selectLifted (StgTopLifted b) = Left b     selectLifted x                = Right x-    (pgm', stringLits) = partitionEithers (map selectLifted pgm)+    (pgm', stringLits) = partitionWith selectLifted pgm     (sunk, pgm'')      = sinkPgm' m pgm'  sinkPgm'
compiler/GHC/StgToJS/Stack.hs view
@@ -66,8 +66,9 @@  import GHC.Prelude -import GHC.JS.Unsat.Syntax+import GHC.JS.JStg.Syntax import GHC.JS.Make+import GHC.JS.Ident  import GHC.StgToJS.Types import GHC.StgToJS.Monad@@ -147,13 +148,13 @@ dropSlots :: Int -> G () dropSlots n = modifySlots (drop n) -push :: [JExpr] -> G JStat+push :: [JStgExpr] -> G JStgStat push xs = do   dropSlots (length xs)   modifyStackDepth (+ (length xs))   flip push' xs <$> getSettings -push' :: StgToJSConfig -> [JExpr] -> JStat+push' :: StgToJSConfig -> [JStgExpr] -> JStgStat push' _ [] = mempty push' cs xs    | csInlinePush cs || l > 32 || l < 2 = adjSp' l <> mconcat items@@ -163,24 +164,24 @@     offset i | i == l    = sp              | otherwise = InfixExpr SubOp sp (toJExpr (l - i))     l = length xs-    f i e = AssignStat ((IdxExpr stack) (toJExpr (offset i))) (toJExpr e)+    f i e = AssignStat ((IdxExpr stack) (toJExpr (offset i))) AssignOp (toJExpr e)   -- | Grow the stack pointer by 'n' without modifying the stack depth. The stack -- is just a JS array so we add to grow (instead of the traditional subtract)-adjSp' :: Int -> JStat+adjSp' :: Int -> JStgStat adjSp' 0 = mempty adjSp' n = sp |= InfixExpr AddOp sp (toJExpr n)  -- | Shrink the stack pointer by 'n'. The stack grows downward so substract-adjSpN' :: Int -> JStat+adjSpN' :: Int -> JStgStat adjSpN' 0 = mempty adjSpN' n = sp |= InfixExpr SubOp sp (toJExpr n)  -- | Wrapper which adjusts the stack pointer /and/ modifies the stack depth -- tracked in 'G'. See also 'adjSp'' which actually does the stack pointer -- manipulation.-adjSp :: Int -> G JStat+adjSp :: Int -> G JStgStat adjSp 0 = return mempty adjSp n = do   -- grow depth by n@@ -190,7 +191,7 @@ -- | Shrink the stack and stack pointer. NB: This function is unsafe when the -- input 'n', is negative. This function wraps around 'adjSpN' which actually -- performs the work.-adjSpN :: Int -> G JStat+adjSpN :: Int -> G JStgStat adjSpN 0 = return mempty adjSpN n = do   modifyStackDepth (\x -> x - n)@@ -212,13 +213,13 @@ -- -- and so on up to 32. pushN :: Array Int Ident-pushN = listArray (1,32) $ map (TxtI . mkFastString . ("h$p"++) . show) [(1::Int)..32]+pushN = listArray (1,32) $ map (global . mkFastString . ("h$p"++) . show) [(1::Int)..32]  -- | Convert all function symbols in 'pushN' to global top-level functions. This -- is a hack which converts the function symbols to variables. This hack is -- caught in 'GHC.StgToJS.Printer.prettyBlock'' to turn these into global -- functions.-pushN' :: Array Int JExpr+pushN' :: Array Int JStgExpr pushN' = fmap (ValExpr . JVar) pushN  -- | Partial Push functions. Like 'pushN' except these push functions skip@@ -234,13 +235,13 @@ -- The 33rd entry skips slots 1-4 to bind the top of the stack and the 6th -- slot. See 'pushOptimized' and 'pushOptimized'' for use cases. pushNN :: Array Integer Ident-pushNN = listArray (1,255) $ map (TxtI . mkFastString . ("h$pp"++) . show) [(1::Int)..255]+pushNN = listArray (1,255) $ map (global . mkFastString . ("h$pp"++) . show) [(1::Int)..255]  -- | Like 'pushN'' but for the partial push functions-pushNN' :: Array Integer JExpr+pushNN' :: Array Integer JStgExpr pushNN' = fmap (ValExpr . JVar) pushNN -pushOptimized' :: [(Id,Int)] -> G JStat+pushOptimized' :: [(Id,Int)] -> G JStgStat pushOptimized' xs = do   slots  <- getSlots   pushOptimized =<< (zipWithM f xs (slots++repeat SlotUnknown))@@ -255,8 +256,8 @@  -- | optimized push that reuses existing values on stack automatically chooses -- an optimized partial push (h$ppN) function when possible.-pushOptimized :: [(JExpr,Bool)] -- ^ contents of the slots, True if same value is already there-              -> G JStat+pushOptimized :: [(JStgExpr,Bool)] -- ^ contents of the slots, True if same value is already there+              -> G JStgStat pushOptimized [] = return mempty pushOptimized xs = do   dropSlots l@@ -281,26 +282,26 @@              | otherwise = InfixExpr SubOp sp (toJExpr (l - i))  -- | push a let-no-escape frame onto the stack-pushLneFrame :: HasDebugCallStack => Int -> ExprCtx -> G JStat+pushLneFrame :: HasDebugCallStack => Int -> ExprCtx -> G JStgStat pushLneFrame size ctx =   let ctx' = ctxLneShrinkStack ctx size   in pushOptimized' (ctxLneFrameVars ctx')  -- | Pop things, don't update the stack knowledge in 'G' popSkip :: Int      -- ^ number of slots to skip-         -> [JExpr] -- ^ assign stack slot values to these-         -> JStat+         -> [JStgExpr] -- ^ assign stack slot values to these+         -> JStgStat popSkip 0 []  = mempty popSkip n []  = adjSpN' n popSkip n tgt = loadSkip n tgt <> adjSpN' (length tgt + n) --- | Load 'length (xs :: [JExpr])' things from the stack at offset 'n :: Int'.+-- | Load 'length (xs :: [JStgExpr])' things from the stack at offset 'n :: Int'. -- This function does no stack pointer manipulation, it merely indexes into the -- stack and loads payloads into 'xs'.-loadSkip :: Int -> [JExpr] -> JStat+loadSkip :: Int -> [JStgExpr] -> JStgStat loadSkip = loadSkipFrom sp   where-    loadSkipFrom :: JExpr -> Int -> [JExpr] -> JStat+    loadSkipFrom :: JStgExpr -> Int -> [JStgExpr] -> JStgStat     loadSkipFrom fr n xs = mconcat items       where         items = reverse $ zipWith f [(0::Int)..] (reverse xs)@@ -312,7 +313,7 @@   -- | Pop but preserve the first N slots-popSkipI :: Int -> [(Ident,StackSlot)] -> G JStat+popSkipI :: Int -> [(Ident,StackSlot)] -> G JStgStat popSkipI 0 [] = pure mempty popSkipI n [] = popN n popSkipI n xs = do@@ -327,10 +328,10 @@   -- now load skipping first N slots   return (loadSkipI n (map fst xs) <> a) --- | Just like 'loadSkip' but operate on 'Ident's rather than 'JExpr'-loadSkipI :: Int -> [Ident] -> JStat+-- | Just like 'loadSkip' but operate on 'Ident's rather than 'JStgExpr'+loadSkipI :: Int -> [Ident] -> JStgStat loadSkipI = loadSkipIFrom sp-  where loadSkipIFrom :: JExpr -> Int -> [Ident] -> JStat+  where loadSkipIFrom :: JStgExpr -> Int -> [Ident] -> JStgStat         loadSkipIFrom fr n xs = mconcat items           where             items = reverse $ zipWith f [(0::Int)..] (reverse xs)@@ -339,11 +340,11 @@             f i ex   = ex ||= IdxExpr stack (toJExpr (offset (i+n)))  -- | Blindly pop N slots-popN :: Int -> G JStat+popN :: Int -> G JStgStat popN n = addUnknownSlots n >> adjSpN n  -- | Generate statements to update the current node with a blackhole-bhStats :: StgToJSConfig -> Bool -> JStat+bhStats :: StgToJSConfig -> Bool -> JStgStat bhStats s pushUpd = mconcat   [ if pushUpd then push' s [r1, var "h$upd_frame"] else mempty   , toJExpr R1 .^ closureEntry_  |= var "h$blackhole"@@ -353,7 +354,7 @@  -- | Wrapper around 'updateThunk'', performs the stack manipulation before -- updating the Thunk.-updateThunk :: G JStat+updateThunk :: G JStgStat updateThunk = do   settings <- getSettings   -- update frame size@@ -366,7 +367,7 @@ -- | Update a thunk by checking 'StgToJSConfig'. If the config inlines black -- holes then update inline, else make an explicit call to the black hole -- handler.-updateThunk' :: StgToJSConfig -> JStat+updateThunk' :: StgToJSConfig -> JStgStat updateThunk' settings =   if csInlineBlackhole settings     then bhStats settings True
compiler/GHC/StgToJS/StaticPtr.hs view
@@ -10,19 +10,18 @@ import GHC.Fingerprint.Type import GHC.Types.Literal -import GHC.JS.Unsat.Syntax+import GHC.JS.JStg.Syntax import GHC.JS.Make  import GHC.StgToJS.Types import GHC.StgToJS.Literal import GHC.StgToJS.Ids -initStaticPtrs :: [SptEntry] -> G JStat+initStaticPtrs :: [SptEntry] -> G JStgStat initStaticPtrs ptrs = mconcat <$> mapM initStatic ptrs   where     initStatic (SptEntry sp_id (Fingerprint w1 w2)) = do       i <- varForId sp_id       fpa <- concat <$> mapM (genLit . mkLitWord64 . fromIntegral) [w1,w2]-      let sptInsert = ApplExpr (var "h$hs_spt_insert") (fpa ++ [i])-      return $ (var "h$initStatic" .^ "push") `ApplStat` [jLam sptInsert]-+      let sptInsert = ApplStat (var "h$hs_spt_insert") (fpa ++ [i])+      return $ (var "h$initStatic" .^ "push") `ApplStat` [Func [] sptInsert]
compiler/GHC/StgToJS/Utils.hs view
@@ -2,83 +2,52 @@ {-# LANGUAGE LambdaCase        #-}  module GHC.StgToJS.Utils-  ( assignToTypedExprs-  , assignCoerce1+  ( assignCoerce1   , assignToExprCtx-  -- * Core Utils+  , fixedLayout+  , assocIdExprs+  -- * Unboxable datacon   , isUnboxableCon   , isUnboxable-  , SlotCount(..)+  , isBoolDataCon+  -- * JSRep   , slotCount   , varSize-  , varSlotCount   , typeSize   , isVoid-  , isPtr-  , isSingleVar   , isMultiVar-  , isMatchable-  , tyConVt-  , idVt-  , typeVt-  , uTypeVt-  , primRepVt-  , typePrimRep'-  , tyConPrimRep'-  , kindPrimRep'-  , primTypeVt-  , argVt-  , dataConType-  , isBoolDataCon-  , fixedLayout+  , idJSRep+  , typeJSRep+  , unaryTypeJSRep+  , primRepToJSRep+  , primOrVoidRepToJSRep   , stackSlotType-  , idPrimReps-  , typePrimReps   , primRepSize-  , assocPrimReps-  , assocIdPrimReps-  , assocIdExprs   , mkArityTag-  , toTypeList-  -- * Stg Utils-  , bindingRefs-  , rhsRefs+  -- * References and Ids   , exprRefs-  , altRefs-  , argRefs   , hasExport   , collectTopIds   , collectIds-  , removeTick+  -- * Live variables   , LiveVars   , liveStatic   , liveVars-  , stgTopBindLive-  , stgBindLive-  , stgBindRhsLive   , stgRhsLive-  , stgArgLive   , stgExprLive-  , stgAltLive-  , stgLetNoEscapeLive-  , bindees   , isUpdatableRhs-  , stgLneLive   , stgLneLive'   , stgLneLiveExpr   , isInlineExpr-  , inspectInlineBinding-  , inspectInlineRhs-  , isInlineForeignCall-  , isInlineApp-  ) where+  )+where  import GHC.Prelude  import GHC.StgToJS.Types import GHC.StgToJS.ExprCtx -import GHC.JS.Unsat.Syntax+import GHC.JS.JStg.Syntax import GHC.JS.Make import GHC.JS.Transform @@ -91,8 +60,6 @@  import GHC.Tc.Utils.TcType -import GHC.Builtin.Types-import GHC.Builtin.Types.Prim import GHC.Builtin.Names import GHC.Builtin.PrimOps (PrimOp(SeqOp), primOpIsReallyInline) @@ -102,7 +69,6 @@ import GHC.Types.Id import GHC.Types.Id.Info import GHC.Types.Unique.FM-import GHC.Types.Unique.Set import GHC.Types.ForeignCall import GHC.Types.TyThing import GHC.Types.Name@@ -119,32 +85,42 @@ import Data.Monoid  -assignToTypedExprs :: [TypedExpr] -> [JExpr] -> JStat+assignToTypedExprs :: [TypedExpr] -> [JStgExpr] -> JStgStat assignToTypedExprs tes es =   assignAllEqual (concatMap typex_expr tes) es -assignTypedExprs :: [TypedExpr] -> [TypedExpr] -> JStat+assignTypedExprs :: [TypedExpr] -> [TypedExpr] -> JStgStat assignTypedExprs tes es =-  -- TODO: check primRep (typex_typ) here?-  assignToTypedExprs tes (concatMap typex_expr es)+  let prim_tes = concatMap typex_expr tes+      prim_es  = concatMap typex_expr es+        -- extract the JExprs, effectively unarising a RuntimeRep thing to+        -- multiple VarType-repped things (e.g., AddrRep takes two VarType-regs)+  in assertPpr (equalLength prim_tes prim_es)+               (ppr (map typex_typ tes) $$ ppr (map typex_typ es))+               (assignAllEqual prim_tes prim_es) -assignToExprCtx :: ExprCtx -> [JExpr] -> JStat+assignToExprCtx :: ExprCtx -> [JStgExpr] -> JStgStat assignToExprCtx ctx es = assignToTypedExprs (ctxTarget ctx) es  -- | Assign first expr only (if it exists), performing coercions between some -- PrimReps (e.g. StablePtr# and Addr#).-assignCoerce1 :: [TypedExpr] -> [TypedExpr] -> JStat+assignCoerce1 :: [TypedExpr] -> [TypedExpr] -> JStgStat assignCoerce1 [x] [y] = assignCoerce x y assignCoerce1 []  []  = mempty-assignCoerce1 _x _y   = pprPanic "assignCoerce1"+-- We silently ignore the case of an empty list on the first argument. It denotes+-- "assign nothing to n empty slots on the right". Usually this case shouldn't come+-- up, but rare cases where the earlier code can't correctly guess the size of type+-- classes causes slots to be allocated when they aren't needed.+assignCoerce1 []  _   = mempty+assignCoerce1 x y     = pprPanic "assignCoerce1"                           (vcat [ text "lengths do not match"                                 -- FIXME: Outputable instance removed until JStg replaces JStat-                                -- , ppr x-                                -- , ppr y+                                , ppr x+                                , ppr y                                 ])  -- | Assign p2 to p1 with optional coercion-assignCoerce :: TypedExpr -> TypedExpr -> JStat+assignCoerce :: TypedExpr -> TypedExpr -> JStgStat -- Coercion between StablePtr# and Addr# assignCoerce (TypedExpr AddrRep [a_val, a_off]) (TypedExpr (BoxedRep (Just Unlifted)) [sptr]) = mconcat     [ a_val |= var "h$stablePtrBuf"@@ -163,7 +139,7 @@ isUnboxableCon :: DataCon -> Bool isUnboxableCon dc   | [t] <- dataConRepArgTys dc-  , [t1] <- typeVt (scaledThing t)+  , [t1] <- typeJSRep (scaledThing t)   = isUnboxable t1 &&     dataConTag dc == 1 &&     length (tyConDataCons $ dataConTyCon dc) == 1@@ -171,7 +147,7 @@  -- | one-constructor types with one primitive field represented as a JS Number -- can be unboxed-isUnboxable :: VarType -> Bool+isUnboxable :: JSRep -> Bool isUnboxable DoubleV = True isUnboxable IntV    = True -- includes Char# isUnboxable _       = False@@ -194,153 +170,59 @@   TwoSlots -> 2  --- | Number of slots occupied by a value with the given VarType-varSize :: VarType -> Int-varSize = slotCount . varSlotCount+-- | Number of slots occupied by a value with the given JSRep+varSize :: JSRep -> Int+varSize = slotCount . jsRepSlots -varSlotCount :: VarType -> SlotCount-varSlotCount VoidV = NoSlot-varSlotCount LongV = TwoSlots -- hi, low-varSlotCount AddrV = TwoSlots -- obj/array, offset-varSlotCount _     = OneSlot+jsRepSlots :: JSRep -> SlotCount+jsRepSlots VoidV = NoSlot+jsRepSlots LongV = TwoSlots -- hi, low+jsRepSlots AddrV = TwoSlots -- obj/array, offset+jsRepSlots _     = OneSlot  typeSize :: Type -> Int-typeSize t = sum . map varSize . typeVt $ t+typeSize t = sum . map varSize . typeJSRep $ t -isVoid :: VarType -> Bool+isVoid :: JSRep -> Bool isVoid VoidV = True isVoid _     = False -isPtr :: VarType -> Bool-isPtr PtrV = True-isPtr _    = False--isSingleVar :: VarType -> Bool-isSingleVar v = varSlotCount v == OneSlot--isMultiVar :: VarType -> Bool-isMultiVar v = case varSlotCount v of+isMultiVar :: JSRep -> Bool+isMultiVar v = case jsRepSlots v of   NoSlot   -> False   OneSlot  -> False   TwoSlots -> True --- | can we pattern match on these values in a case?-isMatchable :: [VarType] -> Bool-isMatchable [DoubleV] = True-isMatchable [IntV]    = True-isMatchable _         = False--tyConVt :: HasDebugCallStack => TyCon -> [VarType]-tyConVt = typeVt . mkTyConTy--idVt :: HasDebugCallStack => Id -> [VarType]-idVt = typeVt . idType+idJSRep :: HasDebugCallStack => Id -> [JSRep]+idJSRep = typeJSRep . idType -typeVt :: HasDebugCallStack => Type -> [VarType]-typeVt t | isRuntimeRepKindedTy t = []-typeVt t = map primRepVt (typePrimRep t)-- map uTypeVt (repTypeArgs t)+typeJSRep :: HasDebugCallStack => Type -> [JSRep]+typeJSRep t = map primRepToJSRep (typePrimRep t)  -- only use if you know it's not an unboxed tuple-uTypeVt :: HasDebugCallStack => UnaryType -> VarType-uTypeVt ut-  | isRuntimeRepKindedTy ut = VoidV---  | isRuntimeRepTy ut = VoidV-  -- GHC panics on this otherwise-  | Just (tc, ty_args) <- splitTyConApp_maybe ut-  , length ty_args /= tyConArity tc = PtrV-  | isPrimitiveType ut = (primTypeVt ut)-  | otherwise          =-    case typePrimRep' ut of-      []   -> VoidV-      [pt] -> primRepVt pt-      _    -> pprPanic "uTypeVt: not unary" (ppr ut)--primRepVt :: HasDebugCallStack => PrimRep -> VarType-primRepVt VoidRep     = VoidV-primRepVt (BoxedRep _) = PtrV -- fixme does ByteArray# ever map to this?-primRepVt IntRep      = IntV-primRepVt Int8Rep     = IntV-primRepVt Int16Rep    = IntV-primRepVt Int32Rep    = IntV-primRepVt WordRep     = IntV-primRepVt Word8Rep    = IntV-primRepVt Word16Rep   = IntV-primRepVt Word32Rep   = IntV-primRepVt Int64Rep    = LongV-primRepVt Word64Rep   = LongV-primRepVt AddrRep     = AddrV-primRepVt FloatRep    = DoubleV-primRepVt DoubleRep   = DoubleV-primRepVt (VecRep{})  = error "uTypeVt: vector types are unsupported"--typePrimRep' :: HasDebugCallStack => UnaryType -> [PrimRep]-typePrimRep' ty = kindPrimRep' empty (typeKind ty)---- | Find the primitive representation of a 'TyCon'. Defined here to--- avoid module loops. Call this only on unlifted tycons.-tyConPrimRep' :: HasDebugCallStack => TyCon -> [PrimRep]-tyConPrimRep' tc = kindPrimRep' empty res_kind-  where-    res_kind = tyConResKind tc---- | Take a kind (of shape @TYPE rr@) and produce the 'PrimRep's--- of values of types of this kind.-kindPrimRep' :: HasDebugCallStack => SDoc -> Kind -> [PrimRep]-kindPrimRep' doc ki-  | Just ki' <- coreView ki-  = kindPrimRep' doc ki'-kindPrimRep' doc (TyConApp _typ [runtime_rep])-  = -- ASSERT( typ `hasKey` tYPETyConKey )-    runtimeRepPrimRep doc runtime_rep-kindPrimRep' doc ki-  = pprPanic "kindPrimRep'" (ppr ki $$ doc)+unaryTypeJSRep :: HasDebugCallStack => UnaryType -> JSRep+unaryTypeJSRep ut = primOrVoidRepToJSRep (typePrimRep1 ut) -primTypeVt :: HasDebugCallStack => Type -> VarType-primTypeVt t = case tyConAppTyCon_maybe (unwrapType t) of-  Nothing -> error "primTypeVt: not a TyCon"-  Just tc-    | tc == charPrimTyCon              -> IntV-    | tc == intPrimTyCon               -> IntV-    | tc == wordPrimTyCon              -> IntV-    | tc == floatPrimTyCon             -> DoubleV-    | tc == doublePrimTyCon            -> DoubleV-    | tc == int8PrimTyCon              -> IntV-    | tc == word8PrimTyCon             -> IntV-    | tc == int16PrimTyCon             -> IntV-    | tc == word16PrimTyCon            -> IntV-    | tc == int32PrimTyCon             -> IntV-    | tc == word32PrimTyCon            -> IntV-    | tc == int64PrimTyCon             -> LongV-    | tc == word64PrimTyCon            -> LongV-    | tc == addrPrimTyCon              -> AddrV-    | tc == stablePtrPrimTyCon         -> AddrV-    | tc == stableNamePrimTyCon        -> PtrV-    | tc == statePrimTyCon             -> VoidV-    | tc == proxyPrimTyCon             -> VoidV-    | tc == realWorldTyCon             -> VoidV-    | tc == threadIdPrimTyCon          -> PtrV-    | tc == weakPrimTyCon              -> PtrV-    | tc == arrayPrimTyCon             -> ArrV-    | tc == smallArrayPrimTyCon        -> ArrV-    | tc == byteArrayPrimTyCon         -> ObjV -- can contain any JS reference, used for JSVal-    | tc == mutableArrayPrimTyCon      -> ArrV-    | tc == smallMutableArrayPrimTyCon -> ArrV-    | tc == mutableByteArrayPrimTyCon  -> ObjV -- can contain any JS reference, used for JSVal-    | tc == mutVarPrimTyCon            -> PtrV-    | tc == mVarPrimTyCon              -> PtrV-    | tc == tVarPrimTyCon              -> PtrV-    | tc == bcoPrimTyCon               -> PtrV -- unsupported?-    | tc == stackSnapshotPrimTyCon     -> PtrV-    | tc == ioPortPrimTyCon            -> PtrV -- unsupported?-    | tc == anyTyCon                   -> PtrV-    | tc == compactPrimTyCon           -> PtrV -- unsupported?-    | tc == eqPrimTyCon                -> VoidV -- coercion token?-    | tc == eqReprPrimTyCon            -> VoidV -- role-    | tc == unboxedUnitTyCon           -> VoidV -- Void#-    | otherwise                        -> PtrV  -- anything else must be some boxed thing+primRepToJSRep :: HasDebugCallStack => PrimRep -> JSRep+primRepToJSRep (BoxedRep _) = PtrV+primRepToJSRep IntRep       = IntV+primRepToJSRep Int8Rep      = IntV+primRepToJSRep Int16Rep     = IntV+primRepToJSRep Int32Rep     = IntV+primRepToJSRep WordRep      = IntV+primRepToJSRep Word8Rep     = IntV+primRepToJSRep Word16Rep    = IntV+primRepToJSRep Word32Rep    = IntV+primRepToJSRep Int64Rep     = LongV+primRepToJSRep Word64Rep    = LongV+primRepToJSRep AddrRep      = AddrV+primRepToJSRep FloatRep     = DoubleV+primRepToJSRep DoubleRep    = DoubleV+primRepToJSRep (VecRep{})   = error "primRepToJSRep: vector types are unsupported" -argVt :: StgArg -> VarType-argVt a = uTypeVt . stgArgType $ a+primOrVoidRepToJSRep :: HasDebugCallStack => PrimOrVoidRep -> JSRep+primOrVoidRepToJSRep VoidRep = VoidV+primOrVoidRepToJSRep (NVRep rep) = primRepToJSRep rep  dataConType :: DataCon -> Type dataConType dc = idType (dataConWrapId dc)@@ -350,16 +232,16 @@  -- standard fixed layout: payload types -- payload starts at .d1 for heap objects, entry closest to Sp for stack frames-fixedLayout :: [VarType] -> CILayout+fixedLayout :: [JSRep] -> CILayout fixedLayout vts = CILayoutFixed (sum (map varSize vts)) vts  -- 2-var values might have been moved around separately, use DoubleV as substitute -- ObjV is 1 var, so this is no problem for implicit metadata-stackSlotType :: Id -> VarType+stackSlotType :: Id -> JSRep stackSlotType i-  | OneSlot <- varSlotCount otype = otype-  | otherwise                     = DoubleV-  where otype = uTypeVt (idType i)+  | OneSlot <- jsRepSlots otype = otype+  | otherwise                   = DoubleV+  where otype = unaryTypeJSRep (idType i)  idPrimReps :: Id -> [PrimRep] idPrimReps = typePrimReps . idType@@ -368,34 +250,31 @@ typePrimReps = typePrimRep . unwrapType  primRepSize :: PrimRep -> SlotCount-primRepSize p = varSlotCount (primRepVt p)+primRepSize p = jsRepSlots (primRepToJSRep p)  -- | Associate the given values to each RrimRep in the given order, taking into -- account the number of slots per PrimRep-assocPrimReps :: [PrimRep] -> [JExpr] -> [(PrimRep, [JExpr])]+assocPrimReps :: [PrimRep] -> [JStgExpr] -> [(PrimRep, [JStgExpr])] assocPrimReps []     _  = [] assocPrimReps (r:rs) vs = case (primRepSize r,vs) of   (NoSlot,   xs)     -> (r,[])    : assocPrimReps rs xs   (OneSlot,  x:xs)   -> (r,[x])   : assocPrimReps rs xs   (TwoSlots, x:y:xs) -> (r,[x,y]) : assocPrimReps rs xs-  err                -> pprPanic "assocPrimReps" (ppr $ map (satJExpr Nothing) <$> err)+  err                -> pprPanic "assocPrimReps" (ppr $ map jStgExprToJS <$> err)  -- | Associate the given values to the Id's PrimReps, taking into account the -- number of slots per PrimRep-assocIdPrimReps :: Id -> [JExpr] -> [(PrimRep, [JExpr])]+assocIdPrimReps :: Id -> [JStgExpr] -> [(PrimRep, [JStgExpr])] assocIdPrimReps i = assocPrimReps (idPrimReps i)  -- | Associate the given JExpr to the Id's PrimReps, taking into account the -- number of slots per PrimRep-assocIdExprs :: Id -> [JExpr] -> [TypedExpr]+assocIdExprs :: Id -> [JStgExpr] -> [TypedExpr] assocIdExprs i es = fmap (uncurry TypedExpr) (assocIdPrimReps i es)  mkArityTag :: Int -> Int -> Int mkArityTag arity registers = arity Bits..|. (registers `Bits.shiftL` 8) -toTypeList :: [VarType] -> [Int]-toTypeList = concatMap (\x -> replicate (varSize x) (fromEnum x))- -------------------------------------------------------------------------------- --                        Stg Utils --------------------------------------------------------------------------------@@ -462,14 +341,16 @@   in  seqList xs `seq` xs   where     acceptId i = all ($ i) [not . isForbidden] -- fixme test this: [isExported[isGlobalId, not.isForbidden]-    -- the GHC.Prim module has no js source file     isForbidden i-      | Just m <- nameModule_maybe (getName i) = m == gHC_PRIM-      | otherwise = False--removeTick :: CgStgExpr -> CgStgExpr-removeTick (StgTick _ e) = e-removeTick e             = e+      -- the GHC.Prim module has no js source file+      | Just m <- nameModule_maybe (getName i)+      , m == gHC_PRIM+      = True+      -- unboxed tuples have no definition+      | isUnboxedTupleDataConLikeName (getName i)+      = True+      | otherwise+      = False  ----------------------------------------------------- -- Live vars@@ -484,11 +365,6 @@ liveVars :: LiveVars -> LiveVars liveVars = filterDVarSet (not . isGlobalId) -stgTopBindLive :: CgStgTopBinding -> [(Id, LiveVars)]-stgTopBindLive = \case-  StgTopLifted b     -> stgBindLive b-  StgTopStringLit {} -> []- stgBindLive :: CgStgBinding -> [(Id, LiveVars)] stgBindLive = \case   StgNonRec b rhs -> [(b, stgRhsLive rhs)]@@ -529,9 +405,6 @@ stgAltLive alt =   delDVarSetList (stgExprLive True (alt_rhs alt)) (alt_bndrs alt) -stgLetNoEscapeLive :: Bool -> StgBinding -> StgExpr -> LiveVars-stgLetNoEscapeLive _someBool _b _e = panic "stgLetNoEscapeLive"- bindees :: CgStgBinding -> [Id] bindees = \case   StgNonRec b _e -> [b]@@ -554,61 +427,48 @@ -- stgLneLiveExpr StgRhsCon {}              = []  -- | returns True if the expression is definitely inline-isInlineExpr :: UniqSet Id -> CgStgExpr -> (UniqSet Id, Bool)-isInlineExpr v = \case+isInlineExpr :: CgStgExpr -> Bool+isInlineExpr = \case   StgApp i args-    -> (emptyUniqSet, isInlineApp v i args)+    -> isInlineApp i args   StgLit{}-    -> (emptyUniqSet, True)+    -> True   StgConApp{}-    -> (emptyUniqSet, True)+    -> True   StgOpApp (StgFCallOp f _) _ _-    -> (emptyUniqSet, isInlineForeignCall f)+    -> isInlineForeignCall f   StgOpApp (StgPrimOp SeqOp) [StgVarArg e] t-    -> (emptyUniqSet, e `elementOfUniqSet` v || isStrictType t)+    -> ctxIsEvaluated e || isStrictType t   StgOpApp (StgPrimOp op) _ _-    -> (emptyUniqSet, primOpIsReallyInline op)+    -> primOpIsReallyInline op   StgOpApp (StgPrimCallOp _c) _ _-    -> (emptyUniqSet, True)-  StgCase e b _ alts-    ->let (_ve, ie)   = isInlineExpr v e-          v'          = addOneToUniqSet v b-          (vas, ias)  = unzip $ map (isInlineExpr v') (fmap alt_rhs alts)-          vr          = L.foldl1' intersectUniqSets vas-      in (vr, (ie || b `elementOfUniqSet` v) && and ias)-  StgLet _ b e-    -> isInlineExpr (inspectInlineBinding v b) e-  StgLetNoEscape _ _b e-    -> isInlineExpr v e-  StgTick  _ e-    -> isInlineExpr v e--inspectInlineBinding :: UniqSet Id -> CgStgBinding -> UniqSet Id-inspectInlineBinding v = \case-  StgNonRec i r -> inspectInlineRhs v i r-  StgRec bs     -> foldl' (\v' (i,r) -> inspectInlineRhs v' i r) v bs--inspectInlineRhs :: UniqSet Id -> Id -> CgStgRhs -> UniqSet Id-inspectInlineRhs v i = \case-  StgRhsCon{}                       -> addOneToUniqSet v i-  StgRhsClosure _ _ ReEntrant _ _ _ -> addOneToUniqSet v i-  _                                 -> v+    -> True+  StgCase e _ _ alts+    ->let ie   = isInlineExpr e+          ias  = map isInlineExpr (fmap alt_rhs alts)+      in ie && and ias+  StgLet _ _ e+    -> isInlineExpr e+  StgLetNoEscape _ _ e+    -> isInlineExpr e+  StgTick _ e+    -> isInlineExpr e  isInlineForeignCall :: ForeignCall -> Bool isInlineForeignCall (CCall (CCallSpec _ cconv safety)) =   not (playInterruptible safety) &&   not (cconv /= JavaScriptCallConv && playSafe safety) -isInlineApp :: UniqSet Id -> Id -> [StgArg] -> Bool-isInlineApp v i = \case+isInlineApp :: Id -> [StgArg] -> Bool+isInlineApp i = \case   _ | isJoinId i -> False   [] -> isUnboxedTupleType (idType i) ||                      isStrictType (idType i) ||-                     i `elementOfUniqSet` v+                     ctxIsEvaluated i    [StgVarArg a]     | DataConWrapId dc <- idDetails i     , isNewTyCon (dataConTyCon dc)-    , isStrictType (idType a) || a `elementOfUniqSet` v || isStrictId a+    , isStrictType (idType a) || ctxIsEvaluated a || isStrictId a     -> True   _ -> False
compiler/GHC/SysTools.hs view
@@ -17,7 +17,6 @@          -- * Interface to system tools         module GHC.SysTools.Tasks,-        module GHC.SysTools.Info,          -- * Fast file copy         copyFile,@@ -35,8 +34,6 @@ import GHC.Utils.Panic import GHC.Driver.Session -import GHC.Linker.ExtraObj-import GHC.SysTools.Info import GHC.SysTools.Tasks import GHC.SysTools.BaseDir import GHC.Settings.IO
compiler/GHC/SysTools/Cpp.hs view
@@ -5,7 +5,7 @@  module GHC.SysTools.Cpp   ( doCpp-  , CppOpts (..)+  , CppOpts(..)   , getGhcVersionPathName   , applyCDefs   , offsetIncludePaths@@ -15,7 +15,7 @@ import GHC.Prelude import GHC.Driver.Session import GHC.Driver.Backend-import GHC.CmmToLlvm.Config+import GHC.CmmToLlvm.Version import GHC.Platform import GHC.Platform.ArchOS @@ -40,11 +40,34 @@ import System.FilePath  data CppOpts = CppOpts-  { cppUseCc       :: !Bool -- ^ Use "cc -E" as preprocessor, otherwise use "cpp"-  , cppLinePragmas :: !Bool -- ^ Enable generation of LINE pragmas+  { useHsCpp       :: !Bool+  -- ^ Use the Haskell C preprocessor, otherwise use the C preprocessor.+  -- See the Note [Preprocessing invocations]+  , cppLinePragmas :: !Bool+  -- ^ Enable generation of LINE pragmas   } --- | Run CPP+{-+Note [Preprocessing invocations]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+We must consider two distinct preprocessors when preprocessing Haskell.+These are:++(1) The Haskell C preprocessor (HsCpp), which preprocesses Haskell files that make use+  of the CPP language extension++(2) The C preprocessor (Cpp), which is used to preprocess C and Cmm files++These preprocessors are indeed different. Despite often sharing the same+underlying program (the C compiler), the set of flags passed determines the+behaviour of the preprocessor, and Cpp and HsCpp behave differently.+Specifically, we rely on "traditional" (pre-standard) preprocessing semantics+(which most compilers expose via the `-traditional` flag) when preprocessing+Haskell source. This avoids, e.g., the preprocessor removing C-style comments.+-}++-- | Run either the Haskell preprocessor or the C preprocessor, as per the+-- 'CppOpts' passed. See Note [Preprocessing invocations]. -- -- UnitEnv is needed to compute MIN_VERSION macros doCpp :: Logger -> TmpFs -> DynFlags -> UnitEnv -> CppOpts -> FilePath -> FilePath -> IO ()@@ -73,9 +96,8 @@     let verbFlags = getVerbFlags dflags      let cpp_prog args-          | cppUseCc opts = GHC.SysTools.runCc Nothing logger tmpfs dflags-                                               (GHC.SysTools.Option "-E" : args)-          | otherwise     = GHC.SysTools.runCpp logger dflags args+          | useHsCpp opts = GHC.SysTools.runHsCpp logger dflags args+          | otherwise     = GHC.SysTools.runCpp logger tmpfs dflags args      let platform   = targetPlatform dflags         targetArch = stringEncodeArch $ platformArch platform@@ -203,17 +225,11 @@ -- | Find out path to @ghcversion.h@ file getGhcVersionPathName :: DynFlags -> UnitEnv -> IO FilePath getGhcVersionPathName dflags unit_env = do-  let candidates = case ghcVersionFile dflags of-        -- the user has provided an explicit `ghcversion.h` file to use.-        Just path -> [path]-        -- otherwise, try to find it in the rts' include-dirs.-        -- Note: only in the RTS include-dirs! not all preload units less we may-        -- use a wrong file. See #25106 where a globally installed-        -- /usr/include/ghcversion.h file was used instead of the one provided-        -- by the rts.-        Nothing -> case lookupUnitId (ue_units unit_env) rtsUnitId of-          Nothing   -> []-          Just info -> (</> "ghcversion.h") <$> collectIncludeDirs [info]+  candidates <- case ghcVersionFile dflags of+    Just path -> return [path]+    Nothing -> do+        ps <- mayThrowUnitErr (preloadUnitsInfo' unit_env [rtsUnitId])+        return ((</> "ghcversion.h") <$> collectIncludeDirs ps)    found <- filterM doesFileExist candidates   case found of
− compiler/GHC/SysTools/Info.hs
@@ -1,243 +0,0 @@-{-# LANGUAGE ScopedTypeVariables #-}------------------------------------------------------------------------------------ Compiler information functions------ (c) The GHC Team 2017----------------------------------------------------------------------------------module GHC.SysTools.Info where--import GHC.Utils.Exception-import GHC.Utils.Error-import GHC.Driver.Session-import GHC.Utils.Outputable-import GHC.Utils.Misc-import GHC.Utils.Logger--import Data.List ( isInfixOf, isPrefixOf )-import Data.IORef--import System.IO--import GHC.Platform-import GHC.Prelude--import GHC.SysTools.Process--{- Note [Run-time linker info]-   ~~~~~~~~~~~~~~~~~~~~~~~~~~~-See also: #5240, #6063, #10110--Before 'runLink', we need to be sure to get the relevant information-about the linker we're using at runtime to see if we need any extra-options.--Generally, the linker changing from what was detected at ./configure-time has always been possible using -pgml, but on Linux it can happen-'transparently' by installing packages like binutils-gold, which-change what /usr/bin/ld actually points to.--Clang vs GCC notes:--For gcc, 'gcc -Wl,--version' gives a bunch of output about how to-invoke the linker before the version information string. For 'clang',-the version information for 'ld' is all that's output. For this-reason, we typically need to slurp up all of the standard error output-and look through it.--Other notes:--We cache the LinkerInfo inside DynFlags, since clients may link-multiple times. The definition of LinkerInfo is there to avoid a-circular dependency.---}--{- Note [ELF needed shared libs]-   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Some distributions change the link editor's default handling of-ELF DT_NEEDED tags to include only those shared objects that are-needed to resolve undefined symbols. For Template Haskell we need-the last temporary shared library also if it is not needed for the-currently linked temporary shared library. We specify --no-as-needed-to override the default. This flag exists in GNU ld and GNU gold.--The flag is only needed on ELF systems. On Windows (PE) and Mac OS X-(Mach-O) the flag is not needed.---}--neededLinkArgs :: LinkerInfo -> [Option]-neededLinkArgs (GnuLD o)     = o-neededLinkArgs (Mold o)      = o-neededLinkArgs (GnuGold o)   = o-neededLinkArgs (LlvmLLD o)   = o-neededLinkArgs (DarwinLD o)  = o-neededLinkArgs (SolarisLD o) = o-neededLinkArgs (AixLD o)     = o-neededLinkArgs UnknownLD     = []---- Grab linker info and cache it in DynFlags.-getLinkerInfo :: Logger -> DynFlags -> IO LinkerInfo-getLinkerInfo logger dflags = do-  info <- readIORef (rtldInfo dflags)-  case info of-    Just v  -> return v-    Nothing -> do-      v <- getLinkerInfo' logger dflags-      writeIORef (rtldInfo dflags) (Just v)-      return v---- See Note [Run-time linker info].-getLinkerInfo' :: Logger -> DynFlags -> IO LinkerInfo-getLinkerInfo' logger dflags = do-  let platform = targetPlatform dflags-      os = platformOS platform-      (pgm,args0) = pgm_l dflags-      args1       = map Option (getOpts dflags opt_l)-      args2       = args0 ++ args1-      args3       = filter notNull (map showOpt args2)--      -- Try to grab the info from the process output.-      parseLinkerInfo stdo _stde _exitc-        | any ("GNU ld" `isPrefixOf`) stdo =-          -- Set DT_NEEDED for all shared libraries. #10110.-          return (GnuLD $ map Option [-- ELF specific flag-                                      -- see Note [ELF needed shared libs]-                                      "-Wl,--no-as-needed"])--        | any ("mold" `isPrefixOf`) stdo =-          return (Mold $ map Option [ --see Note [ELF needed shared libs]-                                      "-Wl,--no-as-needed"])--        | any ("GNU gold" `isPrefixOf`) stdo =-          -- GNU gold only needs --no-as-needed. #10110.-          -- ELF specific flag, see Note [ELF needed shared libs]-          return (GnuGold [Option "-Wl,--no-as-needed"])--        | any (\line -> "LLD" `isPrefixOf` line || "LLD" `elem` words line) stdo =-          return (LlvmLLD $ map Option [ --see Note [ELF needed shared libs]-                                        "-Wl,--no-as-needed" | osElfTarget os || os == OSMinGW32 ])--         -- Unknown linker.-        | otherwise = fail "invalid --version output, or linker is unsupported"--  -- Process the executable call-  catchIO (-    case os of-      OSSolaris2 ->-        -- Solaris uses its own Solaris linker. Even all-        -- GNU C are recommended to configure with Solaris-        -- linker instead of using GNU binutils linker. Also-        -- all GCC distributed with Solaris follows this rule-        -- precisely so we assume here, the Solaris linker is-        -- used.-        return $ SolarisLD []-      OSAIX ->-        -- IBM AIX uses its own non-binutils linker as well-        return $ AixLD []-      OSDarwin ->-        -- Darwin has neither GNU Gold or GNU LD, but a strange linker-        -- that doesn't support --version. We can just assume that's-        -- what we're using.-        return $ DarwinLD []-      OSMinGW32 ->-        -- GHC doesn't support anything but GNU ld on Windows anyway.-        -- Process creation is also fairly expensive on win32, so-        -- we short-circuit here.-        return $ GnuLD $ map Option-          [ -- Emit stack checks-            -- See Note [Windows stack allocations]-           "-fstack-check"-          ]-      _ -> do-        -- In practice, we use the compiler as the linker here. Pass-        -- -Wl,--version to get linker version info.-        (exitc, stdo, stde) <- readProcessEnvWithExitCode pgm-                               (["-Wl,--version"] ++ args3)-                               c_locale_env-        -- Split the output by lines to make certain kinds-        -- of processing easier. In particular, 'clang' and 'gcc'-        -- have slightly different outputs for '-Wl,--version', but-        -- it's still easy to figure out.-        parseLinkerInfo (lines stdo) (lines stde) exitc-    )-    (\err -> do-        debugTraceMsg logger 2-            (text "Error (figuring out linker information):" <+>-             text (show err))-        errorMsg logger $ hang (text "Warning:") 9 $-          text "Couldn't figure out linker information!" $$-          text "Make sure you're using GNU ld, GNU gold" <+>-          text "or the built in OS X linker, etc."-        return UnknownLD-    )---- | Grab compiler info and cache it in DynFlags.-getCompilerInfo :: Logger -> DynFlags -> IO CompilerInfo-getCompilerInfo logger dflags = do-  info <- readIORef (rtccInfo dflags)-  case info of-    Just v  -> return v-    Nothing -> do-      let pgm = pgm_c dflags-      v <- getCompilerInfo' logger pgm-      writeIORef (rtccInfo dflags) (Just v)-      return v---- | Grab assembler info and cache it in DynFlags.-getAssemblerInfo :: Logger -> DynFlags -> IO CompilerInfo-getAssemblerInfo logger dflags = do-  info <- readIORef (rtasmInfo dflags)-  case info of-    Just v  -> return v-    Nothing -> do-      let (pgm, _) = pgm_a dflags-      v <- getCompilerInfo' logger pgm-      writeIORef (rtasmInfo dflags) (Just v)-      return v---- See Note [Run-time linker info].-getCompilerInfo' :: Logger -> String -> IO CompilerInfo-getCompilerInfo' logger pgm = do-  let -- Try to grab the info from the process output.-      parseCompilerInfo _stdo stde _exitc-        -- Regular GCC-        | any ("gcc version" `isInfixOf`) stde =-          return GCC-        -- Regular clang-        | any ("clang version" `isInfixOf`) stde =-          return Clang-        -- FreeBSD clang-        | any ("FreeBSD clang version" `isInfixOf`) stde =-          return Clang-        -- Xcode 5.1 clang-        | any ("Apple LLVM version 5.1" `isPrefixOf`) stde =-          return AppleClang51-        -- Xcode 5 clang-        | any ("Apple LLVM version" `isPrefixOf`) stde =-          return AppleClang-        -- Xcode 4.1 clang-        | any ("Apple clang version" `isPrefixOf`) stde =-          return AppleClang-         -- Unknown compiler.-        | otherwise = fail $ "invalid -v output, or compiler is unsupported (" ++ pgm ++ "): " ++ unlines stde--  -- Process the executable call-  catchIO (do-      (exitc, stdo, stde) <--          readProcessEnvWithExitCode pgm ["-v"] c_locale_env-      -- Split the output by lines to make certain kinds-      -- of processing easier.-      parseCompilerInfo (lines stdo) (lines stde) exitc-      )-      (\err -> do-          debugTraceMsg logger 2-              (text "Error (figuring out C compiler information):" <+>-               text (show err))-          errorMsg logger $ hang (text "Warning:") 9 $-            text "Couldn't figure out C compiler information!" $$-            text "Make sure you're using GNU gcc, or clang"-          return UnknownCC-      )
compiler/GHC/SysTools/Process.hs view
@@ -10,14 +10,14 @@  import GHC.Prelude -import GHC.Driver.DynFlags- import GHC.Utils.Exception import GHC.Utils.Error import GHC.Utils.Outputable import GHC.Utils.Panic import GHC.Utils.Misc import GHC.Utils.Logger+import GHC.Utils.TmpFs+import GHC.Utils.CliOption  import GHC.Types.SrcLoc ( SrcLoc, mkSrcLoc, mkSrcSpan ) import GHC.Data.FastString@@ -32,7 +32,6 @@ import System.IO.Error as IO import System.Process -import GHC.Utils.TmpFs  -- | Enable process jobs support on Windows if it can be expected to work (e.g. -- @process >= 1.6.9.0@).@@ -153,14 +152,14 @@ runSomethingResponseFile   :: Logger   -> TmpFs-  -> DynFlags+  -> TempDir   -> (String->String)   -> String   -> String   -> [Option]   -> Maybe [(String,String)]   -> IO ()-runSomethingResponseFile logger tmpfs dflags filter_fn phase_name pgm args mb_env =+runSomethingResponseFile logger tmpfs tmp_dir filter_fn phase_name pgm args mb_env =     runSomethingWith logger phase_name pgm args $ \real_args -> do         fp <- getResponseFile real_args         let args = ['@':fp]@@ -168,7 +167,7 @@         return (r,())   where     getResponseFile args = do-      fp <- newTempName logger tmpfs (tmpDir dflags) TFL_CurrentModule "rsp"+      fp <- newTempName logger tmpfs tmp_dir TFL_CurrentModule "rsp"       withFile fp WriteMode $ \h -> do           hSetEncoding h utf8           hPutStr h $ unlines $ map escape args
compiler/GHC/SysTools/Tasks.hs view
@@ -10,16 +10,13 @@ module GHC.SysTools.Tasks where  import GHC.Prelude-import GHC.Platform import GHC.ForeignSrcLang-import GHC.IO (catchException) -import GHC.CmmToLlvm.Config (LlvmVersion, llvmVersionStr, supportedLlvmVersionUpperBound, parseLlvmVersion, supportedLlvmVersionLowerBound)+import GHC.CmmToLlvm.Version (LlvmVersion, llvmVersionStr, supportedLlvmVersionUpperBound, parseLlvmVersion, supportedLlvmVersionLowerBound)  import GHC.Settings  import GHC.SysTools.Process-import GHC.SysTools.Info  import GHC.Driver.Session @@ -60,38 +57,9 @@ augmentImports dflags ("-include":fp:fps) = "-include" : augmentByWorkingDirectory dflags fp  : augmentImports dflags fps augmentImports dflags (fp1: fp2: fps) = fp1 : augmentImports dflags (fp2:fps) -runCpp :: Logger -> DynFlags -> [Option] -> IO ()-runCpp logger dflags args = traceSystoolCommand logger "cpp" $ do-  let opts = getOpts dflags opt_P-      modified_imports = augmentImports dflags opts-  let (p,args0) = pgm_P dflags-      args1 = map Option modified_imports-      args2 = [Option "-Werror" | gopt Opt_WarnIsError dflags]-                ++ [Option "-Wundef" | wopt Opt_WarnCPPUndef dflags]-  mb_env <- getGccEnv args2-  runSomethingFiltered logger id  "C pre-processor" p-                       (args0 ++ args1 ++ args2 ++ args) Nothing mb_env--runPp :: Logger -> DynFlags -> [Option] -> IO ()-runPp logger dflags args = traceSystoolCommand logger "pp" $ do-  let prog = pgm_F dflags-      opts = map Option (getOpts dflags opt_F)-  runSomething logger "Haskell pre-processor" prog (args ++ opts)---- | Run compiler of C-like languages and raw objects (such as gcc or clang).-runCc :: Maybe ForeignSrcLang -> Logger -> TmpFs -> DynFlags -> [Option] -> IO ()-runCc mLanguage logger tmpfs dflags args = traceSystoolCommand logger "cc" $ do-  let args1 = map Option userOpts-      args2 = languageOptions ++ args ++ args1-      -- We take care to pass -optc flags in args1 last to ensure that the-      -- user can override flags passed by GHC. See #14452.-  mb_env <- getGccEnv args2-  runSomethingResponseFile logger tmpfs dflags cc_filter dbgstring prog args2-                           mb_env- where-  -- discard some harmless warnings from gcc that we can't turn off-  cc_filter = unlines . doFilter . lines-+-- | Discard some harmless warnings from gcc that we can't turn off+cc_filter :: String -> String+cc_filter = unlines . doFilter . lines where   {-   gcc gives warnings in chunks like so:       In file included from /foo/bar/baz.h:11,@@ -139,6 +107,49 @@    | "warning: call-clobbered register used" `isContainedIn` w = False    | otherwise = True +-- | Run the C preprocessor, which is different from running the+-- Haskell C preprocessor (they're configured separately!).+-- See also Note [Preprocessing invocations] in GHC.SysTools.Cpp+runCpp :: Logger -> TmpFs -> DynFlags -> [Option] -> IO ()+runCpp logger tmpfs dflags args = traceSystoolCommand logger "cpp" $ do+  let (p,args0) = pgm_cpp dflags+      userOpts_c = map Option $ getOpts dflags opt_c+      args2 = args0 ++ args ++ userOpts_c+  mb_env <- getGccEnv args2+  runSomethingResponseFile logger tmpfs (tmpDir dflags) cc_filter "C pre-processor" p+                           args2 mb_env++-- | Run the Haskell C preprocessor.+-- See also Note [Preprocessing invocations] in GHC.SysTools.Cpp+runHsCpp :: Logger -> DynFlags -> [Option] -> IO ()+runHsCpp logger dflags args = traceSystoolCommand logger "hs-cpp" $ do+  let (p,args0) = pgm_P dflags+      opts = getOpts dflags opt_P+      modified_imports = augmentImports dflags opts+      args1 = map Option modified_imports+      args2 = [Option "-Werror" | gopt Opt_WarnIsError dflags]+                ++ [Option "-Wundef" | wopt Opt_WarnCPPUndef dflags]+  mb_env <- getGccEnv args2 -- romes: what about args0 and args?+  runSomethingFiltered logger id "Haskell C pre-processor" p+                       (args0 ++ args1 ++ args2 ++ args) Nothing mb_env++runPp :: Logger -> DynFlags -> [Option] -> IO ()+runPp logger dflags args = traceSystoolCommand logger "pp" $ do+  let prog = pgm_F dflags+      opts = map Option (getOpts dflags opt_F)+  runSomething logger "Haskell pre-processor" prog (args ++ opts)++-- | Run compiler of C-like languages and raw objects (such as gcc or clang).+runCc :: Maybe ForeignSrcLang -> Logger -> TmpFs -> DynFlags -> [Option] -> IO ()+runCc mLanguage logger tmpfs dflags args = traceSystoolCommand logger "cc" $ do+  let args1 = map Option userOpts+      args2 = languageOptions ++ args ++ args1+      -- We take care to pass -optc flags in args1 last to ensure that the+      -- user can override flags passed by GHC. See #14452.+  mb_env <- getGccEnv args2+  runSomethingResponseFile logger tmpfs (tmpDir dflags) cc_filter dbgstring prog args2+                           mb_env+ where   -- force the C compiler to interpret this file as C when   -- compiling .hc files, by adding the -x c option.   -- Also useful for plain .c files, just in case GHC saw a@@ -204,28 +215,14 @@       args1 = map Option (getOpts dflags opt_lc)   runSomething logger "LLVM Compiler" p (args0 ++ args1 ++ args) --- | Run the clang compiler (used as an assembler for the LLVM--- backend on OS X as LLVM doesn't support the OS X system--- assembler)-runClang :: Logger -> DynFlags -> [Option] -> IO ()-runClang logger dflags args = traceSystoolCommand logger "clang" $ do-  let (clang,_) = pgm_lcc dflags-      -- be careful what options we call clang with-      -- see #5903 and #7617 for bugs caused by this.-      (_,args0) = pgm_a dflags-      args1 = map Option (getOpts dflags opt_a)-      args2 = args0 ++ args1 ++ args-  mb_env <- getGccEnv args2-  catchException-    (runSomethingFiltered logger id "Clang (Assembler)" clang args2 Nothing mb_env)-    (\(err :: SomeException) -> do-        errorMsg logger $-            text ("Error running clang! you need clang installed to use the" ++-                  " LLVM backend") $+$-            text "(or GHC tried to execute clang incorrectly)"-        throwIO err-    )+-- | Run the LLVM Assembler+runLlvmAs :: Logger -> DynFlags -> [Option] -> IO ()+runLlvmAs logger dflags args = traceSystoolCommand logger "llvm-as" $ do+  let (p,args0) = pgm_las dflags+      args1 = map Option (getOpts dflags opt_las)+  runSomething logger "LLVM assembler" p (args0 ++ args1 ++ args) + runEmscripten :: Logger -> DynFlags -> [Option] -> IO () runEmscripten logger dflags args = traceSystoolCommand logger "emcc" $ do   let (p,args0) = pgm_a dflags@@ -274,71 +271,6 @@                                 ++ ")") ]                 return Nothing) ---runLink :: Logger -> TmpFs -> DynFlags -> [Option] -> IO ()-runLink logger tmpfs dflags args = traceSystoolCommand logger "linker" $ do-  -- See Note [Run-time linker info]-  ---  -- `-optl` args come at the end, so that later `-l` options-  -- given there manually can fill in symbols needed by-  -- Haskell libraries coming in via `args`.-  linkargs <- neededLinkArgs `fmap` getLinkerInfo logger dflags-  let (p,args0) = pgm_l dflags-      optl_args = map Option (getOpts dflags opt_l)-      args2     = args0 ++ linkargs ++ args ++ optl_args-  mb_env <- getGccEnv args2-  runSomethingResponseFile logger tmpfs dflags ld_filter "Linker" p args2 mb_env-  where-    ld_filter = case (platformOS (targetPlatform dflags)) of-                  OSSolaris2 -> sunos_ld_filter-                  _ -> id-{--  SunOS/Solaris ld emits harmless warning messages about unresolved-  symbols in case of compiling into shared library when we do not-  link against all the required libs. That is the case of GHC which-  does not link against RTS library explicitly in order to be able to-  choose the library later based on binary application linking-  parameters. The warnings look like:--Undefined                       first referenced-  symbol                             in file-stg_ap_n_fast                       ./T2386_Lib.o-stg_upd_frame_info                  ./T2386_Lib.o-templatezmhaskell_LanguageziHaskellziTHziLib_litE_closure ./T2386_Lib.o-templatezmhaskell_LanguageziHaskellziTHziLib_appE_closure ./T2386_Lib.o-templatezmhaskell_LanguageziHaskellziTHziLib_conE_closure ./T2386_Lib.o-templatezmhaskell_LanguageziHaskellziTHziSyntax_mkNameGzud_closure ./T2386_Lib.o-newCAF                              ./T2386_Lib.o-stg_bh_upd_frame_info               ./T2386_Lib.o-stg_ap_ppp_fast                     ./T2386_Lib.o-templatezmhaskell_LanguageziHaskellziTHziLib_stringL_closure ./T2386_Lib.o-stg_ap_p_fast                       ./T2386_Lib.o-stg_ap_pp_fast                      ./T2386_Lib.o-ld: warning: symbol referencing errors--  this is actually coming from T2386 testcase. The emitting of those-  warnings is also a reason why so many TH testcases fail on Solaris.--  Following filter code is SunOS/Solaris linker specific and should-  filter out only linker warnings. Please note that the logic is a-  little bit more complex due to the simple reason that we need to preserve-  any other linker emitted messages. If there are any. Simply speaking-  if we see "Undefined" and later "ld: warning:..." then we omit all-  text between (including) the marks. Otherwise we copy the whole output.--}-    sunos_ld_filter :: String -> String-    sunos_ld_filter = unlines . sunos_ld_filter' . lines-    sunos_ld_filter' x = if (undefined_found x && ld_warning_found x)-                          then (ld_prefix x) ++ (ld_postfix x)-                          else x-    breakStartsWith x y = break (isPrefixOf x) y-    ld_prefix = fst . breakStartsWith "Undefined"-    undefined_found = not . null . snd . breakStartsWith "Undefined"-    ld_warn_break = breakStartsWith "ld: warning: symbol referencing errors"-    ld_postfix = tail . snd . ld_warn_break-    ld_warning_found = not . null . snd . ld_warn_break- -- See Note [Merging object files for GHCi] in GHC.Driver.Pipeline. runMergeObjects :: Logger -> TmpFs -> DynFlags -> [Option] -> IO () runMergeObjects logger tmpfs dflags args =@@ -349,10 +281,10 @@             , "does not support object merging." ]         optl_args = map Option (getOpts dflags opt_lm)         args2     = args0 ++ args ++ optl_args-    if toolSettings_ldSupportsResponseFiles (toolSettings dflags)+    if toolSettings_mergeObjsSupportsResponseFiles (toolSettings dflags)       then do         mb_env <- getGccEnv args2-        runSomethingResponseFile logger tmpfs dflags id "Merge objects" p args2 mb_env+        runSomethingResponseFile logger tmpfs (tmpDir dflags) id "Merge objects" p args2 mb_env       else do         runSomething logger "Merge objects" p args2 @@ -385,6 +317,3 @@   mb_env <- getGccEnv cc_args   runSomethingFiltered logger id "Windres" windres (opts ++ args) Nothing mb_env -touch :: Logger -> DynFlags -> String -> String -> IO ()-touch logger dflags purpose arg = traceSystoolCommand logger "touch" $-  runSomething logger purpose (pgm_T dflags) [FileOption "" arg]
compiler/GHC/Tc/Deriv.hs view
@@ -35,6 +35,7 @@ import GHC.Tc.Gen.HsType import GHC.Core.TyCo.Rep import GHC.Core.TyCo.Ppr ( pprTyVars )+import GHC.Unit.Module.Warnings  import GHC.Rename.Bind import GHC.Rename.Env@@ -60,7 +61,6 @@ import GHC.Utils.Misc import GHC.Utils.Outputable as Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Logger import GHC.Data.Bag import GHC.Utils.FV as FV (fvVarList, unionFV, mkFVs)@@ -294,7 +294,7 @@         -- Importantly, we use rnLocalValBindsLHS, not rnTopBindsLHS, to rename         -- auxiliary bindings as if they were defined locally.         -- See Note [Auxiliary binders] in GHC.Tc.Deriv.Generate.-        ; (bndrs, rn_aux_lhs) <- rnLocalValBindsLHS emptyFsEnv aux_val_binds+        ; (bndrs, rn_aux_lhs) <- rnLocalValBindsLHS emptyMiniFixityEnv aux_val_binds         ; bindLocalNames bndrs $     do  { (rn_aux, dus_aux) <- rnLocalValBindsRHS (mkNameSet bndrs) rn_aux_lhs         ; (rn_inst_infos, fvs_insts) <- mapAndUnzipM rn_inst_info inst_infos@@ -607,7 +607,7 @@ -- -- This returns a Maybe because the user might try to derive Typeable, which is -- a no-op nowadays.-deriveStandalone (L loc (DerivDecl _ deriv_ty mb_lderiv_strat overlap_mode))+deriveStandalone (L loc (DerivDecl (warn, _) deriv_ty mb_lderiv_strat overlap_mode))   = setSrcSpanA loc                       $     addErrCtxt (standaloneCtxt deriv_ty)  $     do { traceTc "Standalone deriving decl for" (ppr deriv_ty)@@ -680,7 +680,8 @@                  return Nothing          else Just <$> mkEqnHelp (fmap unLoc overlap_mode)                                  tvs' cls inst_tys'-                                 deriv_ctxt' mb_deriv_strat' }+                                 deriv_ctxt' mb_deriv_strat'+                                 (fmap unLoc warn) }  -- Typecheck the type in a standalone deriving declaration. --@@ -855,6 +856,7 @@          ; spec <- mkEqnHelp Nothing final_tkvs cls final_cls_args                             (InferContext Nothing) final_mb_deriv_strat+                            Nothing         ; traceTc "deriveTyData 3" (ppr spec)         ; return spec } @@ -1134,13 +1136,14 @@                -- InferContext  => context inferred (deriving on data decl, or                --                  standalone deriving decl with a wildcard)           -> Maybe (DerivStrategy GhcTc)+          -> Maybe (WarningTxt GhcRn)           -> TcRn EarlyDerivSpec -- Make the EarlyDerivSpec for an instance --      forall tvs. theta => cls (tys ++ [ty]) -- where the 'theta' is optional (that's the Maybe part) -- Assumes that this declaration is well-kinded -mkEqnHelp overlap_mode tvs cls cls_args deriv_ctxt deriv_strat = do+mkEqnHelp overlap_mode tvs cls cls_args deriv_ctxt deriv_strat warn = do   is_boot <- tcIsHsBootOrSig   when is_boot $ bale_out DerivErrBootFileFound @@ -1155,7 +1158,8 @@                     , denv_inst_tys     = cls_args'                     , denv_ctxt         = deriv_ctxt                     , denv_skol_info    = skol_info-                    , denv_strat        = deriv_strat' }+                    , denv_strat        = deriv_strat'+                    , denv_warn         = warn }   runReaderT mk_eqn deriv_env   where     skolemise_when_inferring_context ::@@ -1341,7 +1345,8 @@                 , denv_cls          = cls                 , denv_inst_tys     = inst_tys                 , denv_ctxt         = deriv_ctxt-                , denv_skol_info    = skol_info } <- ask+                , denv_skol_info    = skol_info+                , denv_warn         = warn } <- ask        user_ctxt <- askDerivUserTypeCtxt        doDerivInstErrorChecks1 mechanism        loc       <- lift getSrcSpanM@@ -1359,7 +1364,8 @@                    , ds_user_ctxt = user_ctxt                    , ds_overlap = overlap_mode                    , ds_standalone_wildcard = wildcard-                   , ds_mechanism = mechanism' } }+                   , ds_mechanism = mechanism'+                   , ds_warn = warn } }          SupplyContext theta ->             return $ GivenTheta $ DS@@ -1371,7 +1377,8 @@                    , ds_user_ctxt = user_ctxt                    , ds_overlap = overlap_mode                    , ds_standalone_wildcard = Nothing-                   , ds_mechanism = mechanism }+                   , ds_mechanism = mechanism+                   , ds_warn = warn }  mk_eqn_stock :: DerivInstTys -- Information about the arguments to the class              -> DerivM EarlyDerivSpec@@ -1973,7 +1980,7 @@     DerivSpecStock{dsm_stock_dit = dit}       -> data_cons_in_scope_check dit     -- No need to 'data_cons_in_scope_check' for newtype deriving.-    -- Additionally, we also don't need to mark the constructos as+    -- Additionally, we also don't need to mark the constructors as     -- used because newtypes are handled separately elsewhere.     -- See Note [Tracking unused binding and imports] in GHC.Tc.Types     -- or #17328 for more.
compiler/GHC/Tc/Deriv/Functor.hs view
@@ -247,7 +247,7 @@      -- Con a1 a2 ... -> Con (f1 a1) (f2 a2) ...     match_for_con :: Monad m-                  => HsMatchContext GhcPs+                  => HsMatchContextPs                   -> [LPat GhcPs] -> DataCon                   -> [LHsExpr GhcPs -> m (LHsExpr GhcPs)]                   -> m (LMatch GhcPs (LHsExpr GhcPs))@@ -629,7 +629,7 @@ -- constructor @con@ and its arguments. The RHS folds (with @fold@) over @con@ -- and its arguments, applying an expression (from @insides@) to each of the -- respective arguments of @con@.-mkSimpleConMatch :: Monad m => HsMatchContext GhcPs+mkSimpleConMatch :: Monad m => HsMatchContextPs                  -> (RdrName -> [a] -> m (LHsExpr GhcPs))                  -> [LPat GhcPs]                  -> DataCon@@ -664,7 +664,7 @@ -- -- See Note [Generated code for DeriveFoldable and DeriveTraversable] mkSimpleConMatch2 :: Monad m-                  => HsMatchContext GhcPs+                  => HsMatchContextPs                   -> (LHsExpr GhcPs -> [LHsExpr GhcPs]                                       -> m (LHsExpr GhcPs))                   -> [LPat GhcPs]
compiler/GHC/Tc/Deriv/Generate.hs view
@@ -34,7 +34,7 @@         gen_Newtype_fam_insts,         mkCoerceClassMethEqn,         genAuxBinds,-        ordOpTbl, boxConTbl, litConTbl,+        ordOpTbl, boxConTbl,         mkRdrFunBind, mkRdrFunBindEC, mkRdrFunBindSE, error_Expr,          getPossibleDataCons,@@ -83,7 +83,6 @@ import GHC.Utils.Misc import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Lexeme  import GHC.Data.FastString@@ -424,11 +423,12 @@       = emptyBag      negate_expr = nlHsApp (nlHsVar not_RDR)-    lE = mkSimpleGeneratedFunBind loc le_RDR [a_Pat, b_Pat] $+    pats = [a_Pat, b_Pat]+    lE = mkSimpleGeneratedFunBind loc le_RDR pats $         negate_expr (nlHsApp (nlHsApp (nlHsVar lt_RDR) b_Expr) a_Expr)-    gT = mkSimpleGeneratedFunBind loc gt_RDR [a_Pat, b_Pat] $+    gT = mkSimpleGeneratedFunBind loc gt_RDR pats $         nlHsApp (nlHsApp (nlHsVar lt_RDR) b_Expr) a_Expr-    gE = mkSimpleGeneratedFunBind loc ge_RDR [a_Pat, b_Pat] $+    gE = mkSimpleGeneratedFunBind loc ge_RDR pats $         negate_expr (nlHsApp (nlHsApp (nlHsVar lt_RDR) a_Expr) b_Expr)      get_tag con = dataConTag con - fIRST_TAG@@ -516,7 +516,7 @@       where         tag     = get_tag data_con         tag_lit-             = noLocA (HsLit noComments (HsIntPrim NoSourceText (toInteger tag)))+             = noLocA (HsLit noExtField (HsIntPrim NoSourceText (toInteger tag)))      mkInnerEqAlt :: OrdOp -> DataCon -> LMatch GhcPs (LHsExpr GhcPs)     -- First argument 'a' known to be built with K@@ -859,7 +859,7 @@      enum_index       = mkSimpleGeneratedFunBind loc unsafeIndex_RDR-                [noLocA (AsPat noAnn (noLocA c_RDR) noHsTok+                [noLocA (AsPat noAnn (noLocA c_RDR)                            (nlTuplePat [a_Pat, nlWildPat] Boxed)),                                 d_Pat] (            untag_Expr [(a_RDR, ah_RDR)] (@@ -1509,21 +1509,21 @@     int8DataCon_RDR, int16DataCon_RDR, int32DataCon_RDR, int64DataCon_RDR,     word8DataCon_RDR, word16DataCon_RDR, word32DataCon_RDR, word64DataCon_RDR     :: RdrName-gfoldl_RDR     = varQual_RDR  gENERICS (fsLit "gfoldl")-gunfold_RDR    = varQual_RDR  gENERICS (fsLit "gunfold")-toConstr_RDR   = varQual_RDR  gENERICS (fsLit "toConstr")-dataTypeOf_RDR = varQual_RDR  gENERICS (fsLit "dataTypeOf")-dataCast1_RDR  = varQual_RDR  gENERICS (fsLit "dataCast1")-dataCast2_RDR  = varQual_RDR  gENERICS (fsLit "dataCast2")-gcast1_RDR     = varQual_RDR  tYPEABLE (fsLit "gcast1")-gcast2_RDR     = varQual_RDR  tYPEABLE (fsLit "gcast2")-mkConstrTag_RDR = varQual_RDR gENERICS (fsLit "mkConstrTag")-constr_RDR     = tcQual_RDR   gENERICS (fsLit "Constr")-mkDataType_RDR = varQual_RDR  gENERICS (fsLit "mkDataType")-dataType_RDR   = tcQual_RDR   gENERICS (fsLit "DataType")-conIndex_RDR   = varQual_RDR  gENERICS (fsLit "constrIndex")-prefix_RDR     = dataQual_RDR gENERICS (fsLit "Prefix")-infix_RDR      = dataQual_RDR gENERICS (fsLit "Infix")+gfoldl_RDR     = varQual_RDR  gHC_INTERNAL_DATA_DATA (fsLit "gfoldl")+gunfold_RDR    = varQual_RDR  gHC_INTERNAL_DATA_DATA (fsLit "gunfold")+toConstr_RDR   = varQual_RDR  gHC_INTERNAL_DATA_DATA (fsLit "toConstr")+dataTypeOf_RDR = varQual_RDR  gHC_INTERNAL_DATA_DATA (fsLit "dataTypeOf")+dataCast1_RDR  = varQual_RDR  gHC_INTERNAL_DATA_DATA (fsLit "dataCast1")+dataCast2_RDR  = varQual_RDR  gHC_INTERNAL_DATA_DATA (fsLit "dataCast2")+gcast1_RDR     = varQual_RDR  gHC_INTERNAL_TYPEABLE (fsLit "gcast1")+gcast2_RDR     = varQual_RDR  gHC_INTERNAL_TYPEABLE (fsLit "gcast2")+mkConstrTag_RDR = varQual_RDR gHC_INTERNAL_DATA_DATA (fsLit "mkConstrTag")+constr_RDR     = tcQual_RDR   gHC_INTERNAL_DATA_DATA (fsLit "Constr")+mkDataType_RDR = varQual_RDR  gHC_INTERNAL_DATA_DATA (fsLit "mkDataType")+dataType_RDR   = tcQual_RDR   gHC_INTERNAL_DATA_DATA (fsLit "DataType")+conIndex_RDR   = varQual_RDR  gHC_INTERNAL_DATA_DATA (fsLit "constrIndex")+prefix_RDR     = dataQual_RDR gHC_INTERNAL_DATA_DATA (fsLit "Prefix")+infix_RDR      = dataQual_RDR gHC_INTERNAL_DATA_DATA (fsLit "Infix")  eqChar_RDR     = varQual_RDR  gHC_PRIM (fsLit "eqChar#") ltChar_RDR     = varQual_RDR  gHC_PRIM (fsLit "ltChar#")@@ -1610,14 +1610,14 @@ gtDouble_RDR   = varQual_RDR  gHC_PRIM (fsLit ">##" ) geDouble_RDR   = varQual_RDR  gHC_PRIM (fsLit ">=##") -int8DataCon_RDR   = dataQual_RDR gHC_INT (fsLit "I8#")-int16DataCon_RDR  = dataQual_RDR gHC_INT (fsLit "I16#")-int32DataCon_RDR  = dataQual_RDR gHC_INT (fsLit "I32#")-int64DataCon_RDR  = dataQual_RDR gHC_INT (fsLit "I64#")-word8DataCon_RDR  = dataQual_RDR gHC_WORD (fsLit "W8#")-word16DataCon_RDR = dataQual_RDR gHC_WORD (fsLit "W16#")-word32DataCon_RDR = dataQual_RDR gHC_WORD (fsLit "W32#")-word64DataCon_RDR = dataQual_RDR gHC_WORD (fsLit "W64#")+int8DataCon_RDR   = dataQual_RDR gHC_INTERNAL_INT (fsLit "I8#")+int16DataCon_RDR  = dataQual_RDR gHC_INTERNAL_INT (fsLit "I16#")+int32DataCon_RDR  = dataQual_RDR gHC_INTERNAL_INT (fsLit "I32#")+int64DataCon_RDR  = dataQual_RDR gHC_INTERNAL_INT (fsLit "I64#")+word8DataCon_RDR  = dataQual_RDR gHC_INTERNAL_WORD (fsLit "W8#")+word16DataCon_RDR = dataQual_RDR gHC_INTERNAL_WORD (fsLit "W16#")+word32DataCon_RDR = dataQual_RDR gHC_INTERNAL_WORD (fsLit "W32#")+word64DataCon_RDR = dataQual_RDR gHC_INTERNAL_WORD (fsLit "W64#") {- ************************************************************************ *                                                                      *@@ -1656,8 +1656,8 @@     mk_untyped_bracket = HsUntypedBracket noAnn . ExpBr noExtField     mk_typed_bracket = HsTypedBracket noAnn -    mk_tsplice = HsTypedSplice (EpAnnNotUsed, noAnn)-    mk_usplice = HsUntypedSplice EpAnnNotUsed . HsUntypedSpliceExpr noAnn+    mk_tsplice = HsTypedSplice []+    mk_usplice = HsUntypedSplice noExtField . HsUntypedSpliceExpr noAnn     data_cons = getPossibleDataCons tycon tycon_args      pats_etc mk_bracket mk_splice lift_name data_con@@ -2101,7 +2101,7 @@         rep_cvs'    = scopedSort rep_cvs  nlHsAppType :: LHsExpr GhcPs -> Type -> LHsExpr GhcPs-nlHsAppType e s = noLocA (HsAppType noExtField e noHsTok hs_ty)+nlHsAppType e s = noLocA (HsAppType noAnn e hs_ty)   where     hs_ty = mkHsWildCardBndrs $ parenthesizeHsType appPrec $ nlHsCoreTy s @@ -2293,7 +2293,7 @@ mkRdrFunBind :: LocatedN RdrName -> [LMatch GhcPs (LHsExpr GhcPs)]              -> LHsBind GhcPs mkRdrFunBind fun@(L loc _fun_rdr) matches-  = L (na2la loc) (mkFunBind (Generated SkipPmc) fun matches)+  = L (l2l loc) (mkFunBind (Generated OtherExpansion SkipPmc) fun matches)  -- | Make a function binding. If no equations are given, produce a function -- with the given arity that uses an empty case expression for the last@@ -2321,7 +2321,7 @@                -> [LMatch GhcPs (LHsExpr GhcPs)]                -> LHsBind GhcPs mkRdrFunBindEC arity catch_all fun@(L loc _fun_rdr) matches-  = L (na2la loc) (mkFunBind (Generated SkipPmc) fun matches')+  = L (l2l loc) (mkFunBind (Generated OtherExpansion SkipPmc) fun matches')  where    -- Catch-all eqn looks like    --     fmap _ z = case z of {}@@ -2334,7 +2334,7 @@    -- See #4302    matches' = if null matches               then [mkMatch (mkPrefixFunRhs fun)-                            (replicate (arity - 1) nlWildPat ++ [z_Pat])+                            (replicate (arity - 1) (nlWildPat) ++ [z_Pat])                             (catch_all $ nlHsCase z_Expr [])                             emptyLocalBinds]               else matches@@ -2345,7 +2345,7 @@ mkRdrFunBindSE :: Arity -> LocatedN RdrName ->                     [LMatch GhcPs (LHsExpr GhcPs)] -> LHsBind GhcPs mkRdrFunBindSE arity fun@(L loc fun_rdr) matches-  = L (na2la loc) (mkFunBind (Generated SkipPmc) fun matches')+  = L (l2l loc) (mkFunBind (Generated OtherExpansion SkipPmc) fun matches')  where    -- Catch-all eqn looks like    --     compare _ _ = error "Void compare"@@ -2365,7 +2365,7 @@             -> Type             -- The argument type             -> LHsExpr GhcPs    -- Boxed version of the arg -- See Note [Deriving and unboxed types] in GHC.Tc.Deriv.Infer-box cls_str arg arg_ty = assoc_ty_id cls_str boxConTbl arg_ty arg+box cls_str arg arg_ty = nlHsApp (assoc_ty_id cls_str boxConTbl arg_ty) arg  --------------------- primOrdOps :: String    -- The class involved@@ -2405,23 +2405,22 @@     ,(doublePrimTy, (ltDouble_RDR, leDouble_RDR      , eqDouble_RDR, geDouble_RDR, gtDouble_RDR)) ] --- A mapping from a primitive type to a function that constructs its boxed--- version.-boxConTbl :: [(Type, LHsExpr GhcPs -> LHsExpr GhcPs)]+-- A mapping from a primitive type to a DataCon of its boxed version.+boxConTbl :: [(Type, LHsExpr GhcPs)] boxConTbl =-    [ (charPrimTy  , nlHsApp (nlHsVar $ getRdrName charDataCon))-    , (intPrimTy   , nlHsApp (nlHsVar $ getRdrName intDataCon))-    , (wordPrimTy  , nlHsApp (nlHsVar $ getRdrName wordDataCon ))-    , (floatPrimTy , nlHsApp (nlHsVar $ getRdrName floatDataCon ))-    , (doublePrimTy, nlHsApp (nlHsVar $ getRdrName doubleDataCon))-    , (int8PrimTy,   nlHsApp (nlHsVar int8DataCon_RDR))-    , (word8PrimTy,  nlHsApp (nlHsVar word8DataCon_RDR))-    , (int16PrimTy,  nlHsApp (nlHsVar int16DataCon_RDR))-    , (word16PrimTy, nlHsApp (nlHsVar word16DataCon_RDR))-    , (int32PrimTy,  nlHsApp (nlHsVar int32DataCon_RDR))-    , (word32PrimTy, nlHsApp (nlHsVar word32DataCon_RDR))-    , (int64PrimTy,  nlHsApp (nlHsVar int64DataCon_RDR))-    , (word64PrimTy, nlHsApp (nlHsVar word64DataCon_RDR))+    [ (charPrimTy  , nlHsVar $ getRdrName charDataCon)+    , (intPrimTy   , nlHsVar $ getRdrName intDataCon)+    , (wordPrimTy  , nlHsVar $ getRdrName wordDataCon)+    , (floatPrimTy , nlHsVar $ getRdrName floatDataCon)+    , (doublePrimTy, nlHsVar $ getRdrName doubleDataCon)+    , (int8PrimTy,   nlHsVar int8DataCon_RDR)+    , (word8PrimTy,  nlHsVar word8DataCon_RDR)+    , (int16PrimTy,  nlHsVar int16DataCon_RDR)+    , (word16PrimTy, nlHsVar word16DataCon_RDR)+    , (int32PrimTy,  nlHsVar int32DataCon_RDR)+    , (word32PrimTy, nlHsVar word32DataCon_RDR)+    , (int64PrimTy,  nlHsVar int64DataCon_RDR)+    , (word64PrimTy, nlHsVar word64DataCon_RDR)     ]  @@ -2445,28 +2444,8 @@     ,(word64PrimTy, "#Word64")     ] -litConTbl :: [(Type, LHsExpr GhcPs -> LHsExpr GhcPs)]-litConTbl-  = [(charPrimTy  , nlHsApp (nlHsVar charPrimL_RDR))-    ,(intPrimTy   , nlHsApp (nlHsVar intPrimL_RDR)-                      . nlHsApp (nlHsVar toInteger_RDR))-    ,(wordPrimTy  , nlHsApp (nlHsVar wordPrimL_RDR)-                      . nlHsApp (nlHsVar toInteger_RDR))-    ,(addrPrimTy  , nlHsApp (nlHsVar stringPrimL_RDR)-                      . nlHsApp (nlHsApp-                          (nlHsVar map_RDR)-                          (compose_RDR `nlHsApps`-                            [ nlHsVar fromIntegral_RDR-                            , nlHsVar fromEnum_RDR-                            ])))-    ,(floatPrimTy , nlHsApp (nlHsVar floatPrimL_RDR)-                      . nlHsApp (nlHsVar toRational_RDR))-    ,(doublePrimTy, nlHsApp (nlHsVar doublePrimL_RDR)-                      . nlHsApp (nlHsVar toRational_RDR))-    ]- -- | Lookup `Type` in an association list.-assoc_ty_id :: HasDebugCallStack => String           -- The class involved+assoc_ty_id :: HasCallStack => String           -- The class involved             -> [(Type,a)]       -- The table             -> Type             -- The type             -> a                -- The result of the lookup
compiler/GHC/Tc/Deriv/Generics.hs view
@@ -58,7 +58,6 @@ import GHC.Utils.Error( Validity'(..), andValid ) import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Misc  import GHC.Driver.DynFlags
compiler/GHC/Tc/Deriv/Infer.hs view
@@ -48,7 +48,6 @@ import GHC.Utils.Error import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Misc  import GHC.Types.Basic
compiler/GHC/Tc/Deriv/Utils.hs view
@@ -26,6 +26,7 @@  import GHC.Prelude +import GHC.Hs.Extension import GHC.Data.Bag import GHC.Types.Basic @@ -51,6 +52,7 @@ import GHC.Hs import GHC.Driver.Session import GHC.Unit.Module (getModule)+import GHC.Unit.Module.Warnings import GHC.Unit.Module.ModIface (mi_fix)  import GHC.Types.Fixity.Env (lookupFixity)@@ -144,6 +146,8 @@   , denv_strat        :: Maybe (DerivStrategy GhcTc)     -- ^ 'Just' if user requests a particular deriving strategy.     --   Otherwise, 'Nothing'.+  , denv_warn         :: Maybe (WarningTxt GhcRn)+    -- ^ A warning to emit whenever the derived instance is used   }  instance Outputable DerivEnv where@@ -175,7 +179,8 @@                           , ds_standalone_wildcard :: Maybe SrcSpan                               -- See Note [Inferring the instance context]                               -- in GHC.Tc.Deriv.Infer-                          , ds_mechanism           :: DerivSpecMechanism }+                          , ds_mechanism           :: DerivSpecMechanism+                          , ds_warn                :: Maybe (WarningTxt GhcRn)}         -- This spec implies a dfun declaration of the form         --       df :: forall tvs. theta => C tys         -- The Name is the name for the DFun we'll build@@ -644,7 +649,7 @@                , sps_type_or_kind = t_or_k                }) -substPredSpec :: HasDebugCallStack => Subst -> PredSpec -> PredSpec+substPredSpec :: HasCallStack => Subst -> PredSpec -> PredSpec substPredSpec subst ps =   case ps of     SimplePredSpec { sps_pred = pred@@ -1182,8 +1187,9 @@ newDerivClsInst :: DerivSpec ThetaType -> TcM ClsInst newDerivClsInst (DS { ds_name = dfun_name, ds_overlap = overlap_mode                     , ds_tvs = tvs, ds_theta = theta-                    , ds_cls = clas, ds_tys = tys })-  = newClsInst overlap_mode dfun_name tvs theta clas tys+                    , ds_cls = clas, ds_tys = tys+                    , ds_warn = warn })+  = newClsInst overlap_mode dfun_name tvs theta clas tys warn  extendLocalInstEnv :: [ClsInst] -> TcM a -> TcM a -- Add new locally-defined instances; don't bother to check
compiler/GHC/Tc/Errors.hs view
@@ -1,6 +1,7 @@  {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE LambdaCase          #-}+{-# LANGUAGE MultiWayIf          #-} {-# LANGUAGE NamedFieldPuns      #-} {-# LANGUAGE ParallelListComp    #-} {-# LANGUAGE ScopedTypeVariables #-}@@ -12,7 +13,7 @@        warnDefaulting,         -- * GHC API helper functions-       solverReportMsg_ExpectedActuals,+       solverReportMsg_ExpectedActuals, mismatchMsg_ExpectedActuals   ) where  import GHC.Prelude@@ -261,17 +262,12 @@ important :: SolverReportErrCtxt -> TcSolverReportMsg -> SolverReport important ctxt doc   = SolverReport { sr_important_msg = SolverReportWithCtxt ctxt doc-                 , sr_supplementary = []-                 , sr_hints         = [] }+                 , sr_supplementary = [] }  add_relevant_bindings :: RelevantBindings -> SolverReport -> SolverReport add_relevant_bindings binds report@(SolverReport { sr_supplementary = supp })   = report { sr_supplementary = SupplementaryBindings binds : supp } -add_report_hints :: [GhcHint] -> SolverReport -> SolverReport-add_report_hints hints report@(SolverReport { sr_hints = prev_hints })-  = report { sr_hints = prev_hints ++ hints }- -- | Returns True <=> the SolverReportErrCtxt indicates that something is deferred deferringAnyBindings :: SolverReportErrCtxt -> Bool   -- Don't check cec_type_holes, as these don't cause bindings to be deferred@@ -433,7 +429,7 @@ reportBadTelescope ctxt env (ForAllSkol telescope) skols   = do { msg <- mkErrorReport                   env-                  (TcRnSolverReport report ErrorWithoutFlag noHints)+                  (TcRnSolverReport report ErrorWithoutFlag)                   (Just ctxt)                   []        ; reportDiagnostic msg }@@ -469,8 +465,6 @@              flav = ctFlavour ct         ; (suppress, m_evdest) <- case ctEvidence ct of-         -- For this `suppress` stuff-         -- see Note [Wanteds rewrite Wanteds] in GHC.Tc.Types.Constraint            CtGiven {} -> return (False, Nothing)            CtWanted { ctev_rewriters = rewriters, ctev_dest = dest }              -> do { rewriters' <- zonkRewriterSet rewriters@@ -1032,7 +1026,7 @@     frr_origins = acc_errors errs     diag = TcRnSolverReport              (SolverReportWithCtxt ctxt (FixedRuntimeRepError frr_origins))-             ErrorWithoutFlag noHints+             ErrorWithoutFlag      -- Accumulate the different kind of errors arising from syntactic equality.     -- (Only SynEq_FRR origin for the moment.)@@ -1091,9 +1085,7 @@                    -- For given constraints we overwrite the env (and hence src-loc)                    -- with one from the immediately-enclosing implication.                    -- See Note [Inaccessible code]--       ; (eq_err_msg, _hints) <- mkEqErr_help ctxt item' ty1 ty2-       -- The hints wouldn't help in this situation, so we discard them.+       ; eq_err_msg <- mkEqErr_help ctxt item' ty1 ty2        ; let supplementary = [ SupplementaryBindings relevant_binds ]              msg = TcRnInaccessibleCode implic (SolverReportWithCtxt ctxt eq_err_msg)        ; msg <- mkErrorReport (ctLocEnv loc') msg (Just ctxt) supplementary@@ -1183,7 +1175,7 @@  -- See Note [No deferring for multiplicity errors] nonDeferrableOrigin :: CtOrigin -> Bool-nonDeferrableOrigin NonLinearPatternOrigin  = True+nonDeferrableOrigin (NonLinearPatternOrigin {}) = True nonDeferrableOrigin (UsageEnvironmentOf {}) = True nonDeferrableOrigin (FRROrigin {})          = True nonDeferrableOrigin _                       = False@@ -1192,8 +1184,7 @@                  -> NonEmpty ErrorItem     -- items covered by the Report                  -> SolverReport -> TcM () maybeReportError ctxt items@(item1:|_) (SolverReport { sr_important_msg = important-                                                     , sr_supplementary = supp-                                                     , sr_hints = hints })+                                                     , sr_supplementary = supp })   = unless (cec_suppress ctxt  -- Some worse error has occurred, so suppress this diagnostic          || all ei_suppress items) $                            -- if they're all to be suppressed, report nothing@@ -1203,7 +1194,7 @@     do let reason | any (nonDeferrableOrigin . errorItemOrigin) items = ErrorWithoutFlag                   | otherwise                                         = cec_defer_type_errors ctxt                   -- See Note [No deferring for multiplicity errors]-           diag = TcRnSolverReport important reason hints+           diag = TcRnSolverReport important reason        msg <- mkErrorReport (ctLocEnv (errorItemCtLoc item1)) diag (Just ctxt) supp        reportDiagnostic msg @@ -1231,7 +1222,7 @@ mkErrorTerm ctxt ct_loc ty (SolverReport { sr_important_msg = important, sr_supplementary = supp })   = do { msg <- mkErrorReport                   (ctLocEnv ct_loc)-                  (TcRnSolverReport important ErrorWithoutFlag noHints) (Just ctxt) supp+                  (TcRnSolverReport important ErrorWithoutFlag) (Just ctxt) supp          -- This will be reported at runtime, so we always want "error:" in the report, never "warning:"        ; dflags <- getDynFlags        ; let err_msg = pprLocMsgEnvelope (initTcMessageOpts dflags) msg@@ -1418,7 +1409,6 @@  {- Note [Constructing Hole Errors] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~- Whether or not 'mkHoleError' returns an error is not influenced by cec_suppress. In other terms, these "hole" errors are /not/ suppressed by cec_suppress. We want to see them! @@ -1458,11 +1448,14 @@   = do { (imp_errs, hints)            <- unknownNameSuggestions (ctl_rdr lcl_env) WL_Anything occ        ; let-             err    = SolverReportWithCtxt ctxt (ReportHoleError hole $ OutOfScopeHole imp_errs)-             report = SolverReport err [] hints+             err    = SolverReportWithCtxt ctxt+                    $ ReportHoleError hole+                    $ OutOfScopeHole imp_errs hints+             report = SolverReport err []         ; maybeAddDeferredBindings ctxt hole report-       ; mkErrorReport lcl_env (TcRnSolverReport err (cec_out_of_scope_holes ctxt) hints) Nothing []+       ; mkErrorReport lcl_env (TcRnSolverReport err (cec_out_of_scope_holes ctxt))+           Nothing []           -- Pass the value 'Nothing' for the context, as it's generally not helpful           -- to include the context here.        }@@ -1492,14 +1485,16 @@        ; (grouped_skvs, other_tvs) <- liftZonkM $ zonkAndGroupSkolTvs hole_ty        ; let reason | ExprHole _ <- sort = cec_expr_holes ctxt                     | otherwise          = cec_type_holes ctxt-             err  = SolverReportWithCtxt ctxt $ ReportHoleError hole $ HoleError sort other_tvs grouped_skvs+             err  = SolverReportWithCtxt ctxt+                  $ ReportHoleError hole+                  $ HoleError sort other_tvs grouped_skvs              supp = [ SupplementaryBindings rel_binds                     , SupplementaryCts      relevant_cts                     , SupplementaryHoleFits hole_fits ] -       ; maybeAddDeferredBindings ctxt hole (SolverReport err supp [])+       ; maybeAddDeferredBindings ctxt hole (SolverReport err supp) -       ; mkErrorReport lcl_env (TcRnSolverReport err reason noHints) (Just ctxt) supp+       ; mkErrorReport lcl_env (TcRnSolverReport err reason) (Just ctxt) supp        }    where@@ -1528,12 +1523,10 @@  {- Note [Adding deferred bindings] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~- When working with typed holes we have to deal with the case where we want holes to be reported as warnings to users during compile time but as errors during runtime. Therefore, we have to call 'maybeAddDeferredBindings' so that the correct 'Severity' can be computed out of that later on.- -}  @@ -1627,9 +1620,16 @@   | FRROrigin frr_orig <- errorItemOrigin item   = Just $ FRR_Info { frr_info_origin = frr_orig                     , frr_info_not_concrete = Nothing }-  -- Unsolved nominal equalities involving a concrete type variable,+  -- A nominal equality involving a concrete type variable,   -- such as @alpha[conc] ~# rr[sk]@ or @beta[conc] ~# RR@ for a-  -- type family application @RR@, are handled by 'mkTyVarEqErr''.+  -- type family application @RR@.+  | EqPred NomEq ty1 ty2 <- classifyPredType (errorItemPred item)+  = if | Just (tv1, ConcreteFRR frr1) <- isConcreteTyVarTy_maybe ty1+       -> Just $ FRR_Info frr1 (Just (tv1, ty2))+       | Just (tv2, ConcreteFRR frr2) <- isConcreteTyVarTy_maybe ty2+       -> Just $ FRR_Info frr2 (Just (tv2, ty1))+       | otherwise+       -> Nothing   | otherwise   = Nothing @@ -1702,10 +1702,9 @@                      -- givens handled in mkGivenErrorReporter   = do { (ctxt, binds, item) <- relevantBindings True ctxt item        ; traceTc "mkEqErr1" (ppr item $$ pprCtOrigin (errorItemOrigin item))-       ; (err_msg, hints) <- mkEqErr_help ctxt item ty1 ty2+       ; err_msg <- mkEqErr_help ctxt item ty1 ty2        ; let            report = add_relevant_bindings binds-                  $ add_report_hints hints                   $ important ctxt err_msg        ; return report }   where@@ -1754,7 +1753,7 @@  mkEqErr_help :: SolverReportErrCtxt              -> ErrorItem-             -> TcType -> TcType -> TcM (TcSolverReportMsg, [GhcHint])+             -> TcType -> TcType -> TcM TcSolverReportMsg mkEqErr_help ctxt item ty1 ty2   | Just casted_tv1 <- getCastedTyVar_maybe ty1   = mkTyVarEqErr ctxt item casted_tv1 ty2@@ -1764,8 +1763,7 @@   = mkTyVarEqErr ctxt item casted_tv2 ty1    | otherwise-  = do { err <- reportEqErr ctxt item ty1 ty2-       ; return (err, noHints) }+  = reportEqErr ctxt item ty1 ty2  reportEqErr :: SolverReportErrCtxt             -> ErrorItem@@ -1795,14 +1793,14 @@     return $ mkCoercibleExplanation rdr_env fam_envs ty1 ty2  mkTyVarEqErr :: SolverReportErrCtxt -> ErrorItem-             -> (TcTyVar, TcCoercionN) -> TcType -> TcM (TcSolverReportMsg, [GhcHint])+             -> (TcTyVar, TcCoercionN) -> TcType -> TcM TcSolverReportMsg -- tv1 and ty2 are already tidied mkTyVarEqErr ctxt item casted_tv1 ty2   = do { traceTc "mkTyVarEqErr" (ppr item $$ ppr casted_tv1 $$ ppr ty2)        ; mkTyVarEqErr' ctxt item casted_tv1 ty2 }  mkTyVarEqErr' :: SolverReportErrCtxt -> ErrorItem-              -> (TcTyVar, TcCoercionN) -> TcType -> TcM (TcSolverReportMsg, [GhcHint])+              -> (TcTyVar, TcCoercionN) -> TcType -> TcM TcSolverReportMsg mkTyVarEqErr' ctxt item (tv1, co1) ty2    -- Is this a representation-polymorphism error, e.g.@@ -1810,7 +1808,7 @@   | Just frr_info <- mb_concrete_reason   = do       (_, infos) <- liftZonkM $ zonkTidyFRRInfos (cec_tidy ctxt) [frr_info]-      return (FixedRuntimeRepError infos, [])+      return $ FixedRuntimeRepError infos    -- Impredicativity is a simple error to understand;   -- try it before anything more complicated.@@ -1831,13 +1829,13 @@         -- Unlike the other reports, this discards the old 'report_important'         -- instead of augmenting it.  This is because the details are not likely         -- to be helpful since this is just an unimplemented feature.-    return (main_msg, [])+    return main_msg    -- Incompatible kinds   -- This is wrinkle (EIK2) in Note [Equalities with incompatible kinds]   -- in GHC.Tc.Solver.Equality   | hasCoercionHoleCo co1 || hasCoercionHoleTy ty2-  = return (mkBlockedEqErr item, [])+  = return $ mkBlockedEqErr item    | isSkolemTyVar tv1  -- ty2 won't be a meta-tyvar; we would have                        -- swapped in Solver.Equality.canEqTyVarHomo@@ -1852,7 +1850,7 @@     let main_msg = CannotUnifyVariable                      { mismatchMsg       = headline_msg                      , cannotUnifyReason = reason }-    return (main_msg, add_sig)+    return main_msg    | tv1 `elemVarSet` tyCoVarsOfType ty2     -- We report an "occurs check" even for  a ~ F t a, where F is a type@@ -1877,7 +1875,7 @@             { mismatchMsg       = headline_msg             , cannotUnifyReason = occurs_err } -    in return (main_msg, [])+    in return main_msg    -- If the immediately-enclosing implication has 'tv' a skolem, and   -- we know by now its an InferSkol kind of skolem, then presumably@@ -1893,7 +1891,7 @@                , mismatchTyVarInfo     = Just tv_extra                , mismatchAmbiguityInfo = []                , mismatchCoercibleInfo = Nothing }-    return (msg, [])+    return msg    -- Check for skolem escape   | (implic:_) <- cec_encl ctxt   -- Get the innermost context@@ -1905,7 +1903,7 @@             { mismatchMsg       = mismatch_msg             , cannotUnifyReason = SkolemEscape item implic esc_skols } -  in return (main_msg, [])+  in return main_msg    -- Nastiest case: attempt to unify an untouchable variable   -- So tv is a meta tyvar (or started that way before we@@ -1923,18 +1921,16 @@                , mismatchTyVarInfo     = Just tv_extra'                , mismatchAmbiguityInfo = []                , mismatchCoercibleInfo = Nothing }-    return (msg, add_sig)+    return msg    | otherwise-  = do { err <- reportEqErr ctxt item (mkTyVarTy tv1) ty2-       ; return (err, []) }+  = reportEqErr ctxt item (mkTyVarTy tv1) ty2         -- This *can* happen (#6123)         -- Consider an ambiguous top-level constraint (a ~ F a)         -- Not an occurs check, because F is a type function.   where     headline_msg = misMatchOrCND ctxt item ty1 ty2     mismatch_msg = mkMismatchMsg item ty1 ty2-    add_sig      = maybeToList $ suggestAddSig ctxt ty1 ty2      -- The following doesn't use the cterHasProblem mechanism because     -- we need to retrieve the ConcreteTvOrigin. Just knowing whether@@ -2092,32 +2088,6 @@       return $ mkTcTyVar (tyVarName tv) (tyVarKind tv) (SkolemTv new_skol_info lvl overlaps)     _ -> return tv --suggestAddSig :: SolverReportErrCtxt -> TcType -> TcType -> Maybe GhcHint--- See Note [Suggest adding a type signature]-suggestAddSig ctxt ty1 _ty2-  | bndr : bndrs <- inferred_bndrs-  = Just $ SuggestAddTypeSignatures $ NamedBindings (bndr :| bndrs)-  | otherwise-  = Nothing-  where-    inferred_bndrs =-      case getTyVar_maybe ty1 of-        Just tv | isSkolemTyVar tv -> find (cec_encl ctxt) False tv-        _                          -> []--    -- 'find' returns the binders of an InferSkol for 'tv',-    -- provided there is an intervening implication with-    -- ic_given_eqs /= NoGivenEqs (i.e. a GADT match)-    find [] _ _ = []-    find (implic:implics) seen_eqs tv-       | tv `elem` ic_skols implic-       , InferSkol prs <- ic_info implic-       , seen_eqs-       = map fst prs-       | otherwise-       = find implics (seen_eqs || ic_given_eqs implic /= NoGivenEqs) tv- -------------------- mkMismatchMsg :: ErrorItem -> Type -> Type -> MismatchMsg mkMismatchMsg item ty1 ty2 =@@ -2206,33 +2176,7 @@   | otherwise   = Nothing -{- Note [Suggest adding a type signature]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-The OutsideIn algorithm rejects GADT programs that don't have a principal-type, and indeed some that do.  Example:-   data T a where-     MkT :: Int -> T Int--   f (MkT n) = n--Does this have type f :: T a -> a, or f :: T a -> Int?-The error that shows up tends to be an attempt to unify an-untouchable type variable.  So suggestAddSig sees if the offending-type variable is bound by an *inferred* signature, and suggests-adding a declared signature instead.--More specifically, we suggest adding a type sig if we have p ~ ty, and-p is a skolem bound by an InferSkol.  Those skolems were created from-unification variables in simplifyInfer.  Why didn't we unify?  It must-have been because of an intervening GADT or existential, making it-untouchable. Either way, a type signature would help.  For GADTs, it-might make it typeable; for existentials the attempt to write a-signature will fail -- or at least will produce a better error message-next time--This initially came up in #8968, concerning pattern synonyms.--Note [Disambiguating (X ~ X) errors]+{- Note [Disambiguating (X ~ X) errors] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ See #8278 @@ -2604,10 +2548,10 @@                          (RelevantBindings (bd:bds) discards) tc_bndrs }  ------------------------warnDefaulting :: TcTyVar -> [Ct] -> Type -> TcM ()-warnDefaulting _ [] _+warnDefaulting :: [Ct] -> TcTyVar -> Type -> TcM ()+warnDefaulting [] _ _   = panic "warnDefaulting: empty Wanteds"-warnDefaulting the_tv wanteds@(ct:_) default_ty+warnDefaulting wanteds@(ct:_) the_tv default_ty   = do { warn_default <- woptM Opt_WarnTypeDefaults        ; env0 <- liftZonkM $ tcInitTidyEnv             -- don't want to report all the superclass constraints, which@@ -2642,20 +2586,12 @@ -- Prefer using this over manually inspecting the 'TcSolverReportMsg' datatype -- if you just want this information, as the datatype itself is subject to change -- across GHC versions.-solverReportMsg_ExpectedActuals :: TcSolverReportMsg -> [(Type, Type)]+solverReportMsg_ExpectedActuals :: TcSolverReportMsg -> Maybe (Type, Type) solverReportMsg_ExpectedActuals   = \case     Mismatch { mismatchMsg = mismatch_msg } ->-      case mismatch_msg of-        BasicMismatch { mismatch_ty1 = exp, mismatch_ty2 = act } ->-          [(exp, act)]-        KindMismatch { kmismatch_expected = exp, kmismatch_actual = act } ->-          [(exp, act)]-        TypeEqMismatch { teq_mismatch_expected = exp, teq_mismatch_actual = act } ->-          [(exp,act)]-        CouldNotDeduce {} ->-          []-    _ -> []+      mismatchMsg_ExpectedActuals mismatch_msg+    _ -> Nothing  -- | Filter the list by the given predicate, but if that would be empty, -- just give back the original list.
compiler/GHC/Tc/Errors/Hole.hs view
@@ -48,7 +48,7 @@ import GHC.Core.Predicate( Pred(..), classifyPredType, eqRelRole ) import GHC.Types.Name import GHC.Types.Name.Reader-import GHC.Builtin.Names ( gHC_ERR, uNSAFE_COERCE )+import GHC.Builtin.Names ( gHC_INTERNAL_ERR, gHC_INTERNAL_UNSAFE_COERCE ) import GHC.Types.Id import GHC.Types.Var.Set import GHC.Types.Var.Env@@ -402,7 +402,7 @@  Note [Speeding up valid hole-fits] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-To fix #16875 we noted that a lot of time was being spent on unecessary work.+To fix #16875 we noted that a lot of time was being spent on unnecessary work.  When we'd call `tcCheckHoleFit hole hole_ty ty`, we would end up by generating a constraint to show that `hole_ty ~ ty`, including any constraints in `ty`. For@@ -824,7 +824,7 @@                _ -> discard_it }         where           -- We want to filter out undefined and the likes from GHC.Err (#17940)-          not_trivial id = nameModule_maybe (idName id) `notElem` [Just gHC_ERR, Just uNSAFE_COERCE]+          not_trivial id = nameModule_maybe (idName id) `notElem` [Just gHC_INTERNAL_ERR, Just gHC_INTERNAL_UNSAFE_COERCE]            lookup :: HoleFitCandidate -> TcM (Maybe (Id, Type))           lookup (IdHFCand id) = return (Just (id, idType id))@@ -836,9 +836,6 @@                                            Just (dataConWrapId con, dataConNonlinearType con)                                        _ -> Nothing }             where name = case hfc of-#if __GLASGOW_HASKELL__ < 901-                           IdHFCand id     -> idName id-#endif                            GreHFCand gre   -> greName gre                            NameHFCand name -> name           discard_it = go subs seen maxleft ty elts@@ -959,7 +956,7 @@                               , th_implics      = []                               , th_hole         = Nothing } --- | A tcSubsumes which takes into account relevant constraints, to fix trac+-- | A tcSubsumes which takes into account relevant constraints, to fix -- #14273. This makes sure that when checking whether a type fits the hole, -- the type has to be subsumed by type of the hole as well as fulfill all -- constraints on the type of the hole.
compiler/GHC/Tc/Gen/App.hs view
@@ -2,9 +2,11 @@ {-# LANGUAGE DataKinds           #-} {-# LANGUAGE FlexibleContexts    #-} {-# LANGUAGE GADTs               #-}+{-# LANGUAGE MultiWayIf          #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies        #-} {-# LANGUAGE UndecidableInstances #-} -- Wrinkle in Note [Trees That Grow]+{-# LANGUAGE TypeApplications #-} -- Wrinkle in Note [Trees That Grow]  {- %@@ -22,6 +24,7 @@ import GHC.Types.Var import GHC.Builtin.Types ( multiplicityTy ) import GHC.Tc.Gen.Head+import Language.Haskell.Syntax.Basic import GHC.Hs import GHC.Tc.Errors.Types import GHC.Tc.Utils.Monad@@ -29,24 +32,31 @@ import GHC.Tc.Utils.Instantiate import GHC.Tc.Instance.Family ( tcGetFamInstEnvs, tcLookupDataFamInst_maybe ) import GHC.Tc.Gen.HsType+import GHC.Tc.Utils.Concrete  ( unifyConcrete, idConcreteTvs ) import GHC.Tc.Utils.TcMType+import GHC.Tc.Types.Evidence import GHC.Tc.Types.Origin import GHC.Tc.Utils.TcType as TcType import GHC.Tc.Zonk.TcType+import GHC.Core.ConLike (ConLike(..))+import GHC.Core.DataCon (dataConConcreteTyVars) import GHC.Core.TyCon import GHC.Core.TyCo.Rep import GHC.Core.TyCo.Ppr import GHC.Core.TyCo.Subst (substTyWithInScope)-import GHC.Core.TyCo.FVs( shallowTyCoVarsOfType )+import GHC.Core.TyCo.FVs import GHC.Core.Type import GHC.Core.Coercion-import GHC.Tc.Types.Evidence import GHC.Types.Var.Set import GHC.Builtin.PrimOps( tagToEnumKey ) import GHC.Builtin.Names import GHC.Driver.DynFlags+import GHC.Types.Name+import GHC.Types.Name.Env+import GHC.Types.Name.Reader import GHC.Types.SrcLoc import GHC.Types.Var.Env  ( emptyTidyEnv, mkInScopeSet )+import GHC.Types.SourceText import GHC.Data.Maybe import GHC.Utils.Misc import GHC.Utils.Outputable as Outputable@@ -136,12 +146,12 @@ -- True  <=> instantiate -- return a rho-type -- False <=> don't instantiate -- return a sigma-type tcInferSigma inst (L loc rn_expr)-  | (fun@(rn_fun,_), rn_args) <- splitHsApps rn_expr   = addExprCtxt rn_expr $     setSrcSpanA loc     $-    do { do_ql <- wantQuickLook rn_fun-       ; (_tc_fun, fun_sigma) <- tcInferAppHead fun rn_args-       ; (_delta, inst_args, app_res_sigma) <- tcInstFun do_ql inst fun fun_sigma rn_args+    do { (fun@(rn_fun,fun_ctxt), rn_args) <- splitHsApps rn_expr+       ; do_ql <- wantQuickLook rn_fun+       ; (tc_fun, fun_sigma) <- tcInferAppHead fun+       ; (_delta, inst_args, app_res_sigma) <- tcInstFun do_ql inst (tc_fun, fun_ctxt) fun_sigma rn_args        ; _tc_args <- tcValArgs do_ql inst_args        ; return app_res_sigma } @@ -168,7 +178,6 @@       |  fld              -- HsRecSel: record field selectors       |  (expr :: ty)     -- ExprWithTySig: expr with user type sig       |  lit              -- HsOverLit: overloaded literals-      |  $([| head |])    -- HsSpliceE+HsSpliced+HsSplicedExpr: untyped TH expression splices       |  other_expr       -- Other expressions  When tcExpr sees something that starts an application chain (namely,@@ -198,16 +207,6 @@ instantiate that (forall b. b) impredicatively!  And that only happens in tcApp. -We also wish to typecheck application chains with untyped Template Haskell-splices in the head, such as this example from #21038:-    data Foo = MkFoo (forall a. a -> a)-    f = $([| MkFoo |]) $ \x -> x-This should typecheck just as if the TH splice was never in the way—that is,-just as if the user had written `MkFoo $ \x -> x`. We could conceivably have-a case for typed TH expression splices too, but it wouldn't be useful in-practice, since the types of typed TH expressions aren't allowed to have-polymorphic types, such as the type of MkFoo.- Note [tcApp: typechecking applications] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ tcApp implements the APP-Downarrow/Uparrow rule of@@ -323,16 +322,18 @@ tcApp :: HsExpr GhcRn -> ExpRhoType -> TcM (HsExpr GhcTc) -- See Note [tcApp: typechecking applications] tcApp rn_expr exp_res_ty-  | (fun@(rn_fun, fun_ctxt), rn_args) <- splitHsApps rn_expr-  = do { traceTc "tcApp {" $-           vcat [ text "rn_fun:" <+> ppr rn_fun+  = do { (fun@(rn_fun, fun_ctxt), rn_args) <- splitHsApps rn_expr+       ; traceTc "tcApp {" $+           vcat [ text "rn_expr:" <+> ppr rn_expr+                , text "rn_fun:" <+> ppr rn_fun+                , text "fun_ctxt:" <+> ppr fun_ctxt                 , text "rn_args:" <+> ppr rn_args ] -       ; (tc_fun, fun_sigma) <- tcInferAppHead fun rn_args+       ; (tc_fun, fun_sigma) <- tcInferAppHead fun         -- Instantiate        ; do_ql <- wantQuickLook rn_fun-       ; (delta, inst_args, app_res_rho) <- tcInstFun do_ql True fun fun_sigma rn_args+       ; (delta, inst_args, app_res_rho) <- tcInstFun do_ql True (tc_fun, fun_ctxt) fun_sigma rn_args         -- Quick look at result        ; app_res_rho <- if do_ql@@ -348,7 +349,7 @@        --    Note [Handling overloaded and rebindable constructs] in GHC.Rename.Expr        ; let  perhaps_add_res_ty_ctxt thing_inside                  | insideExpansion fun_ctxt-                 = thing_inside+                 = addHeadCtxt fun_ctxt thing_inside                  | otherwise                  = addFunResCtxt rn_fun rn_args app_res_rho exp_res_ty $                    thing_inside@@ -447,7 +448,7 @@     tc_arg :: HsExprArg 'TcpInst -> TcM (HsExprArg 'TcpTc)     tc_arg (EPrag l p) = return (EPrag l (tcExprPrag p))     tc_arg (EWrap w)   = return (EWrap w)-    tc_arg (ETypeArg l at hs_ty ty) = return (ETypeArg l at hs_ty ty)+    tc_arg (ETypeArg l hs_ty ty) = return (ETypeArg l hs_ty ty)      tc_arg eva@(EValArg { eva_arg = arg, eva_arg_ty = Scaled mult arg_ty                         , eva_ctxt = ctxt })@@ -516,7 +517,9 @@                     --    in tcInferSigma, which is used only to implement :type                     -- Otherwise we do eager instantiation; in Fig 5 of the paper                     --    |-inst returns a rho-type-          -> (HsExpr GhcRn, AppCtxt)        -- Error messages only+          -> (HsExpr GhcTc, AppCtxt)+                -- ^ For error messages and to retrieve concreteness information+                -- of the function           -> TcSigmaType -> [HsExprArg 'TcpRn]           -> TcM ( Delta                  , [HsExprArg 'TcpInst]@@ -524,23 +527,44 @@ -- This function implements the |-inst judgement in Fig 4, plus the -- modification in Fig 5, of the QL paper: -- "A quick look at impredicativity" (ICFP'20).-tcInstFun do_ql inst_final (rn_fun, fun_ctxt) fun_sigma rn_args-  = do { traceTc "tcInstFun" (vcat [ ppr rn_fun, ppr fun_sigma+tcInstFun do_ql inst_final (tc_fun, fun_ctxt) fun_sigma rn_args+  = do { traceTc "tcInstFun" (vcat [ text "tc_fun" <+> ppr tc_fun+                                   , text "fun_sigma" <+> ppr fun_sigma+                                   , text "fun_ctxt" <+> ppr fun_ctxt                                    , text "args:" <+> ppr rn_args                                    , text "do_ql" <+> ppr do_ql ])        ; go emptyVarSet [] [] fun_sigma rn_args }   where-    fun_orig = exprCtOrigin (case fun_ctxt of-                               VAExpansion e _ -> e-                               VACall e _ _    -> e)+    fun_orig+      | VAExpansion (OrigStmt{}) _ _ <- fun_ctxt+      = DoOrigin+      | VAExpansion (OrigPat pat) _ _ <- fun_ctxt+      = DoPatOrigin pat+      | VAExpansion (OrigExpr e) _ _ <- fun_ctxt+      = exprCtOrigin e+      | VACall e _ _ <- fun_ctxt+      = exprCtOrigin e +    -- These are the type variables which must be instantiated to concrete+    -- types. See Note [Representation-polymorphic Ids with no binding]+    -- in GHC.Tc.Gen.Head.+    fun_conc_tvs+      | HsVar _ (L _ fun_id) <- tc_fun+      = idConcreteTvs fun_id+      -- Recall that DataCons are represented using ConLikeTc at GhcTc stage,+      -- see Note [Typechecking data constructors] in GHC.Tc.Gen.Head.+      | XExpr (ConLikeTc (RealDataCon dc) _ _) <- tc_fun+      = dataConConcreteTyVars dc+      | otherwise+      = noConcreteTyVars+     -- Count value args only when complaining about a function     -- applied to too many value args     -- See Note [Herald for matchExpectedFunTys] in GHC.Tc.Utils.Unify.     n_val_args = count isHsValArg rn_args      fun_is_out_of_scope  -- See Note [VTA for out-of-scope functions]-      = case rn_fun of+      = case tc_fun of           HsUnboundVar {} -> True           _               -> False @@ -576,7 +600,13 @@     -- go1: fun_ty is not filled-in instantiation variable     --      ('go' dealt with that case) +    -- Handle out-of-scope functions gracefully+    go1 delta acc so_far fun_ty (arg : rest_args)+      | fun_is_out_of_scope, looks_like_type_arg arg   -- See Note [VTA for out-of-scope functions]+      = go delta acc so_far fun_ty rest_args+     -- Rule IALL from Fig 4 of the QL paper+    -- Instantiate invisible foralls and dictionaries.     -- c.f. GHC.Tc.Utils.Instantiate.topInstantiate     go1 delta acc so_far fun_ty args       | (tvs,   body1) <- tcSplitSomeForAllTyVars (inst_fun args) fun_ty@@ -587,15 +617,38 @@         -- E.g. #22908: f :: Foo => blah         -- No foralls!  But if inst_final=False, don't instantiate       , not (null tvs && null theta)-      = do { (inst_tvs, wrap, fun_rho) <- addHeadCtxt fun_ctxt $-                                          instantiateSigma fun_orig tvs theta body2-                 -- addHeadCtxt: important for the class constraints-                 -- that may be emitted from instantiating fun_sigma+      = do { (inst_tvs, wrap, fun_rho) <-+                -- addHeadCtxt: important for the class constraints+                -- that may be emitted from instantiating fun_sigma+                addHeadCtxt fun_ctxt $+                instantiateSigma fun_orig fun_conc_tvs tvs theta body2+                  -- See Note [Representation-polymorphism checking built-ins]+                  -- in GHC.Tc.Gen.Head.+                  -- NB: we are doing this even when "acc" is not empty,+                  -- to handle e.g.+                  --+                  --   badTup :: forall r (a :: TYPE r). a -> (# Int, a #)+                  --   badTup = (# , #) @LiftedRep+                  --+                  -- in which we already have instantiated the first RuntimeRep+                  -- argument of (#,#) to @LiftedRep, but want to rule out the+                  -- second instantiation @r.+            ; go (delta `extendVarSetList` inst_tvs)                 (addArgWrap wrap acc) so_far fun_rho args }                 -- Going around again means we deal easily with                 -- nested  forall a. Eq a => forall b. Show b => blah +    -- Rule ITVDQ from the GHC Proposal #281+    go1 delta acc so_far fun_ty ((EValArg { eva_arg = ValArg arg }) : rest_args)+      | Just (tvb, body) <- tcSplitForAllTyVarBinder_maybe fun_ty+      = assertPpr (binderFlag tvb == Required) (ppr fun_ty $$ ppr arg) $+        -- Any invisible binders have been instantiated by IALL above,+        -- so this forall must be visible (i.e. Required)+        do { (ty_arg, inst_body) <- tcVDQ fun_conc_tvs (tvb, body) arg+           ; let wrap = mkWpTyApps [ty_arg]+           ; go delta (addArgWrap wrap acc) so_far inst_body rest_args }+     -- Rule IRESULT from Fig 4 of the QL paper     go1 delta acc _ fun_ty []        = do { traceTc "tcInstFun:ret" (ppr fun_ty)@@ -608,14 +661,10 @@       = go1 delta (EPrag sp prag : acc) so_far fun_ty args      -- Rule ITYARG from Fig 4 of the QL paper-    go1 delta acc so_far fun_ty ( ETypeArg { eva_ctxt = ctxt, eva_at = at, eva_hs_ty = hs_ty }+    go1 delta acc so_far fun_ty ( ETypeArg { eva_ctxt = ctxt, eva_hs_ty = hs_ty }                                 : rest_args )-      | fun_is_out_of_scope   -- See Note [VTA for out-of-scope functions]-      = go delta acc so_far fun_ty rest_args--      | otherwise-      = do { (ty_arg, inst_ty) <- tcVTA fun_ty hs_ty-           ; let arg' = ETypeArg { eva_ctxt = ctxt, eva_at = at, eva_hs_ty = hs_ty, eva_ty = ty_arg }+      = do { (ty_arg, inst_ty) <- tcVTA fun_conc_tvs fun_ty hs_ty+           ; let arg' = ETypeArg { eva_ctxt = ctxt, eva_hs_ty = hs_ty, eva_ty = ty_arg }            ; go delta (arg' : acc) so_far inst_ty rest_args }      -- Rule IVAR from Fig 4 of the QL paper:@@ -628,20 +677,33 @@         -- Suppose b is instantiated by kappa.  Then we want to make fresh         -- instantiation variables nu1, nu2, and set kappa := nu1 -> nu2         ---        -- In principle what is happening here is not unlike matchActualFunTysRho+        -- In principle what is happening here is not unlike matchActualFunTys         -- but there are many small differences:         --   - We know that the function type in unfilled meta-tyvar-        --     matchActualFunTysRho is much more general, has a loop, etc.+        --     matchActualFunTys is much more general, has a loop, etc.         --   - We must be sure to actually update the variable right now,         --     not defer in any way, because this is a QL instantiation variable.         --   - We need the freshly allocated unification variables, to extend         --     delta with.         -- It's easier just to do the job directly here.-        do { let valArgsCount = countLeadingValArgs args-           ; arg_nus <- replicateM valArgsCount newOpenFlexiTyVar+        do { let val_args       = leadingValArgs args+                 val_args_count = length val_args++            -- Create metavariables for the arguments. Following matchActualFunTy,+            -- we create nu_i :: TYPE kappa_i[conc], ensuring that the arguments+            -- have concrete runtime representations.+            -- When we come to unify the nus (in qlUnify), we will call+            -- unifyKind on the kinds. This will do the right thing, even though+            -- we are manually filling in the nu metavariables.+                 new_arg_tv (ValArg (L _ arg)) i =+                   newOpenFlexiFRRTyVar $+                   FRRExpectedFunTy (ExpectedFunTyArg (HsExprTcThing tc_fun) arg) i+           ; arg_nus <- zipWithM new_arg_tv+                          val_args+                          [length so_far + 1 ..]              -- We need variables for multiplicity (#18731)              -- Otherwise, 'undefined x' wouldn't be linear in x-           ; mults   <- replicateM valArgsCount (newFlexiTyVarTy multiplicityTy)+           ; mults   <- replicateM val_args_count (newFlexiTyVarTy multiplicityTy)            ; res_nu  <- newOpenFlexiTyVar            ; kind_co <- unifyKind Nothing liftedTypeKind (tyVarKind kappa)            ; let delta'  = delta `extendVarSetList` (res_nu:arg_nus)@@ -660,44 +722,103 @@     -- Rule IARG from Fig 4 of the QL paper:     go1 delta acc so_far fun_ty         (eva@(EValArg { eva_arg = ValArg arg, eva_ctxt = ctxt }) : rest_args)-      = do { (wrap, arg_ty, res_ty) <--                matchActualFunTySigma-                  (ExpectedFunTyArg (HsExprRnThing rn_fun) (unLoc arg))-                  (Just $ HsExprRnThing rn_fun)-                  (n_val_args, so_far) fun_ty-          ; (delta', arg') <- if do_ql-                              then addArgCtxt ctxt arg $-                                   -- Context needed for constraints-                                   -- generated by calls in arg-                                   quickLookArg delta arg arg_ty-                              else return (delta, ValArg arg)-          ; let acc' = eva { eva_arg = arg', eva_arg_ty = arg_ty }+      = do { let herald = case fun_ctxt of+                             VAExpansion (OrigStmt{}) _ _ -> ExpectedFunTySyntaxOp DoOrigin tc_fun+                             _ ->  ExpectedFunTyArg (HsExprTcThing tc_fun) (unLoc arg)+           ; (wrap, arg_ty, res_ty) <-+                -- NB: matchActualFunTy does the rep-poly check.+                -- For example, suppose we have f :: forall r (a::TYPE r). a -> Int+                -- In an application (f x), we need 'x' to have a fixed runtime+                -- representation; matchActualFunTy checks that when+                -- taking apart the arrow type (a -> Int).+                matchActualFunTy herald+                  (Just $ HsExprTcThing tc_fun)+                  (n_val_args, fun_sigma) fun_ty++           ; (delta', arg') <- if do_ql+                               then addArgCtxt ctxt arg $+                                    -- Context needed for constraints+                                    -- generated by calls in arg+                                    quickLookArg delta arg arg_ty+                               else return (delta, ValArg arg)+           ; let acc' = eva { eva_arg = arg', eva_arg_ty = arg_ty }                        : addArgWrap wrap acc-          ; go delta' acc' (arg_ty:so_far) res_ty rest_args }+           ; go delta' acc' (arg_ty:so_far) res_ty rest_args } +-- Is the argument supposed to instantiate a forall?+--+-- In other words, given a function application `fn arg`,+-- can we look at the `arg` and conclude that `fn :: forall x. t`+-- or `fn :: forall x -> t`?+--+-- This is a conservative heuristic that returns `False` for "don't know".+-- Used to improve error messages only.+-- See Note [VTA for out-of-scope functions].+looks_like_type_arg :: HsExprArg 'TcpRn -> Bool+looks_like_type_arg ETypeArg{} =+  -- The argument is clearly supposed to instantiate an invisible forall,+  -- i.e. when we see `f @a`, we expect `f :: forall x. t`.+  True+looks_like_type_arg EValArg{ eva_arg = ValArg (L _ e) } =+  -- Check if the argument is supposed to instantiate a visible forall,+  -- i.e. when we see `f (type Int)`, we expect `f :: forall x -> t`,+  --      but not if we see `f True`.+  -- We can't say for sure though. Part 2 of GHC Proposal #281 allows+  -- type arguments without the `type` qualifier, so `f True` could+  -- instantiate `forall (b :: Bool) -> t`.+  case stripParensHsExpr e of+    HsEmbTy _ _ -> True+    _           -> False+looks_like_type_arg _ = False  addArgCtxt :: AppCtxt -> LHsExpr GhcRn            -> TcM a -> TcM a--- There are two cases:--- * In the normal case, we add an informative context---      "In the third argument of f, namely blah"--- * If we are deep inside generated code (isGeneratedCode)---   or if all or part of this particular application is an expansion---   (VAExpansion), just use the less-informative context---       "In the expression: arg"+-- There are four cases:+-- 1. In the normal case, we add an informative context+--          "In the third argument of f, namely blah"+-- 2. If we are deep inside generated code (`isGeneratedCode` is `True`)+--    or if all or part of this particular application is an expansion+--    `VAExpansion`, just use the less-informative context+--          "In the expression: arg" --   Unless the arg is also a generated thing, in which case do nothing.----See Note [Rebindable syntax and HsExpansion] in GHC.Hs.Expr+--   See Note [Rebindable syntax and XXExprGhcRn] in GHC.Hs.Expr+-- 3. We are in an expanded `do`-block's non-bind statement+--    we simply add the statement context+--       "In the statement of the `do`-block .."+-- 4. We are in an expanded do block's bind statement+--    a. Then either we are typechecking the first argument of the bind which is user located+--       so we set the location to be that of the argument+--    b. Or, we are typechecking the second argument which would be a generated lambda+--       so we set the location to be whatever the location in the context is+--  See Note [Expanding HsDo with XXExprGhcRn] in GHC.Tc.Gen.Do+-- For future: we need a cleaner way of doing this bit of adding the right error context.+-- There is a delicate dance of looking at source locations and reconstructing+-- whether the piece of code is a `do`-expanded code or some other expanded code. addArgCtxt ctxt (L arg_loc arg) thing_inside   = do { in_generated_code <- inGeneratedCode        ; case ctxt of            VACall fun arg_no _ | not in_generated_code-             -> setSrcSpanA arg_loc                    $-                addErrCtxt (funAppCtxt fun arg arg_no) $-                thing_inside+             -> do setSrcSpanA arg_loc                    $+                     addErrCtxt (funAppCtxt fun arg arg_no) $+                     thing_inside +           VAExpansion (OrigStmt (L _ stmt@(BindStmt {}))) _ loc+             | isGeneratedSrcSpan (locA arg_loc) -- This arg is the second argument to generated (>>=)+             -> setSrcSpan loc $+                  addStmtCtxt stmt $+                  thing_inside+             | otherwise                        -- This arg is the first argument to generated (>>=)+             -> setSrcSpanA arg_loc $+                  addStmtCtxt stmt $+                  thing_inside+           VAExpansion (OrigStmt (L loc stmt)) _ _+             -> setSrcSpanA loc $+                  addStmtCtxt stmt $+                  thing_inside+            _ -> setSrcSpanA arg_loc $-                addExprCtxt arg     $  -- Auto-suppressed if arg_loc is generated-                thing_inside }+                  addExprCtxt arg     $  -- Auto-suppressed if arg_loc is generated+                  thing_inside }  {- ********************************************************************* *                                                                      *@@ -705,59 +826,537 @@ *                                                                      * ********************************************************************* -} -tcVTA :: TcType            -- Function type-      -> LHsWcType GhcRn   -- Argument type+-- See Note [Visible type application and abstraction]+tcVTA :: ConcreteTyVars+         -- ^ Type variables that must be instantiated to concrete types.+         --+         -- See Note [Representation-polymorphism checking built-ins]+         -- in GHC.Tc.Gen.Head.+      -> TcType            -- ^ Function type+      -> LHsWcType GhcRn   -- ^ Argument type       -> TcM (TcType, TcType) -- Deal with a visible type application -- The function type has already had its Inferred binders instantiated-tcVTA fun_ty hs_ty+tcVTA conc_tvs fun_ty hs_ty   | Just (tvb, inner_ty) <- tcSplitForAllTyVarBinder_maybe fun_ty   , binderFlag tvb == Specified-    -- It really can't be Inferred, because we've just-    -- instantiated those. But, oddly, it might just be Required.-    -- See Note [Required quantifiers in the type of a term]+  = do { tc_inst_forall_arg conc_tvs (tvb, inner_ty) hs_ty }++  | otherwise+  = do { (_, fun_ty) <- liftZonkM $ zonkTidyTcType emptyTidyEnv fun_ty+       ; failWith $ TcRnInvalidTypeApplication fun_ty hs_ty }++-- See Note [Visible type application and abstraction]+tcVDQ :: ConcreteTyVars              -- See Note [Representation-polymorphism checking built-ins]+      -> (ForAllTyBinder, TcType)    -- Function type+      -> LHsExpr GhcRn               -- Argument type+      -> TcM (TcType, TcType)+tcVDQ conc_tvs (tvb, inner_ty) arg+  = do { hs_wc_ty <- expr_to_type arg+       ; tc_inst_forall_arg conc_tvs (tvb, inner_ty) hs_wc_ty }++-- Convert a HsExpr into the equivalent HsType.+-- See [RequiredTypeArguments and the T2T mapping]+expr_to_type :: LHsExpr GhcRn -> TcM (LHsWcType GhcRn)+expr_to_type earg =+  case stripParensLHsExpr earg of+    L _ (HsEmbTy _ hs_ty) ->+      -- The entire type argument is guarded with the `type` herald,+      -- e.g. `vfun (type (Maybe Int))`. This special case supports+      -- named wildcards. See Note [Wildcards in the T2T translation]+      return hs_ty+    e ->+      -- The type argument is not guarded with the `type` herald, or perhaps+      -- only parts of it are, e.g. `vfun (Maybe Int)` or `vfun (Maybe (type Int))`.+      -- Apply a recursive T2T transformation.+      HsWC [] <$> go e+  where+    go :: LHsExpr GhcRn -> TcM (LHsType GhcRn)+    go (L _ (HsEmbTy _ t)) =+      -- HsEmbTy means there is an explicit `type` herald, e.g. vfun :: forall a -> blah+      -- and the call   vfun (type Int)+      --           or   vfun (Int -> type Int)+      -- The T2T transformation can simply discard the herald and use the embedded type.+      unwrap_wc t+    go (L l (HsVar _ lname)) =+      -- as per #281: variables and constructors (regardless of their namespace)+      -- are mapped directly, without modification.+      return (L l (HsTyVar noAnn NotPromoted lname))+    go (L l (HsApp _ lhs rhs)) =+      do { lhs' <- go lhs+         ; rhs' <- go rhs+         ; return (L l (HsAppTy noExtField lhs' rhs')) }+    go (L l (HsAppType _ lhs rhs)) =+      do { lhs' <- go lhs+         ; rhs' <- unwrap_wc rhs+         ; return (L l (HsAppKindTy noExtField lhs' rhs')) }+    go (L l e@(OpApp _ lhs op rhs)) =+      do { lhs' <- go lhs+         ; op'  <- go op+         ; rhs' <- go rhs+         ; op_id <- unwrap_op_tv op'+         ; return (L l (HsOpTy noAnn NotPromoted lhs' op_id rhs')) }+      where+        unwrap_op_tv (L _ (HsTyVar _ _ op_id)) = return op_id+        unwrap_op_tv _ = failWith $ TcRnIllformedTypeArgument (L l e)+    go (L l e@(HsOverLit _ lit)) =+      do { tylit <- case ol_val lit of+             HsIntegral   n -> return $ HsNumTy NoSourceText (il_value n)+             HsIsString _ s -> return $ HsStrTy NoSourceText s+             HsFractional _ -> failWith $ TcRnIllformedTypeArgument (L l e)+         ; return (L l (HsTyLit noExtField tylit)) }+    go (L l e@(HsLit _ lit)) =+      do { tylit <- case lit of+             HsChar   _ c -> return $ HsCharTy NoSourceText c+             HsString _ s -> return $ HsStrTy  NoSourceText s+             _ -> failWith $ TcRnIllformedTypeArgument (L l e)+         ; return (L l (HsTyLit noExtField tylit)) }+    go (L l (ExplicitTuple _ tup_args boxity))+      -- Neither unboxed tuples (#e1,e2#) nor tuple sections (e1,,e2,) can be promoted+      | isBoxed boxity+      , Just es <- tupArgsPresent_maybe tup_args+      = do { ts <- traverse go es+           ; return (L l (HsExplicitTupleTy noExtField ts)) }+    go (L l (ExplicitList _ es)) =+      do { ts <- traverse go es+         ; return (L l (HsExplicitListTy noExtField NotPromoted ts)) }+    go (L l (ExprWithTySig _ e sig_ty)) =+      do { t <- go e+         ; sig_ki <- (unwrap_sig <=< unwrap_wc) sig_ty+         ; return (L l (HsKindSig noAnn t sig_ki)) }+      where+        unwrap_sig :: LHsSigType GhcRn -> TcM (LHsType GhcRn)+        unwrap_sig (L _ (HsSig _ HsOuterImplicit{hso_ximplicit=bndrs} body))+          | null bndrs = return body+          | otherwise  = illegal_implicit_tvs bndrs+        unwrap_sig (L l (HsSig _ HsOuterExplicit{hso_bndrs=bndrs} body)) =+          return $ L l (HsForAllTy noExtField (HsForAllInvis noAnn bndrs) body)+    go (L l (HsPar _ e)) =+      do { t <- go e+         ; return (L l (HsParTy noAnn t)) }+    go (L l (HsUntypedSplice splice_result splice))+      | HsUntypedSpliceTop finalizers e <- splice_result+      = do { t <- go (L l e)+           ; let splice_result' = HsUntypedSpliceTop finalizers t+           ; return (L l (HsSpliceTy splice_result' splice)) }+    go (L l (HsUnboundVar _ rdr))+      | isUnderscore occ = return (L l (HsWildCardTy noExtField))+      | startsWithUnderscore occ =+          -- See Note [Wildcards in the T2T translation]+          do { wildcards_enabled <- xoptM LangExt.NamedWildCards+             ; if wildcards_enabled+               then illegal_wc rdr+               else not_in_scope }+      | otherwise = not_in_scope+      where occ = occName rdr+            not_in_scope = failWith $ mkTcRnNotInScope rdr NotInScope+    go (L l (XExpr (ExpandedThingRn (OrigExpr orig) _))) =+      -- Use the original, user-written expression (before expansion).+      -- Example. Say we have   vfun :: forall a -> blah+      --          and the call  vfun (Maybe [1,2,3])+      --          expanded to   vfun (Maybe (fromListN 3 [1,2,3]))+      -- (This happens when OverloadedLists is enabled).+      -- The expanded expression can't be promoted, as there is no type-level+      -- equivalent of fromListN, so we must use the original.+      go (L l orig)+    go e = failWith $ TcRnIllformedTypeArgument e++    unwrap_wc :: HsWildCardBndrs GhcRn t -> TcM t+    unwrap_wc (HsWC wcs t)+      = do { mapM_ (illegal_wc . nameRdrName) wcs+           ; return t }++    illegal_wc :: RdrName -> TcM t+    illegal_wc rdr = failWith $ TcRnIllegalNamedWildcardInTypeArgument rdr++    illegal_implicit_tvs :: [Name] -> TcM t+    illegal_implicit_tvs tvs+      = do { mapM_ (addErr . TcRnIllegalImplicitTyVarInTypeArgument . nameRdrName) tvs+           ; failM }++{- Note [RequiredTypeArguments and the T2T mapping]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+The "T2T-Mapping" section of GHC Proposal #281 introduces a term-to-type transformation+that comes into play when we typecheck function applications to required type arguments.+Say we have a function that expects a required type argument, vfun :: forall a -> ...+then it is possible to call it as follows:++  vfun (Maybe Int)++The Maybe Int argument is parsed and renamed as a term. There is no syntactic marker+to tell GHC that it is actually a type argument.  We only discover this by the time+we get to type checking, where we know that f's type has a visible forall at the front,+so we are expecting a type argument. More precisely, this happens in tcVDQ in GHC/Tc/Gen/App.hs:++  tcVDQ :: ConcreteTyVars              -- See Note [Representation-polymorphism checking built-ins]+        -> (ForAllTyBinder, TcType)    -- Function type+        -> LHsExpr GhcRn               -- Argument type+        -> TcM (TcType, TcType)++What we want is a type to instantiate the forall-bound variable. But what we have is an HsExpr,+and we need to convert it to an HsType in order to reuse the same code paths as we use for+checking f @ty (see tc_inst_forall_arg).++  f (Maybe Int)+  -- ^^^^^^^^^+  -- parsed and renamed as:   HsApp   (HsVar   "Maybe") (HsVar   "Int")  ::  HsExpr GhcRn+  -- must be converted to:    HsTyApp (HsTyVar "Maybe") (HsTyVar "Int")  ::  HsType GhcRn++We do this using a helper function:++  expr_to_type :: LHsExpr GhcRn -> TcM (LHsWcType GhcRn)++This conversion is in the TcM monad because+* It can fail, if the expression is not convertible to a type.+      vfun [x | x <- xs]     Can't convert list comprehension to a type+      vfun (\x -> x)         Can't convert a lambda to a type+* It needs to check for LangExt.NamedWildCards to generate an appropriate+  error message for HsUnboundVar.+     vfun _a    Not in scope: ‘_a’+                   (NamedWildCards disabled)+     vfun _a    Illegal named wildcard in a required type argument: ‘_a’+                   (NamedWildCards enabled)++Note [Wildcards in the T2T translation]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Suppose f1 :: forall a b. blah+        f2 :: forall a b -> blah++Consider the terms+  f1 @_ @(Either _ _)+  f2 (type _) (type (Either _ _))+Those `_` wildcards are type wildcards, each standing for a monotype.+All good.++Now consider this, with -XNamedWildCards:+  f1 @_a @(Either _a _a)+  f2 (type _a) (type (Either _a _a))+Those `_a` are "named wildcards", specified by the user manual like this: "All+occurrences of the same named wildcard within one type signature will unify to+the same type".  Note "within one signature".  So each type argument is considered+separately, and the examples mean the same as:+  f1 @_a1 @(Either _a2 _a2)+  f2 (type _a1) (type (Either _a2 _a2))+The repeated `_a2` ensures that the two arguments of `Either` are the same type;+but there is no connection with `_a1`.  (NB: `_a1` and `_a2` only scope within+their respective type, no further.)++Now, consider the T2T translation for+   f2 _ (Either _ _)+This is fine: the term wildcard `_` is translated to a type wildcard, so we get+the same as if we had written+   f2 (type _) (type (Either _ _))++But what about /named/ wildcards?+   f2 _a (Either _a _a)+Now we are in difficulties.  The renamer looks for a /term/ variable `_a` in scope,+and won't find one.  Even if it did, the three `_a`'s would not be renamed separately+as above.++Conclusion: we treat a named wildcard in the T2T translation as an error.  If you+want that, use a `(type ty)` argument instead.+-}++tc_inst_forall_arg :: ConcreteTyVars            -- See Note [Representation-polymorphism checking built-ins]+                   -> (ForAllTyBinder, TcType)  -- Function type+                   -> LHsWcType GhcRn           -- Argument type+                   -> TcM (TcType, TcType)+tc_inst_forall_arg conc_tvs (tvb, inner_ty) hs_ty   = do { let tv   = binderVar tvb              kind = tyVarKind tv-       ; ty_arg <- tcHsTypeApp hs_ty kind+             tv_nm   = tyVarName tv+             mb_conc = lookupNameEnv conc_tvs tv_nm+       ; ty_arg0 <- tcHsTypeApp hs_ty kind -       ; inner_ty <- liftZonkM $ zonkTcType inner_ty-             -- See Note [Visible type application zonk]+       -- Is this type variable required to be instantiated to a concrete type?+       -- If so, ensure that that is the case.+       --+       -- See [Wrinkle: VTA] in Note [Representation-polymorphism checking built-ins]+       -- in GHC.Tc.Gen.Head.+       ; th_stage <- getStage+       ; ty_arg <- case mb_conc of+           Nothing   -> return ty_arg0+           Just conc+             -- See [Wrinkle: Typed Template Haskell]+             -- in Note [hasFixedRuntimeRep] in GHC.Tc.Utils.Concrete.+             | Brack _ (TcPending {}) <- th_stage+             -> return ty_arg0+             | otherwise+             ->+             -- Example: user wrote e.g. (#,#) @(F Bool) for a type family F.+             -- Emit [W] F Bool ~ kappa[conc] and pretend the user wrote (#,#) @kappa.+             do { mco <- unifyConcrete (occNameFS $ getOccName $ tv_nm) conc ty_arg0+                ; return $ case mco of { MRefl -> ty_arg0; MCo co -> coercionRKind co } } -       ; let in_scope  = mkInScopeSet (tyCoVarsOfTypes [fun_ty, ty_arg])+       ; let fun_ty    = mkForAllTy tvb inner_ty+             in_scope  = mkInScopeSet (tyCoVarsOfTypes [fun_ty, ty_arg])              insted_ty = substTyWithInScope in_scope [tv] [ty_arg] inner_ty-                         -- NB: tv and ty_arg have the same kind, so this-                         --     substitution is kind-respecting-       ; traceTc "VTA" (vcat [ text "fun_ty" <+> ppr fun_ty-                             , text "tv" <+> ppr tv <+> dcolon <+> debugPprType kind-                             , text "ty_arg" <+> debugPprType ty_arg <+> dcolon-                                             <+> debugPprType (typeKind ty_arg)-                             , text "inner_ty" <+> debugPprType inner_ty-                             , text "insted_ty" <+> debugPprType insted_ty ])+               -- This substitution is well-kinded even when inner_ty+               -- is not fully zonked, because ty_arg is fully zonked.+               -- See Note [Type application substitution].++       ; traceTc "tc_inst_forall_arg (VTA/VDQ)" (+                  vcat [ text "fun_ty" <+> ppr fun_ty+                       , text "tv" <+> ppr tv <+> dcolon <+> debugPprType kind+                       , text "ty_arg" <+> debugPprType ty_arg <+> dcolon+                                       <+> debugPprType (typeKind ty_arg)+                       , text "inner_ty" <+> debugPprType inner_ty+                       , text "insted_ty" <+> debugPprType insted_ty ])        ; return (ty_arg, insted_ty) } -  | otherwise-  = do { (_, fun_ty) <- liftZonkM $ zonkTidyTcType emptyTidyEnv fun_ty-       ; failWith $ TcRnInvalidTypeApplication fun_ty hs_ty }+{- Note [Visible type application and abstraction]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+GHC supports the types+    forall {a}.  a -> t     -- ForAllTyFlag is Inferred+    forall  a.   a -> t     -- ForAllTyFlag is Specified+    forall  a -> a -> t     -- ForAllTyFlag is Required -{- Note [Required quantifiers in the type of a term]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Consider (#15859)+The design of type abstraction and type application for those types has gradually+evolved over time, and is based on the following papers and proposals:+  - "Visible Type Application"+    https://richarde.dev/papers/2016/type-app/visible-type-app.pdf+  - "Type Variables in Patterns"+    https://richarde.dev/papers/2018/pat-tyvars/pat-tyvars.pdf+  - "Modern Scoped Type Variables"+    https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0448-type-variable-scoping.rst+  - "Visible forall in types of terms"+    https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0281-visible-forall.rst -  data A k :: k -> Type      -- A      :: forall k -> k -> Type-  type KindOf (a :: k) = k   -- KindOf :: forall k. k -> Type-  a = (undefined :: KindOf A) @Int+Here we offer an overview of the design mixed with commentary on the+implementation status. The proposals have not been fully implemented at the+time of writing this Note (see "not implemented" in the rest of this Note). -With ImpredicativeTypes (thin ice, I know), we instantiate-KindOf at type (forall k -> k -> Type), so-  KindOf A = forall k -> k -> Type-whose first argument is Required+Now consider functions+    fi :: forall {a}. a -> t     -- Inferred:  type argument cannot be supplied+    fs :: forall a. a -> t       -- Specified: type argument may    be supplied+    fr :: forall a -> a -> t     -- Required:  type argument must   be supplied -We want to reject this type application to Int, but in earlier-GHCs we had an ASSERT that Required could not occur here.+At a call site we may have calls looking like this+    fi             True  -- Inferred: no visible type argument+    fs             True  -- Specified: type argument omitted+    fs      @Bool  True  -- Specified: type argument supplied+    fr (type Bool) True  -- Required: type argument is compulsory, `type` qualifier used+    fr       Bool  True  -- Required: type argument is compulsory, `type` qualifier omitted -The ice is thin; c.f. Note [No Required PiTyBinder in terms]-in GHC.Core.TyCo.Rep.+At definition sites we may have type /patterns/ to abstract over type variables+   fi           x       = rhs   -- Inferred: no type pattern+   fs           x       = rhs   -- Specified: type pattern omitted+   fs @a       (x :: a) = rhs   -- Specified: type pattern supplied+   fr (type a) (x :: a) = rhs   -- Required: type pattern is compulsory, `type` qualifier used+   fr a        (x :: a) = rhs   -- Required: type pattern is compulsory, `type` qualifier omitted +Type patterns in lambdas mostly work the same way as they do in a function LHS,+except for @-binders+   OK:  fs = \           x       -> rhs   -- Specified: type pattern omitted+   Bad: fs = \ @a       (x :: a) -> rhs   -- Specified: type pattern supplied+   OK:  fr = \ (type a) (x :: a) -> rhs   -- Required: type pattern is compulsory, `type` qualifier used+   OK:  fr = \ a        (x :: a) -> rhs   -- Required: type pattern is compulsory, `type` qualifier omitted++When it comes to @-binders in lambdas, they do work, but only in a limited set+of circumstances:+  * the lambda occurs as an argument to a higher-rank function or constructor+      higher-rank function:  h :: (forall a. blah) -> ...+      call site:             x = h (\ @a -> ... )+  * the lambda is annotated with an inline type signature:+      (\ @a -> ... ) :: forall a. blah+  * the lambda is a field in a data structure, whose type is impredicative+      [ \ @a -> ... ] :: [forall a. blah]+  * the @-binder is not the first binder in the lambda:+      \ x @a -> ...++Type patterns may also occur in a constructor pattern. Consider the following data declaration+   data T where+     MkTI :: forall {a}. Show a => a -> T   -- Inferred+     MkTS :: forall a.   Show a => a -> T   -- Specified+     MkTR :: forall a -> Show a => a -> T   -- Required  (NB: not implemented)++Matching on its constructors may look like this+   f (MkTI           x)       = rhs  -- Inferred: no type pattern+   f (MkTS           x)       = rhs  -- Specified: type pattern omitted+   f (MkTS @a       (x :: a)) = rhs  -- Specified: type pattern supplied+   f (MkTR (type a) (x :: a)) = rhs  -- Required: type pattern is compulsory, `type` qualifier used    (NB: not implemented)+   f (MkTR a        (x :: a)) = rhs  -- Required: type pattern is compulsory, `type` qualifier omitted (NB: not implemented)++The moving parts are as follows:+  (abbreviations used: "c.o." = "constructor of")++Syntax of types+---------------+* The types are all initially represented with HsForAllTy (c.o. HsType).+  The binders are in the (hst_tele :: HsForAllTelescope pass) field of the HsForAllTy+  At this stage, we have+      forall {a}. t    -- HsForAllInvis (c.o. HsForAllTelescope) and InferredSpec  (c.o. Specificity)+      forall a. t      -- HsForAllInvis (c.o. HsForAllTelescope) and SpecifiedSpec (c.o. Specificity)+      forall a -> t    -- HsForAllVis (c.o. HsForAllTelescope)++* By the time we get to checking applications/abstractions (e.g. GHC.Tc.Gen.App)+  the types have been kind-checked (e.g. by tcLHsType) into ForAllTy (c.o. Type).+  At this stage, we have:+      forall {a}. t    -- ForAllTy (c.o. Type) and Inferred  (c.o. ForAllTyFlag)+      forall a. t      -- ForAllTy (c.o. Type) and Specified (c.o. ForAllTyFlag)+      forall a -> t    -- ForAllTy (c.o. Type) and Required  (c.o. ForAllTyFlag)++Syntax of applications in HsExpr+--------------------------------+* We represent type applications in HsExpr like this (ignoring parameterisation)+    data HsExpr = HsApp HsExpr HsExpr      -- (f True)    (plain function application)+                | HsAppType HsExpr HsType  -- (f @True)   (function application with `@`)+                | HsEmbTy HsType           -- (type Int)  (embed a type into an expression with `type`)+                | ...++* So (f @ty) is represented, just as you might expect:+    HsAppType f ty++* But (f (type ty)) is represented by:+    HsApp f (HsEmbTy ty)++  Why the difference?  Because we /also/ need to express these /nested/ uses of `type`:++      g (Maybe (type Int))               -- valid for g :: forall (a :: Type) -> t+      g (Either (type Int) (type Bool))  -- valid for g :: forall (a :: Type) -> t++  This nesting makes `type` rather different from `@`. Remember, the HsEmbTy mainly just+  switches namespace, and is subject to the term-to-type transformation.++Syntax of abstractions in Pat+-----------------------------+* Type patterns are represented in Pat roughly like this+     data Pat = ConPat   ConLike [HsTyPat] [Pat]  -- (Con @tp1 @tp2 p1 p2)  (constructor pattern)+              | EmbTyPat HsTyPat                  -- (type tp)              (embed a type into a pattern with `type`)+              | ...+     data HsTyPat = HsTP LHsType+  (In ConPat, the type and term arguments are actually inside HsConPatDetails.)++  * Similar to HsAppType in HsExpr, the [HsTyPat] in ConPat is used just for @ty arguments+  * Similar to HsEmbTy   in HsExpr, EmbTyPat lets you embed a type in a pattern++* Examples:+      \ (MkT @a  (x :: a)) -> rhs    -- ConPat (c.o. Pat) and HsConPatTyArg (c.o. HsConPatTyArg)+      \ (type a) (x :: a)  -> rhs    -- EmbTyPat (c.o. Pat)+      \ a        (x :: a)  -> rhs    -- VarPat (c.o. Pat)+      \ @a       (x :: a)  -> rhs    -- InvisPat (c.o. Pat)++* A HsTyPat is not necessarily a plain variable. At the very least,+  we support kind signatures and wildcards:+      \ (type _)           -> rhs+      \ (type (b :: Bool)) -> rhs+      \ (type (_ :: Bool)) -> rhs+  But in constructor patterns we also support full-on types+      \ (P @(a -> Either b c)) -> rhs+  All these forms are represented with HsTP (c.o. HsTyPat).++Renaming type applications+--------------------------+rnExpr delegates renaming of type arguments to rnHsWcType if possible:+    f @t        -- HsAppType,         t is renamed with rnHsWcType+    f (type t)  -- HsApp and HsEmbTy, t is renamed with rnHsWcType++But what about:+    f t         -- HsApp, no HsEmbTy+We simply rename `t` as a term using a recursive call to rnExpr; in particular,+the type of `f` does not affect name resolution (Lexical Scoping Principle).+We will later convert `t` from a `HsExpr` to a `Type`, see "Typechecking type+applications" later in this Note. The details are spelled out in the "Resolved+Syntax Tree" and "T2T-Mapping" sections of GHC Proposal #281.++Renaming type abstractions+--------------------------+rnPat delegates renaming of type arguments to rnHsTyPat if possible:+  f (P @t)   = rhs  -- ConPat,   t is renamed with rnHsTyPat+  f (type t) = rhs  -- EmbTyPat, t is renamed with rnHsTyPat++But what about:+  f t = rhs   -- VarPat+The solution is as before (see previous section), mutatis mutandis.+Rename `t` as a pattern using a recursive call to `rnPat`, convert it+to a type pattern later.++One particularly prickly issue is that of implicit quantification. Consider:++  f :: forall a -> ...+  f t = ...   -- binding site of `t`+    where+      g :: t -> t   -- use site of `t` or a fresh variable?+      g = ...++Does the signature of `g` refer to `t` bound in `f`, or is it a fresh,+implicitly quantified variable? This is normally controlled by+ScopedTypeVariables, but in this example the renamer can't tell `t` from a term+variable.  Only later (in the type checker) will we find out that it stands for+the forall-bound type variable `a`.  So when RequiredTypeArguments is in effect,+we change implicit quantification to take term variables into account; that is,+we do not implicitly quantify the signature of `g` to `g :: forall t. t->t`+because of the term-level `t` that is in scope.+See Note [Term variable capture and implicit quantification].++Typechecking type applications+------------------------------+Type applications are checked alongside ordinary function applications+in tcInstFun.++First of all, we assume that the function type is known (i.e. not a metavariable)+and contains a `forall`. Consider:+  f :: forall a. a -> a+  f x = const x (f @Int 5)+If the type signature is removed, the definition results in an error:+  Cannot apply expression of type ‘t1’+  to a visible type argument ‘Int’++The same principle applies to required type arguments:+  f :: forall a -> a -> a+  f (type a) x = const x (f (type Int) 5)+If the type signature is removed, the error is:+  Illegal type pattern.+  A type pattern must be checked against a visible forall.++When the type of the function is known and contains a `forall`, all we need to+do is instantiate the forall-bound variable with the supplied type argument.+This is done by tcVTA (if Specified) and tcVDQ (if Required).++tcVDQ unwraps the HsEmbTy and uses the type contained within it.  Crucially, in+tcVDQ we know that we are expecting a type argument.  This means that we can+support+    f (Maybe Int)   -- HsApp, no HsEmbTy+The type argument (Maybe Int) is represented as an HsExpr, but tcVDQ can easily+convert it to HsType.  This conversion is called the "T2T-Mapping" in GHC+Proposal #281.++Typechecking type abstractions+------------------------------+Type abstractions are checked alongside ordinary patterns in GHC.Tc.Gen.Pat.tcMatchPats.+One of its inputs is a list of ExpPatType that has two constructors+  * ExpFunPatTy    ...   -- the type A of a function A -> B+  * ExpForAllPatTy ...   -- the binder (a::A) of forall (a::A) -> B+so when we are checking+  f :: forall a b -> a -> b -> ...+  f (type a) (type b) (x :: a) (y :: b) = ...+our expected pattern types are+  [ ExpForAllPatTy ...      -- forall a ->+  , ExpForAllPatTy ...      -- forall b ->+  , ExpFunPatTy    ...      -- a ->+  , ExpFunPatTy    ...      -- b ->+  ]++The [ExpPatType] is initially constructed by GHC.Tc.Utils.Unify.matchExpectedFunTys,+by decomposing the type signature for `f` in our example.  If we are given a+definition+   g (type a) = ...+we never /infer/ a type g :: forall a -> blah.  We can only /check/+explicit type abstractions in terms.++The [ExpPatType] allows us to use different code paths for type abstractions+and ordinary patterns:+  * tc_pat :: Scaled ExpSigmaTypeFRR -> Checker (Pat GhcRn) (Pat GhcTc)+  * tc_forall_pat :: Checker (Pat GhcRn, TcTyVar) (Pat GhcTc)++tc_forall_pat unwraps the EmbTyPat and uses the type pattern contained+within it. This is another spot where the "T2T-Mapping" can take place,+allowing us to support+  f a (x :: a) = rhs    -- no EmbTyPat++Type patterns in constructor patterns are handled in with tcConTyArg.+Both tc_forall_pat and tcConTyArg delegate most of the work to tcHsTyPat.+ Note [VTA for out-of-scope functions] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Suppose 'wurble' is not in scope, and we have@@ -779,47 +1378,56 @@  Fortunately in tcInstFun we still have access to the function, so we can check if it is a HsUnboundVar.  We use this info to simply skip-over any visible type arguments.  We've already inferred the type of-the function (in tcInferAppHead), so we'll /already/ have emitted a+over any visible type arguments.  We'll /already/ have emitted a Hole constraint; failing preserves that constraint.  We do /not/ want to fail altogether in this case (via failM) because that may abandon an entire instance decl, which (in the presence of -fdefer-type-errors) leads to leading to #17792. +What about required type arguments?  Suppose we see+    f (type Int)+where `f` is out of scope.  Then again we don't want to crash because f's+type (which will be just a fresh unification variable) isn't a visible forall.+Instead we just skip the `(type Int)` argument, as before.+ Downside: the typechecked term has lost its visible type arguments; we don't even kind-check them.  But let's jump that bridge if we come to it.  Meanwhile, let's not crash! --Note [Visible type application zonk]+Note [Type application substitution] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-* Substitutions should be kind-preserving, so we need kind(tv) = kind(ty_arg).+In `tc_inst_forall_arg`, suppose we are checking a visible type+application `f @hs_ty`, where `f :: forall (a :: k). body`.  We will:+  * Compute `ty <- tcHsTypeApp hs_ty k`+  * Then substitute `a :-> ty` in `body`.+Now, you might worry that `a` might not have the same kind as `ty`, so that the+substitution isn't kind-preserving.  How can that happen?  The kinds will+definitely be the same after zonking, and `ty` will be zonked (as this is+a postcondition of `tcHsTypeApp`). But the function type `forall a. body`+might not be fully zonked (hence the worry). -* tcHsTypeApp only guarantees that-    - ty_arg is zonked-    - kind(zonk(tv)) = kind(ty_arg)-  (checkExpectedKind zonks as it goes).+But it's OK!  During type checking, we don't require types to be well-kinded (without+zonking); we only require them to satsisfy the Purely Kinded Type Invariant (PKTI).+See Note [The Purely Kinded Type Invariant (PKTI)] in GHC.Tc.Gen.HsType. -So we must zonk inner_ty as well, to guarantee consistency between zonk(tv)-and inner_ty. Otherwise we can build an ill-kinded type. An example was #14158,-where we had:-   id :: forall k. forall (cat :: k -> k -> *). forall (a :: k). cat a a-and we had the visible type application-  id @(->)+In the case of a type application:+  * `forall a. body` satisfies the PKTI+  * `ty` is zonked+  * If we substitute a fully-zonked thing into an un-zonked Type that+    satisfies the PKTI, the result still satisfies the PKTI. -* We instantiated k := kappa, yielding-    forall (cat :: kappa -> kappa -> *). forall (a :: kappa). cat a a-* Then we called tcHsTypeApp (->) with expected kind (kappa -> kappa -> *).-* That instantiated (->) as ((->) q1 q1), and unified kappa := q1,-  Here q1 :: RuntimeRep-* Now we substitute-     cat  :->  (->) q1 q1 :: TYPE q1 -> TYPE q1 -> *-  but we must first zonk the inner_ty to get-      forall (a :: TYPE q1). cat a a-  so that the result of substitution is well-kinded-  Failing to do so led to #14158.+This last statement isn't obvious, but read+Note [The Purely Kinded Type Invariant (PKTI)] in GHC.Tc.Gen.HsType.+The tricky case is when `body` contains an application of the form `a b1 ... bn`,+and we substitute `a :-> ty` where `ty` has fewer arrows in its kind than `a` does.+That can't happen: the call `tcHsTypeApp hs_ty k` would have rejected the+type application as ill-kinded. +Historical remark: we used to require a stronger invariant than the PKTI,+namely that all types are well-kinded prior to zonking. In that context, we did+need to zonk `body` before performing the substitution above. See test case+#14158, as well as the discussion in #23661. -}  {- *********************************************************************@@ -892,8 +1500,8 @@ quickLookArg1 :: Bool -> Delta -> LHsExpr GhcRn -> TcSigmaTypeFRR               -> TcM (Delta, EValArg 'TcpInst) quickLookArg1 guarded delta larg@(L _ arg) arg_ty-  = do { let (fun@(rn_fun, fun_ctxt), rn_args) = splitHsApps arg-       ; mb_fun_ty <- tcInferAppHead_maybe rn_fun rn_args+  = do { ((rn_fun, fun_ctxt), rn_args) <- splitHsApps arg+       ; mb_fun_ty <- tcInferAppHead_maybe rn_fun        ; traceTc "quickLookArg 1" $          vcat [ text "arg:" <+> ppr arg               , text "head:" <+> ppr rn_fun <+> dcolon <+> ppr mb_fun_ty@@ -914,7 +1522,7 @@          then skipQuickLook delta larg          else     do { do_ql <- wantQuickLook rn_fun-       ; (delta_app, inst_args, app_res_rho) <- tcInstFun do_ql True fun fun_sigma rn_args+       ; (delta_app, inst_args, app_res_rho) <- tcInstFun do_ql True (tc_fun, fun_ctxt) fun_sigma rn_args        ; traceTc "quickLookArg 3" $          vcat [ text "arg:" <+> ppr arg               , text "delta:" <+> ppr delta
compiler/GHC/Tc/Gen/Arrow.hs view
@@ -150,32 +150,22 @@         ; return (L loc cmd') }  tc_cmd :: CmdEnv -> HsCmd GhcRn  -> CmdType -> TcM (HsCmd GhcTc)-tc_cmd env (HsCmdPar x lpar cmd rpar) res_ty+tc_cmd env (HsCmdPar x cmd) res_ty   = do  { cmd' <- tcCmd env cmd res_ty-        ; return (HsCmdPar x lpar cmd' rpar) }+        ; return (HsCmdPar x cmd') } -tc_cmd env (HsCmdLet x tkLet binds tkIn (L body_loc body)) res_ty-  = do  { (binds', body') <- tcLocalBinds binds         $-                             setSrcSpan (locA body_loc) $-                             tc_cmd env body res_ty-        ; return (HsCmdLet x tkLet binds' tkIn (L body_loc body')) }+tc_cmd env (HsCmdLet x binds (L body_loc body)) res_ty+  = do  { (binds', _, body') <- tcLocalBinds binds         $+                                setSrcSpan (locA body_loc) $+                                tc_cmd env body res_ty+        ; return (HsCmdLet x binds' (L body_loc body')) }  tc_cmd env in_cmd@(HsCmdCase x scrut matches) (stk, res_ty)   = addErrCtxt (cmdCtxt in_cmd) $ do-      (scrut', scrut_ty) <- tcInferRho scrut-      hasFixedRuntimeRep_syntactic-        (FRRArrow $ ArrowCmdCase)-        scrut_ty-      matches' <- tcCmdMatches env scrut_ty matches (stk, res_ty)-      return (HsCmdCase x scrut' matches')--tc_cmd env cmd@(HsCmdLamCase x lc_variant match) cmd_ty-  = addErrCtxt (cmdCtxt cmd)-      do { let match_ctxt = ArrowLamCaseAlt lc_variant-         ; checkArgCounts (ArrowMatchCtxt match_ctxt) match-         ; (wrap, match') <--             tcCmdMatchLambda env match_ctxt match cmd_ty-         ; return (mkHsCmdWrap wrap (HsCmdLamCase x lc_variant match')) }+    do { (scrut', scrut_ty) <- tcInferRho scrut+       ; hasFixedRuntimeRep_syntactic (FRRArrow $ ArrowCmdCase) scrut_ty+       ; (mult_co_wrap, matches') <- tcCmdMatches env scrut_ty matches (stk, res_ty)+       ; return (HsCmdCase x (mkLHsWrap mult_co_wrap scrut') matches') }  tc_cmd env (HsCmdIf x NoSyntaxExprRn pred b1 b2) res_ty    -- Ordinary 'if'   = do  { pred' <- tcCheckMonoExpr pred boolTy@@ -268,9 +258,14 @@ -- ------------------------------ -- D;G |-a (\x.cmd) : (t,stk) --> res -tc_cmd env (HsCmdLam x match) cmd_ty-  = do { (wrap, match') <- tcCmdMatchLambda env KappaExpr match cmd_ty-       ; return (mkHsCmdWrap wrap (HsCmdLam x match')) }+tc_cmd env cmd@(HsCmdLam x lam_variant match) cmd_ty+  = (case lam_variant of   -- Add context only for \case and \cases+        LamSingle -> id    -- Avoids clutter in the vanilla-lambda form+        _         -> addErrCtxt (cmdCtxt cmd)) $+    do { let match_ctxt = ArrowLamAlt lam_variant+       ; arity <- checkArgCounts match+       ; (wrap, match') <- tcCmdMatchLambda env match_ctxt arity match cmd_ty+       ; return (mkHsCmdWrap wrap (HsCmdLam x lam_variant match')) }  ------------------------------------------- --              Do notation@@ -322,26 +317,24 @@              -> TcTypeFRR -- ^ Type of the scrutinee.              -> MatchGroup GhcRn (LHsCmd GhcRn)  -- ^ case alternatives              -> CmdType-             -> TcM (MatchGroup GhcTc (LHsCmd GhcTc))+             -> TcM (HsWrapper, MatchGroup GhcTc (LHsCmd GhcTc)) tcCmdMatches env scrut_ty matches (stk, res_ty)-  = tcMatchesCase match_ctxt (unrestricted scrut_ty) matches (mkCheckExpType res_ty)+  = tcCaseMatches tc_body (unrestricted scrut_ty) matches (mkCheckExpType res_ty)   where-    match_ctxt = MC { mc_what = ArrowMatchCtxt ArrowCaseAlt,-                      mc_body = mc_body }-    mc_body body res_ty' = do { res_ty' <- expTypeToType res_ty'+    tc_body body res_ty' = do { res_ty' <- expTypeToType res_ty'                               ; tcCmd env body (stk, res_ty') }  -- | Typechecking for 'HsCmdLam' and 'HsCmdLamCase'. tcCmdMatchLambda :: CmdEnv                  -> HsArrowMatchContext+                 -> Arity                  -> MatchGroup GhcRn (LHsCmd GhcRn)                  -> CmdType                  -> TcM (HsWrapper, MatchGroup GhcTc (LHsCmd GhcTc))-tcCmdMatchLambda env-                 ctxt+tcCmdMatchLambda env ctxt arity                  mg@MG { mg_alts = L l matches, mg_ext = origin }                  (cmd_stk, res_ty)-  = do { (co, arg_tys, cmd_stk') <- matchExpectedCmdArgs n_pats cmd_stk+  = do { (co, arg_tys, cmd_stk') <- matchExpectedCmdArgs arity cmd_stk         ; let check_arg_tys = map (unrestricted . mkCheckExpType) arg_tys        ; matches' <- forM matches $@@ -353,13 +346,10 @@         ; return (mkWpCastN co, mg') }   where-    n_pats | isEmptyMatchGroup mg = 1   -- must be lambda-case-           | otherwise            = matchGroupArity mg-     -- Check the patterns, and the GRHSs inside     tc_match arg_tys cmd_stk' (L mtch_loc (Match { m_pats = pats, m_grhss = grhss }))       = do { (pats', grhss') <- setSrcSpanA mtch_loc           $-                                tcPats match_ctxt pats arg_tys $+                                tcMatchPats match_ctxt pats (map ExpFunPatTy arg_tys) $                                 tc_grhss grhss cmd_stk' (mkCheckExpType res_ty)             ; return $ L mtch_loc (Match { m_ext = noAnn@@ -371,14 +361,14 @@     pg_ctxt    = PatGuard match_ctxt      tc_grhss (GRHSs x grhss binds) stk_ty res_ty-        = do { (binds', grhss') <- tcLocalBinds binds $-                                   mapM (wrapLocMA (tc_grhs stk_ty res_ty)) grhss+        = do { (binds', _, grhss') <- tcLocalBinds binds $+                                      mapM (wrapLocMA (tc_grhs stk_ty res_ty)) grhss              ; return (GRHSs x grhss' binds') }      tc_grhs stk_ty res_ty (GRHS x guards body)         = do { (guards', rhs') <- tcStmtsAndThen pg_ctxt tcGuardStmt guards res_ty $                                   \ res_ty -> tcCmd env body-                                                (stk_ty, checkingExpType "tc_grhs" res_ty)+                                                (stk_ty, checkingExpType res_ty)              ; return (GRHS x guards' rhs') }  matchExpectedCmdArgs :: Arity -> TcType -> TcM (TcCoercionN, [TcTypeFRR], TcType)
compiler/GHC/Tc/Gen/Bind.hs view
@@ -23,7 +23,7 @@  import GHC.Prelude -import {-# SOURCE #-} GHC.Tc.Gen.Match ( tcGRHSsPat, tcMatchesFun )+import {-# SOURCE #-} GHC.Tc.Gen.Match ( tcGRHSsPat, tcFunBindMatches ) import {-# SOURCE #-} GHC.Tc.Gen.Expr  ( tcCheckMonoExpr ) import {-# SOURCE #-} GHC.Tc.TyCl.PatSyn ( tcPatSynDecl, tcPatSynBuilderBind ) @@ -45,7 +45,8 @@ import GHC.Tc.Solver import GHC.Tc.Types.Evidence import GHC.Tc.Types.Constraint-+import GHC.Core.Predicate+import GHC.Core.UsageEnv ( bottomUE ) import GHC.Tc.Gen.HsType import GHC.Tc.Gen.Pat import GHC.Tc.Utils.TcMType@@ -53,8 +54,6 @@ import GHC.Tc.Utils.TcType import GHC.Tc.Validity (checkValidType, checkEscapingKind) import GHC.Tc.Zonk.TcType--import GHC.Core.Predicate ( getEqPredTys_maybe ) import GHC.Core.Reduction ( Reduction(..) ) import GHC.Core.Multiplicity import GHC.Core.FamInstEnv( normaliseType )@@ -63,7 +62,7 @@ import GHC.Core.Type (mkStrLitTy, tidyOpenType, mkCastTy) import GHC.Core.TyCo.Ppr( pprTyVars ) -import GHC.Builtin.Types ( mkConstraintTupleTy )+import GHC.Builtin.Types ( mkConstraintTupleTy, multiplicityTy, oneDataConTy  ) import GHC.Builtin.Types.Prim import GHC.Unit.Module @@ -195,7 +194,14 @@ -- The TcLclEnv has an extended type envt for the new bindings tcTopBinds binds sigs   = do  { -- Pattern synonym bindings populate the global environment-          (binds', (tcg_env, tcl_env)) <- tcValBinds TopLevel binds sigs getEnvs+          (binds', wrap, (tcg_env, tcl_env)) <- tcValBinds TopLevel binds sigs getEnvs+        ; massertPpr (isIdHsWrapper wrap)+                     (text "Non-identity multiplicity wrapper at toplevel:" <+> ppr wrap)+          -- The wrapper (`wrap`) is always the identity because toplevel+          -- binders are unrestricted (and `tcSubmult _ ManyTy` returns the+          -- identity wrapper). Therefore it's safe to drop it altogether.+          --+          -- See Note [Wrapper returned from tcSubMult] in GHC.Tc.Utils.Unify.         ; specs <- tcImpPrags sigs   -- SPECIALISE prags for imported Ids          ; complete_matches <- restoreEnvs (tcg_env, tcl_env) $ tcCompleteSigs sigs@@ -221,9 +227,9 @@       -- combinations are invalid it will be found so at match sites.       -- There it is also where we consider if the type of the pattern match is       -- compatible with the result type constructor 'mb_tc'.-      doOne (L loc c@(CompleteMatchSig (_ext, _src_txt) (L _ ns) mb_tc_nm))+      doOne (L loc c@(CompleteMatchSig (_ext, _src_txt) ns mb_tc_nm))         = fmap Just $ setSrcSpanA loc $ addErrCtxt (text "In" <+> ppr c) $ do-            cls   <- mkUniqDSet <$> mapM (addLocMA tcLookupConLike) ns+            cls   <- mkUniqDSet <$> mapM (addLocM tcLookupConLike) ns             mb_tc <- traverse @Maybe tcLookupLocatedTyCon mb_tc_nm             pure CompleteMatch { cmConLikes = cls, cmResultTyCon = mb_tc }       doOne _ = return Nothing@@ -239,7 +245,7 @@ tcHsBootSigs binds sigs   = do  { unless (null binds) $             rejectBootDecls HsBoot BootBindsRn (concatMap (bagToList . snd) binds)-        ; concatMapM (addLocMA tc_boot_sig) (filter isTypeLSig sigs) }+        ; concatMapM (addLocM tc_boot_sig) (filter isTypeLSig sigs) }   where     tc_boot_sig (TypeSig _ lnames hs_ty) = mapM f lnames       where@@ -250,16 +256,18 @@     tc_boot_sig s = pprPanic "tcHsBootSigs/tc_boot_sig" (ppr s)  ------------------------++-- Why an HsWrapper? See Note [Wrapper returned from tcSubMult] in GHC.Tc.Utils.Unify. tcLocalBinds :: HsLocalBinds GhcRn -> TcM thing-             -> TcM (HsLocalBinds GhcTc, thing)+             -> TcM (HsLocalBinds GhcTc, HsWrapper, thing)  tcLocalBinds (EmptyLocalBinds x) thing_inside   = do  { thing <- thing_inside-        ; return (EmptyLocalBinds x, thing) }+        ; return (EmptyLocalBinds x, idHsWrapper, thing) }  tcLocalBinds (HsValBinds x (XValBindsLR (NValBinds binds sigs))) thing_inside-  = do  { (binds', thing) <- tcValBinds NotTopLevel binds sigs thing_inside-        ; return (HsValBinds x (XValBindsLR (NValBinds binds' sigs)), thing) }+  = do  { (binds', wrapper, thing) <- tcValBinds NotTopLevel binds sigs thing_inside+        ; return (HsValBinds x (XValBindsLR (NValBinds binds' sigs)), wrapper, thing) } tcLocalBinds (HsValBinds _ (ValBinds {})) _ = panic "tcLocalBinds"  tcLocalBinds (HsIPBinds x (IPBinds _ ip_binds)) thing_inside@@ -271,7 +279,10 @@         ; (ev_binds, result) <- checkConstraints (IPSkol ips)                                   [] given_ips thing_inside -        ; return (HsIPBinds x (IPBinds ev_binds ip_binds') , result) }+        -- We don't have linear implicit parameters, yet. So the wrapper can be+        -- the identity.+        -- See Note [Wrapper returned from tcSubMult] in GHC.Tc.Utils.Unify.+        ; return (HsIPBinds x (IPBinds ev_binds ip_binds') , idHsWrapper, result) }   where     ips = [ip | (L _ (IPBind _ (L _ ip) _)) <- ip_binds] @@ -280,7 +291,7 @@         --              ?y = ?x + 1     tc_ip_bind :: Class -> IPBind GhcRn -> TcM (DictId, IPBind GhcTc)     tc_ip_bind ipClass (IPBind _ l_name@(L _ ip) expr)-       = do { ty <- newOpenFlexiTyVarTy+       = do { ty <- newFlexiTyVarTy liftedTypeKind  -- see #24298             ; let p = mkStrLitTy $ hsIPNameFS ip             ; ip_id <- newDict ipClass [ p, ty ]             ; expr' <- tcCheckMonoExpr expr ty@@ -297,10 +308,11 @@     toDict ipClass x ty = mkHsWrap $ mkWpCastR $                           wrapIP $ mkClassPred ipClass [x,ty] +-- Why an HsWrapper? See Note [Wrapper returned from tcSubMult] in GHC.Tc.Utils.Unify. tcValBinds :: TopLevelFlag            -> [(RecFlag, LHsBinds GhcRn)] -> [LSig GhcRn]            -> TcM thing-           -> TcM ([(RecFlag, LHsBinds GhcTc)], thing)+           -> TcM ([(RecFlag, LHsBinds GhcTc)], HsWrapper, thing)  tcValBinds top_lvl binds sigs thing_inside   = do  {   -- Typecheck the signatures@@ -319,7 +331,7 @@         -- For the moment, let bindings and top-level bindings introduce         -- only unrestricted variables.         ; tcExtendSigIds top_lvl poly_ids $-     do { (binds', (extra_binds', thing))+     do { (binds', wrapper, (extra_binds', thing))               <- tcBindGroups top_lvl sig_fn prag_fn binds $                  do { thing <- thing_inside                        -- See Note [Pattern synonym builders don't yield dependencies]@@ -328,15 +340,17 @@                     ; let extra_binds = [ (NonRecursive, builder)                                         | builder <- patsyn_builders ]                     ; return (extra_binds, thing) }-        ; return (binds' ++ extra_binds', thing) }}+        ; return (binds' ++ extra_binds', wrapper, thing) }}   where     patsyns = getPatSynBinds binds     prag_fn = mkPragEnv sigs (foldr (unionBags . snd) emptyBag binds)  ------------------------++-- Why an HsWrapper? See Note [Wrapper returned from tcSubMult] in GHC.Tc.Utils.Unify. tcBindGroups :: TopLevelFlag -> TcSigFun -> TcPragEnv              -> [(RecFlag, LHsBinds GhcRn)] -> TcM thing-             -> TcM ([(RecFlag, LHsBinds GhcTc)], thing)+             -> TcM ([(RecFlag, LHsBinds GhcTc)], HsWrapper, thing) -- Typecheck a whole lot of value bindings, -- one strongly-connected component at a time -- Here a "strongly connected component" has the straightforward@@ -345,16 +359,16 @@  tcBindGroups _ _ _ [] thing_inside   = do  { thing <- thing_inside-        ; return ([], thing) }+        ; return ([], idHsWrapper, thing) }  tcBindGroups top_lvl sig_fn prag_fn (group : groups) thing_inside   = do  { -- See Note [Closed binder groups]           type_env <- getLclTypeEnv         ; let closed = isClosedBndrGroup type_env (snd group)-        ; (group', (groups', thing))+        ; (group', outer_wrapper, (groups', inner_wrapper, thing))                 <- tc_group top_lvl sig_fn prag_fn group closed $                    tcBindGroups top_lvl sig_fn prag_fn groups thing_inside-        ; return (group' ++ groups', thing) }+        ; return (group' ++ groups', outer_wrapper <.> inner_wrapper, thing) }  -- Note [Closed binder groups] -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -377,7 +391,7 @@ tc_group :: forall thing.             TopLevelFlag -> TcSigFun -> TcPragEnv          -> (RecFlag, LHsBinds GhcRn) -> IsGroupClosed -> TcM thing-         -> TcM ([(RecFlag, LHsBinds GhcTc)], thing)+         -> TcM ([(RecFlag, LHsBinds GhcTc)], HsWrapper, thing)  -- Typecheck one strongly-connected component of the original program. -- We get a list of groups back, because there may@@ -391,9 +405,9 @@                  [bind] -> bind                  []     -> panic "tc_group: empty list of binds"                  _      -> panic "tc_group: NonRecursive binds is not a singleton bag"-       ; (bind', thing) <- tc_single top_lvl sig_fn prag_fn bind closed+       ; (bind', wrapper, thing) <- tc_single top_lvl sig_fn prag_fn bind closed                                      thing_inside-       ; return ( [(NonRecursive, bind')], thing) }+       ; return ( [(NonRecursive, bind')], wrapper, thing) }  tc_group top_lvl sig_fn prag_fn (Recursive, binds) closed thing_inside   =     -- To maximise polymorphism, we do a new@@ -404,8 +418,8 @@     do  { traceTc "tc_group rec" (pprLHsBinds binds)         ; whenIsJust mbFirstPatSyn $ \lpat_syn ->             recursivePatSynErr (locA $ getLoc lpat_syn) binds-        ; (binds1, thing) <- go sccs-        ; return ([(Recursive, binds1)], thing) }+        ; (binds1, wrapper, thing) <- go sccs+        ; return ([(Recursive, binds1)], wrapper, thing) }                 -- Rec them all together   where     mbFirstPatSyn = find (isPatSyn . unLoc) binds@@ -415,14 +429,15 @@     sccs :: [SCC (LHsBind GhcRn)]     sccs = stronglyConnCompFromEdgedVerticesUniq (mkEdges sig_fn binds) -    go :: [SCC (LHsBind GhcRn)] -> TcM (LHsBinds GhcTc, thing)+    go :: [SCC (LHsBind GhcRn)] -> TcM (LHsBinds GhcTc, HsWrapper, thing)     go (scc:sccs) = do  { (binds1, ids1) <- tc_scc scc                          -- recursive bindings must be unrestricted                          -- (the ids added to the environment here are the name of the recursive definitions).-                        ; (binds2, thing) <- tcExtendLetEnv top_lvl sig_fn closed ids1-                                                            (go sccs)-                        ; return (binds1 `unionBags` binds2, thing) }-    go []         = do  { thing <- thing_inside; return (emptyBag, thing) }+                        ; ((binds2, inner_wrapper, thing), outer_wrapper) <-+                              tcExtendLetEnv top_lvl sig_fn closed ids1+                              (go sccs)+                        ; return (binds1 `unionBags` binds2, outer_wrapper <.> inner_wrapper, thing) }+    go []         = do  { thing <- thing_inside; return (emptyBag, idHsWrapper, thing) }      tc_scc (AcyclicSCC bind) = tc_sub_group NonRecursive [bind]     tc_scc (CyclicSCC binds) = tc_sub_group Recursive    binds@@ -441,13 +456,13 @@ tc_single :: forall thing.             TopLevelFlag -> TcSigFun -> TcPragEnv           -> LHsBind GhcRn -> IsGroupClosed -> TcM thing-          -> TcM (LHsBinds GhcTc, thing)+          -> TcM (LHsBinds GhcTc, HsWrapper, thing) tc_single _top_lvl sig_fn prag_fn           (L loc (PatSynBind _ psb))           _ thing_inside   = do { (aux_binds, tcg_env) <- tcPatSynDecl (L loc psb) sig_fn prag_fn        ; thing <- setGblEnv tcg_env thing_inside-       ; return (aux_binds, thing)+       ; return (aux_binds, idHsWrapper, thing)        }  tc_single top_lvl sig_fn prag_fn lbind closed thing_inside@@ -455,10 +470,8 @@                                       NonRecursive NonRecursive                                       closed                                       [lbind]-         -- since we are defining a non-recursive binding, it is not necessary here-         -- to define an unrestricted binding. But we do so until toplevel linear bindings are supported.-       ; thing <- tcExtendLetEnv top_lvl sig_fn closed ids thing_inside-       ; return (binds1, thing) }+       ; (thing, wrapper) <- tcExtendLetEnv top_lvl sig_fn closed ids thing_inside+       ; return (binds1, wrapper, thing) }  ------------------------ type BKey = Int -- Just number off the bindings@@ -494,7 +507,7 @@                                -- dependencies based on type signatures             -> IsGroupClosed   -- Whether the group is closed             -> [LHsBind GhcRn]  -- None are PatSynBind-            -> TcM (LHsBinds GhcTc, [TcId])+            -> TcM (LHsBinds GhcTc, [Scaled TcId])  -- Typechecks a single bunch of values bindings all together, -- and generalises them.  The bunch may be only part of a recursive@@ -517,11 +530,13 @@     ; dflags   <- getDynFlags     ; let plan = decideGeneralisationPlan dflags top_lvl closed sig_fn bind_list     ; traceTc "Generalisation plan" (ppr plan)-    ; result@(_, poly_ids) <- case plan of+    ; result@(_, scaled_poly_ids) <- case plan of          NoGen              -> tcPolyNoGen rec_tc prag_fn sig_fn bind_list          InferGen           -> tcPolyInfer rec_tc prag_fn sig_fn bind_list          CheckGen lbind sig -> tcPolyCheck prag_fn sig lbind +    ; let poly_ids = map scaledThing scaled_poly_ids+     ; mapM_ (\ poly_id ->         hasFixedRuntimeRep_syntactic (FRRBinder $ idName poly_id) (idType poly_id))         poly_ids@@ -542,10 +557,10 @@ -- If typechecking the binds fails, then return with each -- signature-less binder given type (forall a.a), to minimise -- subsequent error messages-recoveryCode :: [Name] -> TcSigFun -> TcM (LHsBinds GhcTc, [Id])+recoveryCode :: [Name] -> TcSigFun -> TcM (LHsBinds GhcTc, [Scaled Id]) recoveryCode binder_names sig_fn   = do  { traceTc "tcBindsWithSigs: error recovery" (ppr binder_names)-        ; let poly_ids = map mk_dummy binder_names+        ; let poly_ids = map (Scaled ManyTy) $ map mk_dummy binder_names         ; return (emptyBag, poly_ids) }   where     mk_dummy name@@ -575,7 +590,7 @@                    -- dependencies based on type signatures   -> TcPragEnv -> TcSigFun   -> [LHsBind GhcRn]-  -> TcM (LHsBinds GhcTc, [TcId])+  -> TcM (LHsBinds GhcTc, [Scaled TcId])  tcPolyNoGen rec_tc prag_fn tc_sig_fn bind_list   = do { (binds', mono_infos) <- tcMonoBinds rec_tc tc_sig_fn@@ -584,9 +599,9 @@        ; mono_ids' <- mapM tc_mono_info mono_infos        ; return (binds', mono_ids') }   where-    tc_mono_info (MBI { mbi_poly_name = name, mbi_mono_id = mono_id })+    tc_mono_info (MBI { mbi_poly_name = name, mbi_mono_id = mono_id, mbi_mono_mult = mult })       = do { _specs <- tcSpecPrags mono_id (lookupPragEnv prag_fn name)-           ; return mono_id }+           ; return $ Scaled mult mono_id }            -- NB: tcPrags generates error messages for            --     specialisation pragmas for non-overloaded sigs            -- Indeed that is why we call it here!@@ -600,37 +615,36 @@ ********************************************************************* -}  tcPolyCheck :: TcPragEnv-            -> TcIdSigInfo     -- Must be a complete signature+            -> TcCompleteSig             -> LHsBind GhcRn   -- Must be a FunBind-            -> TcM (LHsBinds GhcTc, [TcId])+            -> TcM (LHsBinds GhcTc, [Scaled TcId]) -- There is just one binding, --   it is a FunBind --   it has a complete type signature, tcPolyCheck prag_fn-            (CompleteSig { sig_bndr  = poly_id-                         , sig_ctxt  = ctxt-                         , sig_loc   = sig_loc })+            sig@(CSig { sig_bndr = poly_id, sig_ctxt = ctxt })             (L bind_loc (FunBind { fun_id = L nm_loc name                                  , fun_matches = matches }))-  = do { traceTc "tcPolyCheck" (ppr poly_id $$ ppr sig_loc)+  = do { traceTc "tcPolyCheck" (ppr sig) +       -- Make a new Name, whose SrcSpan is nm_loc.  For a ClassOp+       -- The original Name, in the FunBind{fun_id}, is bound in the+       -- class declaration, whereas we want a Name bound right here.+       -- We pass mono_name to tcFunBindMatches which in turn puts it in+       -- the BinderStack, whence it shows up in "Relevant bindings.."        ; mono_name <- newNameAt (nameOccName name) (locA nm_loc)++       ; mult <- tcMultAnn (HsNoMultAnn noExtField)        ; (wrap_gen, (wrap_res, matches'))-             <- setSrcSpan sig_loc $ -- Sets the binding location for the skolems-                tcSkolemiseScoped ctxt (idType poly_id) $ \rho_ty ->-                -- Unwraps multiple layers; e.g-                --    f :: forall a. Eq a => forall b. Ord b => blah-                -- NB: tcSkolemiseScoped makes fresh type variables-                -- See Note [Instantiate sig with fresh variables]+             <- tcSkolemiseCompleteSig sig $ \invis_pat_tys rho_ty ->                  let mono_id = mkLocalId mono_name (varMult poly_id) rho_ty in                 tcExtendBinderStack [TcIdBndr mono_id NotTopLevel] $                 -- Why mono_id in the BinderStack?-                --    See Note [Relevant bindings and the binder stack]+                -- See Note [Relevant bindings and the binder stack] -                setSrcSpanA bind_loc $-                tcMatchesFun (L nm_loc (idName mono_id)) matches-                             (mkCheckExpType rho_ty)+                setSrcSpanA bind_loc  $+                tcFunBindMatches ctxt mono_name mult matches invis_pat_tys (mkCheckExpType rho_ty)         -- We make a funny AbsBinds, abstracting over nothing,        -- just so we have somewhere to put the SpecPrags.@@ -648,8 +662,7 @@         ; let bind' = FunBind { fun_id      = L nm_loc poly_id2                              , fun_matches = matches'-                             , fun_ext     = (wrap_gen <.> wrap_res, tick)-                             }+                             , fun_ext     = (wrap_gen <.> wrap_res, tick) }               export = ABE { abe_wrap  = idHsWrapper                           , abe_poly  = poly_id@@ -664,7 +677,7 @@                                  , abs_binds    = unitBag (L bind_loc bind')                                  , abs_sig      = True } -       ; return (unitBag abs_bind, [poly_id]) }+       ; return (unitBag abs_bind, [Scaled mult poly_id]) }  tcPolyCheck _prag_fn sig bind   = pprPanic "tcPolyCheck" (ppr sig $$ ppr bind)@@ -708,18 +721,50 @@ *                                                                      * ********************************************************************* -} +{- Note [Non-variable pattern bindings aren't linear]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++A fundamental limitation of the typechecking algorithm is that we cannot have a+binding which, at the same time,+- is linear in its rhs+- is a non-variable pattern+- binds variables to polymorphic or qualified types++A detailed explanation can be found at:+https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0111-linear-types.rst#let-bindings-and-polymorphism++To address this we to do a few things++- When a pattern is annotated with a multiplicity annotation `let %q pat = rhs+  in body` (note: multiplicity-annotated bindings are always parsed as a+  PatBind, see Note [Multiplicity annotations] in Language.Haskell.Syntax.Binds),+  then the let is never generalised (we use the NoGen plan).+- Whenever the typechecker infers an AbsBind *and* the inner binding is a+  non-variable PatBind, then the multiplicity of the binding is inferred to be+  Many. This is a little infelicitous: sometimes the typechecker infers an+  AbsBind where it didn't need to. This may cause some programs to be spuriously+  rejected, when NoMonoLocalBinds is on.+- LinearLet implies MonoLocalBinds to avoid the AbsBind case altogether.++-}+ tcPolyInfer   :: RecFlag       -- Whether it's recursive after breaking                    -- dependencies based on type signatures   -> TcPragEnv -> TcSigFun   -> [LHsBind GhcRn]-  -> TcM (LHsBinds GhcTc, [TcId])+  -> TcM (LHsBinds GhcTc, [Scaled TcId]) tcPolyInfer rec_tc prag_fn tc_sig_fn bind_list   = do { (tclvl, wanted, (binds', mono_infos))              <- pushLevelAndCaptureConstraints  $                 tcMonoBinds rec_tc tc_sig_fn LetLclBndr bind_list         ; apply_mr <- checkMonomorphismRestriction mono_infos bind_list++       -- AbsBinds which are PatBinds can't be linear.+       -- See Note [Non-variable pattern bindings aren't linear]+       ; binds' <- manyIfPats binds'+        ; traceTc "tcPolyInfer" (ppr apply_mr $$ ppr (map mbi_sig mono_infos))         ; let name_taus  = [ (mbi_poly_name info, idType (mbi_mono_id info))@@ -732,8 +777,9 @@             <- captureConstraints $ simplifyInfer tclvl infer_mode sigs name_taus wanted         ; let inferred_theta = map evVarPred givens-       ; exports <- checkNoErrs $+       ; scaled_exports <- checkNoErrs $                     mapM (mkExport prag_fn residual insoluble qtvs inferred_theta) mono_infos+       ; let exports = map scaledThing scaled_exports           -- NB: *after* the checkNoErrs call above. This ensures that we don't get an error          -- cascade in case mkExport runs into trouble. In particular, this avoids duplicate@@ -743,7 +789,8 @@        ; emitConstraints residual         ; loc <- getSrcSpanM-       ; let poly_ids = map abe_poly exports+       ; let scaled_poly_ids = [ Scaled p (abe_poly export) | Scaled p export <- scaled_exports]+             poly_ids = map scaledThing scaled_poly_ids              abs_bind = L (noAnnSrcSpan loc) $ XHsBindsLR $                         AbsBinds { abs_tvs = qtvs                                  , abs_ev_vars = givens, abs_ev_binds = [ev_binds]@@ -751,8 +798,20 @@                                  , abs_sig = False }         ; traceTc "Binding:" (ppr (poly_ids `zip` map idType poly_ids))-       ; return (unitBag abs_bind, poly_ids) }+       ; return (unitBag abs_bind, scaled_poly_ids) }          -- poly_ids are guaranteed zonked by mkExport+  where+    manyIfPat bind@(L _ (PatBind{pat_lhs=(L _ (VarPat{}))}))+      = return bind+    manyIfPat (L loc pat@(PatBind {pat_mult=mult_ann, pat_lhs=lhs, pat_ext =(pat_ty,_)}))+      = do { mult_co_wrap <- tcSubMult (NonLinearPatternOrigin GeneralisedPatternReason nlWildPatName) ManyTy (getTcMultAnn mult_ann)+           -- The wrapper checks for correct multiplicities.+           -- See Note [Wrapper returned from tcSubMult] in GHC.Tc.Utils.Unify.+           ; let lhs' = mkLHsWrapPat mult_co_wrap lhs pat_ty+           ; return $ L loc pat {pat_lhs=lhs'}+           }+    manyIfPat bind = return bind+    manyIfPats binds' = traverse manyIfPat binds'  checkMonomorphismRestriction :: [MonoBindInfo] -> [LHsBind GhcRn] -> TcM Bool -- True <=> apply the MR@@ -771,8 +830,8 @@     no_mr_name (MBI { mbi_sig = Just sig })        | TISI { sig_inst_sig = info, sig_inst_theta = theta, sig_inst_wcx = wcx } <- sig        = case info of-           CompleteSig { sig_bndr = bndr } -> Just (idName bndr)-           PartialSig { psig_name = nm }+           TcCompleteSig (CSig { sig_bndr = bndr }) -> Just (idName bndr)+           TcPartialSig (PSig { psig_name = nm })              | null theta, isNothing wcx   -> Nothing  -- f :: _ -> _              | otherwise                   -> Just nm  -- f :: Num a => a -> _              -- For the latter case, we don't want the MR:@@ -800,13 +859,12 @@ -- The MR applies, but the signature is overloaded, and it's -- best to complain about this directly -- c.f #11339-checkOverloadedSig (MBI { mbi_sig = mb_sig })-  | Just (TISI { sig_inst_sig = orig_sig, sig_inst_theta = theta, sig_inst_wcx = wcx }) <- mb_sig+checkOverloadedSig (MBI { mbi_sig = Just sig })+  | TISI { sig_inst_sig = orig_sig, sig_inst_theta = theta, sig_inst_wcx = wcx } <- sig   , not (null theta && isNothing wcx)-  = setSrcSpan (sig_loc orig_sig) $+  = setSrcSpan (tcIdSigLoc orig_sig) $     failWith $ TcRnOverloadedSig orig_sig-  | otherwise-  = return ()+checkOverloadedSig _ = return ()  {- Note [When the MR applies] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -860,7 +918,7 @@                                         --          when typechecking the bindings          -> [TyVar] -> TcThetaType      -- Both already zonked          -> MonoBindInfo-         -> TcM ABExport+         -> TcM (Scaled ABExport) -- Only called for generalisation plan InferGen, not by CheckGen or NoGen -- -- mkExport generates exports with@@ -877,7 +935,8 @@ mkExport prag_fn residual insoluble qtvs theta          (MBI { mbi_poly_name = poly_name               , mbi_sig       = mb_sig-              , mbi_mono_id   = mono_id })+              , mbi_mono_id   = mono_id+              , mbi_mono_mult = mono_mult })   = do  { mono_ty <- liftZonkM $ zonkTcType (idType mono_id)         ; poly_id <- mkInferredPolyId residual insoluble qtvs theta poly_name mb_sig mono_ty @@ -907,7 +966,8 @@          ; localSigWarn poly_id mb_sig -        ; return (ABE { abe_wrap = wrap+        ; return (Scaled mono_mult $+                  ABE { abe_wrap = wrap                         -- abe_wrap :: (forall qtvs. theta => mono_ty) ~ idType poly_id                       , abe_poly  = poly_id                       , abe_mono  = mono_id@@ -924,7 +984,7 @@                  -> TcM TcId mkInferredPolyId residual insoluble qtvs inferred_theta poly_name mb_sig_inst mono_ty   | Just (TISI { sig_inst_sig = sig })  <- mb_sig_inst-  , CompleteSig { sig_bndr = poly_id } <- sig+  , TcCompleteSig (CSig { sig_bndr = poly_id }) <- sig   = return poly_id    | otherwise  -- Either no type sig or partial type sig@@ -983,10 +1043,9 @@        ; return (binders, my_theta) }  chooseInferredQuantifiers residual inferred_theta tau_tvs qtvs-  (Just (TISI { sig_inst_sig   = sig@(PartialSig { psig_name = fn_name, psig_hs_ty = hs_ty })-              , sig_inst_wcx   = wcx-              , sig_inst_theta = annotated_theta-              , sig_inst_skols = annotated_tvs }))+    (Just (TISI { sig_inst_sig = sig, sig_inst_wcx = wcx+                , sig_inst_theta = annotated_theta, sig_inst_skols = annotated_tvs }))+  | TcPartialSig (PSig { psig_name = fn_name, psig_hs_ty = hs_ty }) <- sig   = -- Choose quantifiers for a partial type signature     do { let (psig_qtv_nms, psig_qtv_bndrs) = unzip annotated_tvs        ; psig_qtv_bndrs <- liftZonkM $ mapM zonkInvisTVBinder psig_qtv_bndrs@@ -999,14 +1058,15 @@             -- Check whether the quantified variables of the             -- partial signature have been unified together             -- See Note [Quantified variables in partial type signatures]-       ; mapM_ report_dup_tyvar_tv_err  (findDupTyVarTvs psig_qtv_prs)+       ; mapM_ (report_dup_tyvar_tv_err fn_name hs_ty) $+         findDupTyVarTvs psig_qtv_prs              -- Check whether a quantified variable of the partial type             -- signature is not actually quantified.  How can that happen?             -- See Note [Quantification and partial signatures] Wrinkle 4             --     in GHC.Tc.Solver-       ; mapM_ report_mono_sig_tv_err [ pr | pr@(_,tv) <- psig_qtv_prs-                                           , not (tv `elem` qtvs) ]+       ; mapM_ (report_mono_sig_tv_err fn_name hs_ty)+         [ pr | pr@(_,tv) <- psig_qtv_prs, not (tv `elem` qtvs) ]         ; annotated_theta      <- liftZonkM $ zonkTcTypes annotated_theta        ; (free_tvs, my_theta) <- choose_psig_context psig_qtv_set annotated_theta wcx@@ -1083,10 +1143,10 @@              -- Return (annotated_theta ++ diff_theta)              -- See Note [Extra-constraints wildcards] -    report_dup_tyvar_tv_err (n1,n2)+    report_dup_tyvar_tv_err fn_name hs_ty (n1,n2)       = addErrTc (TcRnPartialTypeSigTyVarMismatch n1 n2 fn_name hs_ty) -    report_mono_sig_tv_err (n,tv)+    report_mono_sig_tv_err fn_name hs_ty (n,tv)       = addErrTc (TcRnPartialTypeSigBadQuantifier n fn_name m_unif_ty hs_ty)       where         m_unif_ty = listToMaybe@@ -1099,7 +1159,7 @@                       , Just lhs_tv <- [ getTyVar_maybe lhs ]                       , lhs_tv == tv ] -chooseInferredQuantifiers _ _ _ _ (Just (TISI { sig_inst_sig = sig@(CompleteSig {}) }))+chooseInferredQuantifiers _ _ _ _ (Just sig)   = pprPanic "chooseInferredQuantifiers" (ppr sig)  mk_inf_msg :: Name -> TcType -> TidyEnv -> ZonkM (TidyEnv, SDoc)@@ -1284,7 +1344,8 @@  data MonoBindInfo = MBI { mbi_poly_name :: Name                         , mbi_sig       :: Maybe TcIdSigInst-                        , mbi_mono_id   :: TcId }+                        , mbi_mono_id   :: TcId+                        , mbi_mono_mult :: Mult }  tcMonoBinds :: RecFlag  -- Whether the binding is recursive for typechecking purposes                         -- i.e. the binders are mentioned in their RHSs, and@@ -1301,44 +1362,75 @@   | NonRecursive <- is_rec   -- ...binder isn't mentioned in RHS   , Nothing <- sig_fn name   -- ...with no type signature   = setSrcSpanA b_loc    $-    do  { ((co_fn, matches'), rhs_ty')+    do  { mult <- tcMultAnn (HsNoMultAnn noExtField)++        ; ((co_fn, matches'), rhs_ty')             <- tcInferFRR (FRRBinder name) $ \ exp_ty ->-                          -- tcInferFRR: the type of a let-binder must have-                          -- a fixed runtime rep. See #23176-                       tcExtendBinderStack [TcIdBndr_ExpType name exp_ty NotTopLevel] $-                          -- We extend the error context even for a non-recursive-                          -- function so that in type error messages we show the-                          -- type of the thing whose rhs we are type checking-                       tcMatchesFun (L nm_loc name) matches exp_ty-       ; mono_id <- newLetBndr no_gen name ManyTy rhs_ty'+                 -- tcInferFRR: the type of a let-binder must have+                 -- a fixed runtime rep. See #23176+               tcExtendBinderStack [TcIdBndr_ExpType name exp_ty NotTopLevel] $+                 -- We extend the error context even for a non-recursive+                 -- function so that in type error messages we show the+                 -- type of the thing whose rhs we are type checking.+                 -- See Note [Relevant bindings and the binder stack]+               tcFunBindMatches (InfSigCtxt name) name mult matches [] exp_ty+       ; mono_id <- newLetBndr no_gen name mult rhs_ty'          ; return (unitBag $ L b_loc $-                     FunBind { fun_id = L nm_loc mono_id,+                     FunBind { fun_id      = L nm_loc mono_id,                                fun_matches = matches',-                               fun_ext = (co_fn, []) },+                               fun_ext     = (co_fn, []) },                   [MBI { mbi_poly_name = name                        , mbi_sig       = Nothing-                       , mbi_mono_id   = mono_id }]) }+                       , mbi_mono_id   = mono_id+                       , mbi_mono_mult = mult }]) }  -- SPECIAL CASE 2: see Note [Special case for non-recursive pattern bindings] tcMonoBinds is_rec sig_fn no_gen-           [L b_loc (PatBind { pat_lhs = pat, pat_rhs = grhss })]+           [L b_loc (PatBind { pat_lhs = pat, pat_rhs = grhss, pat_mult = mult_ann })]   | NonRecursive <- is_rec   -- ...binder isn't mentioned in RHS   , all (isNothing . sig_fn) bndrs   = addErrCtxt (patMonoBindsCtxt pat grhss) $-    do { (grhss', pat_ty) <- tcInferFRR FRRPatBind $ \ exp_ty ->+    do { mult <- tcMultAnn mult_ann++       ; (grhss', pat_ty) <- tcInferFRR FRRPatBind $ \ exp_ty ->                           -- tcInferFRR: the type of each let-binder must have                           -- a fixed runtime rep. See #23176-                             tcGRHSsPat grhss exp_ty+                             tcGRHSsPat mult grhss exp_ty         ; let exp_pat_ty :: Scaled ExpSigmaTypeFRR-             exp_pat_ty = unrestricted (mkCheckExpType pat_ty)-       ; (pat', mbis) <- tcLetPat (const Nothing) no_gen pat exp_pat_ty $-                         mapM lookupMBI bndrs+             exp_pat_ty = Scaled mult (mkCheckExpType pat_ty)+       ; (_, (pat', mbis)) <- tcCollectingUsage $+                         tcLetPat (const Nothing) no_gen pat exp_pat_ty $ do+                           tcEmitBindingUsage bottomUE+                           mapM lookupMBI bndrs+            -- What's happening here? Typing pattern-matching (either from case+            -- expression or equation) and typing bindings (let or where) have a+            -- different control flow: for pattern-matching, the rhs is typed+            -- within the `thing_inside` argument. The type-checker walks down+            -- the pattern, and when finally it is done, all variables have been+            -- added to the environment, thing_inside is called. So, when+            -- type-checking patterns, the check for the correctness of+            -- multiplicity is generated in the VarPat case. This is quite+            -- natural.+            --+            -- Bindings, however, have a more complex control flow for our+            -- purpose: we collect all the variables as we go down, then return+            -- them (here as `mapM lookupMBI bndrs`), and in a subsequent+            -- computation (rather than an inner computation), the rhs is+            -- type-checked. This poses a problem here: we're calling+            -- `tcLetPat`, which will verify the proper usage of the introduced+            -- variable when reaching the `VarPat` case. But there is no actual+            -- usage of variable in the `thing_inside`. This would always+            -- fail. So we emit a `bottomUE`, which is compatible with every+            -- usage. So that we can bypass the check in VarPat. Then we use+            -- `tcCollectingUsage` to throw the `bottomUE` away, since it would+            -- let us bypass many linearity checks.         ; return ( unitBag $ L b_loc $                      PatBind { pat_lhs = pat', pat_rhs = grhss'-                             , pat_ext = (pat_ty, ([],[])) }+                             , pat_ext = (pat_ty, ([],[]))+                             , pat_mult = setTcMultAnn mult mult_ann }                  , mbis ) }   where@@ -1446,8 +1538,8 @@ -- it; hence the TcMonoBind data type in which the LHS is done but the RHS isn't  data TcMonoBind         -- Half completed; LHS done, RHS not done-  = TcFunBind  MonoBindInfo  SrcSpan (MatchGroup GhcRn (LHsExpr GhcRn))-  | TcPatBind [MonoBindInfo] (LPat GhcTc) (GRHSs GhcRn (LHsExpr GhcRn))+  = TcFunBind  MonoBindInfo  SrcSpan Mult (MatchGroup GhcRn (LHsExpr GhcRn))+  | TcPatBind [MonoBindInfo] (LPat GhcTc) Mult (HsMultAnn GhcRn) (GRHSs GhcRn (LHsExpr GhcRn))               TcSigmaTypeFRR  tcLhs :: TcSigFun -> LetBndrSpec -> HsBind GhcRn -> TcM TcMonoBind@@ -1466,32 +1558,32 @@     --           Just g = ...f...     -- Hence always typechecked with InferGen     do { mono_info <- tcLhsSigId no_gen (name, sig)-       ; return (TcFunBind mono_info (locA nm_loc) matches) }+       ; mult <- tcMultAnn (HsNoMultAnn noExtField)+       ; return (TcFunBind mono_info (locA nm_loc) mult matches) }    | otherwise  -- No type signature   = do { mono_ty <- newOpenFlexiTyVarTy-       ; mono_id <- newLetBndr no_gen name ManyTy mono_ty-          -- This ^ generates a binder with Many multiplicity because all-          -- let/where-binders are unrestricted. When we introduce linear let-          -- binders, we will need to retrieve the multiplicity information.+       ; mult <- tcMultAnn (HsNoMultAnn noExtField)+       ; mono_id <- newLetBndr no_gen name mult mono_ty        ; let mono_info = MBI { mbi_poly_name = name                              , mbi_sig       = Nothing-                             , mbi_mono_id   = mono_id }-       ; return (TcFunBind mono_info (locA nm_loc) matches) }+                             , mbi_mono_id   = mono_id+                             , mbi_mono_mult = mult}+       ; return (TcFunBind mono_info (locA nm_loc) mult matches) } -tcLhs sig_fn no_gen (PatBind { pat_lhs = pat, pat_rhs = grhss })+tcLhs sig_fn no_gen (PatBind { pat_lhs = pat, pat_rhs = grhss, pat_mult = mult_ann })   = -- See Note [Typechecking pattern bindings]     do  { sig_mbis <- mapM (tcLhsSigId no_gen) sig_names          ; let inst_sig_fun = lookupNameEnv $ mkNameEnv $                              [ (mbi_poly_name mbi, mbi_mono_id mbi)                              | mbi <- sig_mbis ]-+        ; mult <- tcMultAnn mult_ann             -- See Note [Typechecking pattern bindings]         ; ((pat', nosig_mbis), pat_ty)             <- addErrCtxt (patMonoBindsCtxt pat grhss) $                tcInferFRR FRRPatBind $ \ exp_ty ->-               tcLetPat inst_sig_fun no_gen pat (unrestricted exp_ty) $+               tcLetPat inst_sig_fun no_gen pat (Scaled mult exp_ty) $                  -- The above inferred type get an unrestricted multiplicity. It may be                  -- worth it to try and find a finer-grained multiplicity here                  -- if examples warrant it.@@ -1503,12 +1595,12 @@                                 | mbi <- mbis, let id = mbi_mono_id mbi ]                            $$ ppr no_gen) -        ; return (TcPatBind mbis pat' grhss pat_ty) }+        ; return (TcPatBind mbis pat' mult mult_ann grhss pat_ty) }   where     bndr_names = collectPatBinders CollNoDictBinders pat     (nosig_names, sig_names) = partitionWith find_sig bndr_names -    find_sig :: Name -> Either Name (Name, TcIdSigInfo)+    find_sig :: Name -> Either Name (Name, TcIdSig)     find_sig name = case sig_fn name of                       Just (TcIdSig sig) -> Right (name, sig)                       _                  -> Left name@@ -1526,21 +1618,23 @@   = do { mono_id <- tcLookupId name        ; return (MBI { mbi_poly_name = name                      , mbi_sig       = Nothing-                     , mbi_mono_id   = mono_id }) }+                     , mbi_mono_id   = mono_id+                     , mbi_mono_mult = idMult mono_id }) }  --------------------tcLhsSigId :: LetBndrSpec -> (Name, TcIdSigInfo) -> TcM MonoBindInfo+tcLhsSigId :: LetBndrSpec -> (Name, TcIdSig) -> TcM MonoBindInfo tcLhsSigId no_gen (name, sig)   = do { inst_sig <- tcInstSig sig        ; mono_id <- newSigLetBndr no_gen name inst_sig        ; return (MBI { mbi_poly_name = name                      , mbi_sig       = Just inst_sig-                     , mbi_mono_id   = mono_id }) }+                     , mbi_mono_id   = mono_id+                     , mbi_mono_mult = idMult mono_id }) }  ------------ newSigLetBndr :: LetBndrSpec -> Name -> TcIdSigInst -> TcM TcId newSigLetBndr (LetGblBndr prags) name (TISI { sig_inst_sig = id_sig })-  | CompleteSig { sig_bndr = poly_id } <- id_sig+  | TcCompleteSig (CSig { sig_bndr = poly_id }) <- id_sig   = addInlinePrags poly_id (lookupPragEnv prags name) newSigLetBndr no_gen name (TISI { sig_inst_tau = tau })   = newLetBndr no_gen name ManyTy tau@@ -1551,18 +1645,20 @@ ------------------- tcRhs :: TcMonoBind -> TcM (HsBind GhcTc) tcRhs (TcFunBind info@(MBI { mbi_sig = mb_sig, mbi_mono_id = mono_id })-                 loc matches)+                 loc mult matches)   = tcExtendIdBinderStackForRhs [info]  $     tcExtendTyVarEnvForRhs mb_sig       $-    do  { traceTc "tcRhs: fun bind" (ppr mono_id $$ ppr (idType mono_id))-        ; (co_fn, matches') <- tcMatchesFun (L (noAnnSrcSpan loc) (idName mono_id))-                                 matches (mkCheckExpType $ idType mono_id)-        ; return ( FunBind { fun_id = L (noAnnSrcSpan loc) mono_id+    do  { let mono_ty = idType mono_id+              mono_name = idName mono_id+        ; traceTc "tcRhs: fun bind" (ppr mono_id $$ ppr mono_ty)+        ; (co_fn, matches') <- tcFunBindMatches (InfSigCtxt mono_name) mono_name mult+                                                matches [] (mkCheckExpType mono_ty)+        ; return ( FunBind { fun_id      = L (noAnnSrcSpan loc) mono_id                            , fun_matches = matches'-                           , fun_ext = (co_fn, [])+                           , fun_ext     = (co_fn, [])                            } ) } -tcRhs (TcPatBind infos pat' grhss pat_ty)+tcRhs (TcPatBind infos pat' mult mult_ann grhss pat_ty)   = -- When we are doing pattern bindings we *don't* bring any scoped     -- type variables into scope unlike function bindings     -- Wny not?  They are not completely rigid.@@ -1570,11 +1666,21 @@     tcExtendIdBinderStackForRhs infos        $     do  { traceTc "tcRhs: pat bind" (ppr pat' $$ ppr pat_ty)         ; grhss' <- addErrCtxt (patMonoBindsCtxt pat' grhss) $-                    tcGRHSsPat grhss (mkCheckExpType pat_ty)+                    tcGRHSsPat mult grhss (mkCheckExpType pat_ty)          ; return ( PatBind { pat_lhs = pat', pat_rhs = grhss'-                           , pat_ext = (pat_ty, ([],[])) } )}+                           , pat_ext = (pat_ty, ([],[]))+                           , pat_mult = setTcMultAnn mult mult_ann } )} ++-- | @'tcMultAnn' ann@ takes an optional multiplicity annotation. If+-- present the multiplicity is returned, otherwise a fresh unification variable+-- is generated so that multiplicity can be inferred.+tcMultAnn :: HsMultAnn GhcRn -> TcM Mult+tcMultAnn (HsPct1Ann _) = return oneDataConTy+tcMultAnn (HsMultAnn _ p) = tcCheckLHsType p (TheKind multiplicityTy)+tcMultAnn (HsNoMultAnn _) = newFlexiTyVarTy multiplicityTy+ tcExtendTyVarEnvForRhs :: Maybe TcIdSigInst -> TcM a -> TcM a tcExtendTyVarEnvForRhs Nothing thing_inside   = thing_inside@@ -1601,8 +1707,8 @@ getMonoBindInfo tc_binds   = foldr (get_info . unLoc) [] tc_binds   where-    get_info (TcFunBind info _ _)    rest = info : rest-    get_info (TcPatBind infos _ _ _) rest = infos ++ rest+    get_info (TcFunBind info _ _ _)    rest = info : rest+    get_info (TcPatBind infos _ _ _ _ _) rest = infos ++ rest   {- Note [Relevant bindings and the binder stack]@@ -1643,7 +1749,7 @@ * (E2) is fine, despite the existential pattern, because   q::Int, and nothing escapes. -* Even (E3) is fine.  The existential pattern binds a dictionary+* Even (E3) is fine.  The existential pattern bindings a dictionary   for (Integral a) which the view pattern can use to convert the   a-valued field to an Integer, so r :: Integer. @@ -1742,7 +1848,7 @@    | CheckGen            -- One FunBind with a complete signature:        (LHsBind GhcRn)  --   do explicit generalisation-       TcIdSigInfo      -- Always CompleteSig+       TcCompleteSig  -- A consequence of the no-AbsBinds choice (NoGen) is that there is -- no "polymorphic Id" and "monmomorphic Id"; there is just the one@@ -1764,6 +1870,9 @@       | isTopLevel top_lvl             = True         -- See Note [Always generalise top-level bindings] +      | has_mult_anns_and_pats = False+        -- See Note [Non-variable pattern bindings aren't linear]+       | IsGroupClosed _ True <- closed = True         -- The 'True' means that all of the group's         -- free vars have ClosedTypeId=True; so we can ignore@@ -1778,7 +1887,7 @@     -- except a single function binding with a complete signature     one_funbind_with_sig       | [lbind@(L _ (FunBind { fun_id = v }))] <- lbinds-      , Just (TcIdSig sig@(CompleteSig {})) <- sig_fn (unLoc v)+      , Just (TcIdSig (TcCompleteSig sig)) <- sig_fn (unLoc v)       = Just (lbind, sig)       | otherwise       = Nothing@@ -1786,8 +1895,13 @@     binders          = collectHsBindListBinders CollNoDictBinders lbinds     has_partial_sigs = any has_partial_sig binders     has_partial_sig nm = case sig_fn nm of-      Just (TcIdSig (PartialSig {})) -> True-      _                              -> False+      Just (TcIdSig (TcPartialSig {})) -> True+      _                                -> False+    has_mult_anns_and_pats = any has_mult_ann_and_pat lbinds+    has_mult_ann_and_pat (L _ (PatBind{pat_mult=HsNoMultAnn{}})) = False+    has_mult_ann_and_pat (L _ (PatBind{pat_lhs=(L _ (VarPat{}))})) = False+    has_mult_ann_and_pat (L _ (PatBind{})) = True+    has_mult_ann_and_pat _ = False  isClosedBndrGroup :: TcTypeEnv -> Bag (LHsBind GhcRn) -> IsGroupClosed isClosedBndrGroup type_env binds
+ compiler/GHC/Tc/Gen/Do.hs view
@@ -0,0 +1,492 @@++{-# LANGUAGE ConstraintKinds  #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE RankNTypes       #-}+{-# LANGUAGE RecordWildCards  #-}+{-# LANGUAGE TupleSections    #-}+{-# LANGUAGE TypeFamilies     #-}++{-# OPTIONS_GHC -Wno-incomplete-uni-patterns   #-}++{-+(c) The University of Glasgow 2006+(c) The GRASP/AQUA Project, Glasgow University, 1992-1998+(c) The University of Iowa 2023++-}++-- | Expand @Do@ block statements into @(>>=)@, @(>>)@ and @let@s+--   After renaming but right ebefore type checking+module GHC.Tc.Gen.Do (expandDoStmts) where++import GHC.Prelude++import GHC.Rename.Utils ( wrapGenSpan, genHsExpApps, genHsApp, genHsLet,+                          genHsLamDoExp, genHsCaseAltDoExp, genWildPat )+import GHC.Tc.Utils.Monad+import GHC.Tc.Gen.Pat+import GHC.Tc.Utils.TcMType++import GHC.Hs++import GHC.Utils.Outputable+import GHC.Utils.Panic+import GHC.Driver.DynFlags ( DynFlags, getDynFlags )+import GHC.Driver.Ppr (showPpr)++import GHC.Types.SrcLoc+import GHC.Types.Basic+import qualified GHC.LanguageExtensions as LangExt++import Data.List ((\\))+++{-+************************************************************************+*                                                                      *+\subsection{XXExprGhcRn for Do Statements}+*                                                                      *+************************************************************************+-}++-- | Expand the `do`-statments into expressions right after renaming+--   so that they can be typechecked.+--   See Note [Expanding HsDo with XXExprGhcRn] below for `HsDo` specific commentary+--   and Note [Handling overloaded and rebindable constructs] for high level commentary+expandDoStmts :: HsDoFlavour -> [ExprLStmt GhcRn] -> TcM (LHsExpr GhcRn)+expandDoStmts doFlav stmts = do expanded_expr <- expand_do_stmts doFlav stmts+                                case expanded_expr of+                                         L _ (XExpr (PopErrCtxt e)) -> return e+                                         -- The first expanded stmt doesn't need a pop as+                                         -- it would otherwise pop the "In the expression do ... " from+                                         -- the error context+                                         _                          -> return expanded_expr++-- | The main work horse for expanding do block statements into applications of binds and thens+--   See Note [Expanding HsDo with XXExprGhcRn]+expand_do_stmts :: HsDoFlavour -> [ExprLStmt GhcRn] -> TcM (LHsExpr GhcRn)++expand_do_stmts ListComp _ =+  pprPanic "expand_do_stmts: impossible happened. ListComp" empty+        -- handeled by `GHC.Tc.Gen.Match.tcLcStmt`++expand_do_stmts _ [] = pprPanic "expand_do_stmts: impossible happened. Empty stmts" empty++expand_do_stmts _ (stmt@(L _ (TransStmt {})):_) =+  pprPanic "expand_do_stmts: TransStmt" $ ppr stmt+  -- handeled by `GHC.Tc.Gen.Match.tcLcStmt`++expand_do_stmts _ (stmt@(L _ (ParStmt {})):_) =+  pprPanic "expand_do_stmts: ParStmt" $ ppr stmt+  -- handeled by `GHC.Tc.Gen.Match.tcLcStmt`++expand_do_stmts _ (stmt@(L _ (ApplicativeStmt{})): _) =+  pprPanic "expand_do_stmts: Applicative Stmt" $ ppr stmt+  -- Handeled by tcSyntaxOp see `GHC.Tc.Gen.Match.tcStmtsAndThen`+++expand_do_stmts _ [stmt@(L loc (LastStmt _ (L body_loc body) _ ret_expr))]+-- See  Note [Expanding HsDo with XXExprGhcRn] Equation (5) below+-- last statement of a list comprehension, needs to explicitly return it+-- See `checkLastStmt` and `Syntax.Expr.StmtLR.LastStmt`+   | NoSyntaxExprRn <- ret_expr+   -- Last statement is just body if we are not in ListComp context. See Syntax.Expr.LastStmt+   = do traceTc "expand_do_stmts last" (ppr ret_expr)+        return $ mkExpandedStmtPopAt loc stmt body++   | SyntaxExprRn ret <- ret_expr+   --+   --    ------------------------------------------------+   --               return e  ~~> return e+   -- to make T18324 work+   = do traceTc "expand_do_stmts last" (ppr ret_expr)+        let expansion = genHsApp ret (L body_loc body)+        return $ mkExpandedStmtPopAt loc stmt expansion++expand_do_stmts do_or_lc (stmt@(L loc (LetStmt _ bs)) : lstmts) =+-- See  Note [Expanding HsDo with XXExprGhcRn] Equation (3) below+--                      stmts ~~> stmts'+--    ------------------------------------------------+--       let x = e ; stmts ~~> let x = e in stmts'+  do expand_stmts <- expand_do_stmts do_or_lc lstmts+     let expansion = genHsLet bs expand_stmts+     return $ mkExpandedStmtPopAt loc stmt expansion++expand_do_stmts do_or_lc (stmt@(L loc (BindStmt xbsrn pat e)): lstmts)+  | SyntaxExprRn bind_op <- xbsrn_bindOp xbsrn+  , fail_op              <- xbsrn_failOp xbsrn+-- See  Note [Expanding HsDo with XXExprGhcRn] Equation (2) below+-- the pattern binding pat can fail+--      stmts ~~> stmt'    f = \case pat -> stmts';+--                                   _   -> fail "Pattern match failure .."+--    -------------------------------------------------------+--       pat <- e ; stmts   ~~> (>>=) e f+  = do expand_stmts <- expand_do_stmts do_or_lc lstmts+       failable_expr <- mk_failable_expr do_or_lc pat expand_stmts fail_op+       let expansion = genHsExpApps bind_op  -- (>>=)+                       [ e+                       , failable_expr ]+       return $ mkExpandedStmtPopAt loc stmt expansion++  | otherwise+  = pprPanic "expand_do_stmts: The impossible happened, missing bind operator from renamer" (text "stmt" <+> ppr  stmt)++expand_do_stmts do_or_lc (stmt@(L loc (BodyStmt _ e (SyntaxExprRn then_op) _)) : lstmts) =+-- See Note [BodyStmt] in Language.Haskell.Syntax.Expr+-- See  Note [Expanding HsDo with XXExprGhcRn] Equation (1) below+--              stmts ~~> stmts'+--    ----------------------------------------------+--      e ; stmts ~~> (>>) e stmts'+  do expand_stmts_expr <- expand_do_stmts do_or_lc lstmts+     let expansion = genHsExpApps then_op  -- (>>)+                                  [ e+                                  , expand_stmts_expr ]+     return $ mkExpandedStmtPopAt loc stmt expansion++expand_do_stmts do_or_lc+       ((L loc (RecStmt { recS_stmts = L stmts_loc rec_stmts+                        , recS_later_ids = later_ids  -- forward referenced local ids+                        , recS_rec_ids = local_ids     -- ids referenced outside of the rec block+                        , recS_bind_fn = SyntaxExprRn bind_fun   -- the (>>=) expr+                        , recS_mfix_fn = SyntaxExprRn mfix_fun   -- the `mfix` expr+                        , recS_ret_fn  = SyntaxExprRn return_fun -- the `return` expr+                                                          -- use it explicitly+                                                          -- at the end of expanded rec block+                        }))+         : lstmts) =+-- See Note [Typing a RecStmt] in Language.Haskell.Syntax.Expr+-- See  Note [Expanding HsDo with XXExprGhcRn] Equation (4) and (6) below+--                                   stmts ~~> stmts'+--    -------------------------------------------------------------------------------------------+--      rec { later_ids, local_ids, rec_block } ; stmts+--                    ~~> (>>=) (mfix (\[ local_only_ids ++ later_ids ]+--                                           -> do { rec_stmts+--                                                 ; return (local_only_ids ++ later_ids) } ))+--                              (\ [ local_only_ids ++ later_ids ] -> stmts')+  do expand_stmts <- expand_do_stmts do_or_lc lstmts+     -- NB: No need to wrap the expansion with an ExpandedStmt+     -- as we want to flatten the rec block statements into its parent do block anyway+     return $ mkHsApps (wrapGenSpan bind_fun)                                           -- (>>=)+                      [ (wrapGenSpan mfix_fun) `mkHsApp` mfix_expr           -- (mfix (do block))+                      , genHsLamDoExp do_or_lc [ mkBigLHsVarPatTup all_ids ] --        (\ x ->+                                       expand_stmts                          --               stmts')+                      ]+  where+    local_only_ids = local_ids \\ later_ids -- get unique local rec ids;+                                            -- local rec ids and later ids can overlap+    all_ids = local_only_ids ++ later_ids   -- put local ids before return ids++    return_stmt  :: ExprLStmt GhcRn+    return_stmt  = wrapGenSpan $ LastStmt noExtField+                                     (mkBigLHsTup (map nlHsVar all_ids) noExtField)+                                     Nothing+                                     (SyntaxExprRn return_fun)+    do_stmts     :: XRec GhcRn [ExprLStmt GhcRn]+    do_stmts     = L stmts_loc $ rec_stmts ++ [return_stmt]+    do_block     :: LHsExpr GhcRn+    do_block     = L loc $ HsDo noExtField do_or_lc do_stmts+    mfix_expr    :: LHsExpr GhcRn+    mfix_expr    = genHsLamDoExp do_or_lc [ wrapGenSpan (LazyPat noExtField $ mkBigLHsVarPatTup all_ids) ]+                                          $ do_block+                             -- NB: LazyPat because we do not want to eagerly evaluate the pattern+                             -- and potentially loop forever++expand_do_stmts _ stmts = pprPanic "expand_do_stmts: impossible happened" $ (ppr stmts)++-- checks the pattern `pat`for irrefutability which decides if we need to wrap it with a fail block+mk_failable_expr :: HsDoFlavour -> LPat GhcRn -> LHsExpr GhcRn -> FailOperator GhcRn -> TcM (LHsExpr GhcRn)+mk_failable_expr doFlav pat@(L loc _) expr fail_op =+  do { is_strict <- xoptM LangExt.Strict+     ; irrf_pat <- isIrrefutableHsPatRnTcM is_strict pat+     ; traceTc "mk_failable_expr" (vcat [ text "pat:" <+> ppr pat+                                        , text "isIrrefutable:" <+> ppr irrf_pat+                                        ])++     ; if irrf_pat                        -- don't wrap with fail block if+                                          -- the pattern is irrefutable+       then return $ genHsLamDoExp doFlav [pat] expr+       else L loc <$> mk_fail_block doFlav pat expr fail_op+     }++-- makes the fail block with a given fail_op+mk_fail_block :: HsDoFlavour -> LPat GhcRn -> LHsExpr GhcRn -> FailOperator GhcRn -> TcM (HsExpr GhcRn)+mk_fail_block doFlav pat@(L ploc _) e (Just (SyntaxExprRn fail_op)) =+  do  dflags <- getDynFlags+      return $ HsLam noAnn LamCases $ mkMatchGroup (doExpansionOrigin doFlav) -- \+                (wrapGenSpan [ genHsCaseAltDoExp doFlav pat e                 --  pat -> expr+                             , fail_alt_case dflags pat fail_op               --  _   -> fail "fail pattern"+                             ])+        where+          fail_alt_case :: DynFlags -> LPat GhcRn -> HsExpr GhcRn -> LMatch GhcRn (LHsExpr GhcRn)+          fail_alt_case dflags pat fail_op = genHsCaseAltDoExp doFlav genWildPat $+                                             L ploc (fail_op_expr dflags pat fail_op)++          fail_op_expr :: DynFlags -> LPat GhcRn -> HsExpr GhcRn -> HsExpr GhcRn+          fail_op_expr dflags pat fail_op+            = mkExpandedPatRn pat $+                    genHsApp fail_op (mk_fail_msg_expr dflags pat)++          mk_fail_msg_expr :: DynFlags -> LPat GhcRn -> LHsExpr GhcRn+          mk_fail_msg_expr dflags pat+            = nlHsLit $ mkHsString $ showPpr dflags $+              text "Pattern match failure in" <+> pprHsDoFlavour (DoExpr Nothing)+                   <+> text "at" <+> ppr (getLocA pat)+++mk_fail_block _ _ _ _ = pprPanic "mk_fail_block: impossible happened" empty+++{- Note [Expanding HsDo with XXExprGhcRn]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+We expand `do`-blocks before typechecking it, by re-using the existing `XXExprGhcRns` and `RebindableSyntax` machinery.+This is very similar to:+  1. Expansions done in `GHC.Rename.Expr.rnHsIf` for expanding `HsIf`; and+  2. `desugarRecordUpd` in `GHC.Tc.Gen.Expr.tcExpr` for expanding `RecordUpd`+See Note [Handling overloaded and rebindable constructs] in GHC.Rename.Expr++To disabmiguate desugaring (`HsExpr GhcTc -> Core.Expr`) we use the phrase expansion+(`HsExpr GhcRn -> HsExpr GhcRn`)++This expansion is done right before typechecking and after renaming+See Part 2. of Note [Doing XXExprGhcRn in the Renamer vs Typechecker] in `GHC.Rename.Expr`++Historical note START+---------------------+In previous versions of GHC, the `do`-notation wasn't expanded before typechecking,+instead the typechecker would operate directly on the original.+Why? because it ensured that type error messages were explained in terms of+what the programmer has written. In practice, however, this didn't work very well:++* Attempts to typecheck the original source code turned out to be buggy, and virtually impossible+  to fix (#14963, #15598, #21206 and others)++* The typechecker expected the `>>=` operator to have a type that matches+  `m _ -> (_ -> m _) -> m _` for some `m`. With `RebindableSyntax` or+  `QualifiedDo` the `>>=` operator might not have the+  standard type. It might have a type like++      (>>=) :: Wombat m => m a1 a2 b -> (b -> m a2 a3 c) -> m a1 a3 c++  Typechecking the term `(>>=) e1 (\x -> e2)` deals with all of this automatically.++* With `ImpredicativeTypes` the programmer will expect Quick Look to instantiate+  the quantifiers impredicatively (#18324). Again, that happens automatically if+  you typecheck the expanded expression.++Historical note END+-------------------++Do Expansions Equationally+--------------------------+We have the following schema for expanding `do`-statements.+They capture the essence of statement expansions as implemented in `expand_do_stmts`++  DO【 _ 】 maps a sequence of do statements and recursively converts them into expressions++          (1) DO【 s; ss 】      = ‹ExpansionStmt s›((>>) s (‹PopErrCtxt›DO【 ss 】))++          (2) DO【 p <- e; ss 】 = if p is irrefutable+                                   then ‹ExpansionStmt (p <- e)›+                                          (>>=) s (‹PopExprCtxt›(\ p -> DO【 ss 】))+                                   else ‹ExpansionStmt (p <- e)›+                                          (>>=) s (‹PopExprCtxt›(\case p -> DO【 ss 】+                                                                       _ -> fail "pattern p failure"))++          (3) DO【 let x = e; ss 】+                                 = ‹ExpansionStmt (let x = e)› (let x = e in (‹PopErrCtxt›DO【 ss 】))+++          (4) DO【 rec ss; sss 】+                                 = (>>=) e (\vars -> ‹PopErrCtxt›DO【 sss 】))+                                           where (vars, e) = RECDO【 ss 】++          (5) DO【 s 】          = s++  RECDO【 _ 】 maps a sequence of recursively dependent monadic statements and converts it into an expression paired+              with the variables that the rec finds a fix point of.++          (6) RECDO【 ss 】     = (vars, mfix (\~vars -> (>>=) (DO【 ss 】) (return vars)))+                                  where vars are all the variables free in ss+++For a concrete example, consider a `do`-block written by the user++    f = {l0} do {l1} {pl}p <- {l1'} e1+                {l2} g p+                {l3} return {l3'} p++The expanded version (performed by `expand_do_stmts`) looks like:++    f = {g1} (>>=) ({l1'} e1) (\ {pl}p ->+                   {g2} (>>) ({l2} g p)+                             ({l3} return p))++The {l1} etc are location/source span information stored in the AST by the parser,+{g1} are compiler generated source spans.+++The 3 non-obvious points to consider are:+ 1. Wrap the expression with a `fail` block if the pattern match is not irrefutable.+    See Part 1. below+ 2. Generate appropriate warnings for discarded results in a body statement+    eg. say `do { .. ; (g p :: m Int) ; ... }`+    See Part 2. below+ 3. Generating appropriate type error messages which blame the correct source spans+    See Part 3. below++Part 1. Expanding Patterns Bindings+-----------------------------------+If `p` is a failable pattern---checked by `GHC.Tc.Gen.Pat.isIrrefutableHsPatRnTcM`---+we need to wrap it with a `fail`-block. See Equation (2) above.++The expansion of the `do`-block++        do { Just p <- e1; e2 }++(ignoring the location information) will be++        (>>=) (e1)+              (\case                 -- anonymous continuation lambda+                 Just p -> e2+                 _      -> fail "failable pattern p at location")++The `fail`-block wrapping is done by `GHC.Tc.Gen.Do.mk_failable_expr`.++* Note the explicit call to `fail`, in the monad of the `do`-block.  Part of the specification+  of do-notation is that if the pattern match fails, we fail in the monad, *not* just crash+  at runtime.++* According to the language specification, when the pattern is irrefutable,+  we should not add the `fail` alternative. This is important because+  the occurrence of `fail` means that the typechecker will generate a `MonadFail` constraint,+  and irrefutable patterns shouldn't need a fail alternative.++* _Wrinkel 1_: Note that pattern synonyms count as refutable during type checking,+  (see `GHC.Tc.Gen.Pat.isIrrefutableHsPatRnTcM`). They will hence generate a+  `MonadFail` constraint and they will always be wrapped in a `fail`able-block.++  Consider a patten synonym declaration (testcase T24552):++             pattern MyJust :: a -> Maybe a+             pattern MyJust x <- Just x where MyJust = Just++  and a `do`-block with the following bind and return statement++             do { MyJust x <- [MyNothing, MyJust ()]+                ; return x }++  The `do`-expansion will generate the expansion++            (>>=) ([MyNothing, MyJust ()])+                  (\case MyJust x -> return x                     -- (1)+                         _        -> fail "failable pattern .. "  -- (2)+                  )++  This code (specifically the `match` spanning lines (1) and (2)) is a compiler generated code;+  the associated `Origin` in tagged `Generated`+  The alternative statements will thus be ignored by the pattern match check (c.f. `isMatchContextPmChecked`).+  This ensures we do not generate spurious redundant-pattern-match warnings due to the line (2) above.+  See Note [Generated code and pattern-match checking]+  See Note [Long-distance information in matchWrapper]++* _Wrinkle 2_: The call to `fail` will give rise to a `MonadFail` constraint. What `CtOrigin` do we+  attach to that constraint?  When the `MonadFail` constraint can't be solved, it'll show up in error+  messages and it needs to be a good location.  Ideally, it should identify the+  pattern `p`.  Hence, we wrap the `fail` alternative expression with a `ExpandedPat`+  that tags the fail expression with the failable pattern. (See testcase MonadFailErrors.hs)++Part 2. Generate warnings for discarded body statement results+--------------------------------------------------------------+If the `do`-blocks' body statement is an expression that returns a+value that is not of type `()`, we need to warn the user about discarded+the value when `-Wunused-binds` flag is turned on. (See testcase T3263-2.hs)++For example the `do`-block++    do { e1;  e2 } -- where, e1 :: m Int++expands to++    (>>) e1 e2++* If `e1` returns a non-() value we want to emit a warning, telling the user that they+  are discarding the value returned by e1. This is done by `HsToCore.dsExpr` in the `HsApp`+  with a call to `HsToCore.warnUnusedBindValue`.++* The decision to trigger the warning is: if the function is a compiler generated `(>>)`,+  and its first argument `e1` has a non-() type++Part 3. Blaming Offending Source Code and Generating Appropriate Error Messages+-------------------------------------------------------------------------------+To ensure we correctly track source of the offending user written source code,+in this case the `do`-statement, we need to keep track of+which source statement's expansion the typechecker is currently typechecking.+For this purpose we use the `XXExprGhcRn.ExpansionRn`.+It stores the original statement (with location) and the expanded expression++  A. Expanding Body Statements+  -----------------------------+  For example, the `do`-block++      do { e1;  e2; e3 }++  expands (ignoring the location info) to++      ‹ExpandedThingRn do { e1; e2; e3 }›                        -- Original Do Expression+                                                                 -- Expanded Do Expression+          (‹ExpandedThingRn e1›                                  -- Original Statement+               ({(>>) e1}                                        -- Expanded Expression+                  ‹PopErrCtxt› (‹ExpandedThingRn e2›+                         ({(>>) e2}+                            ‹PopErrCtxt› (‹ExpandedThingRn e3› {e3})))))++  * Whenever the typechecker steps through an `ExpandedThingRn`,+    we push the original statement in the error context, set the error location to the+    location of the statement, and then typecheck the expanded expression.+    This is similar to vanilla `XXExprGhcRn` and rebindable syntax+    See Note [Rebindable syntax and XXExprGhcRn] in `GHC.Hs.Expr`.++  * Recall, that when a source function argument fails to typecheck,+    we print an error message like "In the second argument of the function f..".+    However, `(>>)` is generated thus, we don't want to display that to the user; it would be confusing.+    But also, we do not want to completely ignore it as we do want to keep the error blame carets+    as precise as possible, and not just blame the complete `do`-block.+    Thus, when we typecheck the application `(>>) e1`, we push the "In the stmt of do block e1" with+    the source location of `e1` in the error context stack as we walk inside an `ExpandedThingRn`.+    See also Note [splitHsApps].++  * After the expanded expression of a `do`-statement is typechecked+    and before moving to the next statement of the `do`-block, we need to first pop the top+    of the error context stack which contains the error message for+    the previous statement: eg. "In the stmt of a do block: e1".+    This is explicitly encoded in the expansion expression using+    the `XXExprGhcRn.PopErrCtxt`. Whenever `GHC.Tc.Gen.Expr.tcExpr` (via `GHC.Tc.Gen.tcXExpr`)+    sees a `PopErrCtxt` it calls `GHC.Tc.Utils.Monad.popErrCtxt` to pop of the top of error context stack.+    See ‹PopErrCtxt› in the example above.+    Without this popping business for error context stack,+    if there is a type error in `e2`, we would get a spurious and confusing error message+    which mentions "In the stmt of a do block e1" along with the message+    "In the stmt of a do block e2".++  B. Expanding Bind Statements+  -----------------------------+  A `do`-block with a bind statement:++      do { p <- e1; e2 }++  expands (ignoring the location information) to++     ‹ExpandedThingRn do{ p <- e1; e2 }›                                      -- Original Do Expression+                                                                              --+         (‹ExpandedThingRn (p <- e1)›                                         -- Original Statement+                        (((>>=) e1)                                           -- Expanded Expression+                           ‹PopErrCtxt› ((\ p -> ‹ExpandedThingRn (e2)› e2)))+         )+++  However, the expansion lambda `(\p -> e2)` is special as it is generated from a `do`-stmt expansion+  and if a type checker error occurs in the pattern `p` (which is source generated), we need to say+  "in a pattern binding in a do block" and not "in the pattern of a lambda" (cf. Typeable1.hs).+  We hence use a tag `GenReason` in `Ghc.Tc.Origin`. When typechecking a `HsLam` in `Tc.Gen.Expr.tcExpr`+  the `match_ctxt` is set to a `StmtCtxt` if `GenOrigin` is a `DoExpansionOrigin`.+-}
compiler/GHC/Tc/Gen/Export.hs view
@@ -206,7 +206,7 @@                  | explicit_mod = exports                  | has_main                           = Just (noLocA [noLocA (IEVar Nothing-                                     (noLocA (IEName noExtField $ noLocA default_main)))])+                                     (noLocA (IEName noExtField $ noLocA default_main)) Nothing)])                         -- ToDo: the 'noLoc' here is unhelpful if 'main'                         --       turns out to be out of scope                  | otherwise = Nothing@@ -391,7 +391,7 @@             expacc_exp_occs   = occs,             expacc_warn_spans = export_warn_spans,             expacc_dont_warn  = dont_warn_export-          } (L loc ie@(IEVar warn_txt_ps l))+          } (L loc ie@(IEVar warn_txt_ps l doc))         = do mb_gre <- lookupGreAvailRn $ lieWrappedName l              for mb_gre $ \ gre -> do                let avail = availFromGRE gre@@ -405,17 +405,18 @@                                     warn_txt_ps                                     (locA loc) +               doc' <- traverse rnLHsDoc doc                return ( expacc{ expacc_exp_occs   = occs'                               , expacc_warn_spans = export_warn_spans'                               , expacc_dont_warn  = dont_warn_export' }-                      , L loc (IEVar warn_txt_rn (replaceLWrappedName l name))+                      , L loc (IEVar warn_txt_rn (replaceLWrappedName l name) doc')                       , avail )      lookup_ie expacc@ExportAccum{             expacc_exp_occs   = occs,             expacc_warn_spans = export_warn_spans,             expacc_dont_warn  = dont_warn_export-          } (L loc ie@(IEThingAbs (warn_txt_ps, ann) l))+          } (L loc ie@(IEThingAbs (warn_txt_ps, ann) l doc))         = do mb_gre <- lookupGreAvailRn $ lieWrappedName l              for mb_gre $ \ gre -> do                let avail = availFromGRE gre@@ -429,17 +430,18 @@                                     warn_txt_ps                                     (locA loc) +               doc' <- traverse rnLHsDoc doc                return ( expacc{ expacc_exp_occs   = occs'                               , expacc_warn_spans = export_warn_spans'                               , expacc_dont_warn  = dont_warn_export' }-                      , L loc (IEThingAbs (warn_txt_rn, ann) (replaceLWrappedName l name))+                      , L loc (IEThingAbs (warn_txt_rn, ann) (replaceLWrappedName l name) doc')                       , avail )      lookup_ie expacc@ExportAccum{             expacc_exp_occs   = occs,             expacc_warn_spans = export_warn_spans,             expacc_dont_warn  = dont_warn_export-          } (L loc ie@(IEThingAll (warn_txt_ps, ann) l))+          } (L loc ie@(IEThingAll (warn_txt_ps, ann) l doc))         = do mb_gre <- lookupGreAvailRn $ lieWrappedName l              for mb_gre $ \ par -> do                all_kids <- lookup_ie_kids_all ie l par@@ -455,17 +457,18 @@                                     warn_txt_ps                                     (locA loc) +               doc' <- traverse rnLHsDoc doc                return ( expacc{ expacc_exp_occs   = occs'                               , expacc_warn_spans = export_warn_spans'                               , expacc_dont_warn  = dont_warn_export' }-                      , L loc (IEThingAll (warn_txt_rn, ann) (replaceLWrappedName l name))+                      , L loc (IEThingAll (warn_txt_rn, ann) (replaceLWrappedName l name) doc')                       , AvailTC name all_names )      lookup_ie expacc@ExportAccum{             expacc_exp_occs   = occs,             expacc_warn_spans = export_warn_spans,             expacc_dont_warn  = dont_warn_export-          } (L loc ie@(IEThingWith (warn_txt_ps, ann) l wc sub_rdrs))+          } (L loc ie@(IEThingWith (warn_txt_ps, ann) l wc sub_rdrs doc))         = do mb_gre <- addExportErrCtxt ie                      $ lookupGreAvailRn $ lieWrappedName l              for mb_gre $ \ par -> do@@ -491,10 +494,11 @@                                     warn_txt_ps                                     (locA loc) +               doc' <- traverse rnLHsDoc doc                return ( expacc{ expacc_exp_occs   = occs'                               , expacc_warn_spans = export_warn_spans'                               , expacc_dont_warn  = dont_warn_export' }-                      , L loc (IEThingWith (warn_txt_rn, ann) (replaceLWrappedName l name) wc subs)+                      , L loc (IEThingWith (warn_txt_rn, ann) (replaceLWrappedName l name) wc subs doc')                       , AvailTC name all_names )      lookup_ie _ _ = panic "lookup_ie"    -- Other cases covered earlier@@ -523,9 +527,6 @@      ------------- -    rn_warning_txt_loc :: LocatedP (WarningTxt GhcPs) -> RnM (LocatedP (WarningTxt GhcRn))-    rn_warning_txt_loc (L loc warn_txt) = L loc <$> rnWarningTxt warn_txt-     -- Runs for every Name     -- - If there is no new warning, flags that the old warning should not be     --     included (since a warning should only be emitted if all@@ -534,12 +535,12 @@     process_warning :: ExportWarnSpanNames       -- Old aggregate data about warnins                     -> DontWarnExportNames       -- Old names not to warn about                     -> [Name]                              -- Names to warn about-                    -> Maybe (LocatedP (WarningTxt GhcPs)) -- Warning+                    -> Maybe (LWarningTxt GhcPs) -- Warning                     -> SrcSpan                             -- Span of the export list item                     -> RnM (ExportWarnSpanNames, -- Aggregate data about the warnings                             DontWarnExportNames, -- Names not to warn about in the end                                                  -- (when there was a non-warned export)-                            Maybe (LocatedP (WarningTxt GhcRn))) -- Renamed warning+                            Maybe (LWarningTxt GhcRn)) -- Renamed warning     process_warning export_warn_spans                     dont_warn_export                     names Nothing loc@@ -560,7 +561,7 @@                     dont_warn_export                     names (Just warn_txt_ps) loc       = do-          warn_txt_rn <- rn_warning_txt_loc warn_txt_ps+          warn_txt_rn <- rnLWarningTxt warn_txt_ps           let new_export_warn_spans = map (, unLoc warn_txt_rn, loc) names           return ( new_export_warn_spans ++ export_warn_spans                  , dont_warn_export@@ -713,7 +714,7 @@               do { ub <- reportUnboundName unboundName                  ; let l = getLoc n                        gre = mkLocalGRE UnboundGRE NoParent ub-                 ; return (L l (IEName noExtField (L (la2na l) ub)), gre)}+                 ; return (L l (IEName noExtField (L (l2l l) ub)), gre)}             FoundChild child@(GRE { gre_name = child_nm, gre_par = par }) ->               do { checkPatSynParent spec_parent par child_nm                  ; return (replaceLWrappedName n child_nm, child)@@ -906,7 +907,7 @@         || (explicit_in ie1 && explicit_in ie2) )   where     explicit_in (IEModuleContents {}) = False                   -- module M-    explicit_in (IEThingAll _ r)+    explicit_in (IEThingAll _ r _)       = occName child == rdrNameOcc (ieWrappedName $ unLoc r)  -- T(..)     explicit_in _              = True 
compiler/GHC/Tc/Gen/Expr.hs view
@@ -20,7 +20,7 @@          tcCheckMonoExpr, tcCheckMonoExprNC,          tcMonoExpr, tcMonoExprNC,          tcInferRho, tcInferRhoNC,-         tcPolyExpr, tcExpr,+         tcPolyLExpr, tcPolyExpr, tcExpr, tcPolyLExprSig,          tcSyntaxOp, tcSyntaxOpGen, SyntaxOpType(..), synKnownType,          tcCheckId,          ) where@@ -30,7 +30,7 @@ import Language.Haskell.Syntax.Basic (FieldLabelString(..))  import {-# SOURCE #-} GHC.Tc.Gen.Splice-  ( tcTypedSplice, tcTypedBracket, tcUntypedBracket )+  ( tcTypedSplice, tcTypedBracket, tcUntypedBracket, getUntypedSpliceBody )  import GHC.Hs import GHC.Hs.Syn.Type@@ -53,11 +53,11 @@ import GHC.Tc.Gen.Bind        ( tcLocalBinds ) import GHC.Tc.Instance.Family ( tcGetFamInstEnvs ) import GHC.Core.FamInstEnv    ( FamInstEnvs )-import GHC.Rename.Expr        ( mkExpandedExpr )-import GHC.Rename.Env         ( addUsedGRE, getUpdFieldLbls, DeprecationWarnings(..) )+import GHC.Rename.Env         ( addUsedGRE, getUpdFieldLbls ) import GHC.Tc.Utils.Env import GHC.Tc.Gen.Arrow-import GHC.Tc.Gen.Match+import GHC.Tc.Gen.Match( tcBody, tcLambdaMatches, tcCaseMatches+                       , tcGRHSList, tcDoStmts ) import GHC.Tc.Gen.HsType import GHC.Tc.Utils.TcMType import GHC.Tc.Zonk.TcType@@ -74,7 +74,7 @@ import GHC.Core.Class(classTyCon) import GHC.Core.TyCon import GHC.Core.Type-import GHC.Core.Coercion( mkSymCo )+import GHC.Core.Coercion import GHC.Tc.Types.Evidence import GHC.Builtin.Types import GHC.Builtin.Names@@ -87,7 +87,6 @@ import GHC.Data.Maybe import GHC.Utils.Outputable as Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain  import Control.Monad import qualified Data.List.NonEmpty as NE@@ -100,7 +99,6 @@ ************************************************************************ -} - tcCheckPolyExpr, tcCheckPolyExprNC   :: LHsExpr GhcRn         -- Expression to type check   -> TcSigmaType           -- Expected type (could be a polytype)@@ -114,12 +112,13 @@ tcCheckPolyExpr   expr res_ty = tcPolyLExpr   expr (mkCheckExpType res_ty) tcCheckPolyExprNC expr res_ty = tcPolyLExprNC expr (mkCheckExpType res_ty) +----------------- -- These versions take an ExpType tcPolyLExpr, tcPolyLExprNC :: LHsExpr GhcRn -> ExpSigmaType                            -> TcM (LHsExpr GhcTc)  tcPolyLExpr (L loc expr) res_ty-  = setSrcSpanA loc   $  -- Set location /first/; see GHC.Tc.Utils.Monad+  = setSrcSpanA loc  $  -- Set location /first/; see GHC.Tc.Utils.Monad     addExprCtxt expr $  -- Note [Error contexts in generated code]     do { expr' <- tcPolyExpr expr res_ty        ; return (L loc expr') }@@ -129,6 +128,118 @@     do { expr' <- tcPolyExpr expr res_ty        ; return (L loc expr') } +-----------------+tcPolyExpr :: HsExpr GhcRn -> ExpSigmaType -> TcM (HsExpr GhcTc)+tcPolyExpr e (Infer inf) = tcExpr e (Infer inf)+tcPolyExpr e (Check ty)  = tcPolyExprCheck e (Left ty)++-----------------+tcPolyLExprSig :: LHsExpr GhcRn -> TcCompleteSig -> TcM (LHsExpr GhcTc)+tcPolyLExprSig (L loc expr) sig+  = setSrcSpanA loc $+    -- No addExprCtxt.  For (e :: ty) we don't want generate+    --    In the expression e+    --    In the expression e :: ty+    -- We have already got an error-context for (e::ty), so when we+    -- get to `e`, just add the location+    do { traceTc "tcPolyLExprSig" (ppr loc $$ ppr expr)+       ; expr' <- tcPolyExprCheck expr (Right sig)+       ; return (L loc expr') }++-----------------+tcPolyExprCheck :: HsExpr GhcRn+                -> Either TcSigmaType TcCompleteSig+                -> TcM (HsExpr GhcTc)+-- tcPolyExpCheck deals with the special case for HsLam, in case the pushed-down+-- type is a forall-type.  E.g.    (\@a -> blah) :: forall b. b -> Int+--+-- The (Either TcSigmaType TcCompleteSig) deals with:+--   Left ty:    (f e) pushes f's argument type `ty` into `e`+--   Right sig:  (e :: sig) pushes `sig` into `e`+-- The Either stuff is entirely local to this function and its immediate callers.+--+-- See Note [Skolemisation overview] in GHC.Tc.Utils.Unify++tcPolyExprCheck expr res_ty+  = outer_skolemise res_ty $ \pat_tys rho_ty ->+    let+      -- tc_body is a little loop that looks past parentheses+      tc_body (HsPar x (L loc e))+        = setSrcSpanA loc $+          do { e' <- tc_body e+             ; return (HsPar x (L loc e')) }++      -- Look through any untyped splices (#24559)+      -- c.f. Note [Looking through Template Haskell splices in splitHsApps]+      tc_body (HsUntypedSplice splice_res _)+        = do { body <- getUntypedSpliceBody splice_res+             ; tc_body body }++      -- The special case for lambda: go to tcLambdaMatches, passing pat_tys+      tc_body e@(HsLam x lam_variant matches)+        = do { (wrap, matches') <- tcLambdaMatches e lam_variant matches pat_tys+                                                   (mkCheckExpType rho_ty)+               -- NB: tcLambdaMatches concludes with deep skolemisation,+               --     if DeepSubsumption is on;  hence no need to do that here+             ; return (mkHsWrap wrap $ HsLam x lam_variant matches') }++      -- The general case: just do deep skolemisation if necessary,+      -- before handing off to tcExpr+      tc_body e = do { ds_flag <- getDeepSubsumptionFlag+                     ; inner_skolemise ds_flag rho_ty $ \rho_ty' ->+                       tcExpr e (mkCheckExpType rho_ty') }+    in tc_body expr+  where+    -- `outer_skolemise` is used always+    -- It only does shallow skolemisation+    -- It always makes an implication constraint if deferred-errors is on+    outer_skolemise :: Either TcSigmaType TcCompleteSig+                    -> ([ExpPatType] -> TcRhoType -> TcM (HsExpr GhcTc))+                    -> TcM (HsExpr GhcTc)+    outer_skolemise (Left ty) thing_inside+      = do { (wrap, expr') <- tcSkolemiseExpectedType ty thing_inside+           ; return (mkHsWrap wrap expr') }+    outer_skolemise (Right sig) thing_inside+      = do { (wrap, expr') <- tcSkolemiseCompleteSig sig thing_inside+           ; return (mkHsWrap wrap expr') }++    -- inner_skolemise is used when we do not have a lambda+    -- With deep skolemisation we must remember to deeply skolemise+    -- after the (always-shallow) tcSkolemiseCompleteSig+    inner_skolemise :: DeepSubsumptionFlag -> TcRhoType+                    -> (TcRhoType -> TcM (HsExpr GhcTc)) -> TcM (HsExpr GhcTc)+    inner_skolemise Shallow rho_ty thing_inside+      = -- We have already done shallow skolemisation, so nothing further to do+        thing_inside rho_ty+    inner_skolemise Deep rho_ty thing_inside+      = -- Try deep skolemisation+        do { (wrap, expr') <- tcSkolemise Deep ctxt rho_ty thing_inside+           ; return (mkHsWrap wrap expr') }++    ctxt = case res_ty of+             Left {}   -> GenSigCtxt+             Right sig -> sig_ctxt sig+++{- *********************************************************************+*                                                                      *+        tcExpr: the main expression typechecker+*                                                                      *+********************************************************************* -}++tcInferRho, tcInferRhoNC :: LHsExpr GhcRn -> TcM (LHsExpr GhcTc, TcRhoType)+-- Infer a *rho*-type. The return type is always instantiated.+tcInferRho (L loc expr)+  = setSrcSpanA loc   $  -- Set location /first/; see GHC.Tc.Utils.Monad+    addExprCtxt expr $  -- Note [Error contexts in generated code]+    do { (expr', rho) <- tcInfer (tcExpr expr)+       ; return (L loc expr', rho) }++tcInferRhoNC (L loc expr)+  = setSrcSpanA loc $+    do { (expr', rho) <- tcInfer (tcExpr expr)+       ; return (L loc expr', rho) }+ --------------- tcCheckMonoExpr, tcCheckMonoExprNC     :: LHsExpr GhcRn     -- Expression to type check@@ -138,6 +249,7 @@ tcCheckMonoExpr   expr res_ty = tcMonoExpr   expr (mkCheckExpType res_ty) tcCheckMonoExprNC expr res_ty = tcMonoExprNC expr (mkCheckExpType res_ty) +--------------- tcMonoExpr, tcMonoExprNC     :: LHsExpr GhcRn     -- Expression to type check     -> ExpRhoType        -- Expected type@@ -156,47 +268,20 @@         ; return (L loc expr') }  ----------------tcInferRho, tcInferRhoNC :: LHsExpr GhcRn -> TcM (LHsExpr GhcTc, TcRhoType)--- Infer a *rho*-type. The return type is always instantiated.-tcInferRho (L loc expr)-  = setSrcSpanA loc   $  -- Set location /first/; see GHC.Tc.Utils.Monad-    addExprCtxt expr $  -- Note [Error contexts in generated code]-    do { (expr', rho) <- tcInfer (tcExpr expr)-       ; return (L loc expr', rho) }--tcInferRhoNC (L loc expr)-  = setSrcSpanA loc $-    do { (expr', rho) <- tcInfer (tcExpr expr)-       ; return (L loc expr', rho) }---{- *********************************************************************-*                                                                      *-        tcExpr: the main expression typechecker-*                                                                      *-********************************************************************* -}--tcPolyExpr :: HsExpr GhcRn -> ExpSigmaType -> TcM (HsExpr GhcTc)-tcPolyExpr expr res_ty-  = do { traceTc "tcPolyExpr" (ppr res_ty)-       ; (wrap, expr') <- tcSkolemiseExpType GenSigCtxt res_ty $ \ res_ty ->-                          tcExpr expr res_ty-       ; return $ mkHsWrap wrap expr' }- tcExpr :: HsExpr GhcRn -> ExpRhoType -> TcM (HsExpr GhcTc)  -- Use tcApp to typecheck applications, which are treated specially -- by Quick Look.  Specifically:---   - HsVar         lone variables, to ensure that they can get an+--   - HsVar           lone variables, to ensure that they can get an --                     impredicative instantiation (via Quick Look --                     driven by res_ty (in checking mode)).---   - HsApp         value applications---   - HsAppType     type applications---   - ExprWithTySig (e :: type)---   - HsRecSel      overloaded record fields---   - HsExpanded    renamer expansions---   - HsOpApp       operator applications---   - HsOverLit     overloaded literals+--   - HsApp           value applications+--   - HsAppType       type applications+--   - ExprWithTySig   (e :: type)+--   - HsRecSel        overloaded record fields+--   - ExpandedThingRn renamer/pre-typechecker expansions+--   - HsOpApp         operator applications+--   - HsOverLit       overloaded literals -- These constructors are the union of --   - ones taken apart by GHC.Tc.Gen.Head.splitHsApps --   - ones understood by GHC.Tc.Gen.Head.tcInferAppHead_maybe@@ -207,13 +292,14 @@ tcExpr e@(HsAppType {})          res_ty = tcApp e res_ty tcExpr e@(ExprWithTySig {})      res_ty = tcApp e res_ty tcExpr e@(HsRecSel {})           res_ty = tcApp e res_ty-tcExpr e@(XExpr (HsExpanded {})) res_ty = tcApp e res_ty +tcExpr (XExpr e)                 res_ty = tcXExpr e res_ty+ tcExpr e@(HsOverLit _ lit) res_ty   = do { mb_res <- tcShortCutLit lit res_ty          -- See Note [Short cut for overloaded literals] in GHC.Tc.Zonk.Type        ; case mb_res of-           Just lit' -> return (HsOverLit noAnn lit')+           Just lit' -> return (HsOverLit noExtField lit')            Nothing   -> tcApp e res_ty }  -- Typecheck an occurrence of an unbound Id@@ -231,9 +317,9 @@   = do { let lit_ty = hsLitType lit        ; tcWrapResult e (HsLit x (convertLit lit)) lit_ty res_ty } -tcExpr (HsPar x lpar expr rpar) res_ty+tcExpr (HsPar x expr) res_ty   = do { expr' <- tcMonoExprNC expr res_ty-       ; return (HsPar x lpar expr' rpar) }+       ; return (HsPar x expr') }  tcExpr (HsPragE x prag expr) res_ty   = do { expr' <- tcMonoExpr expr res_ty@@ -262,22 +348,9 @@                           unwrapIP $ mkClassPred ipClass [x,ty]   origin = IPOccOrigin x -tcExpr (HsLam _ match) res_ty-  = do  { (wrap, match') <- tcMatchLambda herald match_ctxt match res_ty-        ; return (mkHsWrap wrap (HsLam noExtField match')) }-  where-    match_ctxt = MC { mc_what = LambdaExpr, mc_body = tcBody }-    herald = ExpectedFunTyLam match--tcExpr e@(HsLamCase x lc_variant matches) res_ty-  = do { (wrap, matches')-           <- tcMatchLambda herald match_ctxt matches res_ty-       ; return (mkHsWrap wrap $ HsLamCase x lc_variant matches') }-  where-    match_ctxt = MC { mc_what = LamCaseAlt lc_variant, mc_body = tcBody }-    herald = ExpectedFunTyLamCase lc_variant e--+tcExpr e@(HsLam x lam_variant matches) res_ty+  = do { (wrap, matches') <- tcLambdaMatches e lam_variant matches [] res_ty+       ; return (mkHsWrap wrap $ HsLam x lam_variant matches') }  {- ************************************************************************@@ -311,19 +384,12 @@                            -- See Note [Unboxed tuple RuntimeRep vars] in GHC.Core.TyCon        ; let arg_tys' = case boxity of Unboxed -> drop arity arg_tys                                        Boxed   -> arg_tys-       ; tup_args1 <- tcTupArgs tup_args arg_tys'+       ; tup_args1 <- tcCheckExplicitTuple tup_args arg_tys'        ; return $ mkHsWrapCo coi (ExplicitTuple x tup_args1 boxity) }    | otherwise-  = -- The tup_args are a mixture of Present and Missing (for tuple sections)-    do { let arity = length tup_args--       ; arg_tys <- case boxity of-           { Boxed   -> newFlexiTyVarTys arity liftedTypeKind-           ; Unboxed -> replicateM arity newOpenFlexiTyVarTy }--       -- Handle tuple sections where-       ; tup_args1 <- tcTupArgs tup_args arg_tys+  = -- The tup_args are a mixture of Present and Missing (for tuple sections).+    do { (tup_args1, arg_tys) <- tcInferTupArgs boxity tup_args         ; let expr'       = ExplicitTuple x tup_args1 boxity              missing_tys = [Scaled mult ty | (Missing (Scaled mult _), ty) <- zip tup_args1 arg_tys]@@ -351,7 +417,7 @@        -- This should cause an error, even though (17# :: Int#)        -- is not representation-polymorphic: we don't know how        -- wide the concrete representation of the sum type will be.-       ; hasFixedRuntimeRep_syntactic FRRUnboxedSum res_ty+       ; hasFixedRuntimeRep_syntactic (FRRUnboxedSum Nothing) res_ty        ; return $ mkHsWrapCo coi (ExplicitSum arg_tys' alt arity expr' ) }  @@ -363,12 +429,14 @@ ************************************************************************ -} -tcExpr (HsLet x tkLet binds tkIn expr) res_ty-  = do  { (binds', expr') <- tcLocalBinds binds $-                             tcMonoExpr expr res_ty-        ; return (HsLet x tkLet binds' tkIn expr') }+tcExpr (HsLet x binds expr) res_ty+  = do  { (binds', wrapper, expr') <- tcLocalBinds binds $+                                      tcMonoExpr expr res_ty+          -- The wrapper checks for correct multiplicities.+          -- See Note [Wrapper returned from tcSubMult] in GHC.Tc.Utils.Unify.+        ; return (HsLet x binds' (mkLHsWrap wrapper expr')) } -tcExpr (HsCase x scrut matches) res_ty+tcExpr (HsCase ctxt scrut matches) res_ty   = do  {  -- We used to typecheck the case alternatives first.            -- The case patterns tend to give good type info to use            -- when typechecking the scrutinee.  For example@@ -381,20 +449,16 @@           mult <- newFlexiTyVarTy multiplicityTy            -- Typecheck the scrutinee.  We use tcInferRho but tcInferSigma-          -- would also be possible (tcMatchesCase accepts sigma-types)+          -- would also be possible (tcCaseMatches accepts sigma-types)           -- Interesting litmus test: do these two behave the same?           --     case id        of {..}           --     case (\v -> v) of {..}           -- This design choice is discussed in #17790         ; (scrut', scrut_ty) <- tcScalingUsage mult $ tcInferRho scrut -        ; traceTc "HsCase" (ppr scrut_ty)         ; hasFixedRuntimeRep_syntactic FRRCase scrut_ty-        ; matches' <- tcMatchesCase match_ctxt (Scaled mult scrut_ty) matches res_ty-        ; return (HsCase x scrut' matches') }- where-    match_ctxt = MC { mc_what = x,-                      mc_body = tcBody }+        ; (mult_co_wrap, matches') <- tcCaseMatches tcBody (Scaled mult scrut_ty) matches res_ty+        ; return (HsCase ctxt (mkLHsWrap mult_co_wrap scrut') matches') }  tcExpr (HsIf x pred b1 b2) res_ty   = do { pred'    <- tcCheckMonoExpr pred boolTy@@ -428,11 +492,10 @@ -}  tcExpr (HsMultiIf _ alts) res_ty-  = do { (ues, alts') <- mapAndUnzipM (\alt -> tcCollectingUsage $ wrapLocMA (tcGRHS match_ctxt res_ty) alt) alts+  = do { alts' <- tcGRHSList IfAlt tcBody alts res_ty+                  -- See Note [MultiWayIf linearity checking]        ; res_ty <- readExpType res_ty-       ; tcEmitBindingUsage (supUEs ues)  -- See Note [MultiWayIf linearity checking]        ; return (HsMultiIf res_ty alts') }-  where match_ctxt = MC { mc_what = IfAlt, mc_body = tcBody }  tcExpr (HsDo _ do_or_lc stmts) res_ty   = tcDoStmts do_or_lc stmts res_ty@@ -479,11 +542,13 @@         ; let wrap = mkWpEvVarApps [typeable_ev] <.> mkWpTyApps [expr_ty]         ; loc <- getSrcSpanM         ; static_ptr_ty_con <- tcLookupTyCon staticPtrTyConName-        ; return $ mkHsWrapCo co $ HsApp noComments+        ; return $ mkHsWrapCo co $ HsApp noExtField                             (L (noAnnSrcSpan loc) $ mkHsWrap wrap fromStaticPtr)                             (L (noAnnSrcSpan loc) (HsStatic (fvs, mkTyConApp static_ptr_ty_con [expr_ty]) expr'))         } +tcExpr (HsEmbTy _ _) _ = failWith TcRnIllegalTypeExpr+ {- ************************************************************************ *                                                                      *@@ -534,7 +599,7 @@   where     orig = OccurrenceOf con_name --- Record updates via dot syntax are replaced by desugared expressions+-- Record updates via dot syntax are replaced by expanded expressions -- in the renamer. See Note [Overview of record dot syntax] in -- GHC.Hs.Expr. This is why we match on 'rupd_flds = Left rbnds' here -- and panic otherwise.@@ -546,18 +611,18 @@                        })        res_ty   = assert (notNull rbnds) $-    do  { -- Desugar the record update. See Note [Record Updates].+    do  { -- Expand the record update. See Note [Record Updates].         ; (ds_expr, ds_res_ty, err_ctxt)-            <- desugarRecordUpd record_expr possible_parents rbnds res_ty+            <- expandRecordUpd record_expr possible_parents rbnds res_ty -          -- Typecheck the desugared expression.+          -- Typecheck the expanded expression.         ; expr' <- addErrCtxt err_ctxt $                    tcExpr (mkExpandedExpr expr ds_expr) (Check ds_res_ty)             -- NB: it's important to use ds_res_ty and not res_ty here.             -- Test case: T18802b.          ; addErrCtxt err_ctxt $ tcWrapResultMono expr expr' ds_res_ty res_ty-            -- We need to unify the result type of the desugared+            -- We need to unify the result type of the expanded             -- expression with the expected result type.             --             -- See Note [Unifying result types in tcRecordUpd].@@ -588,7 +653,7 @@ ************************************************************************ -} --- These terms have been replaced by desugaring in the renamer. See+-- These terms have been replaced by their expanded expressions in the renamer. See -- Note [Overview of record dot syntax]. tcExpr (HsGetField _ _ _) _ = panic "GHC.Tc.Gen.Expr: tcExpr: HsGetField: Not implemented" tcExpr (HsProjection _ _) _ = panic "GHC.Tc.Gen.Expr: tcExpr: HsProjection: Not implemented"@@ -608,11 +673,14 @@  tcExpr e@(HsUntypedBracket ps body) res_ty = tcUntypedBracket e body ps res_ty tcExpr (HsUntypedSplice splice _)   res_ty-  = case splice of-      HsUntypedSpliceTop mod_finalizers expr-        -> do { addModFinalizersWithLclEnv mod_finalizers-              ; tcExpr expr res_ty }-      HsUntypedSpliceNested {} -> panic "tcExpr: invalid nested splice"+  -- Since `tcApp` deals with `HsUntypedSplice` (in `splitHsApps`), you might+  -- wonder why we don't delegate to `tcApp` as we do for `HsVar`, etc.+  -- (See the initial block of equations for `tcExpr`.) But we can't do this+  -- for `HsUntypedSplice`; to see why, read Wrinkle (UTS1) in+  -- Note [Looking through Template Haskell splices in splitHsApps] in+  -- GHC.Tc.Gen.Head.+  = do { expr <- getUntypedSpliceBody splice+       ; tcExpr expr res_ty }  {- ************************************************************************@@ -630,6 +698,45 @@ {- ************************************************************************ *                                                                      *+                Expansion Expressions (XXExprGhcRn)+*                                                                      *+************************************************************************+-}++tcXExpr :: XXExprGhcRn -> ExpRhoType -> TcM (HsExpr GhcTc)++tcXExpr (PopErrCtxt (L loc e)) res_ty+  = popErrCtxt $ -- See Part 3 of Note [Expanding HsDo with XXExprGhcRn] in `GHC.Tc.Gen.Do`+      setSrcSpanA loc $+      tcExpr e res_ty++tcXExpr xe@(ExpandedThingRn o e') res_ty+  | OrigStmt ls@(L loc s@LetStmt{}) <- o+  , HsLet x binds e <- e'+  =  do { (binds', wrapper, e') <-  setSrcSpanA loc $+                            addStmtCtxt s $+                            tcLocalBinds binds $+                            tcMonoExprNC e res_ty -- NB: Do not call tcMonoExpr here as it adds+                                                  -- a duplicate error context+        ; return $ mkExpandedStmtTc ls (HsLet x binds' (mkLHsWrap wrapper e'))+        }+  | OrigStmt ls@(L loc s@LastStmt{}) <- o+  =  setSrcSpanA loc $+          addStmtCtxt s $+          mkExpandedStmtTc ls <$> tcExpr e' res_ty+                -- It is important that we call tcExpr (and not tcApp) here as+                -- `e` is the last statement's body expression+                -- and not a HsApp of a generated (>>) or (>>=)+                -- This improves error messages e.g. tests: DoExpansion1, DoExpansion2, DoExpansion3+  | OrigStmt ls@(L loc _) <- o+  = setSrcSpanA loc $+       mkExpandedStmtTc ls <$> tcApp (XExpr xe) res_ty++tcXExpr xe res_ty = tcApp (XExpr xe) res_ty++{-+************************************************************************+*                                                                      *                 Arithmetic sequences [a..b] etc *                                                                      * ************************************************************************@@ -688,27 +795,57 @@        ; return (idHsWrapper, elt_mult, elt_ty, Just fl') }  -----------------tcTupArgs :: [HsTupArg GhcRn]-          -> [TcSigmaType]-              -- ^ Argument types.-              -- This function ensures they all have-              -- a fixed runtime representation.-          -> TcM [HsTupArg GhcTc]-tcTupArgs args tys++-- | Typecheck an explicit tuple @(a,b,c)@ or @(\#a,b,c\#)@.+--+-- Does not handle tuple sections.+tcCheckExplicitTuple :: [HsTupArg GhcRn]+                     -> [TcSigmaType]+                          -- ^ Argument types.+                          -- This function ensures they all have+                          -- a fixed runtime representation.+                     -> TcM [HsTupArg GhcTc]+tcCheckExplicitTuple args tys   = do massert (equalLength args tys)        checkTupSize (length args)        zipWith3M go [1,2..] args tys   where     go :: Int -> HsTupArg GhcRn -> TcType -> TcM (HsTupArg GhcTc)     go i (Missing {})     arg_ty-      = do { mult <- newFlexiTyVarTy multiplicityTy-           ; hasFixedRuntimeRep_syntactic (FRRTupleSection i) arg_ty-           ; return (Missing (Scaled mult arg_ty)) }+      = pprPanic "tcCheckExplicitTuple: tuple sections not handled here"+          (ppr i $$ ppr arg_ty)     go i (Present x expr) arg_ty       = do { expr' <- tcCheckPolyExpr expr arg_ty-           ; hasFixedRuntimeRep_syntactic (FRRTupleArg i) arg_ty-           ; return (Present x expr') }+           ; (co, _) <- hasFixedRuntimeRep (FRRUnboxedTuple i) arg_ty+           ; return (Present x (mkLHsWrap (mkWpCastN co) expr')) } +-- | Typecheck an explicit tuple or tuple section by performing type inference.+tcInferTupArgs :: Boxity+               -> [HsTupArg GhcRn] -- ^ argument types+               -> TcM ([HsTupArg GhcTc], [TcSigmaTypeFRR])+tcInferTupArgs boxity args+  = do { checkTupSize (length args)+       ; zipWithAndUnzipM tc_infer_tup_arg [1,2..] args }+ where+  tc_infer_tup_arg :: Int -> HsTupArg GhcRn -> TcM (HsTupArg GhcTc, TcSigmaTypeFRR)+  tc_infer_tup_arg i (Missing {})+    = do { mult <- newFlexiTyVarTy multiplicityTy+         ; arg_ty <- new_arg_ty i+         ; return (Missing (Scaled mult arg_ty), arg_ty) }+  tc_infer_tup_arg i (Present x lexpr@(L l expr))+    = do { (expr', arg_ty) <- case boxity of+             Unboxed -> tcInferFRR (FRRUnboxedTuple i) (tcPolyExpr expr)+             Boxed   -> do { arg_ty <- newFlexiTyVarTy liftedTypeKind+                           ; L _ expr' <- tcCheckPolyExpr lexpr arg_ty+                           ; return (expr', arg_ty) }+         ; return (Present x (L l expr'), arg_ty) }++  new_arg_ty :: Int -> TcM TcTypeFRR+  new_arg_ty i =+    case boxity of+      Unboxed -> newOpenFlexiFRRTyVarTy (FRRUnboxedTupleSection i)+      Boxed   -> newFlexiTyVarTy liftedTypeKind+ --------------------------- -- See TcType.SyntaxOpType also for commentary tcSyntaxOp :: CtOrigin@@ -735,7 +872,7 @@               -> ([TcSigmaTypeFRR] -> [Mult] -> TcM a)               -> TcM (a, SyntaxExprTc) tcSyntaxOpGen orig (SyntaxExprRn op) arg_tys res_ty thing_inside-  = do { (expr, sigma) <- tcInferAppHead (op, VACall op 0 noSrcSpan) []+  = do { (expr, sigma) <- tcInferAppHead (op, VACall op 0 noSrcSpan)              -- Ugh!! But all this code is scheduled for demolition anyway        ; traceTc "tcSyntaxOpGen" (ppr op $$ ppr expr $$ ppr sigma)        ; (result, expr_wrap, arg_wraps, res_wrap)@@ -768,8 +905,8 @@            -- ^ returns a wrapper :: (type of right shape) "->" (type passed in) tcSynArgE orig op sigma_ty syn_ty thing_inside   = do { (skol_wrap, (result, ty_wrapper))-           <- tcTopSkolemise GenSigCtxt sigma_ty-                (\ rho_ty -> go rho_ty syn_ty)+           <- tcSkolemise Shallow GenSigCtxt sigma_ty $ \rho_ty ->+              go rho_ty syn_ty        ; return (result, skol_wrap <.> ty_wrapper) }     where     go rho_ty SynAny@@ -791,7 +928,7 @@                  , res_wrapper )                     -- :: res_ty_out "->" res_ty                , arg_wrapper1, [], arg_wrapper2 ) )  -- :: arg_ty "->" arg_ty_out                <- matchExpectedFunTys herald GenSigCtxt 1 (mkCheckExpType rho_ty) $-                  \ [arg_ty] res_ty ->+                  \ [ExpFunPatTy arg_ty] res_ty ->                   do { arg_tc_ty <- expTypeToType (scaledThing arg_ty)                      ; res_tc_ty <- expTypeToType res_ty @@ -838,8 +975,7 @@             -- and a wrapper to be applied to the overall expression tcSynArgA orig op sigma_ty arg_shapes res_shape thing_inside   = do { (match_wrapper, arg_tys, res_ty)-           <- matchActualFunTysRho herald orig Nothing-                                   (length arg_shapes) sigma_ty+           <- matchActualFunTys herald orig (length arg_shapes) sigma_ty               -- match_wrapper :: sigma_ty "->" (arg_tys -> res_ty)        ; ((result, res_wrapper), arg_wrappers)            <- tc_syn_args_e (map scaledThing arg_tys) arg_shapes $ \ arg_results arg_res_mults ->@@ -915,19 +1051,19 @@  {- ********************************************************************* *                                                                      *-                 Desugaring record update+                 Expanding record update *                                                                      * ********************************************************************* -}  {- Note [Record Updates] ~~~~~~~~~~~~~~~~~~~~~~~~-To typecheck a record update, we desugar it first.  Suppose we have+To typecheck a record update, we expand it first.  Suppose we have     data T p q = T1 { x :: Int, y :: Bool, z :: Char }                | T2 { v :: Char }                | T3 { x :: Int }                | T4 { p :: Float, y :: Bool, x :: Int }                | T5-Then the record update `e { x=e1, y=e2 }` desugars as follows+Then the record update `e { x=e1, y=e2 }` expands as follows         e { x=e1, y=e2 }     ===>@@ -936,7 +1072,7 @@           T1 _ _ z -> T1 x' y' z           T4 p _ _ -> T4 p y' x' T2, T3 and T5 should not occur, so we omit them from the match.-The critical part of desugaring is to identify T and then T1/T4.+The critical part of expansion is to identify T and then T1/T4.  Wrinkle [Disambiguating fields] @@ -951,17 +1087,17 @@   https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0366-no-ambiguous-field-access.rst.  -All in all, this means that when typechecking a record update via desugaring,+All in all, this means that when typechecking a record update via expansion, we take the following steps:    (0) Perform a first typechecking pass on the record expression (`e` in the example above),       to infer the type of the record being updated.   (1) Disambiguate the record fields (potentially using the type obtained in (0)).-  (2) Desugar the record update as described above, using an HsExpansion.+  (2) Expand the record update as described above, using an XXExprGhcRn.       (a) Create a let-binding to share the record update right-hand sides.-      (b) Desugar the record update to a case expression updating all the+      (b) Expand the record update to a case expression updating all the           relevant constructors (those that have all of the fields being updated).-  (3) Typecheck the desugared code.+  (3) Typecheck the expanded code.  In (0), we call inferRho to infer the type of the record being updated. This returns the inferred type of the record, together with a typechecked expression (of type HsExpr GhcTc)@@ -984,7 +1120,7 @@     data R b = MkR { f :: (forall a. a -> a) -> (Int,b), c :: Int }     foo r = r { f = \ k -> (k 3, k 'x') } -  If we desugar to:+  If we expand to:      ds_foo r =       let f' = \ k -> (k 3, k 'x')@@ -1050,7 +1186,7 @@  Note [Unifying result types in tcRecordUpd] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-After desugaring and typechecking a record update in the way described in+After expanding and typechecking a record update in the way described in Note [Record Updates], we must take care to unify the result types.  Example:@@ -1061,7 +1197,7 @@   f :: F Int -> D Bool -> D Int   f i r = r { fld = i } -This record update desugars to:+This record update expands to:    let x :: F alpha -- metavariable       x = i@@ -1095,13 +1231,13 @@  -} --- | Desugars a record update @record_expr { fld1 = e1, fld2 = e2 }@ into a case expression+-- | Expands a record update @record_expr { fld1 = e1, fld2 = e2 }@ into a case expression -- that matches on the constructors of the record @r@, as described in -- Note [Record Updates]. -- -- Returns a renamed but not-yet-typechecked expression, together with the--- result type of this desugared record update.-desugarRecordUpd :: LHsExpr GhcRn+-- result type of this expanded record update.+expandRecordUpd :: LHsExpr GhcRn                       -- ^ @record_expr@: expression to which the record update is applied                  -> NE.NonEmpty (HsRecUpdParent GhcRn)                       -- ^ Possible parent 'TyCon'/'PatSyn's for the record update,@@ -1111,19 +1247,19 @@                  -> ExpRhoType                       -- ^ the expected result type of the record update                  -> TcM ( HsExpr GhcRn-                           -- desugared record update expression+                           -- Expanded record update expression                         , TcType-                           -- result type of desugared record update+                           -- result type of expanded record update                         , SDoc                            -- error context to push when typechecking-                           -- the desugared code+                           -- the expanded code                         )-desugarRecordUpd record_expr possible_parents rbnds res_ty+expandRecordUpd record_expr possible_parents rbnds res_ty   = do {  -- STEP 0: typecheck the record_expr, the record to be updated.           --           -- Until GHC proposal #366 is implemented, we still use the type of           -- the record to disambiguate its fields, so we must infer the record-          -- type here before we can desugar. See Wrinkle [Disambiguating fields]+          -- type here before we can expand. See Wrinkle [Disambiguating fields]           -- in Note [Record Updates].        ; ((_, record_rho), _lie) <- captureConstraints    $ -- see (1) below                                     tcScalingUsage ManyTy $ -- see (2) below@@ -1133,7 +1269,7 @@             -- Note that we capture, and then discard, the constraints.             -- This `tcInferRho` is used *only* to identify the data type,             -- so we can deal with field disambiguation.-            -- Then we are going to generate a desugared record update, including `record_expr`,+            -- Then we are going to generate a expanded record update, including `record_expr`,             -- and typecheck it from scratch.  We don't want to generate the constraints twice!              -- (2)@@ -1163,7 +1299,7 @@              relevant_cons = nonDetEltsUniqSet cons              relevant_con = head relevant_cons -      -- STEP 2: desugar the record update.+      -- STEP 2: expand the record update.       --       --  (a) Create new variables for the fields we are updating,       --      so that we can share them across constructors.@@ -1238,7 +1374,7 @@              updEnv = listToUniqMap $ upd_ids               make_pat :: ConLike -> LMatch GhcRn (LHsExpr GhcRn)-             -- As explained in Note [Record Updates], to desugar+             -- As explained in Note [Record Updates], to expand              --              --   e { x=e1, y=e2 }              --@@ -1251,7 +1387,7 @@              -- we let-bind x' = e1, y' = e2 and generate the equation:              --              --   T1 _ _ z -> T1 x' y' z-             make_pat conLike = mkSimpleMatch CaseAlt [pat] rhs+             make_pat conLike = mkSimpleMatch RecUpd [pat] rhs                where                  (lhs_con_pats, rhs_con_args)                     = zipWithAndUnzip mk_con_arg [1..] con_fields@@ -1267,7 +1403,7 @@                            , LHsExpr GhcRn )                               -- RHS constructor argument              mk_con_arg i fld_lbl =-               -- The following generates the pattern matches of the desugared `case` expression.+               -- The following generates the pattern matches of the expanded `case` expression.                -- For fields being updated (for example `x`, `y` in T1 and T4 in Note [Record Updates]),                -- wildcards are used to avoid creating unused variables.                case lookupUniqMap updEnv $ flSelector fld_lbl of@@ -1279,13 +1415,13 @@                                       generatedSrcSpan                        in (genVarPat fld_nm, genLHsVar fld_nm) -       -- STEP 2 (b): desugar to HsCase, as per note [Record Updates]+       -- STEP 2 (b): expand to HsCase, as per note [Record Updates]        ; let ds_expr :: HsExpr GhcRn-             ds_expr = HsLet noExtField noHsTok let_binds noHsTok (L gen case_expr)+             ds_expr = HsLet noExtField let_binds (L gen case_expr)               case_expr :: HsExpr GhcRn              case_expr = HsCase RecUpd record_expr-                       $ mkMatchGroup (Generated DoPmc) (wrapGenSpan matches)+                       $ mkMatchGroup (Generated OtherExpansion DoPmc) (wrapGenSpan matches)              matches :: [LMatch GhcRn (LHsExpr GhcRn)]              matches = map make_pat relevant_cons @@ -1302,7 +1438,7 @@                -- See Wrinkle [Using IdSig] in Note [Record Updates].              gen = noAnnSrcSpan generatedSrcSpan -        ; traceTc "desugarRecordUpd" $+        ; traceTc "expandRecordUpd" $             vcat [ text "relevant_con:" <+> ppr relevant_con                  , text "res_ty:" <+> ppr res_ty                  , text "ds_res_ty:" <+> ppr ds_res_ty@@ -1538,7 +1674,7 @@                 -- Yuk: the field_id has the *unique* of the selector Id                 --          (so we can find it easily)                 --      but is a LocalId with the appropriate type of the RHS-                --          (so the desugarer knows the type of local binder to make)+                --          (so the expansion knows the type of local binder to make)            ; return (Just (L loc (FieldOcc field_id lbl), rhs')) }       | otherwise       = do { addErrTc (badFieldConErr (getName con_like) field_lbl)
compiler/GHC/Tc/Gen/Expr.hs-boot view
@@ -5,6 +5,7 @@                            , SyntaxOpType                            , ExpType, ExpRhoType, ExpSigmaType ) import GHC.Tc.Types        ( TcM )+import GHC.Tc.Types.BasicTypes( TcCompleteSig ) import GHC.Tc.Types.Origin ( CtOrigin ) import GHC.Core.Type ( Mult ) import GHC.Hs.Extension ( GhcRn, GhcTc )@@ -23,6 +24,9 @@        -> TcRhoType        -> TcM (LHsExpr GhcTc) +tcPolyLExpr    :: LHsExpr GhcRn -> ExpSigmaType -> TcM (LHsExpr GhcTc)+tcPolyLExprSig :: LHsExpr GhcRn -> TcCompleteSig -> TcM (LHsExpr GhcTc)+ tcPolyExpr :: HsExpr GhcRn -> ExpSigmaType -> TcM (HsExpr GhcTc) tcExpr     :: HsExpr GhcRn -> ExpRhoType   -> TcM (HsExpr GhcTc) @@ -42,4 +46,3 @@               -> SyntaxOpType               -> ([TcSigmaTypeFRR] -> [Mult] -> TcM a)               -> TcM (a, SyntaxExprTc)-
compiler/GHC/Tc/Gen/Foreign.hs view
@@ -84,7 +84,6 @@ import Control.Monad.Trans.Class   ( lift ) import Data.Maybe (isJust)-import GHC.Types.RepType (tyConPrimRep) import GHC.Builtin.Types (unitTyCon)  -- Defines a binding@@ -356,7 +355,7 @@       dflags <- getDynFlags       checkForeignArgs (isFFIArgumentTy dflags safety) arg_tys       checkForeignRes nonIOok checkSafe (isFFIImportResultTy dflags) res_ty-      checkMissingAmpersand idecl (map scaledThing arg_tys) res_ty+      checkMissingAmpersand idecl target (map scaledThing arg_tys) res_ty       case target of           StaticTarget _ _ _ False            | not (null arg_tys) ->@@ -373,8 +372,10 @@  checkCTarget _ DynamicTarget = panic "checkCTarget DynamicTarget" -checkMissingAmpersand :: ForeignImport GhcRn -> [Type] -> Type -> TcM ()-checkMissingAmpersand idecl arg_tys res_ty+checkMissingAmpersand :: ForeignImport GhcRn -> CCallTarget -> [Type] -> Type -> TcM ()+checkMissingAmpersand _ (StaticTarget _ _ _ False) _ _ = return ()++checkMissingAmpersand idecl _ arg_tys res_ty   | null arg_tys && isFunPtrTy res_ty   = addDiagnosticTc $ TcRnFunPtrImportWithoutAmpersand idecl   | otherwise@@ -553,7 +554,7 @@   return PrimCallConv checkCConv decl JavaScriptCallConv = do   dflags <- getDynFlags-  if platformArch (targetPlatform dflags) == ArchJavaScript+  if platformArch (targetPlatform dflags) `elem` [ ArchJavaScript, ArchWasm32 ]       then return JavaScriptCallConv       else do         addErrTc $ TcRnUnsupportedCallConv decl JavaScriptCallConvUnsupported@@ -735,7 +736,6 @@ marshalableTyCon :: DynFlags -> TyCon -> Validity' TypeCannotBeMarshaledReason marshalableTyCon dflags tc   | marshalablePrimTyCon tc-  , not (null (tyConPrimRep tc)) -- Note [Marshalling void]   = validIfUnliftedFFITypes dflags   | otherwise   = boxedMarshalableTyCon tc@@ -751,6 +751,7 @@                     , charTyConKey                     , stablePtrTyConKey                     , boolTyConKey+                    , jsvalTyConKey                     ]   = IsValid @@ -769,7 +770,6 @@ -- types and also unboxed tuple and sum result types. legalFIPrimResultTyCon dflags tc   | marshalablePrimTyCon tc-  , not (null (tyConPrimRep tc))   -- Note [Marshalling void]   = validIfUnliftedFFITypes dflags    | isUnboxedTupleTyCon tc || isUnboxedSumTyCon tc@@ -783,13 +783,3 @@   | xopt LangExt.UnliftedFFITypes dflags =  IsValid   | otherwise = NotValid UnliftedFFITypesNeeded -{--Note [Marshalling void]-~~~~~~~~~~~~~~~~~~~~~~~-We don't treat State# (whose PrimRep is VoidRep) as marshalable.-In turn that means you can't write-        foreign import foo :: Int -> State# RealWorld--Reason: the back end falls over with panic "primRepHint:VoidRep";-        and there is no compelling reason to permit it--}
compiler/GHC/Tc/Gen/Head.hs view
@@ -20,18 +20,17 @@        , AppCtxt(..), appCtxtLoc, insideExpansion        , splitHsApps, rebuildHsApps        , addArgWrap, isHsValArg-       , countLeadingValArgs, isVisibleArg, pprHsExprArgTc-       , countVisAndInvisValArgs, countHsWrapperInvisArgs+       , leadingValArgs, isVisibleArg, pprHsExprArgTc         , tcInferAppHead, tcInferAppHead_maybe-       , tcInferId, tcCheckId-       , obviousSig+       , tcInferId, tcCheckId, obviousSig        , tyConOf, tyConOfET, fieldNotInType        , nonBidirectionalErr -       , addHeadCtxt, addExprCtxt, addFunResCtxt ) where+       , addHeadCtxt, addExprCtxt, addStmtCtxt, addFunResCtxt ) where -import {-# SOURCE #-} GHC.Tc.Gen.Expr( tcExpr, tcCheckMonoExprNC, tcCheckPolyExprNC )+import {-# SOURCE #-} GHC.Tc.Gen.Expr( tcExpr, tcCheckPolyExprNC, tcPolyLExprSig )+import {-# SOURCE #-} GHC.Tc.Gen.Splice( getUntypedSpliceBody )  import GHC.Prelude import GHC.Hs@@ -41,7 +40,7 @@ import GHC.Rename.Unbound     ( unknownNameSuggestions, WhatLooking(..) )  import GHC.Tc.Gen.Bind( chooseInferredQuantifiers )-import GHC.Tc.Gen.Sig( tcUserTypeSig, tcInstSig, lhsSigWcTypeContextSpan )+import GHC.Tc.Gen.Sig( tcUserTypeSig, tcInstSig ) import GHC.Tc.TyCl.PatSyn( patSynBuilderOcc ) import GHC.Tc.Utils.Monad import GHC.Tc.Utils.Unify@@ -67,7 +66,6 @@ import GHC.Core.TyCo.Rep import GHC.Core.Type -import GHC.Types.Var( isInvisibleFunArg ) import GHC.Types.Id import GHC.Types.Id.Info import GHC.Types.Name@@ -85,7 +83,7 @@ import GHC.Utils.Misc import GHC.Utils.Outputable as Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain+import qualified GHC.LanguageExtensions as LangExt  import GHC.Data.Maybe import Control.Monad@@ -158,7 +156,7 @@ * The "user head" or "error head" of the application, to be reported to the   user in case of an error.  Example:          (`op` e)-  expands (via HsExpanded) to+  expands (via ExpandedThingRn) to          (rightSection op e)   but we don't want to see 'rightSection' in error messages. So we keep the   innermost un-expanded head as the "error head".@@ -177,7 +175,6 @@              , eva_arg_ty :: !(XEVAType p) }    | ETypeArg { eva_ctxt  :: AppCtxt-             , eva_at    :: !(LHsToken "@" GhcRn)              , eva_hs_ty :: LHsWcType GhcRn  -- The type arg              , eva_ty    :: !(XETAType p) }  -- Kind-checked type arg @@ -187,7 +184,7 @@   | EWrap    EWrap  data EWrap = EPar    AppCtxt-           | EExpand (HsExpr GhcRn)+           | EExpand HsThingRn            | EHsWrap HsWrapper  data EValArg (p :: TcPass) where  -- See Note [EValArg]@@ -204,9 +201,9 @@  data AppCtxt   = VAExpansion-       (HsExpr GhcRn)    -- Inside an expansion of this expression-       SrcSpan           -- The SrcSpan of the expression-                         --    noSrcSpan if outermost; see Note [AppCtxt]+       HsThingRn+       SrcSpan+       SrcSpan    | VACall        (HsExpr GhcRn) Int  -- In the third argument of function f@@ -241,16 +238,16 @@ -}  appCtxtLoc :: AppCtxt -> SrcSpan-appCtxtLoc (VAExpansion _ l) = l+appCtxtLoc (VAExpansion _ l _) = l appCtxtLoc (VACall _ _ l)    = l  insideExpansion :: AppCtxt -> Bool insideExpansion (VAExpansion {}) = True-insideExpansion (VACall {})      = False+insideExpansion (VACall {})      = False -- but what if the VACall has a generated context?  instance Outputable AppCtxt where-  ppr (VAExpansion e _) = text "VAExpansion" <+> ppr e-  ppr (VACall f n _)    = text "VACall" <+> int n <+> ppr f+  ppr (VAExpansion e l _) = text "VAExpansion" <+> ppr e <+> ppr l+  ppr (VACall f n l)    = text "VACall" <+> int n <+> ppr f  <+> ppr l  type family XPass p where   XPass 'TcpRn   = 'Renamed@@ -269,75 +266,108 @@ mkEValArg ctxt e = EValArg { eva_arg = ValArg e, eva_ctxt = ctxt                            , eva_arg_ty = noExtField } -mkETypeArg :: AppCtxt -> LHsToken "@" GhcRn -> LHsWcType GhcRn -> HsExprArg 'TcpRn-mkETypeArg ctxt at hs_ty =+mkETypeArg :: AppCtxt -> LHsWcType GhcRn -> HsExprArg 'TcpRn+mkETypeArg ctxt hs_ty =   ETypeArg { eva_ctxt = ctxt-           , eva_at = at, eva_hs_ty = hs_ty+           , eva_hs_ty = hs_ty            , eva_ty = noExtField } -addArgWrap :: HsWrapper -> [HsExprArg 'TcpInst] -> [HsExprArg 'TcpInst]+addArgWrap :: HsWrapper -> [HsExprArg p] -> [HsExprArg p] addArgWrap wrap args  | isIdHsWrapper wrap = args  | otherwise          = EWrap (EHsWrap wrap) : args  splitHsApps :: HsExpr GhcRn-            -> ( (HsExpr GhcRn, AppCtxt)  -- Head-               , [HsExprArg 'TcpRn])      -- Args--- See Note [splitHsApps]+            -> TcM ( (HsExpr GhcRn, AppCtxt)  -- Head+                   , [HsExprArg 'TcpRn])      -- Args+-- See Note [splitHsApps].+--+-- This uses the TcM monad solely because we must run modFinalizers when looking+-- through HsUntypedSplices+-- (see Note [Looking through Template Haskell splices in splitHsApps]). splitHsApps e = go e (top_ctxt 0 e) []   where     top_ctxt :: Int -> HsExpr GhcRn -> AppCtxt     -- Always returns VACall fun n_val_args noSrcSpan     -- to initialise the argument splitting in 'go'     -- See Note [AppCtxt]-    top_ctxt n (HsPar _ _ fun _)           = top_lctxt n fun+    top_ctxt n (HsPar _ fun)               = top_lctxt n fun     top_ctxt n (HsPragE _ _ fun)           = top_lctxt n fun-    top_ctxt n (HsAppType _ fun _ _)         = top_lctxt (n+1) fun+    top_ctxt n (HsAppType _ fun _)         = top_lctxt (n+1) fun     top_ctxt n (HsApp _ fun _)             = top_lctxt (n+1) fun-    top_ctxt n (XExpr (HsExpanded orig _)) = VACall orig      n noSrcSpan+    top_ctxt n (XExpr (ExpandedThingRn o _))+      | OrigExpr fun <- o                  = VACall fun  n noSrcSpan     top_ctxt n other_fun                   = VACall other_fun n noSrcSpan      top_lctxt n (L _ fun) = top_ctxt n fun      go :: HsExpr GhcRn -> AppCtxt -> [HsExprArg 'TcpRn]-       -> ((HsExpr GhcRn, AppCtxt), [HsExprArg 'TcpRn])+       -> TcM ((HsExpr GhcRn, AppCtxt), [HsExprArg 'TcpRn])     -- Modify the AppCtxt as we walk inwards, so it describes the next argument-    go (HsPar _ _ (L l fun) _)       ctxt args = go fun (set l ctxt) (EWrap (EPar ctxt)     : args)+    go (HsPar _ (L l fun))           ctxt args = go fun (set l ctxt) (EWrap (EPar ctxt)     : args)     go (HsPragE _ p (L l fun))       ctxt args = go fun (set l ctxt) (EPrag      ctxt p     : args)-    go (HsAppType _ (L l fun) at ty) ctxt args = go fun (dec l ctxt) (mkETypeArg ctxt at ty : args)+    go (HsAppType _ (L l fun) ty)    ctxt args = go fun (dec l ctxt) (mkETypeArg ctxt ty    : args)     go (HsApp _ (L l fun) arg)       ctxt args = go fun (dec l ctxt) (mkEValArg  ctxt arg   : args) -    -- See Note [Looking through HsExpanded]-    go (XExpr (HsExpanded orig fun)) ctxt args-      = go fun (VAExpansion orig (appCtxtLoc ctxt))-               (EWrap (EExpand orig) : args)+    -- See Note [Looking through Template Haskell splices in splitHsApps]+    go e@(HsUntypedSplice splice_res splice) ctxt args+      = do { fun <- getUntypedSpliceBody splice_res+           ; go fun ctxt' (EWrap (EExpand (OrigExpr e)) : args) }+      where+        ctxt' :: AppCtxt+        ctxt' = case splice of+            HsUntypedSpliceExpr _ (L l _) -> set l ctxt -- l :: SrcAnn AnnListItem+            HsQuasiQuote _ _ (L l _)      -> set l ctxt -- l :: SrcAnn NoEpAnns +    -- See Note [Looking through ExpandedThingRn]+    go (XExpr (ExpandedThingRn o e)) ctxt args+      | isHsThingRnExpr o+      = go e (VAExpansion o (appCtxtLoc ctxt) (appCtxtLoc ctxt))+               (EWrap (EExpand o) : args)++      | OrigStmt (L _ stmt) <- o                -- so that we set `(>>)` as generated+      , BodyStmt{} <- stmt                      -- and get the right unused bind warnings+      = go e (VAExpansion o generatedSrcSpan generatedSrcSpan)+                                                -- See Part 3. in Note [Expanding HsDo with XXExprGhcRn]+               (EWrap (EExpand o) : args)       -- in `GHC.Tc.Gen.Do`+++      | OrigPat (L loc _) <- o                              -- so that we set the compiler generated fail context+      = go e (VAExpansion o (locA loc) (locA loc))          -- to be originating from a failable pattern+                                                            -- See Part 1. Wrinkle 2. of+               (EWrap (EExpand o) : args)                   -- Note [Expanding HsDo with XXExprGhcRn]+                                                            -- in `GHC.Tc.Gen.Do`++      | otherwise+      = go e (VAExpansion o (appCtxtLoc ctxt) (appCtxtLoc ctxt))+               (EWrap (EExpand o) : args)+     -- See Note [Desugar OpApp in the typechecker]     go e@(OpApp _ arg1 (L l op) arg2) _ args-      = ( (op, VACall op 0 (locA l))-        ,   mkEValArg (VACall op 1 generatedSrcSpan) arg1-          : mkEValArg (VACall op 2 generatedSrcSpan) arg2-          : EWrap (EExpand e)-          : args )+      = pure ( (op, VACall op 0 (locA l))+             ,   mkEValArg (VACall op 1 generatedSrcSpan) arg1+               : mkEValArg (VACall op 2 generatedSrcSpan) arg2+               : EWrap (EExpand (OrigExpr e))+               : args ) -    go e ctxt args = ((e,ctxt), args)+    go e ctxt args = pure ((e,ctxt), args) -    set :: SrcSpanAnnA -> AppCtxt -> AppCtxt-    set l (VACall f n _)        = VACall f n (locA l)-    set _ ctxt@(VAExpansion {}) = ctxt+    set :: EpAnn ann -> AppCtxt -> AppCtxt+    set l (VACall f n _)          = VACall f n (locA l)+    set l (VAExpansion orig ol _) = VAExpansion orig ol (locA l) -    dec :: SrcSpanAnnA -> AppCtxt -> AppCtxt-    dec l (VACall f n _)        = VACall f (n-1) (locA l)-    dec _ ctxt@(VAExpansion {}) = ctxt+    dec :: EpAnn ann -> AppCtxt -> AppCtxt+    dec l (VACall f n _)          = VACall f (n-1) (locA l)+    dec l (VAExpansion orig ol _) = VAExpansion orig ol (locA l)  -- | Rebuild an application: takes a type-checked application head -- expression together with arguments in the form of typechecked 'HsExprArg's -- and returns a typechecked application of the head to the arguments. ----- This performs a representation-polymorphism check to ensure that the--- remaining value arguments in an application have a fixed RuntimeRep.+-- This performs a representation-polymorphism check to ensure that+-- representation-polymorphic unlifted newtypes have been eta-expanded. ----- See Note [Checking for representation-polymorphic built-ins].+-- See Note [Eta-expanding rep-poly unlifted newtypes]. rebuildHsApps :: HsExpr GhcTc                       -- ^ the function being applied               -> AppCtxt@@ -347,7 +377,7 @@                       -- ^ result type of the application               -> TcM (HsExpr GhcTc) rebuildHsApps fun ctxt args app_res_rho-  = do { tcRemainingValArgs args app_res_rho fun+  = do { rejectRepPolyNewtypes args app_res_rho fun        ; return $ rebuild_hs_apps fun ctxt args }  -- | The worker function for 'rebuildHsApps': simply rebuilds@@ -363,43 +393,50 @@ rebuild_hs_apps fun ctxt (arg : args)   = case arg of       EValArg { eva_arg = ValArg arg, eva_ctxt = ctxt' }-        -> rebuild_hs_apps (HsApp noAnn lfun arg) ctxt' args-      ETypeArg { eva_hs_ty = hs_ty, eva_at = at, eva_ty = ty, eva_ctxt = ctxt' }-        -> rebuild_hs_apps (HsAppType ty lfun at hs_ty) ctxt' args+        -> rebuild_hs_apps (HsApp noExtField lfun arg) ctxt' args+      ETypeArg { eva_hs_ty = hs_ty, eva_ty = ty, eva_ctxt = ctxt' }+        -> rebuild_hs_apps (HsAppType ty lfun hs_ty) ctxt' args       EPrag ctxt' p         -> rebuild_hs_apps (HsPragE noExtField p lfun) ctxt' args       EWrap (EPar ctxt')         -> rebuild_hs_apps (gHsPar lfun) ctxt' args       EWrap (EExpand orig)-        -> rebuild_hs_apps (XExpr (ExpansionExpr (HsExpanded orig fun))) ctxt args+        | OrigExpr oe <- orig+        -> rebuild_hs_apps (mkExpandedExprTc oe fun) ctxt args+        | otherwise+        -> rebuild_hs_apps fun ctxt args       EWrap (EHsWrap wrap)         -> rebuild_hs_apps (mkHsWrap wrap fun) ctxt args   where-    lfun = L (noAnnSrcSpan $ appCtxtLoc ctxt) fun+    lfun = L (noAnnSrcSpan $ appCtxtLoc' ctxt) fun+    appCtxtLoc' (VAExpansion _ _ l) = l+    appCtxtLoc' v = appCtxtLoc v -{- Note [Checking for representation-polymorphic built-ins]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+{- Note [Representation-polymorphic Ids with no binding]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We cannot have representation-polymorphic or levity-polymorphic function arguments. See Note [Representation polymorphism invariants]-in GHC.Core.  That is checked by the calls to `hasFixedRuntimeRep` in-`tcEValArg`.+in GHC.Core.  That is checked in 'GHC.Tc.Gen.App.tcInstFun', see the call+to 'matchActualFunTy', which performs the representation-polymorphism+check. -But some /built-in/ functions have representation-polymorphic argument-types. Users can't define such Ids; they are all GHC built-ins or data-constructors.  Specifically they are:+However, some special Ids have representation-polymorphic argument+types. These are all GHC built-ins or data constructors. They have no binding;+instead they have compulsory unfoldings. Specifically, these Ids are: -1. A few wired-in Ids such as coerce and unsafeCoerce#,-2. Primops, such as raise#.-3. Newtype constructors with `UnliftedNewtypes` which have-   a representation-polymorphic argument.-4. Representation-polymorphic data constructors: unboxed tuples+1. Some wired-in Ids, such as coerce, oneShot and unsafeCoerce# (which is only+   partly wired-in),+2. Representation-polymorphic primops, such as raise#.+3. Representation-polymorphic data constructors: unboxed tuples    and unboxed sums.+4. Newtype constructors with `UnliftedNewtypes` which have+   a representation-polymorphic argument.  For (1) consider   badId :: forall r (a :: TYPE r). a -> a   badId = unsafeCoerce# @r @r @a @a -The wired-in function+The (partly) wired-in function   unsafeCoerce# :: forall (r1 :: RuntimeRep) (r2 :: RuntimeRep)                    (a :: TYPE r1) (b :: TYPE r2).                    a -> b@@ -419,13 +456,16 @@  Test cases: T14561, RepPolyWrappedVar2. -For primops (2) the situation is similar; they are eta-expanded in-CorePrep to be saturated, and that eta-expansion must not add a-representation-polymorphic lambda.+For primops (2) and unboxed tuples/sums (3), the situation is similar;+they are eta-expanded in CorePrep to be saturated, and that eta-expansion+must not add a representation-polymorphic lambda.  Test cases: T14561b, RepPolyWrappedVar, UnliftedNewtypesCoerceFail. -For (3), consider a representation-polymorphic newtype with+The Note [Representation-polymorphism checking built-ins] explains how we handle+cases (1) (2) and (3).++For (4), consider a representation-polymorphic newtype with UnliftedNewtypes:    type Id :: forall r. TYPE r -> TYPE r@@ -439,217 +479,269 @@  Test cases: T18481, UnliftedNewtypesLevityBinder -So these cases need special treatment. We add a special case-in tcApp to check whether an application of an Id has any remaining-representation-polymorphic arguments, after instantiation and application-of previous arguments.  This is achieved by the tcRemainingValArgs-function, which computes the types of the remaining value arguments, and checks-that each of these have a fixed runtime representation.+(4) is handled differently than (1) (2) and (3);+see Note [Eta-expanding rep-poly unlifted newtypes]. -Note that this function also ensures that data constructors always-appear saturated, by performing eta-expansion if necessary.-See Note [Typechecking data constructors].+Note [Representation-polymorphism checking built-ins]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Some primops and wired-in functions are representation-polymorphic, but must+only be instantiated at particular, concrete representations.+There are three cases, all for `hasNoBinding` Ids: -Wrinkle [Arity]+* Wired-in Ids.  For example, `seq`+  is a wired-in Id, defined in GHC.Types.Id.Make.seqId, with this type: -  We don't want to check for arguments past the arity of the function.+  seq :: forall {r} a (b :: TYPE r). a -> b -> b -  For example+  It is more like a macro than a regular Id: it has /compulsory/ unfolding, so+  we inline it at every call site.  At those call sites we should instantiate+  `r` with a concrete RuntimeRep, so that the lambda has a concrete representation.+  So somehow the type checker has to ensure that `seq` is called with a concrete+  instantiation for `r`. -      raise# :: forall {r :: RuntimeRep} (a :: Type) (b :: TYPE r). a -> b+  NB: unsafeCoerce# is not quite wired-in (see Note [Wiring in unsafeCoerce#] in GHC.HsToCore),+  but it gets a similar treatment. -  has arity 1, so an instantiation such as:+* PrimOps. Some representation-polymorphic primops must be called at a concrete+  type.  For example: -      foo :: forall w r (z :: TYPE r). w -> z -> z-      foo = raise# @w @(z -> z)+  catch# :: forall {r} {l} (k :: TYPE r) (w :: TYPE (BoxedRep l)).+              (State# RealWorld -> (# State# RealWorld, k #) )+           -> (w -> State# RealWorld -> (# State# RealWorld, k #) )+           -> State# RealWorld -> (# State# RealWorld, k #) -  is unproblematic.  This means we must take care not to perform a-  representation-polymorphism check on `z`.+  This primop pushes a "catch frame" on the stack, which must "know"+  the return convention of `k`.  So `k` must be concrete, so we know+  what kind of catch-frame to push. (See #21868 for more details. -  To achieve this, we consult the arity of the 'Id' which is the head-  of the application (or just use 1 for a newtype constructor),-  and keep track of how many value-level arguments we have seen,-  to ensure we stop checking once we reach the arity.-  This is slightly complicated by the need to include both visible-  and invisible arguments, as the arity counts both:-  see GHC.Tc.Gen.Head.countVisAndInvisValArgs.+  So again we want to ensure that `r` is instantiated with a concrete RuntimeRep. -  Test cases: T20330{a,b}+* Unboxed-tuple data constructors.  Consider the unboxed pair data constructor: -Wrinkle [Syntactic check]+  (#,#) :: forall {r1} {r2} (a :: TYPE r1) (b :: TYPE r2). a -> b -> (# a, b #) -  We only perform a syntactic check in tcRemainingValArgs. That is,-  we will reject partial applications such as:+  Again, we need concrete `r1` and `r2`. For example, we want to reject -    type RR :: RuntimeREp-    type family RR where { RR = IntRep }-    type T :: TYPE RR-    type family T where { T = Int# }+    f :: forall r (a :: TYPE r). a -> (# Int, a #)+    f = (#,#) 3 -    (# , #) @LiftedRep @RR e1+As pointed out in #21906; we see here that it is not enough to simply check+the representation of the argument types, as for example "k :: TYPE r" in the+type of catch# occurs in negative position but not directly as the type of+an argument. -  Why do we reject? Wee would need to elaborate this partial application-  of (# , #) as follows:+NB: we specifically *DO NOT* handle representation-polymorphic unlifted newtypes+with this mechanism. See Note [Eta-expanding rep-poly unlifted newtypes] for an+overview of representation-polymorphism checks for those. -    let x1 = e1-    in-      ( \ @(ty2 :: TYPE RR) (x2 :: ty2 |> TYPE RR[0])-      -> ( ( (# , #) @LiftedRep @RR @Char @ty2 x1 ) |> co1 )-           x2-      ) |> co2+To achieve this goal, for these these three kinds of `hasNoBinding` functions: -  That is, we need to cast the partial application+* We identify the quantified variable `r` as a "concrete quantifier" -    (# , #) @LiftedRep @RR @Char @ty2 x1+* When instantiating a concrete quantifier, such as `r`, at a call site, we+  instantiate with a ConcreteTv meta-tyvar, `r0[conc]`.+  See Note [ConcreteTv] in GHC.Tc.Utils.Concrete. -  so that the next argument we provide to it has a fixed RuntimeRep,-  and then eta-expand it. This is quite tricky, and other parts-  of the compiler aren't set up to handle this mix of applications-  and casts (e.g. checkCanEtaExpand in GHC.Core.Lint).+Now the type checker will ensure that `r0` is instantiated with a concrete+RuntimeRep. -  So we refrain from doing so, and instead limit ourselves to a simple syntactic-  check. See the wiki page https://gitlab.haskell.org/ghc/ghc/-/wikis/Remaining-ValArgs-  for a more in-depth discussion.--}+Here are the moving parts: --- | Typecheck the remaining value arguments in a partial application,--- ensuring they have a fixed RuntimeRep in the sense of Note [Fixed RuntimeRep]--- in GHC.Tc.Utils.Concrete.------ Example:------ > repPolyId :: forall r (a :: TYPE r). a -> a--- > repPolyId = coerce------ This is an invalid instantiation of 'coerce', as we can't eta expand it--- to------ > \@r \@(a :: TYPE r) (x :: a) -> coerce @r @a @a x------ because the binder `x` does not have a fixed runtime representation.-tcRemainingValArgs :: HasDebugCallStack-                   => [HsExprArg 'TcpTc]-                   -> TcRhoType-                   -> HsExpr GhcTc-                   -> TcM ()-tcRemainingValArgs applied_args app_res_rho fun = case fun of+* In the IdDetails of an Id, we record a mapping from type variable name+  to concreteness information, in the form of a ConcreteTvOrigin.+  See 'idDetailsConcreteTvs'. -  HsVar _ (L _ fun_id)+  The ConcreteTvOrigin is used to determine which error message to show+  to the user if the type variable gets instantiated to a non-concrete type;+  this is slightly more granular than simply storing a set of type variable names. -    -- (1): unsafeCoerce#-    -- 'unsafeCoerce#' is peculiar: it is patched in manually as per-    -- Note [Wiring in unsafeCoerce#] in GHC.HsToCore.-    -- Unfortunately, even though its arity is set to 1 in GHC.HsToCore.mkUnsafeCoercePrimPair,-    -- at this stage, if we query idArity, we get 0. This is because-    -- we end up looking at the non-patched version of unsafeCoerce#-    -- defined in Unsafe.Coerce, and that one indeed has arity 0.-    ---    -- We thus manually specify the correct arity of 1 here.-    | idName fun_id == unsafeCoercePrimName-    -> tc_remaining_args 1 (RepPolyWiredIn fun_id)+* The domain of this NameEnv is the outer forall'd TyVars of that+  Id's type.  (A bit yukky because it means that alpha-renaming that type+  would be invalid.  But we never do that.)  So `seq` has+    Type:       forall {r} a (b :: TYPE r). a -> b -> b+    IdDetails:  RepPolyId [ r :-> ConcreteFRR (FixedRuntimeRepOrigin b (..)) ] -    -- (2): primops and other wired-in representation-polymorphic functions,-    -- such as 'rightSection', 'oneShot', etc; see bindings with Compulsory unfoldings-    -- in GHC.Types.Id.Make-    | isWiredInName (idName fun_id) && hasNoBinding fun_id-    -> tc_remaining_args (idArity fun_id) (RepPolyWiredIn fun_id)-       -- NB: idArity consults the IdInfo of the Id. This can be a problem-       -- in the presence of hs-boot files, as we might not have finished-       -- typechecking; inspecting the IdInfo at this point can cause-       -- strange Core Lint errors (see #20447).-       -- We avoid this entirely by only checking wired-in names,-       -- as those are the only ones this check is applicable to anyway.+* When instantiating the type of an Id at a call site, at the call to+  GHC.Tc.Utils.Instantiate.instantiateSigma in GHC.Tc.Gen.App.tcInstFun,+  create ConcreteTv metavariables (instead of TauTvs) based on the+  ConcreteTyVars stored in the IdDetails of the Id. -  XExpr (ConLikeTc (RealDataCon con) _ _)-    -- (3): Representation-polymorphic newtype constructors.-    | isNewDataCon con-    -- (4): Unboxed tuples and unboxed sums-    || isUnboxedTupleDataCon con-    || isUnboxedSumDataCon con-    -> tc_remaining_args (dc_val_arity con) (RepPolyDataCon con)+Note that the /only/ place that one of these restricted rep-poly Ids can enter+typechecking is in `tcInferId`, and all the interesting cases then land+in `tcInstFun` where we take care to instantantiate those concrete+type variables correctly. -  _ -> return ()+  Design alternative: in some ways, it would be more kosher for the concrete-ness+  to be stored in the /type/, thus  forall (r[conc] :: RuntimeRep). ty.+  But that pollutes Type for a very narrow use-case; so instead we adopt the+  more ad-hoc solution described above. -  where+Examples: -    dc_val_arity :: DataCon -> Arity-    dc_val_arity con = count (not . isEqPrimPred) (dataConTheta con)-                     + length (dataConStupidTheta con)-                     + dataConSourceArity con-      -- Count how many value-level arguments this data constructor expects:-      --    - dictionary arguments from the context (including the stupid context),-      --    - source value arguments.-      -- Tests: EtaExpandDataCon, EtaExpandStupid{1,2}.+  ok :: forall (a :: Type) (b :: Type). a -> b -> b+  ok = seq -    nb_applied_vis_val_args :: Int-    nb_applied_vis_val_args = count isHsValArg applied_args+  bad :: forall s (b :: TYPE s). Int -> b -> b+  bad x = seq x -    nb_applied_val_args :: Int-    nb_applied_val_args = countVisAndInvisValArgs applied_args+    Here we will instantiate the RuntimeRep skolem variable r from the type+    of seq to a concrete metavariable rr[conc].+    For 'ok' we will unify rr := LiftedRep, and for 'bad' we will fail to+    solve rr[conc] ~# s[sk] and report a representation-polymorphism error to+    the user. -    tc_remaining_args :: Arity -> RepPolyFun -> TcM ()-    tc_remaining_args arity rep_poly_fun =-      tc_rem_args-        (nb_applied_vis_val_args + 1)-        (nb_applied_val_args + 1)-        rem_arg_tys+  type RR :: RuntimeRep+  type family RR where { RR = IntRep } -      where+  tricky1, tricky2 :: forall (b :: TYPE RR). Int -> b -> b+  tricky1 = seq+  tricky2 = seq @RR -      rem_arg_tys :: [(Scaled Type, FunTyFlag)]-      rem_arg_tys = getRuntimeArgTys app_res_rho-        -- We do not need to zonk app_res_rho first, because the number of arrows-        -- in the (possibly instantiated) inferred type of the function will-        -- be at least the arity of the function.+    'tricky1' proceeds as above: we instantiate r |-> rr[conc], get a Wanted+    rr[conc] ~# RR, which we solve by rewriting the type family. -      -- The following function is essentially "mapM hasFixedRuntimeRep rem_arg_tys",-      -- but we need to keep track of indices for error messages, hence the manual recursion.-      tc_rem_args :: Int-                     -- visible value argument index, starting from 1-                     -- (only used to report the argument position in error messages)-                  -> Int-                     -- value argument index, starting from 1-                     -- used to count up to the arity to ensure that-                     -- we don't check too many argument types-                  -> [(Scaled Type, FunTyFlag)]-                     -- run-time argument types-                  -> TcM ()-      tc_rem_args _ i_val _-        | i_val > arity-        = return ()-      tc_rem_args _ _ []-        -- Should never happen: it would mean that the arity is higher-        -- than the number of arguments apparent from the type.-        = pprPanic "tcRemainingValArgs" debug_msg-      tc_rem_args i_visval !i_val ((Scaled _ arg_ty, af) : tys)-        = do { let (i_visval', arg_pos)-                     | isInvisibleFunArg af = ( i_visval    , ArgPosInvis )-                     | otherwise            = ( i_visval + 1, ArgPosVis i_visval )-                   frr_ctxt = FRRNoBindingResArg rep_poly_fun arg_pos-             ; hasFixedRuntimeRep_syntactic frr_ctxt arg_ty-                 -- Why is this a syntactic check? See Wrinkle [Syntactic check] in-                 -- Note [Checking for representation-polymorphic built-ins].-             ; tc_rem_args i_visval' (i_val + 1) tys }+    For 'tricky2', we again create a fresh ConcreteTv metavariable rr[conc],+    and we then proceed as if the user had written "seq @rr", but adding an+    additional [W] rr ~ RR to the constraint solving context. -      debug_msg :: SDoc-      debug_msg =-        vcat-          [ text "app_head =" <+> ppr fun-          , text "arity =" <+> ppr arity-          , text "applied_args =" <+> ppr applied_args-          , text "nb_applied_val_args =" <+> ppr nb_applied_val_args ]+[Wrinkle: VTA] +  We must also handle the case when the user has instantiated the type variables+  themselves, with a visible type application. We do this in GHC.Tc.Gen.App.tcVTA. +  For example:++    type F :: Type -> RuntimeRep+    type family F a where { F Bool = IntRep }++    foo = (# , #) @(F Bool) @FloatRep++  We want to accept "foo" even though "F Bool" is not a concrete RuntimeRep.+  We proceed as follows (see tcVTA):++    - create a fresh concrete metavariable kappa,+    - emit [W] F Bool ~ kappa[conc]+    - pretend the user wrote (#,#) @kappa.++  The solver will then unify kappa := IntRep, after rewriting the type family+  application on the LHS of the Wanted.++  Note that this is a bit of a corner case: only a few built-ins, such as+  unsafeCoerce# and unboxed tuples, have specified (not inferred) RuntimeRep+  quantified variables which can be instantiated by the user with a+  visible type application.+  For example,++    coerce :: forall {r :: RuntimeRep} (a :: TYPE r) (b :: TYPE r)+           .  Coercible a b => a -> b++  does not allow the RuntimeRep argument to be specified by a visible type+  application.++Note [Eta-expanding rep-poly unlifted newtypes]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Any occurrence of a newtype constructor must appear at a known representation.+If the newtype is applied to an argument, then we are done: by (I2) in+Note [Representation polymorphism invariants], the argument has a known+representation, and we are done. So we are left with the situation of an+unapplied newtype constructor. For example:++  type N :: TYPE r -> TYPE r+  newtype N a = MkN a++  ok :: N Int# -> N Int#+  ok = MkN++  bad :: forall r (a :: TYPE r). N (# Int, r #) -> N (# Int, r #)+  bad = MkN++The difficulty is that, unlike the situation described in+Note [Representation-polymorphism checking built-ins],+it is not necessarily the case that we simply need to check the instantiation+of a single variable. Consider for example:++  type RR :: Type -> Type -> RuntimeRep+  type family RR a b where ...++  type T :: forall a -> forall b -> TYPE (RR a b)+  type family T a b where ...++  type M :: forall a -> forall b -> TYPE (RR a b)+  newtype M a b = MkM (T a b)++Now, suppose we instantiate MkM, say with two types X, Y from the environment:++  foo :: T X Y -> M X Y+  foo = MkM @X @Y++we need to check that we can eta-expand MkM, for which we need to know the+representation of its argument, which is "RR X Y".++To do this, in "rejectRepPolyNewtypes", we perform a syntactic representation-+polymorphism check on the instantiated argument of the newtype, and reject+the definition if the representation isn't concrete (in the sense of Note [Concrete types]+in GHC.Tc.Utils.Concrete).++For example, we would accept "ok" above, as "IntRep" is a concrete RuntimeRep.+However, we would reject "foo", because "RR X Y" is not a concrete RuntimeRep.+If we wanted to accept "foo" (performing a PHASE 2 check (in the sense of+Note [The Concrete mechanism] in GHC.Tc.Utils.Concrete), we would have to+significantly re-engineer unlifted newtypes in GHC. Currently, "MkM" has type:++  MkM :: forall a b. T a b %1 -> M a b++However, we should only be able to use MkM when we know the representation of+T a b (which is RR a b). This means that MkM should instead have type:++  MkM :: forall {must_be_conc} a b (co :: RR a b ~# must_be_conc)+      .  T a b |> GRefl Nominal (TYPE co) %1 -> M a b++where "must_be_conc" is a skolem type variable that must be instantiated to+a concrete type, just as in Note [Representation-polymorphism checking built-ins].+This means that any instantiation of "MkM", such as "MkM @X @Y" from "foo",+would create a fresh concrete metavariable "gamma[conc]" and emit a Wanted constraint++  [W] co :: RR X Y ~# gamma[conc]++However, this all seems like a lot of work for a feature that no one is asking for,+so we decided to keep the much simpler syntactic check. Note that one possible+advantage of this approach is that we should be able to stop skipping+representation-polymorphism checks in the output of the desugarer; see (C) in+Wrinkle [Representation-polymorphic lambdas] in Note [Typechecking data constructors].+-}++-- | Reject any unsaturated use of an unlifted newtype constructor+-- if the representation of its argument isn't known.+--+-- See Note [Eta-expanding rep-poly unlifted newtypes].+rejectRepPolyNewtypes :: [HsExprArg 'TcpTc]+                      -> TcRhoType+                      -> HsExpr GhcTc+                      -> TcM ()+rejectRepPolyNewtypes _applied_args app_res_rho fun = case fun of++  XExpr (ConLikeTc (RealDataCon con) _ _)+    -- Check that this is an unsaturated occurrence of a+    -- representation-polymorphic newtype constructor.+    | isNewDataCon con+    , not $ tcHasFixedRuntimeRep $ dataConTyCon con+    , Just (_rem_arg_af, _rem_arg_mult, rem_arg_ty, _nt_res_ty)+        <- splitFunTy_maybe app_res_rho+    -> do { let frr_ctxt = FRRRepPolyUnliftedNewtype con+          ; hasFixedRuntimeRep_syntactic frr_ctxt rem_arg_ty }++  _ -> return ()+ isHsValArg :: HsExprArg id -> Bool isHsValArg (EValArg {}) = True isHsValArg _            = False -countLeadingValArgs :: [HsExprArg id] -> Int-countLeadingValArgs []                   = 0-countLeadingValArgs (EValArg {}  : args) = 1 + countLeadingValArgs args-countLeadingValArgs (EWrap {}    : args) = countLeadingValArgs args-countLeadingValArgs (EPrag {}    : args) = countLeadingValArgs args-countLeadingValArgs (ETypeArg {} : _)    = 0+leadingValArgs :: [HsExprArg id] -> [EValArg id]+leadingValArgs []                        = []+leadingValArgs (arg@(EValArg {}) : args) = eva_arg arg : leadingValArgs args+leadingValArgs (EWrap {}    : args)      = leadingValArgs args+leadingValArgs (EPrag {}    : args)      = leadingValArgs args+leadingValArgs (ETypeArg {} : _)         = []  isValArg :: HsExprArg id -> Bool isValArg (EValArg {}) = True@@ -660,36 +752,6 @@ isVisibleArg (ETypeArg {}) = True isVisibleArg _             = False --- | Count visible and invisible value arguments in a list--- of 'HsExprArg' arguments.-countVisAndInvisValArgs :: [HsExprArg id] -> Arity-countVisAndInvisValArgs []                  = 0-countVisAndInvisValArgs (EValArg {} : args) = 1 + countVisAndInvisValArgs args-countVisAndInvisValArgs (EWrap wrap : args) =-  case wrap of { EHsWrap hsWrap            -> countHsWrapperInvisArgs hsWrap + countVisAndInvisValArgs args-               ; EPar   {}                 -> countVisAndInvisValArgs args-               ; EExpand {}                -> countVisAndInvisValArgs args }-countVisAndInvisValArgs (EPrag {}   : args) = countVisAndInvisValArgs args-countVisAndInvisValArgs (ETypeArg {}: args) = countVisAndInvisValArgs args---- | Counts the number of invisible term-level arguments applied by an 'HsWrapper'.--- Precondition: this wrapper contains no abstractions.-countHsWrapperInvisArgs :: HsWrapper -> Arity-countHsWrapperInvisArgs = go-  where-    go WpHole = 0-    go (WpCompose wrap1 wrap2) = go wrap1 + go wrap2-    go fun@(WpFun {}) = nope fun-    go (WpCast {}) = 0-    go evLam@(WpEvLam {}) = nope evLam-    go (WpEvApp _) = 1-    go tyLam@(WpTyLam {}) = nope tyLam-    go (WpTyApp _) = 0-    go (WpLet _) = 0-    go (WpMultCoercion {}) = 0--    nope x = pprPanic "countHsWrapperInvisApps" (ppr x)- instance OutputableBndrId (XPass p) => Outputable (HsExprArg p) where   ppr (EValArg { eva_arg = arg })      = text "EValArg" <+> ppr arg   ppr (EPrag _ p)                      = text "EPrag" <+> ppr p@@ -717,21 +779,77 @@ Operator sections are desugared in the renamer; see GHC.Rename.Expr Note [Handling overloaded and rebindable constructs]. But for reasons explained there, we rename OpApp to OpApp.  Then,-here in the typechecker, we desugar it to a use of HsExpanded.+here in the typechecker, we desugar it to a use of ExpandedThingRn. That makes it possible to typecheck something like      e1 `f` e2 where    f :: forall a. t1 -> forall b. t2 -> t3 -Note [Looking through HsExpanded]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Note [Looking through ExpandedThingRn]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ When creating an application chain in splitHsApps, we must deal with-     HsExpanded f1 (f `HsApp` e1) `HsApp` e2 `HsApp` e3+     ExpandedThingRn f1 (f `HsApp` e1) `HsApp` e2 `HsApp` e3  as a single application chain `f e1 e2 e3`.  Otherwise stuff like overloaded labels (#19154) won't work. -It's easy to achieve this: `splitHsApps` unwraps `HsExpanded`.+It's easy to achieve this: `splitHsApps` unwraps `ExpandedThingRn`.++In order to be able to more accurately reconstruct the original `SrcSpan`s+from the renamer in `rebuildHsApps`, we also have to track the `SrcSpan`+of the current application in `VAExpansion` when unwrapping `ExpandedThingRn`+in `splitHsApps`, just as we track it in a non-expanded expression.++Previously, `rebuildHsApps` substituted the location of the original+expression as given by `splitHsApps` for this. As a result, the application+head in expanded expressions, e.g. the call to `fromListN`, would either+have `noSrcSpan` set as its location post-typecheck, or get the location+of the original expression, depending on whether the `XExpr` given to+`splitHsApps` is in the outermost layer. The span it got in the renamer+would always be discarded, causing #23120.++Note [Looking through Template Haskell splices in splitHsApps]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+When typechecking an application, we must look through untyped TH splices in+order to typecheck examples like the one in #21077:++  data Foo = MkFoo () (forall a. a -> a)++  foo :: Foo+  foo = $([| MkFoo () |]) $ \x -> x++In principle, this is straightforward to accomplish. By the time we typecheck+`foo`, the renamer will have already run the splice, so all we have to do is+look at the expanded version of the splice in `splitHsApps`. See the+`HsUntypedSplice` case in `splitHsApps` for how this is accomplished.++There is one slight complication in that untyped TH splices also include+modFinalizers (see Note [Delaying modFinalizers in untyped splices] in+GHC.Rename.Splice), which must be run during typechecking. splitHsApps is a+convenient place to run the modFinalizers, so we do so there. This is the only+reason that `splitHsApps` uses the TcM monad.++`HsUntypedSplice` covers both ordinary TH splices, such as the example above,+as well as quasiquotes (see Note [Quasi-quote overview] in+Language.Haskell.Syntax.Expr). The `splitHsApps` case for `HsUntypedSplice`+handles both of these. This is easy to accomplish, since all the real work in+handling splices and quasiquotes has already been performed by the renamer by+the time we get to `splitHsApps`.++Wrinkle (UTS1):+  `tcExpr` has a separate case for `HsUntypedSplice`s that do /not/ occur at the+  head of an application. This is important to handle programs like this one:++    foo :: (forall a. a -> a) -> b -> b+    foo = $([| \g x -> g x |])++  Here, it is vital that we push the expected type inwards so that `g` gets the+  type `forall a. a -> a`, and the `tcExpr` case for `HsUntypedSplice` performs+  this pushing. Without it, we would instead infer `g` to have type `b -> b`,+  which isn't sufficiently general. Unfortunately, this does mean that there are+  two different places in the code where an `HsUntypedSplice`'s modFinalizers can+  be ran, depending on whether the splice appears at the head of an application+  or not. -}  {- *********************************************************************@@ -741,7 +859,6 @@ ********************************************************************* -}  tcInferAppHead :: (HsExpr GhcRn, AppCtxt)-               -> [HsExprArg 'TcpRn]                -> TcM (HsExpr GhcTc, TcSigmaType) -- Infer type of the head of an application --   i.e. the 'f' in (f e1 ... en)@@ -752,11 +869,6 @@ --   * An expression with a type signature (e :: ty) -- See Note [Application chains and heads] in GHC.Tc.Gen.App ----- Why do we need the arguments to infer the type of the head of the--- application? Simply to inform add_head_ctxt about whether or not--- to put push a new "In the expression..." context. (We don't push a--- new one if there are no arguments, because we already have.)--- -- Note that [] and (,,) are both HsVar: --   see Note [Empty lists] and [ExplicitTuple] in GHC.Hs.Expr --@@ -764,40 +876,42 @@ --     cases are dealt with by splitHsApps. -- -- See Note [tcApp: typechecking applications] in GHC.Tc.Gen.App-tcInferAppHead (fun,ctxt) args+tcInferAppHead (fun,ctxt)   = addHeadCtxt ctxt $-    do { mb_tc_fun <- tcInferAppHead_maybe fun args+    do { mb_tc_fun <- tcInferAppHead_maybe fun        ; case mb_tc_fun of             Just (fun', fun_sigma) -> return (fun', fun_sigma)             Nothing -> tcInfer (tcExpr fun) }  tcInferAppHead_maybe :: HsExpr GhcRn-                     -> [HsExprArg 'TcpRn]                      -> TcM (Maybe (HsExpr GhcTc, TcSigmaType)) -- See Note [Application chains and heads] in GHC.Tc.Gen.App -- Returns Nothing for a complicated head-tcInferAppHead_maybe fun args+tcInferAppHead_maybe fun   = case fun of       HsVar _ (L _ nm)          -> Just <$> tcInferId nm       HsRecSel _ f              -> Just <$> tcInferRecSelId f       ExprWithTySig _ e hs_ty   -> Just <$> tcExprWithSig e hs_ty       HsOverLit _ lit           -> Just <$> tcInferOverLit lit-      HsUntypedSplice (HsUntypedSpliceTop _ e) _-                                -> tcInferAppHead_maybe e args       _                         -> return Nothing  addHeadCtxt :: AppCtxt -> TcM a -> TcM a+addHeadCtxt (VAExpansion (OrigStmt (L loc stmt)) _ _) thing_inside =+  do setSrcSpanA loc $+       addStmtCtxt stmt+         thing_inside addHeadCtxt fun_ctxt thing_inside   | not (isGoodSrcSpan fun_loc)   -- noSrcSpan => no arguments   = thing_inside                  -- => context is already set   | otherwise   = setSrcSpan fun_loc $-    case fun_ctxt of-      VAExpansion orig _ -> addExprCtxt orig thing_inside-      VACall {}          -> thing_inside+    do case fun_ctxt of+         VAExpansion (OrigExpr orig) _ _ -> addExprCtxt orig thing_inside+         _                               -> thing_inside   where     fun_loc = appCtxtLoc fun_ctxt + {- ********************************************************************* *                                                                      *                  Record selectors@@ -842,7 +956,7 @@ -- outermost constructor ignoring parentheses. obviousSig :: HsExpr GhcRn -> Maybe (LHsSigWcType GhcRn) obviousSig (ExprWithTySig _ _ ty) = Just ty-obviousSig (HsPar _ _ p _)        = obviousSig (unLoc p)+obviousSig (HsPar _ p)            = obviousSig (unLoc p) obviousSig (HsPragE _ _ p)        = obviousSig (unLoc p) obviousSig _                      = Nothing @@ -879,21 +993,17 @@ tcExprWithSig expr hs_ty   = do { sig_info <- checkNoErrs $  -- Avoid error cascade                      tcUserTypeSig loc hs_ty Nothing-       ; (expr', poly_ty) <- tcExprSig ctxt expr sig_info+       ; (expr', poly_ty) <- tcExprSig expr sig_info        ; return (ExprWithTySig noExtField expr' hs_ty, poly_ty) }   where     loc = getLocA (dropWildCards hs_ty)-    ctxt = ExprSigCtxt (lhsSigWcTypeContextSpan hs_ty) -tcExprSig :: UserTypeCtxt -> LHsExpr GhcRn -> TcIdSigInfo -> TcM (LHsExpr GhcTc, TcSigmaType)-tcExprSig ctxt expr (CompleteSig { sig_bndr = poly_id, sig_loc = loc })-  = setSrcSpan loc $   -- Sets the location for the implication constraint-    do { let poly_ty = idType poly_id-       ; (wrap, expr') <- tcSkolemiseScoped ctxt poly_ty $ \rho_ty ->-                          tcCheckMonoExprNC expr rho_ty-       ; return (mkLHsWrap wrap expr', poly_ty) }+tcExprSig :: LHsExpr GhcRn -> TcIdSig -> TcM (LHsExpr GhcTc, TcSigmaType)+tcExprSig expr (TcCompleteSig sig)+   = do { expr' <- tcPolyLExprSig expr sig+        ; return (expr', idType (sig_bndr sig)) } -tcExprSig _ expr sig@(PartialSig { psig_name = name, sig_loc = loc })+tcExprSig expr sig@(TcPartialSig (PSig { psig_name = name, psig_loc = loc }))   = setSrcSpan loc $   -- Sets the location for the implication constraint     do { (tclvl, wanted, (expr', sig_inst))              <- pushLevelAndCaptureConstraints  $@@ -983,20 +1093,20 @@        ; let            thing    = NameThing from_name            mb_thing = Just thing-           herald   = ExpectedFunTyArg thing (HsLit noAnn hs_lit)-       ; (wrap2, sarg_ty, res_ty) <- matchActualFunTySigma herald mb_thing-                                                           (1, []) from_ty+           herald   = ExpectedFunTyArg thing (HsLit noExtField hs_lit)+       ; (wrap2, sarg_ty, res_ty) <- matchActualFunTy herald mb_thing (1, from_ty) from_ty         ; co <- unifyType mb_thing (hsLitType hs_lit) (scaledThing sarg_ty)+       -- See Note [Source locations for implicit function calls] in GHC.Iface.Ext.Ast        ; let lit_expr = L (l2l loc) $ mkHsWrapCo co $-                        HsLit noAnn hs_lit+                        HsLit noExtField hs_lit              from_expr = mkHsWrap (wrap2 <.> wrap1) $                          HsVar noExtField (L loc from_id)-             witness = HsApp noAnn (L (l2l loc) from_expr) lit_expr+             witness = HsApp noExtField (L (l2l loc) from_expr) lit_expr              lit' = lit { ol_ext = OverLitTc { ol_rebindable = rebindable                                              , ol_witness = witness                                              , ol_type = res_ty } }-       ; return (HsOverLit noAnn lit', res_ty) }+       ; return (HsOverLit noExtField lit', res_ty) }  {- ********************************************************************* *                                                                      *@@ -1065,13 +1175,15 @@           pprov = case lookupGRE_Name gre nm of                       Just gre -> nest 2 (pprNameProvenance gre)                       Nothing  -> empty-      fail_with_msg dataName nm pprov+          err | isClassTyCon tc = ClassTE+              | otherwise       = TyConTE+      fail_with_msg dataName nm pprov err      fail_tyvar nm =       let pprov = nest 2 (text "bound at" <+> ppr (getSrcLoc nm))-      in fail_with_msg varName nm pprov+      in fail_with_msg varName nm pprov TyVarTE -    fail_with_msg whatName nm pprov = do+    fail_with_msg whatName nm pprov err = do       (import_errs, hints) <- get_suggestions whatName       unit_state <- hsc_units <$> getTopEnv       let@@ -1081,15 +1193,64 @@         import_err_msg = vcat $ map ppr import_errs         info = ErrInfo { errInfoContext = pprov, errInfoSupplementary = import_err_msg $$ hint_msg }       failWithTc $ TcRnMessageWithInfo unit_state (-              mkDetailedMessage info (TcRnIncorrectNameSpace nm False))+              mkDetailedMessage info (TcRnIllegalTermLevelUse nm err))      get_suggestions ns = do-       let occ = mkOccNameFS ns (occNameFS (occName id_name))-       lcl_env <- getLocalRdrEnv-       unknownNameSuggestions lcl_env WL_Anything (mkRdrUnqual occ)+      required_type_arguments <- xoptM LangExt.RequiredTypeArguments+      if required_type_arguments && isVarNameSpace ns+      then return ([], [])  -- See Note [Suppress hints with RequiredTypeArguments]+      else do+        let occ = mkOccNameFS ns (occNameFS (occName id_name))+        lcl_env <- getLocalRdrEnv+        unknownNameSuggestions lcl_env WL_Anything (mkRdrUnqual occ)      return_id id = return (HsVar noExtField (noLocA id), idType id) +{- Note [Suppress hints with RequiredTypeArguments]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+When a type variable is used at the term level, GHC assumes the user might+have made a typo and suggests a term variable with a similar name.++For example, if the user writes+  f (Proxy :: Proxy nap) (Proxy :: Proxy gap) = nap (+1) [1,2,3]+then GHC will helpfully suggest `map` instead of `nap`+  • Illegal term-level use of the type variable ‘nap’+  • Perhaps use ‘map’ (imported from Prelude)++Importantly, GHC does /not/ suggest `gap`, which is in scope.+Question: How does GHC know not to suggest `gap`?  After all, the edit distance+          between `map`, `nap`, and `gap` is equally short.+Answer: GHC takes the namespace into consideration. `gap` is a `tvName`, and GHC+        would only suggest a `varName` at the term level.++In other words, the current hint infrastructure assumes that the namespace of an+entity is a reliable indicator of its level+   term-level name <=> term-level entity+   type-level name <=> type-level entity++With RequiredTypeArguments, this assumption does not hold. Consider+  bad :: forall a b -> ...+  bad nap gap = nap++This use of `nap` on the RHS is illegal because `nap` stands for a type+variable. It cannot be returned as the result of a function. At the same time,+it is bound as a `varName`, i.e. in the term-level namespace.++Unless we suppress hints, GHC gets awfully confused+    • Illegal term-level use of the variable ‘nap’+    • Perhaps use one of these:+        ‘nap’ (line 2), ‘gap’ (line 2), ‘map’ (imported from Prelude)++GHC shouldn't suggest `gap`, which is also a type variable; using it would+result in the same error. And it especially shouldn't suggest using `nap`+instead of `nap`, which is absurd.++The proper solution is to overhaul the hint system to consider what a name+stands for instead of looking at its namespace alone. This is tracked in #24231.+As a temporary measure, we avoid those potentially misleading hints by+suppressing them entirely if RequiredTypeArguments is in effect.+-}+ check_local_id :: Id -> TcM () check_local_id id   = do { checkThLocalId id@@ -1226,15 +1387,17 @@        A. Any arguments to such lambda abstractions are guaranteed to have          a fixed runtime representation. This is enforced in 'tcApp' by-         'matchActualFunTySigma'.+         'matchActualFunTy'.        B. If there are fewer arguments than there are bound term variables,-         hasFixedRuntimeRep_remainingValArgs will ensure that we are still-         instantiating at a representation-monomorphic type, e.g.+         we will ensure that the appropriate type arguments are instantiated+         concretely, such as 'r' in           ( /\r (a :: TYPE r). \ (x %p :: a). K @r @a x) @IntRep @Int#            :: Int# -> T IntRep Int# +         See Note [Representation-polymorphic Ids with no binding] in GHC.Tc.Gen.Head.+       C. In the output of the desugarer in (4) above, we have a representation          polymorphic lambda, which Lint would normally reject. So for that one          pass, we switch off Lint's representation-polymorphism checks; see@@ -1461,6 +1624,17 @@              Misc utility functions *                                                                      * ********************************************************************* -}++addStmtCtxt :: ExprStmt GhcRn -> TcRn a -> TcRn a+addStmtCtxt stmt thing_inside+  = do let err_doc = pprStmtInCtxt (HsDoStmt (DoExpr Nothing)) stmt+       addErrCtxt err_doc thing_inside+  where+    pprStmtInCtxt :: HsStmtContextRn -> StmtLR GhcRn GhcRn (LHsExpr GhcRn) -> SDoc+    pprStmtInCtxt ctxt stmt+      = vcat [ hang (text "In a stmt of"+                     <+> pprAStmtContext ctxt <> colon) 2 (pprStmt stmt)+             ]  addExprCtxt :: HsExpr GhcRn -> TcRn a -> TcRn a addExprCtxt e thing_inside
compiler/GHC/Tc/Gen/HsType.hs view
@@ -69,7 +69,7 @@         tcMult,          -- Pattern type signatures-        tcHsPatSigType,+        tcHsPatSigType, tcHsTyPat,         HoleMode(..),          -- Error messages@@ -99,7 +99,6 @@ import GHC.Tc.Zonk.TcType  import GHC.Core.Type-import GHC.Core.Predicate import GHC.Core.TyCo.Rep import GHC.Core.TyCo.Ppr @@ -124,7 +123,6 @@ import GHC.Types.Unique.Supply import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Builtin.Names hiding ( wildCardName ) import GHC.Driver.DynFlags import qualified GHC.LanguageExtensions as LangExt@@ -639,9 +637,19 @@   = do { ty <- tcTopLHsType DerivClauseCtxt hs_ty        ; let (tvs, pred)    = splitForAllTyCoVars ty              (kind_args, _) = splitFunTys (typeKind pred)-       ; case getClassPredTys_maybe pred of-           Just (cls, tys) -> return (tvs, cls, tys, map scaledThing kind_args)-           Nothing -> failWithTc $ TcRnIllegalDerivingItem hs_ty }+      -- Checking that `pred` a is type class application+       ; case splitTyConApp_maybe pred of+          Just (tyCon, tyConArgs) ->+            case tyConClass_maybe tyCon of+              Just clas ->+                return (tvs, clas, tyConArgs, map scaledThing kind_args)+              Nothing -> failWithTc $ TcRnIllegalInstance+                                    $ IllegalClassInstance+                                        (TypeThing ty)+                                    $ IllegalInstanceHead+                                    $ InstHeadNonClass (Just tyCon)+          Nothing -> failWithTc $ TcRnIllegalDerivingItem hs_ty+    }  -- | Typecheck a deriving strategy. For most deriving strategies, this is a -- no-op, but for the @via@ strategy, this requires typechecking the @via@ type.@@ -742,7 +750,7 @@ -}  tcFamTyPats :: TyCon-            -> HsTyPats GhcRn                -- Patterns+            -> HsFamEqnPats GhcRn                -- Patterns             -> TcM (TcType, TcKind)          -- (lhs_type, lhs_kind) -- Check the LHS of a type/data family instance -- e.g.   type instance F ty1 .. tyn = ...@@ -1167,20 +1175,33 @@  tc_hs_type mode (HsOpTy _ _ ty1 (L _ op) ty2) exp_kind   | op `hasKey` unrestrictedFunTyConKey-  = tc_fun_type mode (HsUnrestrictedArrow noHsUniTok) ty1 ty2 exp_kind+  = tc_fun_type mode (HsUnrestrictedArrow noExtField) ty1 ty2 exp_kind  --------- Foralls-tc_hs_type mode (HsForAllTy { hst_tele = tele, hst_body = ty }) exp_kind-  = do { (tv_bndrs, ty') <- tcTKTelescope mode tele $-                            tc_lhs_type mode ty exp_kind+tc_hs_type mode t@(HsForAllTy { hst_tele = tele, hst_body = ty }) exp_kind+  | HsForAllInvis{} <- tele+  = tc_hs_forall_ty tele ty exp_kind+                 -- For an invisible forall, we allow the body to have+                 -- an arbitrary kind (hence exp_kind above).+                 -- See Note [Body kind of a HsForAllTy]++  | HsForAllVis{} <- tele+  = do { ek <- newOpenTypeKind+       ; r <- tc_hs_forall_ty tele ty ek+       ; checkExpectedKind t r ek exp_kind }+                 -- For a visible forall, we require that the body is of kind TYPE r.+                 -- See Note [Body kind of a HsForAllTy]++  where+    tc_hs_forall_ty tele ty ek+      = do { (tv_bndrs, ty') <- tcTKTelescope mode tele $+                                tc_lhs_type mode ty ek                  -- Pass on the mode from the type, to any wildcards                  -- in kind signatures on the forall'd variables                  -- e.g.      f :: _ -> Int -> forall (a :: _). blah-                 -- Why exp_kind?  See Note [Body kind of a HsForAllTy] -       -- Do not kind-generalise here!  See Note [Kind generalisation]--       ; return (mkForAllTys tv_bndrs ty') }+             -- Do not kind-generalise here!  See Note [Kind generalisation]+           ; return (mkForAllTys tv_bndrs ty') }  tc_hs_type mode (HsQualTy { hst_ctxt = ctxt, hst_body = rn_ty }) exp_kind   | null (unLoc ctxt)@@ -1207,7 +1228,7 @@        ; checkWiredInTyCon listTyCon        ; checkExpectedKind rn_ty (mkListTy tau_ty) liftedTypeKind exp_kind } --- See Note [Distinguishing tuple kinds] in GHC.Hs.Type+-- See Note [Distinguishing tuple kinds] in Language.Haskell.Syntax.Type -- See Note [Inferring tuple kinds] tc_hs_type mode rn_ty@(HsTupleTy _ HsBoxedOrConstraintTuple hs_tys) exp_kind      -- (NB: not zonking before looking at exp_k, to avoid left-right bias)@@ -1357,14 +1378,14 @@        ; ty1'  <- tc_lhs_type mode ty1 arg_k        ; ty2'  <- tc_lhs_type mode ty2 res_k        ; mult' <- tc_mult mode mult-       ; checkExpectedKind (HsFunTy noAnn mult ty1 ty2)+       ; checkExpectedKind (HsFunTy noExtField mult ty1 ty2)                            (tcMkVisFunTy mult' ty1' ty2')                            liftedTypeKind exp_kind }   KindLevel ->  -- no representation polymorphism in kinds. yet.     do { ty1'  <- tc_lhs_type mode ty1 liftedTypeKind        ; ty2'  <- tc_lhs_type mode ty2 liftedTypeKind        ; mult' <- tc_mult mode mult-       ; checkExpectedKind (HsFunTy noAnn mult ty1 ty2)+       ; checkExpectedKind (HsFunTy noExtField mult ty1 ty2)                            (tcMkVisFunTy mult' ty1' ty2')                            liftedTypeKind exp_kind } @@ -1530,12 +1551,12 @@        -> [HsArg GhcRn (LHsType GhcRn) (LHsKind GhcRn)]        -> (LHsType GhcRn,            [HsArg GhcRn (LHsType GhcRn) (LHsKind GhcRn)]) -- AZ temp-    go (L _  (HsAppTy _ f a))      as = go f (HsValArg a : as)-    go (L _  (HsAppKindTy _ ty at k)) as = go ty (HsTypeArg at k : as)+    go (L _  (HsAppTy _ f a))      as = go f (HsValArg noExtField a : as)+    go (L _  (HsAppKindTy _ ty k)) as = go ty (HsTypeArg noExtField k : as)     go (L sp (HsParTy _ f))        as = go f (HsArgPar (locA sp) : as)     go (L _  (HsOpTy _ prom l op@(L sp _) r)) as-      = ( L (na2la sp) (HsTyVar noAnn prom op)-        , HsValArg l : HsValArg r : as )+      = ( L (l2l sp) (HsTyVar noAnn prom op)+        , HsValArg noExtField l : HsValArg noExtField r : as )     go f as = (f, as)  ---------------------------@@ -1651,7 +1672,7 @@                                            ty_app_err ki_arg substed_fun_ki        ---------------- HsValArg: a normal argument (fun ty)-      (HsValArg arg : args, Just (ki_binder, inner_ki))+      (HsValArg _ arg : args, Just (ki_binder, inner_ki))         -- next binder is invisible; need to instantiate it         | Named (Bndr kv flag) <- ki_binder         , isInvisibleForAllTyFlag flag   -- ForAllTy with Inferred or Specified@@ -1672,7 +1693,7 @@                 ; go (n+1) fun' subst' inner_ki args }            -- no binder; try applying the substitution, or infer another arrow in fun kind-      (HsValArg _ : _, Nothing)+      (HsValArg _ _ : _, Nothing)         -> try_again_after_substing_or $            do { let arrows_needed = n_initial_val_args all_args               ; co <- matchExpectedFunKind (HsTypeRnThing $ unLoc hs_ty) arrows_needed substed_fun_ki@@ -1899,10 +1920,10 @@  appTypeToArg :: LHsType GhcRn -> [LHsTypeArg GhcRn] -> LHsType GhcRn appTypeToArg f []                       = f-appTypeToArg f (HsValArg arg     : args) = appTypeToArg (mkHsAppTy f arg) args+appTypeToArg f (HsValArg _ arg   : args) = appTypeToArg (mkHsAppTy f arg) args appTypeToArg f (HsArgPar _       : args) = appTypeToArg f                 args-appTypeToArg f (HsTypeArg at arg : args)-  = appTypeToArg (mkHsAppKindTy f at arg) args+appTypeToArg f (HsTypeArg _ arg  : args)+  = appTypeToArg (mkHsAppKindTy noExtField f arg) args   {- *********************************************************************@@ -1985,10 +2006,7 @@              -> return (mkTyConTy tc, tyConKind tc)             AGlobal (AConLike (RealDataCon dc))-             -> do { data_kinds <- xoptM LangExt.DataKinds-                   ; unless (data_kinds || specialPromotedDc dc) $-                       promotionErr name NoDataKindsDC-                   ; when (isFamInstTyCon (dataConTyCon dc)) $+             -> do { when (isFamInstTyCon (dataConTyCon dc)) $                        -- see #15245                        promotionErr name FamDataConPE                    ; let (_, _, _, theta, _, _) = dataConFullSig dc@@ -1999,6 +2017,8 @@                    ; let tc = promoteDataCon dc                    ; return (mkTyConApp tc [], tyConKind tc) } +           AGlobal AnId{}    -> promotionErr name TermVariablePE+           ATcId{}           -> promotionErr name TermVariablePE            APromotionErr err -> promotionErr name err             _  -> wrongThingErr WrongThingType thing name }@@ -2035,25 +2055,23 @@  Note [Body kind of a HsForAllTy] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-The body of a forall is usually a type, but in principle-there's no reason to prohibit *unlifted* types.-In fact, GHC can itself construct a function with an-unboxed tuple inside a for-all (via CPR analysis; see+The body of a forall is usually a type.+Because of representation polymorphism, it can be a TYPE r, for any r.+(In fact, GHC can itself construct a function with an+unboxed tuple inside a for-all via CPR analysis; see typecheck/should_compile/tc170). -Moreover in instance heads we get forall-types with-kind Constraint.--It's tempting to check that the body kind is (TYPE _). But this is-wrong. For example:+A forall can also be used in an instance head, then the body should+be a constraint. -  class C a b-  newtype N = Mk Foo deriving (C a)+Right now, we do not have any easy way to enforce that a type is+either a TYPE something or CONSTRAINT something, so we accept any kind.+This is unsound (#22063). We could fix this by implementing a TypeLike+predicate, see #20000. -We're doing newtype-deriving for C. But notice how `a` isn't in scope in-the predicate `C a`. So we quantify, yielding `forall a. C a` even though-`C a` has kind `* -> Constraint`. The `forall a. C a` is a bit cheeky, but-convenient. Bottom line: don't check for (TYPE _) here.+For a forall with a required argument, we do not allow constraints;+e.g. forall a -> Eq a is invalid. Therefore, we can enforce that the body+is a TYPE something in this case (#24176).  Note [Body kind of a HsQualTy] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -2110,7 +2128,7 @@    * It zonks any kinds.  The returned type should have no mutable kind     or type variables (hence returning Type not TcType):-      - any unconstrained kind variables are defaulted to (Any *) just+      - any unconstrained kind variables are defaulted to (Any @Type) just         as in GHC.Tc.Zonk.Type.       - there are no mutable type variables because we are         kind-checking a type@@ -2121,7 +2139,7 @@         ..a:kappa in scope..             let f :: forall b. T '[a,b] -> Int In this case, f's type could have a mutable kind variable kappa in it;-and we might then default it to (Any *) when dealing with f's type+and we might then default it to (Any @Type) when dealing with f's type signature.  But we don't expect this to happen because we can't get a lexically scoped type variable with a mutable kind variable in it.  A delicate point, this.  If it becomes an issue we might need to@@ -2146,7 +2164,7 @@ In the e1 example, the context of the splice fixes kappa to *.  But in the e2 example, we'll desugar the type, zonking the kind unification variables as we go.  When we encounter the unconstrained kappa, we-want to default it to '*', not to (Any *).+want to default it to 'Type', not to (Any @Type).  -} @@ -2452,7 +2470,7 @@                       -> TyConBinder mkExplicitTyConBinder dep_set (Bndr tv flag) =   case flag of-    HsBndrRequired    -> mkRequiredTyConBinder dep_set tv+    HsBndrRequired{}  -> mkRequiredTyConBinder dep_set tv     HsBndrInvisible{} -> mkNamedTyConBinder Specified tv  -- | Kind-check a 'LHsQTyVars'. Used in 'inferInitialKind' (for tycon kinds and@@ -2564,26 +2582,17 @@                    --               ^^^^^^^^^                    -- We do it here because at this point the environment has been                    -- extended with both 'implicit_tcv_prs' and 'explicit_tv_prs'.+                   --+                   -- Also see Note [Arity of type families and type synonyms]                  ; res_kind :: ContextKind <- kc_res_ki --                 -- Work out extra_arity, the number of extra invisible binders from-                 -- the kind signature that should be part of the TyCon's arity.-                 -- See Note [Arity inference in kcCheckDeclHeader_sig]-                 ; let n_invis_tcbs = countWhile isInvisibleTyConBinder excess_sig_tcbs-                       invis_arity = case res_kind of-                          AnyKind    -> n_invis_tcbs -- No kind signature, so make all the invisible binders-                                                     -- the signature into part of the arity of the TyCon-                          OpenKind   -> n_invis_tcbs -- Result kind is (TYPE rr), so again make all the-                                                     -- invisible binders part of the arity of the TyCon-                          TheKind ki -> 0 `max` (n_invis_tcbs - invisibleTyBndrCount ki)--                 ; let (invis_tcbs, resid_tcbs) = splitAt invis_arity excess_sig_tcbs-                 ; let sig_res_kind' = mkTyConKind resid_tcbs sig_res_kind+                 ; let sig_res_kind' = mkTyConKind excess_sig_tcbs sig_res_kind -                 ; traceTc "kcCheckDeclHeader_sig 2" $ vcat [ ppr excess_sig_tcbs-                                                            , ppr invis_arity, ppr invis_tcbs-                                                            , ppr n_invis_tcbs ]+                 ; traceTc "kcCheckDeclHeader_sig 2" $+                    vcat [ text "excess_sig_tcbs" <+> ppr excess_sig_tcbs+                         , text "res_kind" <+> ppr res_kind+                         , text "sig_res_kind'" <+> ppr sig_res_kind'+                         ]                   -- Unify res_ki (from the type declaration) with                  -- sig_res_kind', the residual kind from the kind signature.@@ -2591,8 +2600,8 @@                   -- Add more binders for data/newtype, so the result kind has no arrows                  -- See Note [Datatype return kinds]-                 ; if null resid_tcbs || not (needsEtaExpansion flav)-                   then return (invis_tcbs,      sig_res_kind')+                 ; if null excess_sig_tcbs || not (needsEtaExpansion flav)+                   then return ([],              sig_res_kind')                    else return (excess_sig_tcbs, sig_res_kind)           } @@ -2619,7 +2628,7 @@               dup_chk_prs  = implicit_prs ++ mkTyVarNamePairs skol_scoped_tvs         ; unless (null implicit_nms) $  -- No need if no implicit tyvars           checkForDuplicateScopedTyVars dup_chk_prs-        ; checkForDisconnectedScopedTyVars flav all_tcbs implicit_prs+        ; checkForDisconnectedScopedTyVars name flav all_tcbs implicit_prs          -- Swizzle the Names so that the TyCon uses the user-declared implicit names         -- E.g  type T :: k -> Type@@ -2755,7 +2764,7 @@     --                                            or k -> (AnonTCB)     zippable :: TyConBndrVis -> HsBndrVis GhcRn -> Bool     zippable vis (HsBndrInvisible _) = isInvisSpecTcbVis vis  -- (a)-    zippable vis  HsBndrRequired     = isVisibleTcbVis vis    -- (b)+    zippable vis (HsBndrRequired _)  = isVisibleTcbVis vis    -- (b)      -- See GHC Proposal #425, section "Kind checking",     -- where zippable and skippable are defined.@@ -2787,8 +2796,8 @@     -- See Note [Source locations for implicitly bound type variables]     -- in GHC.Tc.Rename.HsType -{- See Note [kcCheckDeclHeader_sig]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+{- Note [kcCheckDeclHeader_sig]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Given a kind signature 'sig_kind' and a declaration header, kcCheckDeclHeader_sig verifies that the declaration conforms to the signature. The end result is a PolyTcTyCon 'tc' such that:@@ -2829,85 +2838,43 @@     part of the signature (k -> Type) with the kind signature of the decl,     (j -> Type).  This unification, done in kcCheckDeclHeader, needs TcTyVars. -  * The tricky extra_arity part is described in-    Note [Arity inference in kcCheckDeclHeader_sig]--Note [Arity inference in kcCheckDeclHeader_sig]+Note [Arity of type families and type synonyms] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Consider these declarations:-  type family S1 :: forall k2. k1 -> k2 -> Type-  type family S2 (a :: k1) (b :: k2) :: Type--Both S1 and S2 can be given the same standalone kind signature:-  type S1 :: forall k1 k2. k1 -> k2 -> Type-  type S2 :: forall k1 k2. k1 -> k2 -> Type--And, indeed, tyConKind S1 == tyConKind S2. However,-tyConBinders and tyConResKind for S1 and S2 are different:--  tyConBinders S1  ==  [spec k1]-  tyConResKind S1  ==  forall k2. k1 -> k2 -> Type-  tyConKind    S1  ==  forall k1 k2. k1 -> k2 -> Type--  tyConBinders S2  ==  [spec k1, spec k2, anon-vis (a :: k1), anon-vis (b :: k2)]-  tyConResKind S2  ==  Type-  tyConKind    S1  ==  forall k1 k2. k1 -> k2 -> Type--This difference determines the /arity/:-  tyConArity tc == length (tyConBinders tc)-That is, the arity of S1 is 1, while the arity of S2 is 4.--'kcCheckDeclHeader_sig' needs to infer the desired arity, to split the-standalone kind signature into binders and the result kind. It does so-in two rounds:--1. matchUpSigWithDecl matches up-   - the [TyConBinder] from (applying splitTyConKind to) the kind signature-   - with the [LHsTyVarBndr] from the type declaration.-   That may leave some excess TyConBinder: in the case of S2 there are-   no excess TyConBinders, but in the case of S1 there are two (since-   there are no LHsTYVarBndrs.--2. Split off further TyConBinders (in the case of S1, one more) to-   make it possible to unify the residual return kind with the-   signature in the type declaration.  More precisely, split off such-   enough invisible that the remainder of the standalone kind-   signature and the user-written result kind signature have the same-   number of invisible quantifiers.--As another example consider the following declarations:+Consider -    type F :: Type -> forall j. j -> forall k1 k2. (k1, k2) -> Type-    type family F a b+  type F0 :: forall k. k -> k -> Type+  type family F0 -    type G :: Type -> forall j. j -> forall k1 k2. (k1, k2) -> Type-    type family G a b :: forall r2. (r1, r2) -> Type+  type F1 :: forall k. k -> k -> Type+  type family F1 @k -For both F and G, the signature (after splitTyConKind) has-  sig_tcbs :: [TyConBinder]-    = [ anon-vis (@a_aBq), spec (@j_auA), anon-vis (@(b_aBr :: j_auA))-      , spec (@k1_auB), spec (@k2_auC)-      , anon-vis (@(c_aBs :: (k1_auB, k2_auC)))]+  type F2a :: forall k. k -> k -> Type+  type family F2a @k a -matchUpSigWithDecl will consume the first three of these, passing on-  excess_sig_tcbs-    = [ spec (@k1_auB), spec (@k2_auC)-      , anon-vis (@(c_aBs :: (k1_auB, k2_auC)))]+  type F2b :: forall k. k -> k -> Type+  type family F2b a -For F, there is no result kind signature in the declaration for F, so-we absorb all invisible binders into F's arity. The resulting arity of-F is 3+2=5.+  type F3 :: forall k. k -> k -> Type+  type family F3 a b -Now, in the case of G, we have a result kind sig 'forall r2. (r2,r2)->Type'.-This has one invisible binder, so we split of enough extra binders from-our excess_sig_tcbs to leave just one to match 'r2'.+All five have the same /kind/, but what /arity/ do they have?+For a type family, the arity is critical:+* A type family must always appear saturated (up to its arity)+* A type family can match only on `arity` arguments, not further ones+* The arity is recorded by `tyConArity`, and is equal to the number of+  `TyConBinders` in the `TyCon`.+* In this context "arity" includes both kind and type arguments. -    res_ki  =  forall    r2. (r1, r2) -> Type-    kisig   =  forall k1 k2. (k1, k2) -> Type-                     ^^^-                     split off this one.+The arity is not determined by the kind signature (all five have the same signature).+Rather, it is determined by the declaration of the family:+* `F0` has arity 0.+* `F1` has arity 1.+* `F2a` has arity 2.+* `F2b` also has arity 2: the kind argument is invisible.+* `F3` has arity 3; again the kind argument is invisible. -The resulting arity of G is 3+1=4.+The matching-up of kind signature with the declaration itself is done by+`matchUpWithSigDecl`.  Note [discardResult in kcCheckDeclHeader_sig] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -2998,6 +2965,12 @@                  | AnyKind        -- ^ any kind will do                  | OpenKind       -- ^ something of the form @TYPE _@ +-- debug only+instance Outputable ContextKind where+  ppr AnyKind = text "AnyKind"+  ppr OpenKind = text "OpenKind"+  ppr (TheKind k) = text "TheKind" <+> ppr k+ ----------------------- newExpectedKind :: ContextKind -> TcM TcKind newExpectedKind (TheKind k)   = return k@@ -3027,25 +3000,32 @@ *                                                                      * ********************************************************************* -} -checkForDisconnectedScopedTyVars :: TyConFlavour TyCon -> [TcTyConBinder]+checkForDisconnectedScopedTyVars :: Name -> TyConFlavour TyCon -> [TcTyConBinder]                                  -> [(Name,TcTyVar)] -> TcM () -- See Note [Disconnected type variables]+-- For the type synonym case see Note [Out of arity type variables] -- `scoped_prs` is the mapping gotten by unifying --    - the standalone kind signature for T, with --    - the header of the type/class declaration for T-checkForDisconnectedScopedTyVars flav sig_tcbs scoped_prs-  = when (needsEtaExpansion flav) $+checkForDisconnectedScopedTyVars name flav all_tcbs scoped_prs          -- needsEtaExpansion: see wrinkle (DTV1) in Note [Disconnected type variables]-    mapM_ report_disconnected (filterOut ok scoped_prs)+  | needsEtaExpansion flav     = mapM_ report_disconnected (filterOut ok scoped_prs)+  | flav == TypeSynonymFlavour = mapM_ report_out_of_arity (filterOut ok scoped_prs)+  | otherwise = pure ()   where-    sig_tvs = mkVarSet (binderVars sig_tcbs)-    ok (_, tc_tv) = tc_tv `elemVarSet` sig_tvs+    all_tvs = mkVarSet (binderVars all_tcbs)+    ok (_, tc_tv) = tc_tv `elemVarSet` all_tvs      report_disconnected :: (Name,TcTyVar) -> TcM ()     report_disconnected (nm, _)       = setSrcSpan (getSrcSpan nm) $         addErrTc $ TcRnDisconnectedTyVar nm +    report_out_of_arity :: (Name,TcTyVar) -> TcM ()+    report_out_of_arity (tv_nm, _)+      = setSrcSpan (getSrcSpan tv_nm) $+        addErrTc $ TcRnOutOfArityTyVar name tv_nm+ checkForDuplicateScopedTyVars :: [(Name,TcTyVar)] -> TcM () -- Check for duplicates -- See Note [Aliasing in type and class declarations]@@ -3159,6 +3139,63 @@    The scoped-tyvar stuff is needed precisely for data/class/newtype declarations,   where needsEtaExpansion is True.++Note [Out of arity type variables]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+(Relevant ticket: #24470)+Type synonyms have a special scoping rule that allows implicit quantification in+the outermost kind signature:++  type P_e :: k -> Type+  type P_e @k = Proxy :: k -> Type     -- explicit binding++  type P_i    = Proxy :: k -> Type     -- implicit binding (relies on the special rule)++This is a deprecated feature (warning flag: -Wimplicit-rhs-quantification) but+we have to support it for a couple more releases. It is explained in more detail+in Note [Implicit quantification in type synonyms] in GHC.Rename.HsType.++Type synonyms `P_e` and `P_i` are equivalent.  Both of them have kind+`forall k. k -> Type` and arity 1. (Recall that the arity of a type synonym is+the number of arguments it requires at use sites; the arity matter because+unsaturated application of type families and type synonyms is not allowed).++We start to see problems when implicit RHS quantification (as in `P_i`) is+combined with a standalone king signature (like the one that `P_e` has).+That is:++  type P_i_sig :: k -> Type+  type P_i_sig = Proxy :: k -> Type++Per GHC Proposal #425, the arity of `P_i_sig` is determined /by the LHS only/,+which has no binders. So the arity of `P_i_sig` is 0.+At the same time, the legacy implicit quantification rule dictates that `k` is+brought into scope, as if there was a binder `@k` on the LHS.++We end up with a `k` that is in scope on the RHS but cannot be bound implicitly+on the LHS without affecting the arity. This led to #24470 (a compiler crash)++  GHC internal error: ‘k’ is not in scope during type checking,+                      but it passed the renamer++This problem occurs only if the arity of the type synonym is insufficiently+high to accommodate an implicit binding. It can be worked around by adding an+unused binder on the LHS:++  type P_w :: k -> Type+  type P_w @_w = Proxy :: k -> Type++The variable `_w` is unused. The only effect of the `@_w` binder is that the+arity of `P_w` is changed from 0 to 1. However, bumping the arity is exactly+what's needed to make the implicit binding of `k` possible.++All this is a rather unfortunate bit of accidental complexity that will go away+when GHC drops support for implicit RHS quantification. In the meantime, we+ought to produce a proper error message instead of a compiler panic, and we do+that with a check in checkForDisconnectedScopedTyVars:++  | flav == TypeSynonymFlavour = mapM_ report_out_of_arity (filterOut ok scoped_prs)+ -}  {- *********************************************************************@@ -3550,7 +3587,7 @@   | SMDSkolemTv SkolemInfo  -smVanilla :: HasDebugCallStack => SkolemMode+smVanilla :: HasCallStack => SkolemMode smVanilla = SM { sm_clone  = panic "sm_clone"  -- We always override this                , sm_parent = False                , sm_tvtv   = pprPanic "sm_tvtv" callStackDoc -- We always override this@@ -3716,7 +3753,7 @@   -> TcM CandidatesQTvs -- filterConstrainedCandidates removes any candidates that are free in -- 'wanted'; instead, it promotes them.  This bit is very much like--- decideMonoTyVars in GHC.Tc.Solver, but constraints are so much+-- decidePromotedTyVars in GHC.Tc.Solver, but constraints are so much -- simpler in kinds, it is much easier here. (In particular, we never -- quantify over a constraint in a type.) filterConstrainedCandidates wanted dvs@@ -4333,34 +4370,122 @@   (HsPS { hsps_ext  = HsPSRn { hsps_nwcs = sig_wcs, hsps_imp_tvs = sig_ns }         , hsps_body = hs_ty })   ctxt_kind+  = tc_type_in_pat ctxt hole_mode hs_ty sig_wcs sig_ns ctxt_kind+++-- Typecheck type patterns, in data constructor patterns, e.g+--    f (MkT @a @(Maybe b) ...) = ...+--+-- We have two completely separate typing rules,+--   one for binder type patterns  (handled by `tc_bndr_in_pat`)+--   one for unifier type patterns (handled by `tc_type_in_pat`)+-- The two cases are distinguished by `tyPatToBndr`.+-- See Note [Type patterns: binders and unifiers]+tcHsTyPat :: HsTyPat GhcRn               -- The type pattern+          -> Kind                        -- What kind is expected+          -> TcM ( [(Name, TcTyVar)]     -- Wildcards+                 , [(Name, TcTyVar)]     -- The new bit of type environment, binding+                                         -- the scoped type variables+                 , TcType)               -- The type+tcHsTyPat hs_pat@(HsTP{hstp_ext = hstp_rn, hstp_body = hs_ty}) expected_kind+  = case tyPatToBndr hs_pat of+    Nothing   -> tc_unif_in_pat hs_ty wcs all_ns (TheKind expected_kind)+    Just bndr -> tc_bndr_in_pat bndr  wcs imp_ns  expected_kind+  where+    all_ns = imp_ns ++ exp_ns+    HsTPRn{hstp_nwcs = wcs, hstp_imp_tvs = imp_ns, hstp_exp_tvs = exp_ns} = hstp_rn+    tc_unif_in_pat = tc_type_in_pat TypeAppCtxt HM_TyAppPat++-- `tc_bndr_in_pat` is used in type patterns to handle the binders case.+-- See Note [Type patterns: binders and unifiers]+tc_bndr_in_pat :: HsTyVarBndr flag GhcRn+               -> [Name]  -- All named wildcards in type+               -> [Name]  -- Implicit (but not explicit) binders in type+               -> Kind    -- Expected kind+               -> TcM ( [(Name, TcTyVar)]     -- Wildcards+                      , [(Name, TcTyVar)]     -- The new bit of type environment, binding+                                              -- the scoped type variables+                      , TcType)               -- The type+tc_bndr_in_pat bndr wcs imp_ns expected_kind = do+  traceTc "tc_bndr_in_pat 1" (ppr expected_kind)+  case bndr of+    UserTyVar _ _ (L _ name) -> do+      tv <- newPatTyVar name expected_kind+      pure ([], [(name,tv)], mkTyVarTy tv)+    KindedTyVar _ _ (L _ name) ki -> do+      tkv_prs <- mapM new_implicit_tv imp_ns+      wcs <- addTypeCtxt ki              $+             solveEqualities "tc_bndr_in_pat" $+               -- See Note [Failure in local type signatures]+               -- and c.f #16033+             bindNamedWildCardBinders wcs $ \ wcs ->+             tcExtendNameTyVarEnv tkv_prs $+             do { sig_kind <- tcLHsKindSig (TyVarBndrKindCtxt name) ki+                ; discardResult $+                  unifyKind (Just (NameThing name)) sig_kind expected_kind+                ; pure wcs }++      mapM_ emitNamedTypeHole wcs++      tv <- newPatTyVar name expected_kind++      traceTc "tc_bndr_in_pat 2" $ vcat+        [ text "expected_kind" <+> ppr expected_kind+        , text "wcs" <+> ppr wcs+        , text "(name,tv)" <+>  ppr (name,tv)+        , text "tkv_prs" <+> ppr tkv_prs]++      pure (wcs, (name,tv) : tkv_prs, mkTyVarTy tv)+  where+    new_implicit_tv name+      = do { kind <- newMetaKindVar+           ; tv   <- newPatTyVar name kind+             -- NB: tv's Name is fresh+           ; return (name, tv) }++-- * In type patterns `tc_type_in_pat` is used to handle the unifiers case.+--   See Note [Type patterns: binders and unifiers]+--+-- * In patterns `tc_type_in_pat` is used to check pattern signatures.+tc_type_in_pat :: UserTypeCtxt+               -> HoleMode -- HM_Sig when in a SigPat, HM_TyAppPat when in a ConPat checking type applications.+               -> LHsType GhcRn          -- The type in pattern+               -> [Name]                 -- All named wildcards in type+               -> [Name]                 -- All binders in type+               -> ContextKind                -- What kind is expected+               -> TcM ( [(Name, TcTyVar)]     -- Wildcards+                      , [(Name, TcTyVar)]     -- The new bit of type environment, binding+                                              -- the scoped type variables+                      , TcType)       -- The type+tc_type_in_pat ctxt hole_mode hs_ty wcs ns ctxt_kind   = addSigCtxt ctxt hs_ty $-    do { sig_tkv_prs <- mapM new_implicit_tv sig_ns+    do { tkv_prs <- mapM new_implicit_tv ns        ; mode <- mkHoleMode TypeLevel hole_mode-       ; (wcs, sig_ty)-            <- addTypeCtxt hs_ty                     $-               solveEqualities "tcHsPatSigType" $+       ; (wcs, ty)+            <- addTypeCtxt hs_ty                $+               solveEqualities "tc_type_in_pat" $                  -- See Note [Failure in local type signatures]                  -- and c.f #16033-               bindNamedWildCardBinders sig_wcs $ \ wcs ->-               tcExtendNameTyVarEnv sig_tkv_prs $+               bindNamedWildCardBinders wcs $ \ wcs ->+               tcExtendNameTyVarEnv tkv_prs $                do { ek     <- newExpectedKind ctxt_kind-                  ; sig_ty <- tc_lhs_type mode hs_ty ek-                  ; return (wcs, sig_ty) }+                  ; ty <- tc_lhs_type mode hs_ty ek+                  ; return (wcs, ty) }          ; mapM_ emitNamedTypeHole wcs -          -- sig_ty might have tyvars that are at a higher TcLevel (if hs_ty+          -- ty might have tyvars that are at a higher TcLevel (if hs_ty           -- contains a forall). Promote these.           -- Ex: f (x :: forall a. Proxy a -> ()) = ... x ...           -- When we instantiate x, we have to compare the kind of the argument           -- to a's kind, which will be a metavariable.           -- kindGeneralizeNone does this:-        ; kindGeneralizeNone sig_ty-        ; sig_ty <- liftZonkM $ zonkTcType sig_ty-        ; checkValidType ctxt sig_ty+        ; kindGeneralizeNone ty+        ; ty <- liftZonkM $ zonkTcType ty+        ; checkValidType ctxt ty -        ; traceTc "tcHsPatSigType" (ppr sig_tkv_prs)-        ; return (wcs, sig_tkv_prs, sig_ty) }+        ; traceTc "tc_type_in_pat" (ppr tkv_prs)+        ; return (wcs, tkv_prs, ty) }   where     new_implicit_tv name       = do { kind <- newMetaKindVar@@ -4368,13 +4493,76 @@                        RuleSigCtxt rname _  -> do                         skol_info <- mkSkolemInfo (RuleSkol rname)                         newSkolemTyVar skol_info name kind-                       _              -> newPatSigTyVar name kind+                       _              -> newPatTyVar name kind                        -- See Note [Typechecking pattern signature binders]-             -- NB: tv's Name may be fresh (in the case of newPatSigTyVar)+             -- NB: tv's Name may be fresh (in the case of newPatTyVar)            ; return (name, tv) } -{- Note [Typechecking pattern signature binders]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- See Note [Type patterns: binders and unifiers]+tyPatToBndr :: HsTyPat GhcRn -> Maybe (HsTyVarBndr () GhcRn)+tyPatToBndr HsTP{hstp_body = (L _ hs_ty)} = go hs_ty where+  go :: HsType GhcRn -> Maybe (HsTyVarBndr () GhcRn)+  go (HsParTy _ (L _ ty)) = go ty+  go (HsTyVar an _ name)+    | isTyVarName (unLoc name)+    = Just (UserTyVar an () name)+  go (HsKindSig an (L _ (HsTyVar _ _ name)) ki)+    | isTyVarName (unLoc name)+    = Just (KindedTyVar an () name ki)+  go _ = Nothing++{- Note [Type patterns: binders and unifiers]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+A type pattern, of type `HsTyPat`, represents a type argument in a data+constructor pattern.  For example+    f (MkT @a @(Maybe b) p q) = ...+Here the `@a` and `@(Maybe b)` are type patterns.  In general, then a+`HsTyPat` is represented by a `HsType`.++However, for /typechecking/ purposes (only) we distinguish two categories of+type pattern:+* Binder type patterns+* Unifier type patterns++Binder type patterns are a subset of type patterns described by the following grammar:++  tp_bndr ::=+      tv                    -- type variable+    | tv '::' kind          -- type variable with kind annotation+    | '(' tp_bndr ')'       -- parentheses++This subset of HsTyPat can be represented by HsTyVarBndr, which is also used+in foralls and type declaration headers. We could also extend this with wildcards (#23501).++Unifier type patterns include all other forms of type patterns, such as `Maybe x`.+This distinction allows the typechecker to accept more programs.+Consider this example from #18986:++  data T where+    MkT :: forall (f :: forall k. k -> Type).+      f Int -> f Maybe -> T++  k :: T -> ()+  k (MkT @f (x :: f Int) (y :: f Maybe)) = ()++In general case (if we treat `f` as a unifier) we would create a metavariable for its kind:+  f :: kappa+Checking `x :: f Int` would unify+  kappa := Type -> Type+and then checking `y :: f Maybe` would unify+  kappa := (Type -> Type) -> Type+leading to a type error:+    • Expecting one more argument to ‘Maybe’+      Expected a type, but ‘Maybe’ has kind ‘* -> *’++However, `@f` is a simple type variable binder, we don't need a metavariable for its kind, we+can add it directly to the context with its polymorphic kind:+  f :: forall k . k -> Type+This way both `f Int` and `f Maybe` can be accepted because `k` can be instantiated differently at+each call site.++Note [Typechecking pattern signature binders]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ See also Note [Type variables in the type environment] in GHC.Tc.Utils. Consider 
compiler/GHC/Tc/Gen/Match.hs view
@@ -1,10 +1,10 @@- {-# LANGUAGE ConstraintKinds  #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE RankNTypes       #-} {-# LANGUAGE RecordWildCards  #-} {-# LANGUAGE TupleSections    #-} {-# LANGUAGE TypeFamilies     #-}+{-# LANGUAGE ScopedTypeVariables  #-}  {-# OPTIONS_GHC -Wno-incomplete-uni-patterns   #-} @@ -16,12 +16,11 @@  -- | Typecheck some @Matches@ module GHC.Tc.Gen.Match-   ( tcMatchesFun-   , tcGRHS+   ( tcFunBindMatches+   , tcCaseMatches+   , tcLambdaMatches+   , tcGRHSList    , tcGRHSsPat-   , tcMatchesCase-   , tcMatchLambda-   , TcMatchCtxt(..)    , TcStmtChecker    , TcExprStmtChecker    , TcCmdStmtChecker@@ -38,15 +37,16 @@ import GHC.Prelude  import {-# SOURCE #-}   GHC.Tc.Gen.Expr( tcSyntaxOp, tcInferRho, tcInferRhoNC-                                       , tcMonoExpr, tcMonoExprNC, tcExpr+                                       , tcMonoExprNC, tcExpr                                        , tcCheckMonoExpr, tcCheckMonoExprNC-                                       , tcCheckPolyExpr )+                                       , tcCheckPolyExpr, tcPolyLExpr ) -import GHC.Rename.Utils ( bindLocalNames, isIrrefutableHsPatRn )+import GHC.Rename.Utils ( bindLocalNames, isIrrefutableHsPat ) import GHC.Tc.Errors.Types import GHC.Tc.Utils.Monad import GHC.Tc.Utils.Env import GHC.Tc.Gen.Pat+import GHC.Tc.Gen.Do import GHC.Tc.Gen.Head( tcCheckId ) import GHC.Tc.Utils.TcMType import GHC.Tc.Utils.TcType@@ -59,7 +59,7 @@ import GHC.Core.Multiplicity import GHC.Core.UsageEnv import GHC.Core.TyCon--- Create chunkified tuple tybes for monad comprehensions+-- Create chunkified tuple types for monad comprehensions import GHC.Core.Make  import GHC.Hs@@ -72,116 +72,130 @@ import GHC.Utils.Misc import GHC.Driver.DynFlags ( getDynFlags ) -import GHC.Types.Fixity (LexicalFixity(..)) import GHC.Types.Name import GHC.Types.Id import GHC.Types.SrcLoc+import GHC.Types.Basic( VisArity, isDoExpansionGenerated )  import Control.Monad import Control.Arrow ( second ) import qualified Data.List.NonEmpty as NE+import Data.Maybe (mapMaybe) +import qualified GHC.LanguageExtensions as LangExt++ {- ************************************************************************ *                                                                      *-\subsection{tcMatchesFun, tcMatchesCase}+\subsection{tcFunBindMatches, tcCaseMatches} *                                                                      * ************************************************************************ -@tcMatchesFun@ typechecks a @[Match]@ list which occurs in a-@FunMonoBind@.  The second argument is the name of the function, which+`tcFunBindMatches` typechecks a `[Match]` list which occurs in a+`FunBind`.  The second argument is the name of the function, which is used in error messages.  It checks that all the equations have the-same number of arguments before using @tcMatches@ to do the work.+same number of arguments before using `tcMatches` to do the work. -} -tcMatchesFun :: LocatedN Name -- MatchContext Id-             -> MatchGroup GhcRn (LHsExpr GhcRn)-             -> ExpRhoType    -- Expected type of function-             -> TcM (HsWrapper, MatchGroup GhcTc (LHsExpr GhcTc))-                                -- Returns type of body-tcMatchesFun fun_name matches exp_ty-  = do  {  -- Check that they all have the same no of arguments-           -- Location is in the monad, set the caller so that-           -- any inter-equation error messages get some vaguely-           -- sensible location.        Note: we have to do this odd-           -- ann-grabbing, because we don't always have annotations in-           -- hand when we call tcMatchesFun...-          traceTc "tcMatchesFun" (ppr fun_name $$ ppr exp_ty)-        ; checkArgCounts what matches+tcFunBindMatches :: UserTypeCtxt+                 -> Name            -- Function name+                 -> Mult            -- The multiplicity of the binder+                 -> MatchGroup GhcRn (LHsExpr GhcRn)+                 -> [ExpPatType]    -- Scoped skolemised binders+                 -> ExpRhoType      -- Expected type of function; caller+                                    -- has skolemised any outer forall's+                 -> TcM (HsWrapper, MatchGroup GhcTc (LHsExpr GhcTc))+-- See Note [Skolemisation overview] in GHC.Tc.Utils.Unify+tcFunBindMatches ctxt fun_name mult matches invis_pat_tys exp_ty+  = assertPpr (funBindPrecondition matches) (pprMatches matches) $+    do  {  -- Check that they all have the same no of arguments+          arity <- checkArgCounts matches -        ; matchExpectedFunTys herald ctxt arity exp_ty $ \ pat_tys rhs_ty ->-             -- NB: exp_type may be polymorphic, but-             --     matchExpectedFunTys can cope with that-          tcScalingUsage ManyTy $-          -- toplevel bindings and let bindings are, at the-          -- moment, always unrestricted. The value being bound-          -- must, accordingly, be unrestricted. Hence them-          -- being scaled by Many. When let binders come with a-          -- multiplicity, then @tcMatchesFun@ will have to take-          -- a multiplicity argument, and scale accordingly.-          tcMatches match_ctxt pat_tys rhs_ty matches }+        ; traceTc "tcFunBindMatches 1" (ppr fun_name $$ ppr mult $$ ppr exp_ty $$ ppr arity)++        ; (wrap_fun, (wrap_mult, r))+             <- matchExpectedFunTys herald ctxt arity exp_ty $ \ pat_tys rhs_ty ->+                tcScalingUsage mult $+                   -- Makes sure that if the binding is unrestricted, it counts as+                   -- consuming its rhs Many times.++                do { traceTc "tcFunBindMatches 2" (vcat [ pprUserTypeCtxt ctxt, ppr invis_pat_tys+                                                      , ppr pat_tys $$ ppr rhs_ty ])+                   ; tcMatches tcBody (invis_pat_tys ++ pat_tys) rhs_ty matches }++        ; return (wrap_fun <.> wrap_mult, r) }   where-    arity  = matchGroupArity matches-    herald = ExpectedFunTyMatches (NameThing (unLoc fun_name)) matches-    ctxt   = GenSigCtxt  -- Was: FunSigCtxt fun_name True-                         -- But that's wrong for f :: Int -> forall a. blah-    what   = FunRhs { mc_fun = fun_name, mc_fixity = Prefix, mc_strictness = strictness }-    match_ctxt = MC { mc_what = what, mc_body = tcBody }-    strictness-      | [L _ match] <- unLoc $ mg_alts matches-      , FunRhs{ mc_strictness = SrcStrict } <- m_ctxt match-      = SrcStrict-      | otherwise-      = NoSrcStrict+    herald        = ExpectedFunTyMatches (NameThing fun_name) matches +funBindPrecondition :: MatchGroup GhcRn (LHsExpr GhcRn) -> Bool+funBindPrecondition (MG { mg_alts = L _ alts })+  = not (null alts) && all is_fun_rhs alts+  where+    is_fun_rhs (L _ (Match { m_ctxt = FunRhs {} })) = True+    is_fun_rhs _                                    = False++tcLambdaMatches :: HsExpr GhcRn -> HsLamVariant+                -> MatchGroup GhcRn (LHsExpr GhcRn)+                -> [ExpPatType]  -- Already skolemised+                -> ExpSigmaType  -- NB can be a sigma-type+                -> TcM (HsWrapper, MatchGroup GhcTc (LHsExpr GhcTc))+tcLambdaMatches e lam_variant matches invis_pat_tys res_ty+  =  do { arity <- checkArgCounts matches+            -- Check argument counts since this is also used for \cases++        ; (wrapper, (mult_co_wrap, r))+            <- matchExpectedFunTys herald GenSigCtxt arity res_ty $ \ pat_tys rhs_ty ->+               tcMatches tc_body (invis_pat_tys ++ pat_tys) rhs_ty matches++        ; return (wrapper <.> mult_co_wrap, r) }+  where+    herald = ExpectedFunTyLam lam_variant e+             -- See Note [Herald for matchExpectedFunTys] in GHC.Tc.Utils.Unify++    tc_body | isDoExpansionGenerated (mg_ext matches)+              -- See Part 3. B. of Note [Expanding HsDo with XXExprGhcRn] in+              -- `GHC.Tc.Gen.Do`. Testcase: Typeable1+            = tcBodyNC -- NB: Do not add any error contexts+                       -- It has already been done+            | otherwise+            = tcBody+ {--@tcMatchesCase@ doesn't do the argument-count check because the+@tcCaseMatches@ doesn't do the argument-count check because the parser guarantees that each equation has exactly one argument. -} -tcMatchesCase :: (AnnoBody body) =>-                TcMatchCtxt body      -- ^ Case context-             -> Scaled TcSigmaTypeFRR -- ^ Type of scrutinee-             -> MatchGroup GhcRn (LocatedA (body GhcRn)) -- ^ The case alternatives-             -> ExpRhoType                               -- ^ Type of the whole case expression-             -> TcM (MatchGroup GhcTc (LocatedA (body GhcTc)))+tcCaseMatches :: (AnnoBody body, Outputable (body GhcTc))+              => TcMatchAltChecker body    -- ^ Typecheck the alternative RHSS+              -> Scaled TcSigmaTypeFRR     -- ^ Type of scrutinee+              -> MatchGroup GhcRn (LocatedA (body GhcRn)) -- ^ The case alternatives+              -> ExpRhoType                               -- ^ Type of the whole case expression+              -> TcM (HsWrapper, MatchGroup GhcTc (LocatedA (body GhcTc)))                 -- Translated alternatives                 -- wrapper goes from MatchGroup's ty to expected ty -tcMatchesCase ctxt (Scaled scrut_mult scrut_ty) matches res_ty-  = tcMatches ctxt [Scaled scrut_mult (mkCheckExpType scrut_ty)] res_ty matches--tcMatchLambda :: ExpectedFunTyOrigin -- see Note [Herald for matchExpectedFunTys] in GHC.Tc.Utils.Unify-              -> TcMatchCtxt HsExpr-              -> MatchGroup GhcRn (LHsExpr GhcRn)-              -> ExpRhoType-              -> TcM (HsWrapper, MatchGroup GhcTc (LHsExpr GhcTc))-tcMatchLambda herald match_ctxt match res_ty-  =  do { checkArgCounts (mc_what match_ctxt) match-        ; matchExpectedFunTys herald GenSigCtxt n_pats res_ty $ \ pat_tys rhs_ty -> do-            -- checking argument counts since this is also used for \cases-            tcMatches match_ctxt pat_tys rhs_ty match }-  where-    n_pats | isEmptyMatchGroup match = 1   -- must be lambda-case-           | otherwise               = matchGroupArity match+tcCaseMatches tc_body (Scaled scrut_mult scrut_ty) matches res_ty+  = tcMatches tc_body [ExpFunPatTy (Scaled scrut_mult (mkCheckExpType scrut_ty))] res_ty matches  -- @tcGRHSsPat@ typechecks @[GRHSs]@ that occur in a @PatMonoBind@.--tcGRHSsPat :: GRHSs GhcRn (LHsExpr GhcRn) -> ExpRhoType+tcGRHSsPat :: Mult -> GRHSs GhcRn (LHsExpr GhcRn) -> ExpRhoType            -> TcM (GRHSs GhcTc (LHsExpr GhcTc)) -- Used for pattern bindings-tcGRHSsPat grhss res_ty-  = tcScalingUsage ManyTy $-      -- Like in tcMatchesFun, this scaling happens because all-      -- let bindings are unrestricted. A difference, here, is-      -- that when this is not the case, any more, we will have to-      -- make sure that the pattern is strict, otherwise this will-      -- desugar to incorrect code.-    tcGRHSs match_ctxt grhss res_ty+tcGRHSsPat mult grhss res_ty+  = tcScalingUsage mult $ do+    { (mult_co_wrapper, r) <- tcGRHSs PatBindRhs tcBody grhss res_ty+    ; return $ mkWrap mult_co_wrapper r }   where-    match_ctxt :: TcMatchCtxt HsExpr -- AZ-    match_ctxt = MC { mc_what = PatBindRhs,-                      mc_body = tcBody }+    mkWrap wrap grhss@(GRHSs { grhssGRHSs = L loc (GRHS x guards body) : rhss }) =+      grhss { grhssGRHSs = L loc (GRHS x guards (mkLHsWrap wrap body)) : rhss }+    mkWrap _ (GRHSs { grhssGRHSs = [] }) = panic "tcGRHSsPat: empty GHRSs"+    mkWrap _ _ = panic "tcGRHSsPat: non-empty extensions"+    -- Should be the following but it warns of redundant pattern and I couldn't+    -- find a way to silence them+    --+    -- mkWrap _ (GRHSs { grhssGRHSs = L _ (XGRHS absent) : _ }) = dataConCantHappen absent+    -- mkWrap _ (XGRHSs absent) = dataConCantHappen absent  {- ********************************************************************* *                                                                      *@@ -189,12 +203,11 @@ *                                                                      * ********************************************************************* -} -data TcMatchCtxt body   -- c.f. TcStmtCtxt, also in this module-  = MC { mc_what :: HsMatchContext GhcTc,  -- What kind of thing this is-         mc_body :: LocatedA (body GhcRn)  -- Type checker for a body of-                                           -- an alternative-                 -> ExpRhoType-                 -> TcM (LocatedA (body GhcTc)) }+-- | Type checker for a body of a match alternative+type TcMatchAltChecker body   -- c.f. TcStmtChecker, also in this module+  =  LocatedA (body GhcRn)+  -> ExpRhoType+  -> TcM (LocatedA (body GhcTc))  type AnnoBody body   = ( Outputable (body GhcRn)@@ -202,98 +215,123 @@     , Anno (Match GhcTc (LocatedA (body GhcTc))) ~ SrcSpanAnnA     , Anno [LocatedA (Match GhcRn (LocatedA (body GhcRn)))] ~ SrcSpanAnnL     , Anno [LocatedA (Match GhcTc (LocatedA (body GhcTc)))] ~ SrcSpanAnnL-    , Anno (GRHS GhcRn (LocatedA (body GhcRn))) ~ SrcAnn NoEpAnns-    , Anno (GRHS GhcTc (LocatedA (body GhcTc))) ~ SrcAnn NoEpAnns+    , Anno (GRHS GhcRn (LocatedA (body GhcRn))) ~ EpAnnCO+    , Anno (GRHS GhcTc (LocatedA (body GhcTc))) ~ EpAnnCO     , Anno (StmtLR GhcRn GhcRn (LocatedA (body GhcRn))) ~ SrcSpanAnnA     , Anno (StmtLR GhcTc GhcTc (LocatedA (body GhcTc))) ~ SrcSpanAnnA     )  -- | Type-check a MatchGroup.-tcMatches :: (AnnoBody body ) => TcMatchCtxt body-          -> [Scaled ExpSigmaTypeFRR] -- ^ Expected pattern types.+tcMatches :: (AnnoBody body, Outputable (body GhcTc))+          => TcMatchAltChecker body+          -> [ExpPatType]             -- ^ Expected pattern types.           -> ExpRhoType               -- ^ Expected result-type of the Match.           -> MatchGroup GhcRn (LocatedA (body GhcRn))-          -> TcM (MatchGroup GhcTc (LocatedA (body GhcTc)))+          -> TcM (HsWrapper, MatchGroup GhcTc (LocatedA (body GhcTc))) -tcMatches ctxt pat_tys rhs_ty (MG { mg_alts = L l matches-                                  , mg_ext = origin })+tcMatches tc_body pat_tys rhs_ty (MG { mg_alts = L l matches+                                     , mg_ext = origin })   | null matches  -- Deal with case e of {}     -- Since there are no branches, no one else will fill in rhs_ty     -- when in inference mode, so we must do it ourselves,     -- here, using expTypeToType   = do { tcEmitBindingUsage bottomUE-       ; pat_tys <- mapM scaledExpTypeToType pat_tys+       ; pat_tys <- mapM scaledExpTypeToType (filter_out_forall_pat_tys pat_tys)        ; rhs_ty  <- expTypeToType rhs_ty-       ; return (MG { mg_alts = L l []-                    , mg_ext = MatchGroupTc pat_tys rhs_ty origin-                    }) }+       ; return (idHsWrapper, MG { mg_alts = L l []+                                 , mg_ext = MatchGroupTc pat_tys rhs_ty origin+                                 }) }    | otherwise-  = do { umatches <- mapM (tcCollectingUsage . tcMatch ctxt pat_tys rhs_ty) matches-       ; let (usages,matches') = unzip umatches+  = do { umatches <- mapM (tcCollectingUsage . tcMatch tc_body pat_tys rhs_ty) matches+       ; let (usages, wmatches) = unzip umatches+       ; let (wrappers, matches') = unzip wmatches+       ; let wrapper = mconcat wrappers        ; tcEmitBindingUsage $ supUEs usages-       ; pat_tys  <- mapM readScaledExpType pat_tys+       ; pat_tys  <- mapM readScaledExpType (filter_out_forall_pat_tys pat_tys)        ; rhs_ty   <- readExpType rhs_ty-       ; return (MG { mg_alts   = L l matches'-                    , mg_ext    = MatchGroupTc pat_tys rhs_ty origin-                    }) }+       ; traceTc "tcMatches" (ppr matches' $$ ppr pat_tys $$ ppr rhs_ty)+       ; return (wrapper, MG { mg_alts   = L l matches'+                             , mg_ext    = MatchGroupTc pat_tys rhs_ty origin+                             }) }+  where+    -- We filter out foralls because we have no use for them in HsToCore.+    filter_out_forall_pat_tys :: [ExpPatType] -> [Scaled ExpSigmaTypeFRR]+    filter_out_forall_pat_tys = mapMaybe match_fun_pat_ty+      where+        match_fun_pat_ty (ExpFunPatTy t)  = Just t+        match_fun_pat_ty ExpForAllPatTy{} = Nothing  --------------tcMatch :: (AnnoBody body) => TcMatchCtxt body-        -> [Scaled ExpSigmaType]        -- Expected pattern types+tcMatch :: (AnnoBody body)+        => TcMatchAltChecker body+        -> [ExpPatType]          -- Expected pattern types         -> ExpRhoType            -- Expected result-type of the Match.         -> LMatch GhcRn (LocatedA (body GhcRn))-        -> TcM (LMatch GhcTc (LocatedA (body GhcTc)))+        -> TcM (HsWrapper, LMatch GhcTc (LocatedA (body GhcTc))) -tcMatch ctxt pat_tys rhs_ty match-  = wrapLocMA (tc_match ctxt pat_tys rhs_ty) match+tcMatch tc_body pat_tys rhs_ty match+  = do { (L loc (wrapper, r)) <- wrapLocMA (tc_match pat_tys rhs_ty) match+       ; return (wrapper, L loc r) }   where-    tc_match ctxt pat_tys rhs_ty-             match@(Match { m_pats = pats, m_grhss = grhss })-      = add_match_ctxt match $-        do { (pats', grhss') <- tcPats (mc_what ctxt) pats pat_tys $-                                tcGRHSs ctxt grhss rhs_ty-           ; return (Match { m_ext = noAnn-                           , m_ctxt = mc_what ctxt, m_pats = pats'-                           , m_grhss = grhss' }) }+    tc_match pat_tys rhs_ty+             match@(Match { m_ctxt = ctxt, m_pats = pats, m_grhss = grhss })+      = add_match_ctxt $+        do { (pats', (wrapper, grhss')) <- tcMatchPats ctxt pats pat_tys $+                                           tcGRHSs ctxt tc_body grhss rhs_ty+             -- NB: pats' are just the /value/ patterns+             -- See Note [tcMatchPats] in GHC.Tc.Gen.Pat +           ; return (wrapper, Match { m_ext   = noAnn+                                    , m_ctxt  = ctxt+                                    , m_pats  = pats'+                                    , m_grhss = grhss' }) }+      where         -- For (\x -> e), tcExpr has already said "In the expression \x->e"-        -- so we don't want to add "In the lambda abstraction \x->e"-    add_match_ctxt match thing_inside-        = case mc_what ctxt of-            LambdaExpr -> thing_inside+        --     so we don't want to add "In the lambda abstraction \x->e"+        -- But for \cases with many alternatives, it is helpful to say+        --     which particular alternative we are looking at+        add_match_ctxt thing_inside = case ctxt of+            LamAlt LamSingle -> thing_inside+            StmtCtxt (HsDoStmt{}) -> thing_inside -- this is an expanded do stmt             _          -> addErrCtxt (pprMatchInCtxt match) thing_inside  ------------- tcGRHSs :: AnnoBody body-        => TcMatchCtxt body -> GRHSs GhcRn (LocatedA (body GhcRn)) -> ExpRhoType-        -> TcM (GRHSs GhcTc (LocatedA (body GhcTc)))-+        => HsMatchContextRn+        -> TcMatchAltChecker body+        -> GRHSs GhcRn (LocatedA (body GhcRn))+        -> ExpRhoType+        -> TcM (HsWrapper, GRHSs GhcTc (LocatedA (body GhcTc))) -- Notice that we pass in the full res_ty, so that we get -- good inference from simple things like --      f = \(x::forall a.a->a) -> <stuff> -- We used to force it to be a monotype when there was more than one guard -- but we don't need to do that any more+tcGRHSs ctxt tc_body (GRHSs _ grhss binds) res_ty+  = do  { (binds', wrapper, grhss') <- tcLocalBinds binds $ do+                                       tcGRHSList ctxt tc_body grhss res_ty+        ; return (wrapper, GRHSs emptyComments grhss' binds') } -tcGRHSs ctxt (GRHSs _ grhss binds) res_ty-  = do  { (binds', ugrhss)-            <- tcLocalBinds binds $-               mapM (tcCollectingUsage . wrapLocMA (tcGRHS ctxt res_ty)) grhss-        ; let (usages, grhss') = unzip ugrhss+tcGRHSList :: forall body. AnnoBody body+           => HsMatchContextRn -> TcMatchAltChecker body+           -> [LGRHS GhcRn (LocatedA (body GhcRn))] -> ExpRhoType+           -> TcM [LGRHS GhcTc (LocatedA (body GhcTc))]+tcGRHSList ctxt tc_body grhss res_ty+   = do { (usages, grhss') <- mapAndUnzipM (wrapLocSndMA tc_alt) grhss         ; tcEmitBindingUsage $ supUEs usages-        ; return (GRHSs emptyComments grhss' binds') }----------------tcGRHS :: TcMatchCtxt body -> ExpRhoType -> GRHS GhcRn (LocatedA (body GhcRn))-       -> TcM (GRHS GhcTc (LocatedA (body GhcTc)))+        ; return grhss' }+   where+     stmt_ctxt = PatGuard ctxt -tcGRHS ctxt res_ty (GRHS _ guards rhs)-  = do  { (guards', rhs')-            <- tcStmtsAndThen stmt_ctxt tcGuardStmt guards res_ty $-               mc_body ctxt rhs-        ; return (GRHS noAnn guards' rhs') }-  where-    stmt_ctxt  = PatGuard (mc_what ctxt)+     tc_alt :: GRHS GhcRn (LocatedA (body GhcRn))+            -> TcM (UsageEnv, GRHS GhcTc (LocatedA (body GhcTc)))+     tc_alt (GRHS _ guards rhs)+       = tcCollectingUsage $+         do  { (guards', rhs')+                   <- tcStmtsAndThen stmt_ctxt tcGuardStmt guards res_ty $+                      tc_body rhs+             ; return (GRHS noAnn guards' rhs') }  {- ************************************************************************@@ -315,15 +353,20 @@                             (mkCheckExpType elt_ty)         ; return $ mkHsWrapCo co (HsDo list_ty ListComp (L l stmts')) } -tcDoStmts doExpr@(DoExpr _) (L l stmts) res_ty-  = do  { stmts' <- tcStmts (HsDoStmt doExpr) tcDoStmt stmts res_ty-        ; res_ty <- readExpType res_ty-        ; return (HsDo res_ty doExpr (L l stmts')) }+tcDoStmts doExpr@(DoExpr _) ss@(L l stmts) res_ty+  = do  { isApplicativeDo <- xoptM LangExt.ApplicativeDo+        ; if isApplicativeDo+          then do { stmts' <- tcStmts (HsDoStmt doExpr) tcDoStmt stmts res_ty+                  ; res_ty <- readExpType res_ty+                  ; return (HsDo res_ty doExpr (L l stmts')) }+          else do { expanded_expr <- expandDoStmts doExpr stmts+                                               -- Do expansion on the fly+                  ; mkExpandedExprTc (HsDo noExtField doExpr ss) <$> tcExpr (unLoc expanded_expr) res_ty }+        } -tcDoStmts mDoExpr@(MDoExpr _) (L l stmts) res_ty-  = do  { stmts' <- tcStmts (HsDoStmt mDoExpr) tcDoStmt stmts res_ty-        ; res_ty <- readExpType res_ty-        ; return (HsDo res_ty mDoExpr (L l stmts')) }+tcDoStmts mDoExpr@(MDoExpr _) ss@(L _ stmts) res_ty+  = do  { expanded_expr <- expandDoStmts mDoExpr stmts -- Do expansion on the fly+        ; mkExpandedExprTc (HsDo noExtField mDoExpr ss) <$> tcExpr (unLoc expanded_expr) res_ty  }  tcDoStmts MonadComp (L l stmts) res_ty   = do  { stmts' <- tcStmts (HsDoStmt MonadComp) tcMcStmt stmts res_ty@@ -334,9 +377,15 @@ tcBody :: LHsExpr GhcRn -> ExpRhoType -> TcM (LHsExpr GhcTc) tcBody body res_ty   = do  { traceTc "tcBody" (ppr res_ty)-        ; tcMonoExpr body res_ty+        ; tcPolyLExpr body res_ty         } +tcBodyNC :: LHsExpr GhcRn -> ExpRhoType -> TcM (LHsExpr GhcTc)+tcBodyNC body res_ty+  = do  { traceTc "tcBodyNC" (ppr res_ty)+        ; tcMonoExprNC body res_ty+        }+ {- ************************************************************************ *                                                                      *@@ -349,13 +398,13 @@ type TcCmdStmtChecker  = TcStmtChecker HsCmd  TcRhoType  type TcStmtChecker body rho_type-  =  forall thing. HsStmtContext GhcTc+  =  forall thing. HsStmtContextRn                 -> Stmt GhcRn (LocatedA (body GhcRn))                 -> rho_type                 -- Result type for comprehension                 -> (rho_type -> TcM thing)  -- Checker for what follows the stmt                 -> TcM (Stmt GhcTc (LocatedA (body GhcTc)), thing) -tcStmts :: (AnnoBody body) => HsStmtContext GhcTc+tcStmts :: (AnnoBody body) => HsStmtContextRn         -> TcStmtChecker body rho_type   -- NB: higher-rank type         -> [LStmt GhcRn (LocatedA (body GhcRn))]         -> rho_type@@ -365,7 +414,7 @@                         const (return ())        ; return stmts' } -tcStmtsAndThen :: (AnnoBody body) => HsStmtContext GhcTc+tcStmtsAndThen :: (AnnoBody body) => HsStmtContextRn                -> TcStmtChecker body rho_type    -- NB: higher-rank type                -> [LStmt GhcRn (LocatedA (body GhcRn))]                -> rho_type@@ -382,7 +431,7 @@ -- LetStmts are handled uniformly, regardless of context tcStmtsAndThen ctxt stmt_chk (L loc (LetStmt x binds) : stmts)                                                              res_ty thing_inside-  = do  { (binds', (stmts',thing)) <- tcLocalBinds binds $+  = do  { (binds', _, (stmts',thing)) <- tcLocalBinds binds $               tcStmtsAndThen ctxt stmt_chk stmts res_ty thing_inside         ; return (L loc (LetStmt x binds') : stmts', thing) } @@ -857,7 +906,6 @@   = do { body' <- tcMonoExprNC body res_ty        ; thing <- thing_inside (panic "tcDoStmt: thing_inside")        ; return (LastStmt x body' noret noSyntaxExpr, thing) }- tcDoStmt ctxt (BindStmt xbsrn pat rhs) res_ty thing_inside   = do  {       -- Deal with rebindable syntax:                 --       (>>=) :: rhs_ty ->_rhs_mult (pat_ty ->_pat_mult new_res_ty) ->_fun_mult res_ty@@ -896,7 +944,6 @@                \ [rhs_ty] [rhs_mult] -> tcScalingUsage rhs_mult $ tc_app_stmts (mkCheckExpType rhs_ty))          ; return (ApplicativeStmt body_ty pairs' mb_join', thing) }- tcDoStmt _ (BodyStmt _ rhs then_op _) res_ty thing_inside   = do  {       -- Deal with rebindable syntax;                 --   (>>) :: rhs_ty -> new_res_ty -> res_ty@@ -909,7 +956,6 @@         ; hasFixedRuntimeRep_syntactic (FRRBodyStmt DoNotation 1) rhs_ty         ; hasFixedRuntimeRep_syntactic (FRRBodyStmt DoNotation 2) new_res_ty         ; return (BodyStmt rhs_ty rhs' then_op' noSyntaxExpr, thing) }- tcDoStmt ctxt (RecStmt { recS_stmts = L l stmts, recS_later_ids = later_names                        , recS_rec_ids = rec_names, recS_ret_fn = ret_op                        , recS_mfix_fn = mfix_op, recS_bind_fn = bind_op })@@ -988,7 +1034,7 @@ -- yet determined. tcMonadFailOp orig pat fail_op res_ty = do     dflags <- getDynFlags-    if isIrrefutableHsPatRn dflags pat+    if isIrrefutableHsPat dflags pat       then return Nothing       else Just . snd <$> (tcSyntaxOp orig fail_op [synKnownType stringTy]                             (mkCheckExpType res_ty) $ \_ _ -> return ())@@ -1038,7 +1084,7 @@ -}  tcApplicativeStmts-  :: HsStmtContext GhcTc+  :: HsStmtContextRn   -> [(SyntaxExpr GhcRn, ApplicativeArg GhcRn)]   -> ExpRhoType                         -- rhs_ty   -> (TcRhoType -> TcM t)               -- thing_inside@@ -1154,21 +1200,33 @@ -}  -- | @checkArgCounts@ takes a @[RenamedMatch]@ and decides whether the same--- number of args are used in each equation.+-- number of /required/ args are used in each equation.+-- Returns the arity, the number of required args+-- E.g.  f @a True  y = ...+--       f    False z = ...+--       The MatchGroup for `f` has arity 2, not 3 checkArgCounts :: AnnoBody body-          => HsMatchContext GhcTc -> MatchGroup GhcRn (LocatedA (body GhcRn))-          -> TcM ()-checkArgCounts _ (MG { mg_alts = L _ [] })-    = return ()-checkArgCounts matchContext (MG { mg_alts = L _ (match1:matches) })+               => MatchGroup GhcRn (LocatedA (body GhcRn))+               -> TcM VisArity+checkArgCounts (MG { mg_alts = L _ [] })+    = return 1 -- See Note [Empty MatchGroups] in GHC.Rename.Bind+               --   case e of {} or \case {}+               -- Both have arity 1++checkArgCounts (MG { mg_alts = L _ (match1:matches) })+    | null matches  -- There was only one match; nothing to check+    = return n_args1++    -- Two or more matches: check that they agree on arity     | Just bad_matches <- mb_bad_matches-    = failWithTc $ TcRnMatchesHaveDiffNumArgs matchContext+    = failWithTc $ TcRnMatchesHaveDiffNumArgs (m_ctxt (unLoc match1))                  $ MatchArgMatches match1 bad_matches     | otherwise-    = return ()+    = return n_args1   where-    n_args1 = args_in_match match1-    mb_bad_matches = NE.nonEmpty [m | m <- matches, args_in_match m /= n_args1]+    n_args1 = reqd_args_in_match match1+    mb_bad_matches = NE.nonEmpty [m | m <- matches, reqd_args_in_match m /= n_args1] -    args_in_match :: (LocatedA (Match GhcRn body1) -> Int)-    args_in_match (L _ (Match { m_pats = pats })) = length pats+    reqd_args_in_match :: LocatedA (Match GhcRn body1) -> VisArity+    -- Counts the number of /required/ args in the match+    reqd_args_in_match (L _ (Match { m_pats = pats })) = count (isVisArgPat . unLoc) pats
compiler/GHC/Tc/Gen/Match.hs-boot view
@@ -1,17 +1,21 @@ module GHC.Tc.Gen.Match where-import GHC.Hs           ( GRHSs, MatchGroup, LHsExpr )-import GHC.Tc.Types.Evidence  ( HsWrapper )-import GHC.Tc.Utils.TcType( ExpSigmaType, ExpRhoType )+import GHC.Hs           ( GRHSs, MatchGroup, LHsExpr, Mult )+import GHC.Tc.Utils.TcType( ExpSigmaType, ExpRhoType, ExpPatType ) import GHC.Tc.Types     ( TcM )+import GHC.Tc.Types.Origin  ( UserTypeCtxt )+import GHC.Tc.Types.Evidence  ( HsWrapper )+import GHC.Types.Name    ( Name ) import GHC.Hs.Extension ( GhcRn, GhcTc )-import GHC.Parser.Annotation ( LocatedN )-import GHC.Types.Name (Name) -tcGRHSsPat    :: GRHSs GhcRn (LHsExpr GhcRn)+tcGRHSsPat    :: Mult+              -> GRHSs GhcRn (LHsExpr GhcRn)               -> ExpRhoType               -> TcM (GRHSs GhcTc (LHsExpr GhcTc)) -tcMatchesFun :: LocatedN Name-             -> MatchGroup GhcRn (LHsExpr GhcRn)-             -> ExpSigmaType-             -> TcM (HsWrapper, MatchGroup GhcTc (LHsExpr GhcTc))+tcFunBindMatches  :: UserTypeCtxt+                  -> Name+                  -> Mult+                  -> MatchGroup GhcRn (LHsExpr GhcRn)+                  -> [ExpPatType]+                  -> ExpSigmaType+                  -> TcM (HsWrapper, MatchGroup GhcTc (LHsExpr GhcTc))
compiler/GHC/Tc/Gen/Pat.hs view
@@ -1,6 +1,7 @@ {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE RankNTypes #-}+{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TupleSections #-} {-# LANGUAGE TypeFamilies #-} @@ -18,8 +19,9 @@    , newLetBndr    , LetBndrSpec(..)    , tcCheckPat, tcCheckPat_O, tcInferPat-   , tcPats+   , tcMatchPats    , addDataConStupidTheta+   , isIrrefutableHsPatRnTcM    ) where @@ -65,7 +67,6 @@ import GHC.Utils.Misc import GHC.Utils.Outputable as Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import qualified GHC.LanguageExtensions as LangExt import Control.Arrow  ( second ) import Control.Monad@@ -76,6 +77,7 @@ import Language.Haskell.Syntax.Basic (FieldLabelString(..))  import Data.List( partition )+import Data.Maybe (isJust)  {- ************************************************************************@@ -98,34 +100,122 @@              penv = PE { pe_lazy = True                        , pe_ctxt = ctxt                        , pe_orig = PatOrigin }+       ; dflags <- getDynFlags+       ; mult_co_wrap <- manyIfLazy dflags pat+       -- The wrapper checks for correct multiplicities.+       -- See Note [Wrapper returned from tcSubMult] in GHC.Tc.Utils.Unify.+       ; (pat', r) <- tc_lpat pat_ty penv pat thing_inside+       ; pat_ty' <- readExpType (scaledThing pat_ty)+       ; return (mkLHsWrapPat mult_co_wrap pat' pat_ty', r) }+  where+    -- The logic is partly duplicated from decideBangHood in+    -- GHC.HsToCore.Utils. Ugh…+    manyIfLazy dflags lpat+      | xopt LangExt.Strict dflags = xstrict lpat+      | otherwise = not_xstrict lpat+      where+        xstrict p@(L _ (LazyPat _ _)) = checkManyPattern LazyPatternReason p pat_ty+        xstrict (L _ (ParPat _ p)) = xstrict p+        xstrict _ = return WpHole -       ; tc_lpat pat_ty penv pat thing_inside }+        not_xstrict (L _ (BangPat _ _)) = return WpHole+        not_xstrict (L _ (VarPat _ _)) = return WpHole+        not_xstrict (L _ (ParPat _ p)) = not_xstrict p+        not_xstrict p = checkManyPattern LazyPatternReason p pat_ty  ------------------tcPats :: HsMatchContext GhcTc-       -> [LPat GhcRn]             -- ^ atterns-       -> [Scaled ExpSigmaTypeFRR] -- ^ types of the patterns-       -> TcM a                    -- ^ checker for the body-       -> TcM ([LPat GhcTc], a)+tcMatchPats :: forall a.+               HsMatchContextRn+            -> [LPat GhcRn]          -- ^ patterns+            -> [ExpPatType]             -- ^ types of the patterns+            -> TcM a                    -- ^ checker for the body+            -> TcM ([LPat GhcTc], a)+-- See Note [tcMatchPats]+--+-- PRECONDITION:+--    number of visible pats::[LPat GhcRn]   (p is visible, @p is invisible)+--      ==+--    number of visible pat_tys::[ExpPatType]   (ExpFunPatTy is visible,+--                                               ExpForAllPatTy b is visible iff b is Required)+--+-- POSTCONDITION:+--   Returns only the /value/ patterns; see Note [tcMatchPats] --- This is the externally-callable wrapper function--- Typecheck the patterns, extend the environment to bind the variables,--- do the thing inside, use any existentially-bound dictionaries to--- discharge parts of the returning LIE, and deal with pattern type--- signatures+tcMatchPats match_ctxt pats pat_tys thing_inside+  = assertPpr (count isVisibleExpPatType pat_tys == count (isVisArgPat . unLoc) pats)+              (ppr pats $$ ppr pat_tys) $+       -- Check PRECONDITION+       -- When we get @patterns the (length pats) will change+    do { err_ctxt <- getErrCtxt+       ; let loop :: [LPat GhcRn] -> [ExpPatType] -> TcM ([LPat GhcTc], a) ---   1. Initialise the PatState---   2. Check the patterns---   3. Check the body---   4. Check that no existentials escape+             -- No more patterns.  Discard excess pat_tys;+             -- they should all be invisible.  Example:+             --    f :: Int -> forall a b. blah+             --    f x @p = rhs+             -- We will call tcMatchPats with+             --   pats = [x, @p]+             --   pat_tys = [Int, @a, @b]+             loop [] pat_tys+               = assertPpr (not (any isVisibleExpPatType pat_tys)) (ppr pats $$ ppr pat_tys) $+                 do { res <- setErrCtxt err_ctxt thing_inside+                    ; return ([], res) } -tcPats ctxt pats pat_tys thing_inside-  = tc_lpats pat_tys penv pats thing_inside+             -- ExpForAllPat: expecting a type pattern+             loop all_pats@(pat : pats) (ExpForAllPatTy (Bndr tv vis) : pat_tys)+               | isVisibleForAllTyFlag vis+               = do { (_p, (ps, res)) <- tc_forall_lpat tv penv pat $+                                         loop pats pat_tys++                    ; return (ps, res) }+                    -- This VisPat is Erased.+                    -- See Note [Invisible binders in functions] in GHC.Hs.Pat++               -- Invisible (Specified) forall in type, and an @a type pattern+               -- E.g.    f :: forall a. Bool -> a -> blah+               --         f @b True  x = rhs1  -- b is bound to skolem a+               --         f @c False y = rhs2  -- c is bound to skolem a+               | L _ (InvisPat _ tp) <- pat+               , isSpecifiedForAllTyFlag vis+               = do { (_p, (ps, res)) <- tc_ty_pat tp tv $+                                         loop pats pat_tys+                    ; return (ps, res) }++               | otherwise  -- Discard invisible pat_ty+               = loop all_pats pat_tys++             -- This case handles the user error when an InvisPat is used+             -- without a corresponding invisible (Specified) forall in the type+             -- E.g. 1.  f :: Int+             --          f @a = ...   -- loop (InvisPat{} : _) []+             --      2.  f :: Int -> Int+             --          f @a x = ... -- loop (InvisPat{} : _) (ExpFunPatTy{} : _)+             --      3.  f :: forall a -> Int+             --          f @a t = ... -- loop (InvisPat{} : _) (ExpForAllPatTy (Bndr _ Required) : _)+             --      4.  f :: forall {a}. Int+             --          f @a t = ... -- loop (InvisPat{} : _) (ExpForAllPatTy (Bndr _ Inferred) : _)+             loop (L loc (InvisPat _ tp) : _) _ =+                failAt (locA loc) (TcRnInvisPatWithNoForAll tp)++             -- ExpFunPatTy: expecting a value pattern+             -- tc_lpat will error if it sees a @t type pattern+             loop (pat : pats) (ExpFunPatTy pat_ty : pat_tys)+               = do { (p, (ps, res)) <- tc_lpat pat_ty penv pat $+                                        loop pats pat_tys+                    ; return (p : ps, res) }+                    -- This VisPat is Retained.+                    -- See Note [Invisible binders in functions] in GHC.Hs.Pat++             loop pats@(_:_) [] = pprPanic "tcMatchPats" (ppr pats)+                    -- Failure of PRECONDITION++       ; loop pats pat_tys }   where-    penv = PE { pe_lazy = False, pe_ctxt = LamPat ctxt, pe_orig = PatOrigin }+    penv = PE { pe_lazy = False, pe_ctxt = LamPat match_ctxt, pe_orig = PatOrigin } + tcInferPat :: FixedRuntimeRepContext-           -> HsMatchContext GhcTc+           -> HsMatchContextRn            -> LPat GhcRn            -> TcM a            -> TcM ((LPat GhcTc, a), TcSigmaTypeFRR)@@ -135,14 +225,14 @@  where     penv = PE { pe_lazy = False, pe_ctxt = LamPat ctxt, pe_orig = PatOrigin } -tcCheckPat :: HsMatchContext GhcTc+tcCheckPat :: HsMatchContextRn            -> LPat GhcRn -> Scaled TcSigmaTypeFRR            -> TcM a                     -- Checker for body            -> TcM (LPat GhcTc, a) tcCheckPat ctxt = tcCheckPat_O ctxt PatOrigin  -- | A variant of 'tcPat' that takes a custom origin-tcCheckPat_O :: HsMatchContext GhcTc+tcCheckPat_O :: HsMatchContextRn              -> CtOrigin              -- ^ origin to use if the type needs inst'ing              -> LPat GhcRn -> Scaled TcSigmaTypeFRR              -> TcM a                 -- Checker for body@@ -153,7 +243,26 @@     penv = PE { pe_lazy = False, pe_ctxt = LamPat ctxt, pe_orig = orig }  -{-+{- Note [tcMatchPats]+~~~~~~~~~~~~~~~~~~~~~+tcMatchPats is the externally-callable wrapper function for+  function definitions  f p1 .. pn = rhs+  lambdas               \p1 .. pn -> body+Typecheck the patterns, extend the environment to bind the variables, do the+thing inside, use any existentially-bound dictionaries to discharge parts of+the returning LIE, and deal with pattern type signatures++It takes the list of patterns writen by the user, but it returns only the+/value/ patterns.  For example:+     f :: forall a. forall b -> a -> Mabye b -> blah+     f @a w x (Just y) = ....+tcMatchPats returns only the /value/ patterns [x, Just y].  Why?  The+desugarer expects only value patterns.  (We could change that, but we would+have to do so carefullly.)  However, distinguishing value patterns from type+patterns is a bit tricky; e.g. the `w` in this example.  So it's very+convenient to filter them out right here.++ ************************************************************************ *                                                                      *                 PatEnv, PatCtxt, LetBndrSpec@@ -169,7 +278,7 @@  data PatCtxt   = LamPat   -- Used for lambdas, case etc-       (HsMatchContext GhcTc)+      HsMatchContextRn    | LetPat   -- Used only for let(rec) pattern bindings              -- See Note [Typing patterns in pattern bindings]@@ -325,21 +434,21 @@ tcMultiple :: Checker inp out -> Checker [inp] [out] tcMultiple tc_pat penv args thing_inside   = do  { err_ctxt <- getErrCtxt-        ; let loop _ []+        ; let loop []                 = do { res <- thing_inside                      ; return ([], res) } -              loop penv (arg:args)+              loop (arg:args)                 = do { (p', (ps', res))                                 <- tc_pat penv arg $                                    setErrCtxt err_ctxt $-                                   loop penv args+                                   loop args                 -- setErrCtxt: restore context before doing the next pattern                 -- See Note [Nesting] above                       ; return (p':ps', res) } -        ; loop penv args }+        ; loop args }  -------------------- tc_lpat :: Scaled ExpSigmaTypeFRR@@ -360,9 +469,100 @@  -------------------- -- See Note [Wrapper returned from tcSubMult] in GHC.Tc.Utils.Unify.-checkManyPattern :: Scaled a -> TcM HsWrapper-checkManyPattern pat_ty = tcSubMult NonLinearPatternOrigin ManyTy (scaledMult pat_ty)+checkManyPattern :: NonLinearPatternReason -> LPat GhcRn -> Scaled a -> TcM HsWrapper+checkManyPattern reason pat pat_ty = tcSubMult (NonLinearPatternOrigin reason pat) ManyTy (scaledMult pat_ty) ++tc_forall_lpat :: TcTyVar -> Checker (LPat GhcRn) (LPat GhcTc)+tc_forall_lpat tv penv (L span pat) thing_inside+  = setSrcSpanA span $+    do  { (pat', res) <- maybeWrapPatCtxt pat (tc_forall_pat tv penv pat)+                                          thing_inside+        ; return (L span pat', res) }++tc_forall_pat :: TcTyVar -> Checker (Pat GhcRn) (Pat GhcTc)+tc_forall_pat tv penv (ParPat x lpat) thing_inside+  = do { (lpat', res) <- tc_forall_lpat tv penv lpat thing_inside+       ; return (ParPat x lpat', res) }++tc_forall_pat tv _ (EmbTyPat _ tp) thing_inside+  -- The entire type pattern is guarded with the `type` herald:+  --    f (type t) (x :: t) = ...+  -- This special case is not necessary for correctness but avoids+  -- a redundant `ExpansionPat` node.+  = do { (arg_ty, result) <- tc_ty_pat tp tv thing_inside+       ; return (EmbTyPat arg_ty tp, result) }++tc_forall_pat tv _ pat thing_inside+  -- The type pattern is not guarded with the `type` herald, or perhaps+  -- only parts of it are, e.g.+  --    f (t :: Type)        (x :: t) = ...    -- no `type` herald+  --    f ((type t) :: Type) (x :: t) = ...    -- nested `type` herald+  -- Apply a recursive T2T transformation.+  = do { tp <- pat_to_type_pat pat+       ; (arg_ty, result) <- tc_ty_pat tp tv thing_inside+       ; let pat' = XPat $ ExpansionPat pat (EmbTyPat arg_ty tp)+       ; return (pat', result) }++-- Convert a Pat into the equivalent HsTyPat.+-- See `expr_to_type` (GHC.Tc.Gen.App) for the HsExpr counterpart.+-- The `TcM` monad is only used to fail on ill-formed type patterns.+pat_to_type_pat :: Pat GhcRn -> TcM (HsTyPat GhcRn)+pat_to_type_pat (EmbTyPat _ tp) = return tp+pat_to_type_pat (VarPat _ lname)  = return (HsTP x b)+  where b = noLocA (HsTyVar noAnn NotPromoted lname)+        x = HsTPRn { hstp_nwcs    = []+                   , hstp_imp_tvs = []+                   , hstp_exp_tvs = [unLoc lname] }+pat_to_type_pat (WildPat _) = return (HsTP x b)+  where b = noLocA (HsWildCardTy noExtField)+        x = HsTPRn { hstp_nwcs    = []+                   , hstp_imp_tvs = []+                   , hstp_exp_tvs = [] }+pat_to_type_pat (SigPat _ pat sig_ty)+  = do { HsTP x_hstp t <- pat_to_type_pat (unLoc pat)+       ; let { !(HsPS x_hsps k) = sig_ty+             ; x = append_hstp_hsps x_hstp x_hsps+             ; b = noLocA (HsKindSig noAnn t k) }+       ; return (HsTP x b) }+  where+    -- Quadratic for nested signatures ((p :: t1) :: t2)+    -- but those are unlikely to occur in practice.+    append_hstp_hsps :: HsTyPatRn -> HsPSRn -> HsTyPatRn+    append_hstp_hsps t p+      = HsTPRn { hstp_nwcs     = hstp_nwcs    t ++ hsps_nwcs    p+               , hstp_imp_tvs  = hstp_imp_tvs t ++ hsps_imp_tvs p+               , hstp_exp_tvs  = hstp_exp_tvs t }+pat_to_type_pat (ParPat _ pat)+  = do { HsTP x t <- pat_to_type_pat (unLoc pat)+       ; return (HsTP x (noLocA (HsParTy noAnn t))) }+pat_to_type_pat (SplicePat (HsUntypedSpliceTop mod_finalizers pat) splice) = do+      { HsTP x t <- pat_to_type_pat pat+      ; return (HsTP x (noLocA (HsSpliceTy (HsUntypedSpliceTop mod_finalizers t) splice))) }+pat_to_type_pat pat =+  -- There are other cases to handle (ConPat, ListPat, TuplePat, etc), but these+  -- would always be rejected by the unification in `tcHsTyPat`, so it's fine to+  -- skip them here. This won't continue to be the case when visible forall is+  -- permitted in data constructors:+  --+  --   data T a where { Typed :: forall a -> a -> T a }+  --   g :: T Int -> Int+  --   g (Typed Int x) = x   -- Note the `Int` type pattern+  --+  -- See ticket #18389. When this feature lands, it would be best to extend+  -- `pat_to_type_pat` to handle as many pattern forms as possible.+  failWith $ TcRnIllformedTypePattern pat+  -- This failure is the only use of the TcM monad in `pat_to_type_pat`++tc_ty_pat :: HsTyPat GhcRn -> TcTyVar -> TcM r -> TcM (TcType, r)+tc_ty_pat tp tv thing_inside+  = do { (sig_wcs, sig_ibs, arg_ty) <- tcHsTyPat tp (varType tv)+       ; _ <- unifyType Nothing arg_ty (mkTyVarTy tv)+       ; result <- tcExtendNameTyVarEnv sig_wcs $+                   tcExtendNameTyVarEnv sig_ibs $+                   thing_inside+       ; return (arg_ty, result) }+ tc_pat  :: Scaled ExpSigmaTypeFRR         -- ^ Fully refined result type         -> Checker (Pat GhcRn) (Pat GhcTc)@@ -378,16 +578,16 @@         ; pat_ty <- readExpType (scaledThing pat_ty)         ; return (mkHsWrapPat (wrap <.> mult_wrap) (VarPat x (L l id)) pat_ty, res) } -  ParPat x lpar pat rpar -> do+  ParPat x pat -> do         { (pat', res) <- tc_lpat pat_ty penv pat thing_inside-        ; return (ParPat x lpar pat' rpar, res) }+        ; return (ParPat x pat', res) }    BangPat x pat -> do         { (pat', res) <- tc_lpat pat_ty penv pat thing_inside         ; return (BangPat x pat', res) }    LazyPat x pat -> do-        { mult_wrap <- checkManyPattern pat_ty+        { mult_wrap <- checkManyPattern LazyPatternReason (noLocA ps_pat) pat_ty             -- See Note [Wrapper returned from tcSubMult] in GHC.Tc.Utils.Unify.         ; (pat', (res, pat_ct))                 <- tc_lpat pat_ty (makeLazy penv) pat $@@ -405,14 +605,14 @@         ; return (mkHsWrapPat mult_wrap (LazyPat x pat') pat_ty, res) }    WildPat _ -> do-        { mult_wrap <- checkManyPattern pat_ty+        { mult_wrap <- checkManyPattern OtherPatternReason (noLocA ps_pat) pat_ty             -- See Note [Wrapper returned from tcSubMult] in GHC.Tc.Utils.Unify.         ; res <- thing_inside         ; pat_ty <- expTypeToType (scaledThing pat_ty)         ; return (mkHsWrapPat mult_wrap (WildPat pat_ty) pat_ty, res) } -  AsPat x (L nm_loc name) at pat -> do-        { mult_wrap <- checkManyPattern pat_ty+  AsPat x (L nm_loc name) pat -> do+        { mult_wrap <- checkManyPattern OtherPatternReason (noLocA ps_pat) pat_ty             -- See Note [Wrapper returned from tcSubMult] in GHC.Tc.Utils.Unify.         ; (wrap, bndr_id) <- setSrcSpanA nm_loc (tcPatBndr penv name pat_ty)         ; (pat', res) <- tcExtendIdEnv1 name bndr_id $@@ -426,10 +626,10 @@             --             -- If you fix it, don't forget the bindInstsOfPatIds!         ; pat_ty <- readExpType (scaledThing pat_ty)-        ; return (mkHsWrapPat (wrap <.> mult_wrap) (AsPat x (L nm_loc bndr_id) at pat') pat_ty, res) }+        ; return (mkHsWrapPat (wrap <.> mult_wrap) (AsPat x (L nm_loc bndr_id) pat') pat_ty, res) }    ViewPat _ expr pat -> do-        { mult_wrap <- checkManyPattern pat_ty+        { mult_wrap <- checkManyPattern ViewPatternReason (noLocA ps_pat) pat_ty          -- See Note [Wrapper returned from tcSubMult] in GHC.Tc.Utils.Unify.          --          -- It should be possible to have view patterns at linear (or otherwise@@ -443,7 +643,7 @@          -- Expression must be a function         ; let herald = ExpectedFunTyViewPat $ unLoc expr         ; (expr_wrap1, Scaled _mult inf_arg_ty, inf_res_sigma)-            <- matchActualFunTySigma herald (Just . HsExprRnThing $ unLoc expr) (1,[]) expr_ty+            <- matchActualFunTy herald (Just . HsExprRnThing $ unLoc expr) (1,expr_ty) expr_ty                -- See Note [View patterns and polymorphism]                -- expr_wrap1 :: expr_ty "->" (inf_arg_ty -> inf_res_sigma) @@ -460,7 +660,7 @@                               (Scaled w pat_ty) inf_res_sigma           -- expr_wrap2' :: (inf_arg_ty -> inf_res_sigma) "->"           --                (pat_ty -> inf_res_sigma)-          -- NB: pat_ty comes from matchActualFunTySigma, so it has a+          -- NB: pat_ty comes from matchActualFunTy, so it has a           -- fixed RuntimeRep, as needed to call mkWpFun.         ; let               expr_wrap = expr_wrap2' <.> expr_wrap1 <.> mult_wrap@@ -482,7 +682,7 @@  Then, when taking that arrow apart we want to get a *sigma* type (forall b. b->(Int,b)), because that's what we want to bind 'x' to.-Fortunately that's what matchActualFunTySigma returns anyway.+Fortunately that's what matchActualFunTy returns anyway. -}  -- Type signatures in patterns@@ -595,7 +795,7 @@ -- -- When there is no negation, neg_lit_ty and lit_ty are the same   NPat _ (L l over_lit) mb_neg eq -> do-        { mult_wrap <- checkManyPattern pat_ty+        { mult_wrap <- checkManyPattern OtherPatternReason (noLocA ps_pat) pat_ty           -- See Note [Wrapper returned from tcSubMult] in GHC.Tc.Utils.Unify.           --           -- It may be possible to refine linear pattern so that they work in@@ -648,7 +848,7 @@ -- See Note [NPlusK patterns]   NPlusKPat _ (L nm_loc name)                (L loc lit) _ ge minus -> do-        { mult_wrap <- checkManyPattern pat_ty+        { mult_wrap <- checkManyPattern OtherPatternReason (noLocA ps_pat) pat_ty             -- See Note [Wrapper returned from tcSubMult] in GHC.Tc.Utils.Unify.         ; let pat_exp_ty = scaledThing pat_ty               orig = LiteralOrigin lit@@ -702,6 +902,10 @@    SplicePat (HsUntypedSpliceNested _) _ -> panic "tc_pat: nested splice in splice pat" +  EmbTyPat _ _ -> failWith TcRnIllegalTypePattern++  InvisPat _ _ -> panic "tc_pat: invisible pattern appears recursively in the pattern"+   XPat (HsPatExpanded lpat rpat) -> do     { (rpat', res) <- tc_pat pat_ty penv rpat thing_inside     ; return (XPat $ ExpansionPat lpat rpat', res) }@@ -1028,7 +1232,7 @@          ; when (any isEqPred prov_theta) warnMonoLocalBinds -        ; mult_wrap <- checkManyPattern pat_ty+        ; mult_wrap <- checkManyPattern PatternSynonymReason nlWildPatName pat_ty             -- See Note [Wrapper returned from tcSubMult] in GHC.Tc.Utils.Unify.          ; (univ_ty_args, ex_ty_args) <- splitConTyArgs con_like arg_pats@@ -1058,7 +1262,7 @@           -- 'tcDataConPat'.)         ; let             bad_arg_tys :: [(Int, Scaled Type)]-            bad_arg_tys = filter (\ (_, Scaled _ arg_ty) -> typeLevity_maybe arg_ty == Nothing)+            bad_arg_tys = filter (\ (_, Scaled _ arg_ty) -> not (typeHasFixedRuntimeRep arg_ty))                         $ zip [0..] arg_tys'         ; massertPpr (null bad_arg_tys) $             vcat [ text "tcPatSynPat: pattern arguments do not have a fixed RuntimeRep"@@ -1426,12 +1630,7 @@  tcConTyArg :: Subst -> Checker (HsConPatTyArg GhcRn, TyVar) () tcConTyArg tenv penv (HsConPatTyArg _ rn_ty, con_tv) thing_inside-  = do { (sig_wcs, sig_ibs, arg_ty) <- tcHsPatSigType TypeAppCtxt HM_TyAppPat rn_ty AnyKind-               -- AnyKind is a bit suspect: it really should be the kind gotten-               -- from instantiating the constructor type. But this would be-               -- hard to get right, because earlier type patterns might influence-               -- the kinds of later patterns. In any case, it all gets checked-               -- by the calls to unifyType below which unifies kinds+  = do { (sig_wcs, sig_ibs, arg_ty) <- tcHsTyPat rn_ty (substTy tenv (varType con_tv))         ; case NE.nonEmpty sig_ibs of            Just sig_ibs_ne | inPatBind penv ->@@ -1618,3 +1817,27 @@   where     has_existentials :: Bool     has_existentials = any (`elemVarSet` tyCoVarsOfTypes arg_tys) ex_tvs++-- | Very similar to GHC.Tc.Pat.isIrrefutableHsPat, but doesn't typecheck the pattern+--   It does depend on the type checker monad (`TcM`) however as we need to check ConPat case in more detail.+--   Specifically, we call `tcLookupGlobal` to obtain constructor details from global packages+--   for a comprehensive irrefutability check and avoid false negatives. (testcase pattern-fails.hs)+isIrrefutableHsPatRnTcM :: Bool -> LPat GhcRn -> TcM Bool+isIrrefutableHsPatRnTcM is_strict = isIrrefutableHsPatHelperM is_strict isConLikeIrr+  where+      doWork is_strict = isIrrefutableHsPatHelperM is_strict isConLikeIrr++      isConLikeIrr is_strict (L _ dcName) details =+        do { tyth <- tcLookupGlobal dcName+           ; case tyth of+               (ATyCon tycon) -> doCheck is_strict tycon details+               (AConLike cl) ->+                 case cl of+                   RealDataCon dc -> doCheck is_strict (dataConTyCon dc) details+                   PatSynCon _pat -> return False -- conservative+               _ -> return False                  -- conservative+           }++      doCheck is_strict tycon details =  do { let b = isJust (tyConSingleDataCon_maybe tycon)+                                            ; bs <- mapM (doWork is_strict) (hsConPatArgs details)+                                            ; return (b && and bs) }
compiler/GHC/Tc/Gen/Sig.hs view
@@ -8,12 +8,9 @@ {-# LANGUAGE TypeFamilies #-}  module GHC.Tc.Gen.Sig(-       TcSigInfo(..),-       TcIdSigInfo(..), TcIdSigInst,-       TcPatSynInfo(..),-       TcSigFun,+       TcSigInfo(..), TcIdSig(..), TcSigFun, -       isPartialSig, hasCompleteSig, tcIdSigName, tcSigInfoName,+       isPartialSig, hasCompleteSig, tcSigInfoName, tcIdSigLoc,        completeSigPolyId_maybe, isCompleteHsSig,        lhsSigWcTypeContextSpan, lhsSigTypeContextSpan, @@ -44,7 +41,7 @@ import GHC.Tc.Types.Origin import GHC.Tc.Utils.TcType import GHC.Tc.Validity ( checkValidType )-import GHC.Tc.Utils.Unify( tcTopSkolemise, unifyType )+import GHC.Tc.Utils.Unify( DeepSubsumptionFlag(..), tcSkolemise, unifyType ) import GHC.Tc.Utils.Instantiate( topInstantiate, tcInstTypeBndrs ) import GHC.Tc.Utils.Env( tcLookupId ) import GHC.Tc.Types.Evidence( HsWrapper, (<.>) )@@ -54,7 +51,6 @@ import GHC.Core.Multiplicity import GHC.Core.TyCo.Rep( mkNakedFunTy ) -import GHC.Types.Error import GHC.Types.Var ( TyVar, Specificity(..), tyVarKind, binderVars, invisArgTypeLike ) import GHC.Types.Id  ( Id, idName, idType, setInlinePragma                      , mkLocalId, realIdUnfolding )@@ -95,16 +91,16 @@ * When starting a mutually recursive group, like f/g above, we   call tcTySig on each signature in the group. -* tcTySig: Sig -> TcIdSigInfo+* tcTySig: Sig -> TcIdSig   - For a /complete/ signature, like 'f' above, tcTySig kind-checks-    the HsType, producing a Type, and wraps it in a CompleteSig, and+    the HsType, producing a Type, and wraps it in a TcCompleteSig, and     extend the type environment with this polymorphic 'f'.    - For a /partial/signature, like 'g' above, tcTySig does nothing     Instead it just wraps the pieces in a PartialSig, to be handled     later. -* tcInstSig: TcIdSigInfo -> TcIdSigInst+* tcInstSig: TcIdSig -> TcIdSigInst   In tcMonoBinds, when looking at an individual binding, we use   tcInstSig to instantiate the signature forall's in the signature,   and attribute that instantiated (monomorphic) type to the@@ -145,30 +141,8 @@  -} - {- ********************************************************************* *                                                                      *-             Utility functions for TcSigInfo-*                                                                      *-********************************************************************* -}--tcIdSigName :: TcIdSigInfo -> Name-tcIdSigName (CompleteSig { sig_bndr = id }) = idName id-tcIdSigName (PartialSig { psig_name = n })  = n--tcSigInfoName :: TcSigInfo -> Name-tcSigInfoName (TcIdSig     idsi) = tcIdSigName idsi-tcSigInfoName (TcPatSynSig tpsi) = patsig_name tpsi--completeSigPolyId_maybe :: TcSigInfo -> Maybe TcId-completeSigPolyId_maybe sig-  | TcIdSig sig_info <- sig-  , CompleteSig { sig_bndr = id } <- sig_info = Just id-  | otherwise                                 = Nothing---{- *********************************************************************-*                                                                      *                Typechecking user signatures *                                                                      * ********************************************************************* -}@@ -196,7 +170,7 @@                     -- NoRRC: do not report redundant constraints                     -- The user has no control over the signature!              sig = completeSigFromId ctxt id-       ; return [TcIdSig sig] }+       ; return [TcIdSig (TcCompleteSig sig)] }  tcTySig (L loc (TypeSig _ names sig_ty))   = setSrcSpanA loc $@@ -213,8 +187,7 @@ tcTySig _ = return []  -tcUserTypeSig :: SrcSpan -> LHsSigWcType GhcRn -> Maybe Name-              -> TcM TcIdSigInfo+tcUserTypeSig :: SrcSpan -> LHsSigWcType GhcRn -> Maybe Name -> TcM TcIdSig -- A function or expression type signature -- Returns a fully quantified type signature; even the wildcards -- are quantified with ordinary skolems that should be instantiated@@ -230,23 +203,23 @@   | isCompleteHsSig hs_sig_ty   = do { sigma_ty <- tcHsSigWcType ctxt_no_rrc hs_sig_ty        ; traceTc "tcuser" (ppr sigma_ty)-       ; return $-         CompleteSig { sig_bndr  = mkLocalId name ManyTy sigma_ty+       ; return $ TcCompleteSig $+         CSig { sig_bndr  = mkLocalId name ManyTy sigma_ty                                    -- We use `Many' as the multiplicity here,                                    -- as if this identifier corresponds to                                    -- anything, it is a top-level                                    -- definition. Which are all unrestricted in                                    -- the current implementation.-                     , sig_ctxt  = ctxt_rrc  -- Report redundant constraints-                     , sig_loc   = loc } }-                       -- Location of the <type> in   f :: <type>+              , sig_ctxt  = ctxt_rrc  -- Report redundant constraints+              , sig_loc   = loc } }   -- Location of the <type> in   f :: <type>    -- Partial sig with wildcards   | otherwise-  = return (PartialSig { psig_name = name, psig_hs_ty = hs_sig_ty-                       , sig_ctxt = ctxt_no_rrc, sig_loc = loc })+  = return $ TcPartialSig $+    PSig { psig_name = name, psig_hs_ty = hs_sig_ty+         , psig_ctxt = ctxt_no_rrc, psig_loc = loc }   where-    name   = case mb_name of+    name = case mb_name of                Just n  -> n                Nothing -> mkUnboundName (mkVarOccFS (fsLit "<expression>")) @@ -276,12 +249,12 @@     go (L _ (HsParTy _ hs_ty)) = go hs_ty  -- Look under parens     go _ = NoRRC  -- Did not find it -completeSigFromId :: UserTypeCtxt -> Id -> TcIdSigInfo+completeSigFromId :: UserTypeCtxt -> Id -> TcCompleteSig -- Used for instance methods and record selectors completeSigFromId ctxt id-  = CompleteSig { sig_bndr = id-                , sig_ctxt = ctxt-                , sig_loc  = getSrcSpan id }+  = CSig { sig_bndr = id+         , sig_ctxt = ctxt+         , sig_loc  = getSrcSpan id }  isCompleteHsSig :: LHsSigWcType GhcRn -> Bool -- ^ If there are no wildcards, return a LHsSigWcType@@ -299,7 +272,7 @@     go (L _ ty) = case ty of       HsWildCardTy _                 -> False       HsAppTy _ ty1 ty2              -> go ty1 && go ty2-      HsAppKindTy _ ty _ ki          -> go ty && go ki+      HsAppKindTy _ ty ki            -> go ty && go ki       HsFunTy _ w ty1 ty2            -> go ty1 && go ty2 && go (arrowToHsType w)       HsListTy _ ty                  -> go ty       HsTupleTy _ _ tys              -> gos tys@@ -401,7 +374,7 @@ completely solving them. -} -tcPatSynSig :: Name -> LHsSigType GhcRn -> TcM TcPatSynInfo+tcPatSynSig :: Name -> LHsSigType GhcRn -> TcM TcPatSynSig -- See Note [Pattern synonym signatures] -- See Note [Recipe for checking a signature] in GHC.Tc.Gen.HsType tcPatSynSig name sig_ty@(L _ (HsSig{sig_bndrs = hs_outer_bndrs, sig_body = hs_ty}))@@ -476,13 +449,14 @@               , text "ex_tvs" <+> ppr_tvs (binderVars ex_bndrs)               , text "prov" <+> ppr prov               , text "body_ty" <+> ppr body_ty ]-       ; return (TPSI { patsig_name = name-                      , patsig_implicit_bndrs = kv_bndrs ++ implicit_bndrs-                      , patsig_univ_bndrs     = univ_bndrs-                      , patsig_req            = req-                      , patsig_ex_bndrs       = ex_bndrs-                      , patsig_prov           = prov-                      , patsig_body_ty        = body_ty }) }+       ; return $+         PatSig { patsig_name = name+                , patsig_implicit_bndrs = kv_bndrs ++ implicit_bndrs+                , patsig_univ_bndrs     = univ_bndrs+                , patsig_req            = req+                , patsig_ex_bndrs       = ex_bndrs+                , patsig_prov           = prov+                , patsig_body_ty        = body_ty } }   where     ctxt = PatSynCtxt name @@ -514,9 +488,9 @@ ********************************************************************* -}  -tcInstSig :: TcIdSigInfo -> TcM TcIdSigInst+tcInstSig :: TcIdSig -> TcM TcIdSigInst -- Instantiate a type signature; only used with plan InferGen-tcInstSig hs_sig@(CompleteSig { sig_bndr = poly_id, sig_loc = loc })+tcInstSig hs_sig@(TcCompleteSig (CSig { sig_bndr = poly_id, sig_loc = loc }))   = setSrcSpan loc $  -- Set the binding site of the tyvars     do { (tv_prs, theta, tau) <- tcInstTypeBndrs (idType poly_id)               -- See Note [Pattern bindings and complete signatures]@@ -528,9 +502,9 @@                       , sig_inst_theta = theta                       , sig_inst_tau   = tau }) } -tcInstSig hs_sig@(PartialSig { psig_hs_ty = hs_ty-                             , sig_ctxt = ctxt-                             , sig_loc = loc })+tcInstSig hs_sig@(TcPartialSig (PSig { psig_hs_ty = hs_ty+                                     , psig_ctxt = ctxt+                                     , psig_loc = loc }))   = setSrcSpan loc $  -- Set the binding site of the tyvars     do { traceTc "Staring partial sig {" (ppr hs_sig)        ; (wcs, wcx, tv_prs, theta, tau) <- tcHsPartialSigType ctxt hs_ty@@ -545,7 +519,6 @@        ; traceTc "End partial sig }" (ppr inst_sig)        ; return inst_sig } - {- Note [Pattern bindings and complete signatures] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Consider@@ -778,7 +751,7 @@  tcSpecPrags :: Id -> [LSig GhcRn]             -> TcM [LTcSpecPrag]--- Add INLINE and SPECIALSE pragmas+-- Add INLINE and SPECIALISE pragmas --    INLINE prags are added to the (polymorphic) Id directly --    SPECIALISE prags are passed to the desugarer via TcSpecPrags -- Pre-condition: the poly_id is zonked@@ -832,7 +805,7 @@ -- See Note [Handling SPECIALISE pragmas], wrinkle 1 tcSpecWrapper ctxt poly_ty spec_ty   = do { (sk_wrap, inst_wrap)-               <- tcTopSkolemise ctxt spec_ty $ \ spec_tau ->+               <- tcSkolemise Shallow ctxt spec_ty $ \spec_tau ->                   do { (inst_wrap, tau) <- topInstantiate orig poly_ty                      ; _ <- unifyType Nothing spec_tau tau                             -- Deliberately ignore the evidence
compiler/GHC/Tc/Gen/Splice.hs view
@@ -21,7 +21,7 @@ -- | Template Haskell splices module GHC.Tc.Gen.Splice(      tcTypedSplice, tcTypedBracket, tcUntypedBracket,-     runAnnotation,+     runAnnotation, getUntypedSpliceBody,       runMetaE, runMetaP, runMetaT, runMetaD, runQuasi,      tcTopSpliceExpr, lookupThName_maybe,@@ -120,11 +120,10 @@  import GHC.Utils.Misc import GHC.Utils.Panic as Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Lexeme import GHC.Utils.Outputable import GHC.Utils.Logger-import GHC.Utils.Exception (throwIO, ErrorCall(..), SomeException(..))+import GHC.Utils.Exception (throwIO, ErrorCall(..))  import GHC.Utils.TmpFs ( newTempName, TempFileLifetime(..) ) @@ -640,13 +639,16 @@ ************************************************************************ -} +-- None of these functions add constraints to the LIE+ tcTypedBracket    :: HsExpr GhcRn -> LHsExpr GhcRn -> ExpRhoType -> TcM (HsExpr GhcTc) tcUntypedBracket  :: HsExpr GhcRn -> HsQuote GhcRn -> [PendingRnSplice] -> ExpRhoType                   -> TcM (HsExpr GhcTc)-tcTypedSplice :: Name -> LHsExpr GhcRn -> ExpRhoType -> TcM (HsExpr GhcTc)-        -- None of these functions add constraints to the LIE+tcTypedSplice     :: Name -> LHsExpr GhcRn -> ExpRhoType -> TcM (HsExpr GhcTc) -runAnnotation     :: CoreAnnTarget -> LHsExpr GhcRn -> TcM Annotation+getUntypedSpliceBody :: HsUntypedSpliceResult (HsExpr GhcRn) -> TcM (HsExpr GhcRn)+runAnnotation        :: CoreAnnTarget -> LHsExpr GhcRn -> TcM Annotation+ {- ************************************************************************ *                                                                      *@@ -797,7 +799,7 @@           TcRnTHError $ TypedTHError $ TypedTHWithPolyType exp_ty        ; codeCon <- tcLookupTyCon codeTyConName        ; let rep = getRuntimeRep exp_ty-       ; return (mkTyConApp codeCon [rep, m_ty, exp_ty]) }+       ; return (mkTyConApp codeCon [m_ty, rep, exp_ty]) }  quotationCtxtDoc :: LHsExpr GhcRn -> SDoc quotationCtxtDoc br_body@@ -816,6 +818,16 @@ ************************************************************************ -} +-- getUntypedSpliceBody: the renamer has expanded the splice.+-- Just run the finalizers that it produced, and return+-- the renamed expression+getUntypedSpliceBody (HsUntypedSpliceTop { utsplice_result_finalizers = mod_finalizers+                                         , utsplice_result = rn_expr })+  = do { addModFinalizersWithLclEnv mod_finalizers+       ; return rn_expr }+getUntypedSpliceBody (HsUntypedSpliceNested {})+  = panic "tcTopUntypedSplice: invalid nested splice"+ tcTypedSplice splice_name expr res_ty   = addErrCtxt (typedSpliceCtxtDoc splice_name expr) $     setSrcSpan (getLocA expr)    $ do@@ -972,7 +984,7 @@ -- do a debug-print.  The warning is because this should never happen -- /except/ when doing debug prints. stubNestedSplice = warnPprTrace True "stubNestedSplice" empty $-                   HsLit noComments (mkHsString "stubNestedSplice")+                   HsLit noExtField (mkHsString "stubNestedSplice")   {-@@ -1003,7 +1015,7 @@               ; let specialised_to_annotation_wrapper_expr                       = L loc' (mkHsWrap wrapper                                  (HsVar noExtField (L (noAnnSrcSpan loc) to_annotation_wrapper_id)))-              ; return (L loc' (HsApp noComments+              ; return (L loc' (HsApp noExtField                                 specialised_to_annotation_wrapper_expr expr'))                                 }) @@ -1270,7 +1282,7 @@     fail_with_exn phase exn = do         exn_msg <- liftIO $ Panic.safeShowException exn         failWithTc $ TcRnTHError $ THSpliceFailed $-          SpliceThrewException phase (SomeException exn) exn_msg expr show_code+          SpliceThrewException phase (toException exn) exn_msg expr show_code  {- Note [Running typed splices in the zonker]@@ -1884,7 +1896,7 @@         ; rdr_ty <- cvt th_origin loc (mkThAppTs (TH.ConT th_nm) th_tys)           -- #9262 says to bring vars into scope, like in HsForAllTy case           -- of rnHsTyKi-        ; let tv_rdrs = extractHsTyRdrTyVars rdr_ty+        ; tv_rdrs <- filterInScopeM $ extractHsTyRdrTyVars rdr_ty           -- Rename  to HsType Name         ; ((tv_names, rn_ty), _fvs)             <- checkNoErrs $ -- If there are out-of-scope Names here, then we@@ -1977,8 +1989,7 @@ getThSpliceOrigin :: TcM Origin getThSpliceOrigin = do   warn <- goptM Opt_EnableThSpliceWarnings-  if warn then return FromSource else return (Generated SkipPmc)-+  if warn then return FromSource else return (Generated OtherExpansion SkipPmc)  getThing :: TH.Name -> TcM TcTyThing getThing th_name
compiler/GHC/Tc/Gen/Splice.hs-boot view
@@ -10,7 +10,7 @@ import GHC.Types.Annotations ( Annotation, CoreAnnTarget ) import GHC.Hs.Extension ( GhcRn, GhcPs, GhcTc ) -import GHC.Hs ( HsQuote, HsExpr, LHsExpr, LHsType, LPat, LHsDecl, ThModFinalizers )+import GHC.Hs ( HsQuote, HsExpr, LHsExpr, LHsType, LPat, LHsDecl, ThModFinalizers, HsUntypedSpliceResult ) import qualified Language.Haskell.TH as TH  tcTypedSplice :: Name@@ -30,7 +30,8 @@  runTopSplice :: DelayedSplice -> TcM (HsExpr GhcTc) -runAnnotation     :: CoreAnnTarget -> LHsExpr GhcRn -> TcM Annotation+runAnnotation        :: CoreAnnTarget -> LHsExpr GhcRn -> TcM Annotation+getUntypedSpliceBody :: HsUntypedSpliceResult (HsExpr GhcRn) -> TcM (HsExpr GhcRn)  tcTopSpliceExpr :: SpliceType -> TcM (LHsExpr GhcTc) -> TcM (LHsExpr GhcTc) 
compiler/GHC/Tc/Instance/Class.hs view
@@ -1,4 +1,4 @@-+{-# LANGUAGE MultiWayIf #-} {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}  module GHC.Tc.Instance.Class (@@ -23,11 +23,13 @@ import GHC.Tc.Types.Evidence import GHC.Tc.Types.Origin (InstanceWhat (..), SafeOverlapping) import GHC.Tc.Instance.Family( tcGetFamInstEnvs, tcInstNewTyCon_maybe, tcLookupDataFamInst )-import GHC.Rename.Env( addUsedGRE, DeprecationWarnings (..) )+import GHC.Rename.Env( addUsedGRE, addUsedDataCons, DeprecationWarnings (..) )  import GHC.Builtin.Types import GHC.Builtin.Types.Prim import GHC.Builtin.Names+import GHC.Builtin.PrimOps ( PrimOp(..) )+import GHC.Builtin.PrimOps.Ids ( primOpId )  import GHC.Types.FieldLabel import GHC.Types.Name.Reader@@ -46,15 +48,27 @@ import GHC.Core.TyCon import GHC.Core.Class -import GHC.Core ( Expr(Var, App, Cast) )+import GHC.Core ( Expr(..) ) +import GHC.StgToCmm.Closure ( isSmallFamily )+ import GHC.Utils.Outputable import GHC.Utils.Panic import GHC.Utils.Misc( splitAtList, fstOf3 ) import GHC.Data.FastString +import GHC.Unit.Module.Warnings++import GHC.Hs.Extension+ import Language.Haskell.Syntax.Basic (FieldLabelString(..))+import GHC.Types.Id.Info+import GHC.Tc.Errors.Types+import Control.Monad +import Data.Functor+import Data.Maybe+ {- ******************************************************************* *                                                                    *               A helper for associated types within@@ -133,6 +147,7 @@   | isCTupleClass clas                 = matchCTuple                       clas tys   | cls_name == typeableClassName      = matchTypeable                     clas tys   | cls_name == withDictClassName      = matchWithDict                          tys+  | cls_name == dataToTagClassName     = matchDataToTag                    clas tys   | cls_name == hasFieldClassName      = matchHasField    dflags short_cut clas tys   | cls_name == unsatisfiableClassName = return NoInstance -- See (B) in Note [Implementation of Unsatisfiable constraints] in GHC.Tc.Errors   | otherwise                          = matchInstEnv     dflags short_cut clas tys@@ -177,12 +192,13 @@                  | otherwise                 -> do { let dfun_id = instanceDFunId ispec+                            warn    = instanceWarning ispec                       ; traceTc "matchClass success" $                         vcat [text "dict" <+> ppr pred <+> parens (if canonical then text "canonical" else text "non-canonical"),                               text "witness" <+> ppr dfun_id                                              <+> ppr (idType dfun_id) ]                                 -- Record that this dfun is needed-                      ; match_one (null unsafeOverlaps) canonical dfun_id inst_tys }+                      ; match_one (null unsafeOverlaps) canonical dfun_id inst_tys warn }              -- More than one matches (or Safe Haskell fail!). Defer any             -- reactions of a multitude until we learn more about the reagent@@ -194,8 +210,8 @@      pred = mkClassPred clas tys  match_one :: SafeOverlapping -> Canonical -> DFunId -> [DFunInstType]-          -> TcM ClsInstResult-match_one so canonical dfun_id mb_inst_tys+          -> Maybe (WarningTxt GhcRn) -> TcM ClsInstResult+match_one so canonical dfun_id mb_inst_tys warn   = do { traceTc "match_one" (ppr dfun_id $$ ppr mb_inst_tys)        ; (tys, theta) <- instDFunType dfun_id mb_inst_tys        ; traceTc "match_one 2" (ppr dfun_id $$ ppr tys $$ ppr theta)@@ -203,7 +219,8 @@                           , cir_mk_ev       = evDFunApp dfun_id tys                           , cir_canonical   = canonical                           , cir_what        = TopLevInstance { iw_dfun_id = dfun_id-                                                             , iw_safe_over = so } } }+                                                             , iw_safe_over = so+                                                             , iw_warn = warn } } }   {- Note [Shortcut solving: overlap]@@ -380,8 +397,8 @@  makeLitDict :: Class -> Type -> EvExpr -> TcM ClsInstResult -- makeLitDict adds a coercion that will convert the literal into a dictionary--- of the appropriate type.  See Note [KnownNat & KnownSymbol and EvLit]--- in GHC.Tc.Types.Evidence.  The coercion happens in 2 steps:+-- of the appropriate type.  See Note [KnownNat & KnownSymbol and EvLit].+-- The coercion happens in 2 steps: -- --     Integer -> SNat n     -- representation of literal to singleton --     SNat n  -> KnownNat n -- singleton to dictionary@@ -599,10 +616,339 @@        See test-case T21575b. +++Note [DataToTag overview]+~~~~~~~~~~~~~~~~~~~~~~~~~+Class `DataToTag` is defined like this, in GHC.Magic:++  type DataToTag :: forall {lev :: Levity}.+                    TYPE (BoxedRep lev) -> Constraint+  class DataToTag a where+     dataToTag# :: a -> Int#++`dataToTag#`, evaluates its argument and returns the index of the data+constructor used to build that argument.  Clearly, `dataToTag#` cannot+work on /any/ type, only on data types, hence the type-class constraint.++Users cannot define instances of `DataToTag`+(see `GHC.Tc.Validity.check_special_inst_head`).+Instead, GHC's constraint solver has built-in solving behaviour,+ implemented in `GHC.Tc.Instance.Class.matchGlobalInst`.++(#20441: This common handling of special typeclasses is a bit of a+mess and could use some love, and a dedicated Note.)++GHC solves a wanted constraint `DataToTag @{lev} dty`+when all of the following conditions are met:++C1: `dty` is an algebraic data type, i.e. `dty` matches any of:+       * a "data" declaration,+       * a "data instance" declaration,+       * a boxed tuple type+      "type data" declarations are NOT included; see also wrinkle W2c+      of Note [Type data declarations] in GHC.Rename.Module.+      (In principle we could accept newtypes that wrap algebraic data+      types, but we do not do so.)++C2: All of the constructors of that "data" or "data instance"+      declaration are in scope.  Otherwise, `dataToTag#` could be+      used to peek behind the curtain when used with an abstract+      data type whose constructors are intentionally hidden.++C3: `lev` is statically known, either Lifted or Unlifted:+      Otherwise the argument to `dataToTag#` would be+      representation-polymorphic and we couldn't do anything+      with it without Core Lint rightfully complaining.+      This guarantees invariant (DTT1) below.++It would be possible for GHC to generate custom code for each type, like+this:++   instance DataToTag [a] where+     dataToTag# []    = 0#+     dataToTag# (_:_) = 1#++But, to avoid all this boilerplate code, and improve optimisation opportunities,+GHC generates instances like this:++   instance DataToTag [a] where+     dataToTag# = dataToTagSmall#++using one of two dedicated primops: `dataToTagSmall#` and `dataToTagLarge#`.+(Why two primops? What's the difference? See wrinkles DTW4 and DTW5.)+Both primops have the following over-polymorphic type:++  dataToTagLarge# :: forall {l::levity} (a::TYPE (BoxedRep l)). a -> Int#++Every call to either primop that we generate should look like+(dataToTagSmall# @{lev} @ty) with two type arguments that satisfy+these conditions:++(DTT1) `lev` is concrete (either lifted or unlifted), not polymorphic.+   This is an invariant--we must satisfy this or Core Lint will complain.+   (This falls under situation 1 in GHC.Core.Lint's+   Note [Linting representation-polymorphic builtins].)++(DTT2) `ty` is always headed by a TyCon corresponding to one of the following:+   * A boxed tuple+   * A "data" declaration (but NOT a "type data" declaration)+   * The /representation type/ for a "data instance" declaration+     (but NOT the data family TyCon itself)++   This ensures that the DataCons associated with `ty` are easily+   accessible and safe to use in Core without running afoul of+   invariant I1 from Note [Type data declarations] in+   GHC.Rename.Module.  See Note [caseRules for dataToTag] in+   GHC.Core.Opt.ConstantFold for why this matters.++   While wrinkle DTW7 is unresolved, this cannot be a true invariant.+   But with a little effort we can ensure that every primop+   call we generate in a DataToTag instance satisfies this condition.++(DTT3) If the TyCon in wrinkle DTT2 is a "large data type" with more+   constructors than fit in pointer tags on the target, then the+   primop must be dataToTagLarge# and not dataToTagSmall#.+   Otherwise, the primop must be dataToTagSmall# and not dataToTagLarge#.+   (See wrinkles DTW4 and DTW5.)++These two primops have special handling in several parts of+the compiler:++H1. They have a couple of built-in rewrite rules, implemented in+    GHC.Core.Opt.ConstantFold.dataToTagRule++H2. The simplifier rewrites most case expressions scrutinizing their results.+    See Note [caseRules for dataToTag] in GHC.Core.Opt.ConstantFold.++H3. Each evaluates its argument.  But we want to omit this eval when the+    actual argument is already evaluated and properly tagged.  To do this,++    * We have a special case in GHC.Stg.InferTags.Rewrite.rewriteOpApp+      ensuring that any inferred tag information on the argument is+      retained until code generation.++    * We generate code via special cases in GHC.StgToCmm.Expr.cgExpr+      instead of with the other primops in GHC.StgToCmm.Prim.emitPrimOp;+      tag info is not readily available in the latter function.+      (Wrinkle DTW4 describes what we generate after the eval.)++Wrinkles:++(DTW1) To guarantee (DTT2) we need to take care with data families.+  Consider  data family D a+            data instance D (Either p q) = D1 | D2 p q+  To solve the constraint+     [W] DataToTag (D (Either t1 t2))+  GHC uses the built-in instance+     instance DataToTag (D (Either p q)) where+        dataToTag# x = dataToTagSmall# @Lifted @(R:DEither p q)+                                       (x |> sym (ax:DEither p q))+  where `ax:DEither` is the axiom arising from the `data instance`:+    ax:DEither p q :: D (Either p q) ~ R:DEither p q++  Notice that we cast `x` before giving it to `dataToTagSmall#`, so+  that (DTT2) is satisfied.++(DTW2) Suppose we have module A (T(..)) where { data T = TCon }+  and in module B, the constraint `DataToTag T` is needed. Per+  condition C2, we only solve this constraint if `TCon` is in+  scope.  So we had better not later report a warning about the+  import of `TCon` being unused in module B!++  To avoid this simply call `addUsedDataCons` when creating a built-in+  DataToTag instance.++(DTW3) Similar to DTW2, consider this example:++    {-# LANGUAGE MagicHash #-}+    module A (X(X2, X3), g) where+    -- see also testsuite/tests/warnings/should_compile/DataToTagWarnings.hs+    import GHC.Exts (dataToTag#, Int#)+    data X = X1 | X2 | X3 | X4+    g :: X -> Int#+    g X2 = 12#+    g v = dataToTag# v++  QUESTION: What warnings should be emitted with -Wunused-top-binds?++  The X1 and X4 constructors are used only in the solving of a+  `DataToTag X` constraint in the second equation for `g`.  But if+  these constructors were just removed, they would not be needed for+  the solving of that `DataToTag X` constraint!  So for now we take+  the stance that both X1 and X4 should be reported as unused.++  It's not entirely clear if this is the right behavior:+  Notice that removing X1 changes the value of `g X3` from 2# to 1#.+  (Removing X4 causes no observable change in behavior.)+  But this is a very obscure program!  The current "warn about both"+  approach is not obviously wrong, either, and is consistent with the+  behavior of derived Ix instances.++  To get these warnings, we do nothing; in particular we do not call+  keepAlive on the constructor names.+  (Contrast with Note [Unused name reporting and HasField].)++(DTW4) Why have two primops, `dataToTagSmall#` and `dataToTagLarge#`?+  The way tag information is stored at runtime is described in+  Note [Tagging big families] in GHC.StgToCmm.Expr.  In particular,+  for "big data types" we must consult the heap object's info table at+  least in the mAX_PTR_TAG case, while for "small data types" we can+  always just examine the tag bits on the pointer itself. So:++  * dataToTagSmall# consults the tag bits in the pointer, ignoring the+    info table.  It should, therefore, be used only for data type with+    few enough constructors that the tag always fits in the pointer.++  * dataToTagLarge# also consults the tag bits in the pointer, but+    must fall back to examining the info table whenever those tag+    bits are equal to mAX_PTR_TAG.++  One could imagine having one primop with a small/large tag, or just+  the data type width, but the PrimOp data type is not currently set+  up for that.  Looking at the type information on the argument during+  code generation is also possible, but would be less reliable.+  Remember: type information is not always preserved in STG.++(DTW5) How do the two primops differ in their semantics?  We consider+  a call `dataToTagSmall# x` to result in undefined behavior whenever+  the target supports pointer tagging but the actual constructor index+  for `x` is too large to fit in the pointer's tag bits.  Otherwise,+  `dataToTagSmall#` behaves identically to `dataToTagLarge#`.++  This allows the rewrites performed in GHC.Core.Opt.ConstantFold to+  safely treat `dataToTagSmall#` identically to `dataToTagLarge#`:+  the allowed program behaviors for the former is always a superset of+  the allowed program behaviors for the latter.++  This undefined behavior is only observable if a user writes a+  wrongly-sized primop call.  The calls we generate are properly-sized+  (condition DTT3 above) so that the type system protects us.++(DTW6) We make no promises about the primops used to implement+  DataToTag instances.  Changes to GHC's representation of algebraic+  data types at runtime may force us to redesign these primops.+  Indeed, accommodating such changes without breaking users of the+  original (no longer existing) "dataToTag#" primop is one of the+  main reasons the DataToTag class exists!++  In particular, our current two primop implementations (as described+  in wrinkle DTW4) are adequate for every DataToTag instance only+  because every Haskell-land data constructor use gets translated to+  its own "real" heap or static data object at runtime and the index+  of that constructor is always exposed via pointer tagging and via+  the object's info table.++(DTW7) Currently, the generated module GHC.PrimopWrappers in ghc-prim+  contains the following non-sense definitions:++    {-# NOINLINE dataToTagSmall# #-}+    dataToTagSmall# :: a_levpoly -> Int#+    dataToTagSmall# a1 = GHC.Prim.dataToTagSmall# a1+    {-# NOINLINE dataToTagLarge# #-}+    dataToTagLarge# :: a_levpoly -> Int#+    dataToTagLarge# a1 = GHC.Prim.dataToTagLarge# a1++  Why do these exist? GHCi uses these symbols for... something.  There+  is on-going work to get rid of them.  See also #24169, #20155, and !6245.+  Their continued existence makes it difficult to do several nice things:++   * As explained in DTW6, the dataToTag# primops are very internal.+     We would like to hide them from GHC.Prim entirely to prevent+     their mis-use, but doing so would cause GHC.PrimopWrappers to+     fail to compile.++   * The primops are applied at the (confusingly monomorphic) type+     variable `a_levpoly` in the above definitions.  In particular,+     they do not satisfy conditions DTT2 and DTT3 above.  We would+     very much like these conditions to be invariants, but while+     GHC.PrimopWrappers breaks them we cannot do so.  (The code that+     would check these invariants in Core Lint exists but remains+     commented out for now.)++   * This in turn means that `GHC.Core.Opt.ConstantFold.caseRules`+     must check for condition DTT2 before doing the work described in+     Note [caseRules for dataToTag].++   * Likewise, wrinkle DTW5 is only necessary because condition DTT3+     is not an invariant.  Otherwise, invoking the currently-specified+     undefined behavior of `dataToTagSmall# @ty` would require passing it+     an argument which will not really have type `ty` at runtime.  And+     evaluating such an expression is always undefined behavior anyway!++++Historical note:+During its time as a primop, `dataToTag#` underwent several changes,+mostly relating to under what circumstances it evaluates its argument.+Today, that story is simple: A dataToTag primop always evaluates its+argument, unless tag inference determines the argument was already+evaluated and correctly tagged.  Getting here was a long journey, with+many similarities to the story behind Note [Strict Field Invariant] in+GHC.Stg.InferTags.  See also #15696.+ -} + {- ******************************************************************** *                                                                     *+                   Class lookup for DataToTag+*                                                                     *+***********************************************************************-}++matchDataToTag :: Class -> [Type] -> TcM ClsInstResult+-- See Note [DataToTag overview]+matchDataToTag dataToTagClass [levity, dty] = do+  famEnvs <- tcGetFamInstEnvs+  (gbl_env, _lcl_env) <- getEnvs+  platform <- getPlatform+  if | isConcreteType levity -- condition C3+     , Just (rawTyCon, rawTyConArgs) <- tcSplitTyConApp_maybe dty+     , let (repTyCon, repArgs, repCo)+             = tcLookupDataFamInst famEnvs rawTyCon rawTyConArgs++     , not (isTypeDataTyCon repTyCon)+     , Just constrs <- tyConAlgDataCons_maybe repTyCon+         -- condition C1++     , let  rdr_env = tcg_rdr_env gbl_env+            inScope con = isJust $ lookupGRE_Name rdr_env $ dataConName con+     , all inScope constrs -- condition C2++     , let  repTy = mkTyConApp repTyCon repArgs+            numConstrs = tyConFamilySize repTyCon+            !whichOp -- see wrinkle DTW4+              | isSmallFamily platform numConstrs+                = primOpId DataToTagSmallOp+              | otherwise+                = primOpId DataToTagLargeOp++            -- See wrinkle DTW1; we must apply the underlying+            -- operation at the representation type and cast it+            methodRep = Var whichOp `App` Type levity `App` Type repTy+            methodCo = mkFunCo Representational+                               FTF_T_T+                               (mkNomReflCo ManyTy)+                               (mkSymCo repCo)+                               (mkReflCo Representational intPrimTy)+            dataToTagDataCon = tyConSingleDataCon (classTyCon dataToTagClass)+            mk_ev _ = evDataConApp dataToTagDataCon+                                   [levity, dty]+                                   [methodRep `Cast` methodCo]+     -> addUsedDataCons rdr_env repTyCon -- See wrinkles DTW2 and DTW3+          $> OneInst { cir_new_theta = [] -- (Ignore stupid theta.)+                     , cir_mk_ev = mk_ev+                     , cir_canonical = True+                     , cir_what = BuiltinInstance+                     }+     | otherwise -> pure NoInstance++matchDataToTag _ _ = pure NoInstance++++{- ********************************************************************+*                                                                     *                    Class lookup for Typeable *                                                                     * ***********************************************************************-}@@ -915,7 +1261,8 @@                -- the field selector should be in scope              , Just gre <- lookupGRE_FieldLabel rdr_env fl -             -> do { sel_id <- tcLookupId (flSelector fl)+             -> do { let name = flSelector fl+                   ; sel_id <- tcLookupId name                    ; (tv_prs, preds, sel_ty) <- tcInstType newMetaTyVars sel_id                           -- The first new wanted constraint equates the actual@@ -945,7 +1292,11 @@                    ; if not (isNaughtyRecordSelector sel_id) && isTauTy sel_ty                      then do { -- See Note [Unused name reporting and HasField]                                addUsedGRE AllDeprecationWarnings gre-                             ; keepAlive (greName gre)+                             ; keepAlive name+                             ; unless (null $ snd $ sel_cons $ idDetails sel_id)+                                 $ addDiagnostic $ TcRnHasFieldResolvedIncomplete name+                                 -- Only emit an incomplete selector warning if it's an implicit instance+                                 -- See Note [Detecting incomplete record selectors] in GHC.HsToCore.Pmc                              ; return OneInst { cir_new_theta   = theta                                               , cir_mk_ev       = mk_ev                                               , cir_canonical   = True
compiler/GHC/Tc/Instance/Family.hs view
@@ -46,7 +46,6 @@ import GHC.Utils.Outputable import GHC.Utils.Misc import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.FV  import GHC.Data.Bag( Bag, unionBags, unitBag )@@ -404,7 +403,7 @@   , let rep_tc = dataFamInstRepTyCon rep_fam         co     = mkUnbranchedAxInstCo Representational ax rep_args                                       (mkCoVarCos cvs)-  = assert (null rep_cos) $ -- See Note [Constrained family instances] in GHC.Core.FamInstEnv+  = assert (null rep_cos) $ -- See Note [Constrained family instances] in ??? (renamed?)     Just (rep_tc, rep_args, co)    | otherwise
compiler/GHC/Tc/Instance/FunDeps.hs view
@@ -96,7 +96,7 @@ Then `improveFromInstEnv` should return a FDEqn with    FDEqn { fd_qtvs = [], fd_eqs = [Pair Bool ty] } -describing an equality (Int ~ ty).  To do this we /match/ the instance head+describing an equality (Bool ~ ty).  To do this we /match/ the instance head against the [W], using just the LHS of the fundep; if we match, we return an equality for the RHS. @@ -527,7 +527,7 @@ closeWrtFunDeps is used  - when checking the coverage condition for an instance declaration  - when determining which tyvars are unquantifiable during generalization, in-   GHC.Tc.Solver.decideMonoTyVars.+   GHC.Tc.Solver.decidePromotedTyVars.  Note [Equality superclasses] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
compiler/GHC/Tc/Instance/Typeable.hs view
@@ -13,7 +13,7 @@ import GHC.Prelude import GHC.Platform -import GHC.Types.Basic ( Boxity(..), TypeOrConstraint(..), neverInlinePragma )+import GHC.Types.Basic ( TypeOrConstraint(..), neverInlinePragma ) import GHC.Types.SourceText ( SourceText(..) ) import GHC.Iface.Env( newGlobalBinder ) import GHC.Core.TyCo.Rep( Type(..), TyLit(..) )@@ -25,7 +25,7 @@ import GHC.Builtin.Names import GHC.Builtin.Types.Prim ( primTyCons ) import GHC.Builtin.Types-                  ( tupleTyCon, sumTyCon, runtimeRepTyCon+                  ( runtimeRepTyCon                   , levityTyCon, vecCountTyCon, vecElemTyCon                   , nilDataCon, consDataCon ) import GHC.Types.Name@@ -39,7 +39,6 @@ import GHC.Data.Bag import GHC.Types.Var ( VarBndr(..) ) import GHC.Core.Map.Type-import GHC.Settings.Constants import GHC.Utils.Fingerprint(Fingerprint(..), fingerprintString, fingerprintFingerprints) import GHC.Utils.Outputable import GHC.Utils.Panic@@ -105,7 +104,7 @@  * GHC.Prim doesn't have any associated object code, so we need to put the   representations for types defined in this module elsewhere. We chose this-  place to be GHC.Types. GHC.Tc.Instance.Typeable.mkPrimTypeableBinds is responsible for+  place to be GHC.Types. GHC.Tc.Instance.Typeable.mkPrimTypeableTodos is responsible for   injecting the bindings for the GHC.Prim representations when compiling   GHC.Types. @@ -354,12 +353,10 @@ -- The majority of the types we need here are contained in 'primTyCons'. -- However, not all of them: in particular unboxed tuples are absent since we -- don't want to include them in the original name cache. See--- Note [Built-in syntax and the OrigNameCache] in "GHC.Iface.Env" for more.+-- Note [Built-in syntax and the OrigNameCache] in "GHC.Types.Name.Cache" for more. ghcPrimTypeableTyCons :: [TyCon] ghcPrimTypeableTyCons = concat-    [ map (tupleTyCon Unboxed) [0..mAX_TUPLE_SIZE]-    , map sumTyCon [2..mAX_SUM_SIZE]-    , primTyCons+    [ primTyCons     ]  -- | These are types which are defined in GHC.Types but are needed in order to
compiler/GHC/Tc/Module.hs view
@@ -1,12 +1,8 @@ {-# LANGUAGE CPP #-}-{-# LANGUAGE BangPatterns #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE NondecreasingIndentation #-}-{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-}-{-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE TupleSections #-}  {-# OPTIONS_GHC -Wno-incomplete-record-updates #-} @@ -132,7 +128,6 @@ import GHC.Utils.Error import GHC.Utils.Outputable as Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Misc import GHC.Utils.Logger @@ -302,8 +297,8 @@         -- We will rename it properly after renaming everything else so that         -- haddock can link the identifiers         ; tcg_env <- return (tcg_env-                              { tcg_doc_hdr = fmap (\(WithHsDocIdentifiers str _) -> WithHsDocIdentifiers str [])-                                                                                 <$> maybe_doc_hdr })+                              { tcg_hdr_info = (fmap (\(WithHsDocIdentifiers str _) -> WithHsDocIdentifiers str [])+                                                <$> maybe_doc_hdr , maybe_mod ) })         ; -- If the whole module is warned about or deprecated           -- (via mod_deprec) record that in tcg_warns. If we do thereby add           -- a WarnAll, it will override any subsequent deprecations added to tcg_warns@@ -352,7 +347,7 @@                       -- Rename the module header properly after we have renamed everything else                       ; maybe_doc_hdr <- traverse rnLHsDoc maybe_doc_hdr;                       ; tcg_env <- return (tcg_env-                                            { tcg_doc_hdr = maybe_doc_hdr })+                                            { tcg_hdr_info = (maybe_doc_hdr, maybe_mod) })                        ; -- add extra source files to tcg_dependent_files                         addDependentFiles src_files@@ -792,10 +787,6 @@              -- TODO: Maybe setGlobalTypeEnv should be strict.           setGlobalTypeEnv tcg_env_w_binds type_env' } -#if __GLASGOW_HASKELL__ <= 810-  | otherwise = panic "checkHiBootIface: unreachable code"-#endif- {- Note [DFun impedance matching] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ We return a list of "impedance-matching" bindings for the dfuns@@ -3124,14 +3115,15 @@ -- exception/signal an error. type RenamedStuff =         (Maybe (HsGroup GhcRn, [LImportDecl GhcRn], Maybe [(LIE GhcRn, Avails)],-                Maybe (LHsDoc GhcRn)))+                Maybe (LHsDoc GhcRn), Maybe (XRec GhcRn ModuleName)))  -- | Extract the renamed information from TcGblEnv. getRenamedStuff :: TcGblEnv -> RenamedStuff getRenamedStuff tc_result   = fmap (\decls -> ( decls, tcg_rn_imports tc_result-                    , tcg_rn_exports tc_result, tcg_doc_hdr tc_result ) )+                    , tcg_rn_exports tc_result, doc_hdr, name_hdr ))          (tcg_rn_decls tc_result)+  where (doc_hdr, name_hdr) = tcg_hdr_info tc_result  runTypecheckerPlugin :: ModSummary -> TcGblEnv -> TcM TcGblEnv runTypecheckerPlugin sum gbl_env = do
compiler/GHC/Tc/Solver.hs view
@@ -38,6 +38,7 @@ import GHC.Data.FastString import GHC.Data.List.SetOps import GHC.Types.Name+import GHC.Types.Unique.Set import GHC.Types.Id import GHC.Utils.Outputable import GHC.Builtin.Utils@@ -63,11 +64,13 @@ import GHC.Core.Ppr import GHC.Core.TyCon    ( TyConBinder, isTypeFamilyTyCon ) import GHC.Builtin.Types-import GHC.Core.Unify    ( tcMatchTyKi )+import GHC.Core.Unify    ( tcMatchTyKis ) import GHC.Unit.Module ( getModule ) import GHC.Utils.Misc import GHC.Utils.Panic+import GHC.Types.TyThing ( MonadThings(lookupId) ) import GHC.Types.Var+import GHC.Types.Var.Env import GHC.Types.Var.Set import GHC.Types.Basic import GHC.Types.Id.Make  ( unboxedUnitExpr )@@ -77,10 +80,11 @@ import Control.Monad import Control.Monad.Trans.Class        ( lift ) import Control.Monad.Trans.State.Strict ( StateT(runStateT), put )-import Data.Foldable      ( toList )+import Data.Foldable      ( toList, traverse_ ) import Data.List          ( partition )-import Data.List.NonEmpty ( NonEmpty(..) )-import GHC.Data.Maybe     ( mapMaybe )+import Data.List.NonEmpty ( NonEmpty(..), nonEmpty )+import qualified Data.List.NonEmpty as NE+import GHC.Data.Maybe     ( mapMaybe, runMaybeT, MaybeT )  {- *********************************************************************************@@ -545,10 +549,7 @@      try_callstack_defaulting :: WantedConstraints -> TcS WantedConstraints     try_callstack_defaulting wc-      | isEmptyWC wc-      = return wc-      | otherwise-      = defaultCallStacks wc+      = defaultConstraints [defaultCallStack, defaultExceptionContext] wc  -- | If an implication contains a Given of the form @Unsatisfiable msg@, use -- it to solve all Wanteds within the implication.@@ -625,7 +626,7 @@          -- it's only used for the ambiguity check, which throws the evidence away anyway.          -- This avoids problems with circularity; where we are trying to look          -- up the "unsatisfiable" Id while we are in the middle of typechecking it.-       ; if mod == gHC_TYPEERROR then return (Var unsat_ev) else+       ; if mod == gHC_INTERNAL_TYPEERROR then return (Var unsat_ev) else     do { unsatisfiable_id <- tcLookupId unsatisfiableIdName           -- See Note [Evidence terms from Unsatisfiable Givens]@@ -693,19 +694,56 @@ (such as primitive equality constraints). -} +-- | A 'TcS' action which can may default a 'Ct'.+type CtDefaultingStrategy = Ct -> MaybeT TcS ()++-- | Default @ExceptionContext@ constraints to @emptyExceptionContext@.+defaultExceptionContext :: CtDefaultingStrategy+defaultExceptionContext ct+  = do { ClassPred cls tys <- pure $ classifyPredType (ctPred ct)+       ; Just {} <- pure $ isExceptionContextPred cls tys+       ; emptyEC <- Var <$> lift (lookupId emptyExceptionContextName)+       ; let ev = ctEvidence ct+       ; let ev_tm = mkEvCast emptyEC (wrapIP (ctEvPred ev))+       ; lift $ warnTcS $ TcRnDefaultedExceptionContext (ctLoc ct)+       ; lift $ setEvBindIfWanted ev False ev_tm+       }+ -- | Default any remaining @CallStack@ constraints to empty @CallStack@s.-defaultCallStacks :: WantedConstraints -> TcS WantedConstraints -- See Note [Overview of implicit CallStacks] in GHC.Tc.Types.Evidence-defaultCallStacks wanteds+defaultCallStack :: CtDefaultingStrategy+defaultCallStack ct+  = do { ClassPred cls tys <- pure $ classifyPredType (ctPred ct)+       ; Just {} <- pure $ isCallStackPred cls tys+       ; lift $ solveCallStack (ctEvidence ct) EvCsEmpty+       }++defaultConstraints :: [CtDefaultingStrategy]+                   -> WantedConstraints+                   -> TcS WantedConstraints+-- See Note [Overview of implicit CallStacks] in GHC.Tc.Types.Evidence+defaultConstraints defaulting_strategies wanteds+  | isEmptyWC wanteds = return wanteds+  | otherwise   = do simples <- handle_simples (wc_simple wanteds)        mb_implics <- mapBagM handle_implic (wc_impl wanteds)        return (wanteds { wc_simple = simples                        , wc_impl = catBagMaybes mb_implics })    where-+  handle_simples :: Bag Ct -> TcS (Bag Ct)   handle_simples simples-    = catBagMaybes <$> mapBagM defaultCallStack simples+    = catBagMaybes <$> mapBagM handle_simple simples+    where+      handle_simple :: Ct -> TcS (Maybe Ct)+      handle_simple ct = go defaulting_strategies+        where+          go [] = return (Just ct)+          go (f:fs) = do+              mb <- runMaybeT (f ct)+              case mb of+                Just () -> return Nothing+                Nothing -> go fs    handle_implic :: Implication -> TcS (Maybe Implication)   -- The Maybe is because solving the CallStack constraint@@ -717,19 +755,9 @@     = do { wanteds <- setEvBindsTcS (ic_binds implic) $                       -- defaultCallStack sets a binding, so                       -- we must set the correct binding group-                      defaultCallStacks (ic_wanted implic)+                      defaultConstraints defaulting_strategies (ic_wanted implic)          ; setImplicationStatus (implic { ic_wanted = wanteds }) } -  defaultCallStack ct-    | ClassPred cls tys <- classifyPredType (ctPred ct)-    , Just {} <- isCallStackPred cls tys-    = do { solveCallStack (ctEvidence ct) EvCsEmpty-         ; return Nothing }--  defaultCallStack ct-    = return (Just ct)-- {- Note [When to do type-class defaulting] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In GHC 7.6 and 7.8.2, we did type-class defaulting only if insolubleWC@@ -1357,7 +1385,7 @@              ; bound_theta_vars <- mapM TcM.newEvVar bound_theta               ; let full_theta = map idType bound_theta_vars-             ; skol_info <- mkSkolemInfo (InferSkol [ (name, mkSigmaTy [] full_theta ty)+             ; skol_info <- mkSkolemInfo (InferSkol [ (name, mkPhiTy full_theta ty)                                                     | (name, ty) <- name_taus ])        } @@ -1422,7 +1450,7 @@                                    , wc_impl   = implics }) }   where     full_theta = map idType full_theta_vars-    skol_info = InferSkol [ (name, mkSigmaTy [] full_theta ty)+    skol_info = InferSkol [ (name, mkPhiTy full_theta ty)                           | (name, ty) <- name_taus ]     -- We don't add the quantified variables here, because they are     -- also bound in ic_skols and we want them to be tidied@@ -3649,7 +3677,7 @@                        , text "groups  =" <+> ppr groups                        , text "info    =" <+> ppr info ] -       ; something_happeneds <- mapM (disambigGroup default_tys) groups+       ; something_happeneds <- mapM (disambigGroup wanteds default_tys) groups         ; traceTcS "applyDefaultingRules }" (ppr something_happeneds) @@ -3657,9 +3685,10 @@     where run_defaulting_plugin wanteds p =             do { groups <- runTcPluginTcS (p wanteds)                ; defaultedGroups <--                    filterM (\g -> disambigGroup-                                   (deProposalCandidates g)-                                   (deProposalTyVar g, deProposalCts g))+                    filterM (\g -> disambigMultiGroup+                                   wanteds+                                   (deProposalCts g)+                                   (deProposals g))                     groups                ; traceTcS "defaultingPlugin " $ ppr defaultedGroups                ; case defaultedGroups of@@ -3733,55 +3762,79 @@                        (ovl_strings && (cls `hasKey` isStringClassKey))  -------------------------------disambigGroup :: [Type]            -- The default types-              -> (TcTyVar, [Ct])   -- All constraints sharing same type variable+disambigGroup :: WantedConstraints -- ^ Original constraints, for diagnostic purposes+              -> [Type]            -- ^ The default types+              -> (TcTyVar, [Ct])   -- ^ All constraints sharing same type variable               -> TcS Bool   -- True <=> something happened, reflected in ty_binds -disambigGroup [] _-  = return False-disambigGroup (default_ty:default_tys) group@(the_tv, wanteds)-  = do { traceTcS "disambigGroup {" (vcat [ ppr default_ty, ppr the_tv, ppr wanteds ])-       ; fake_ev_binds_var <- TcS.newTcEvBinds-       ; tclvl             <- TcS.getTcLevel-       ; success <- nestImplicTcS fake_ev_binds_var (pushTcLevel tclvl) try_group+disambigGroup orig_wanteds default_tys (the_tv, wanteds)+  = disambigMultiGroup orig_wanteds wanteds [[(the_tv, default_ty)] | default_ty <- default_tys] -       ; if success then-             -- Success: record the type variable binding, and return-             do { unifyTyVar the_tv default_ty-                ; wrapWarnTcS $ warnDefaulting the_tv wanteds default_ty-                ; traceTcS "disambigGroup succeeded }" (ppr default_ty)-                ; return True }-         else-             -- Failure: try with the next type-             do { traceTcS "disambigGroup failed, will try other default types }"-                           (ppr default_ty)-                ; disambigGroup default_tys group } }+disambigMultiGroup :: WantedConstraints -- ^ Original constraints, for diagnostic purposes+                   -> [Ct]       -- ^ check these are solved by defaulting+                   -> [[(TcTyVar, Type)]]  -- ^ defaulting type assignments to try+                   -> TcS Bool   -- True <=> something happened, reflected in ty_binds+disambigMultiGroup orig_wanteds wanteds = anyM propose   where-    try_group-      | Just subst <- mb_subst-      = do { lcl_env <- TcS.getLclEnv-           ; tc_lvl <- TcS.getTcLevel-           ; let loc = mkGivenLoc tc_lvl (getSkolemInfo unkSkol) (mkCtLocEnv lcl_env)-           -- Equality constraints are possible due to type defaulting plugins-           ; wanted_evs <- sequence [ newWantedNC loc rewriters pred'-                                    | wanted <- wanteds-                                    , CtWanted { ctev_pred = pred-                                               , ctev_rewriters = rewriters }-                                        <- return (ctEvidence wanted)-                                    , let pred' = substTy subst pred ]-           ; fmap isEmptyWC $-             solveSimpleWanteds $ listToBag $-             map mkNonCanonical wanted_evs }+    propose proposal+        = do { traceTcS "disambigMultiGroup {" (vcat [ ppr proposal, ppr wanteds ])+             ; invalid_tvs <- filterOutM TcS.isUnfilledMetaTyVar tvs+             ; traverse_ (errInvalidDefaultedTyVar orig_wanteds proposal) (nonEmpty invalid_tvs)+             ; fake_ev_binds_var <- TcS.newTcEvBinds+             ; tclvl             <- TcS.getTcLevel+             ; mb_subst <- nestImplicTcS fake_ev_binds_var (pushTcLevel tclvl) try_group -      | otherwise-      = return False+             ; case mb_subst of+                   Just subst -> -- Success: record the type variable bindings, and return+                       do { deep_tvs <- filterM TcS.isUnfilledMetaTyVar $ nonDetEltsUniqSet $ closeOverKinds (mkVarSet tvs)+                          ; forM_ deep_tvs $ \ tv -> mapM_ (unifyTyVar tv) (lookupVarEnv (getTvSubstEnv subst) tv)+                          ; wrapWarnTcS $ mapM_ (uncurry $ warnDefaulting wanteds) proposal+                          ; traceTcS "disambigMultiGroup succeeded }" (ppr proposal)+                          ; return True }+                   Nothing -> -- Failure: try with the next defaulting group+                       do { traceTcS "disambigMultiGroup failed, will try other default types }"+                               (ppr proposal)+                          ; return False } }+      where+        (tvs, default_tys) = unzip proposal -    the_ty   = mkTyVarTy the_tv-    mb_subst = tcMatchTyKi the_ty default_ty-      -- Make sure the kinds match too; hence this call to tcMatchTyKi-      -- E.g. suppose the only constraint was (Typeable k (a::k))-      -- With the addition of polykinded defaulting we also want to reject-      -- ill-kinded defaulting attempts like (Eq []) or (Foldable Int) here.+        try_group+          | Just subst <- mb_subst+          = do { lcl_env <- TcS.getLclEnv+               ; tc_lvl <- TcS.getTcLevel+               ; let loc = mkGivenLoc tc_lvl (getSkolemInfo unkSkol) (mkCtLocEnv lcl_env)+               -- Equality constraints are possible due to type defaulting plugins+               ; wanted_evs <- sequence [ newWantedNC loc rewriters pred'+                                        | wanted <- wanteds+                                        , CtWanted { ctev_pred = pred+                                                   , ctev_rewriters = rewriters }+                                            <- return (ctEvidence wanted)+                                        , let pred' = substTy subst pred ]+               ; residual_wc <- solveSimpleWanteds $ listToBag $ map mkNonCanonical wanted_evs+               ; return $ if isEmptyWC residual_wc then Just subst else Nothing }++          | otherwise+          = return Nothing++        mb_subst = tcMatchTyKis (mkTyVarTys tvs) default_tys+          -- Make sure the kinds match too; hence this call to tcMatchTyKi+          -- E.g. suppose the only constraint was (Typeable k (a::k))+          -- With the addition of polykinded defaulting we also want to reject+          -- ill-kinded defaulting attempts like (Eq []) or (Foldable Int) here.++errInvalidDefaultedTyVar :: WantedConstraints -> [(TcTyVar, Type)] -> NonEmpty TcTyVar -> TcS ()+errInvalidDefaultedTyVar wanteds proposal problematic_tvs+  = failTcS $ TcRnInvalidDefaultedTyVar tidy_wanteds tidy_proposal tidy_problems+  where+    proposal_tvs = concatMap (\(tv, ty) -> tv : tyCoVarsOfTypeList ty) proposal+    tidy_env = tidyFreeTyCoVars emptyTidyEnv $ proposal_tvs ++ NE.toList problematic_tvs+    tidy_wanteds = map (tidyCt tidy_env) $ flattenWC wanteds+    tidy_proposal = [(tidyTyCoVarOcc tidy_env tv, tidyType tidy_env ty) | (tv, ty) <- proposal]+    tidy_problems = fmap (tidyTyCoVarOcc tidy_env) problematic_tvs++    flattenWC :: WantedConstraints -> [Ct]+    flattenWC (WC { wc_simple = cts, wc_impl = impls })+      = ctsElts cts ++ concatMap (flattenWC . ic_wanted) impls  -- In interactive mode, or with -XExtendedDefaultRules, -- we default Show a to Show () to avoid gratuitous errors on "show []"
compiler/GHC/Tc/Solver/Dict.hs view
@@ -34,6 +34,7 @@ import GHC.Core.Multiplicity ( scaledThing ) import GHC.Core.Unify ( ruleMatchTyKiX ) +import GHC.Types.Name import GHC.Types.Name.Set import GHC.Types.Var import GHC.Types.Id( mkTemplateLocals )@@ -46,6 +47,8 @@ import GHC.Utils.Panic import GHC.Utils.Misc +import GHC.Unit.Module+ import GHC.Data.Bag  import GHC.Driver.DynFlags@@ -57,7 +60,7 @@  import Control.Monad.Trans.Maybe( MaybeT, runMaybeT ) import Control.Monad.Trans.Class( lift )-import Control.Monad( mzero )+import Control.Monad   {- *********************************************************************@@ -95,7 +98,6 @@         ; doTopFunDepImprovement dict_ct -       ; tryLastResortProhibitedSuperClass dict_ct        ; simpleStage (updInertDicts dict_ct)        ; stopWithStage (dictCtEvidence dict_ct) "Kept inert DictCt" } @@ -795,7 +797,9 @@     try_solve_from_instance (ev_binds, solved_dicts) ev       | let pred = ctEvPred ev       , ClassPred cls tys <- classifyPredType pred-      = do { inst_res <- lift $ matchGlobalInst dflags True cls tys+      = do { inst_res <- lift $ matchGlobalInst dflags True cls tys loc_w+           ; lift $ warn_custom_warn_instance inst_res loc_w+                 -- See Note [Implementation of deprecated instances]            ; case inst_res of                OneInst { cir_new_theta   = preds                        , cir_mk_ev       = mk_ev@@ -956,12 +960,64 @@                    ; return local_res }             NoInstance  -- No local instances, so try global ones-              -> do { global_res <- matchGlobalInst dflags False clas tys+              -> do { global_res <- matchGlobalInst dflags False clas tys loc+                    ; warn_custom_warn_instance global_res loc+                          -- See Note [Implementation of deprecated instances]                     ; traceTcS "} matchClassInst global result" $ ppr global_res                     ; return global_res } }   where     pred = mkClassPred clas tys +{- Note [Implementation of deprecated instances]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+This note describes the implementation of the deprecated instances GHC proposal+  https://github.com/ghc-proposals/ghc-proposals/blob/master/proposals/0575-deprecated-instances.rst++In the parser, we parse deprecations/warnings attached to instances:++  instance {-# DEPRECATED "msg" #-} Show X+  deriving instance {-# WARNING "msg2" #-} Eq Y++(Note that non-standalone deriving instance declarations do not support this mechanism.)+(Note that the DEPRECATED and WARNING pragmas can be used here interchangeably.)++We store the resulting warning message in the extension field of `ClsInstDecl`+(respectively, `DerivDecl`; See Note [Trees That Grow]).++In `GHC.Tc.TyCl.Instance.tcClsInstDecl` (respectively, `GHC.Tc.Deriv.Utils.newDerivClsInst`),+we pass on that information to `ClsInst` (and eventually store it in `IfaceClsInst` too).++Next, if we solve a constraint using such an instance, in+`GHC.Tc.Instance.Class.matchInstEnv`, we pass it further into the+`Ghc.Tc.Types.Origin.InstanceWhat`.++Finally, if the instance solving function `GHC.Tc.Solver.Monad.matchGlobalInst` returns+a `Ghc.Tc.Instance.Class.ClsInstResult` with `Ghc.Tc.Types.Origin.InstanceWhat` containing+a warning, when called from either `matchClassInst` or `shortCutSolver`, we call+`warn_custom_warn_instance` that ultimately emits the warning if needed.++Note that we only emit a warning when the instance is used in a different module+than it is defined, which keeps the behaviour in line with the deprecation of+top-level identifiers.+-}++-- | Emits the custom warning for a deprecated instance+--+-- See Note [Implementation of deprecated instances]+warn_custom_warn_instance :: ClsInstResult -> CtLoc -> TcS ()+warn_custom_warn_instance (OneInst{ cir_what = what }) ct_loc+  | TopLevInstance{ iw_dfun_id = dfun, iw_warn = Just warn } <- what = do+      let mod = nameModule $ getName dfun+      this_mod <- getModule+      when (this_mod /= mod)+          -- We don't emit warnings for usages inside of the same module+          -- to prevent it being triggered for instance child declarations+        $ ctLocWarnTcS ct_loc+          $ TcRnPragmaWarning+              { pragma_warning_info = PragmaWarningInstance dfun (ctl_origin ct_loc)+              , pragma_warning_msg  = warn }+warn_custom_warn_instance _ _ = return ()+ {- Note [Instance and Given overlap] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Example, from the OutsideIn(X) paper:@@ -1310,38 +1366,6 @@ but that doesn't work for the example from #22216. -} -{- *******************************************************************-*                                                                    *-         Last resort prohibited superclass-*                                                                    *-**********************************************************************-}--tryLastResortProhibitedSuperClass :: DictCt -> SolverStage ()--- ^ As a last resort, we TEMPORARILY allow a prohibited superclass solve,--- emitting a loud warning when doing so: we might be creating non-terminating--- evidence (as we are in T22912 for example).------ See Note [Migrating away from loopy superclass solving] in GHC.Tc.TyCl.Instance.-tryLastResortProhibitedSuperClass dict_ct-  = Stage $ do { inerts <- getInertCans-               ; last_resort inerts dict_ct }--last_resort :: InertCans -> DictCt -> TcS (StopOrContinue ())-last_resort inerts (DictCt { di_ev = ev_w, di_cls = cls, di_tys = xis })-  | let loc_w  = ctEvLoc ev_w-        orig_w = ctLocOrigin loc_w-  , ScOrigin _ NakedSc <- orig_w   -- work_item is definitely Wanted-  , Just ct_i <- lookupInertDict inerts loc_w cls xis-  , let ev_i = dictCtEvidence ct_i-  , isGiven ev_i-  = do { setEvBindIfWanted ev_w True (ctEvTerm ev_i)-       ; ctLocWarnTcS loc_w $-         TcRnLoopySuperclassSolve loc_w (ctEvPred ev_w)-       ; return $ Stop ev_w (text "Loopy superclass") }-  | otherwise-  = continueWith ()-- {- ********************************************************************* *                                                                      * *          Functional dependencies, instantiation of equations@@ -1480,7 +1504,7 @@      Decompose to        [W] kfresh0 ~ kb0        [W] (yfresh0::kfresh0) ~ (b0::kb0)-     Preserve orientiation when decomposing!!+     Preserve orientation when decomposing!!  (W2) Suppose we happen to tackle the second Wanted from (W1)      first. Then in canEqCanLHSHetero we emit a /kind/ equality, as
compiler/GHC/Tc/Solver/Equality.hs view
@@ -21,6 +21,7 @@ import GHC.Tc.Utils.TcType import GHC.Tc.Instance.Family ( tcTopNormaliseNewTypeTF_maybe ) import GHC.Tc.Instance.FunDeps( FunDepEqn(..) )+import qualified GHC.Tc.Utils.Monad    as TcM  import GHC.Core.Type import GHC.Core.Predicate@@ -46,7 +47,6 @@  import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Misc import GHC.Utils.Monad import GHC.Utils.Constants( debugIsOn )@@ -466,29 +466,24 @@ can_eq_nc_forall :: CtEvidence -> EqRel                  -> Type -> Type    -- LHS and RHS                  -> TcS (StopOrContinue (Either IrredCt EqCt))--- (forall as. phi1) ~ (forall bs. phi2)--- Check for length match of as, bs--- Then build an implication constraint: forall as. phi1 ~ phi2[as/bs]--- But remember also to unify the kinds of as and bs---  (this is the 'go' loop), and actually substitute phi2[as |> cos / bs]--- Remember also that we might have forall z (a:z). blah---  so we must proceed one binder at a time (#13879)+-- See Note [Solving forall equalities]  can_eq_nc_forall ev eq_rel s1 s2- | CtWanted { ctev_loc = loc, ctev_dest = orig_dest, ctev_rewriters = rewriters } <- ev- = do { let free_tvs       = tyCoVarsOfTypes [s1,s2]-            (bndrs1, phi1) = tcSplitForAllTyVarBinders s1-            (bndrs2, phi2) = tcSplitForAllTyVarBinders s2+ | CtWanted { ctev_dest = orig_dest } <- ev+ = do { let (bndrs1, phi1, bndrs2, phi2) = split_foralls s1 s2             flags1 = binderFlags bndrs1             flags2 = binderFlags bndrs2-      ; if not (all2 eqForAllVis flags1 flags2) -- Note [ForAllTy and type equality]-        then do { traceTcS "Forall failure" $++      ; if eq_rel == NomEq && not (all2 eqForAllVis flags1 flags2) -- Note [ForAllTy and type equality]+        then do { traceTcS "Forall failure: visibility-mismatch" $                      vcat [ ppr s1, ppr s2, ppr bndrs1, ppr bndrs2                           , ppr flags1, ppr flags2 ]                 ; canEqHardFailure ev s1 s2 }-        else-   do { traceTcS "Creating implication for polytype equality" $ ppr ev-      ; let empty_subst1 = mkEmptySubst $ mkInScopeSet free_tvs++        else do {+        traceTcS "Creating implication for polytype equality" (ppr ev)+      ; let free_tvs     = tyCoVarsOfTypes [s1,s2]+            empty_subst1 = mkEmptySubst $ mkInScopeSet free_tvs       ; skol_info <- mkSkolemInfo (UnifyForAllSkol phi1)       ; (subst1, skol_tvs) <- tcInstSkolTyVarsX skol_info empty_subst1 $                               binderVars bndrs1@@ -496,31 +491,44 @@       ; let phi1' = substTy subst1 phi1              -- Unify the kinds, extend the substitution-            go :: [TcTyVar] -> Subst -> [TyVarBinder]-               -> TcS (TcCoercion, Cts)-            go (skol_tv:skol_tvs) subst (bndr2:bndrs2)-              = do { let tv2 = binderVar bndr2-                   ; (kind_co, wanteds1) <- unify loc rewriters Nominal (tyVarKind skol_tv)-                                                  (substTy subst (tyVarKind tv2))-                   ; let subst' = extendTvSubstAndInScope subst tv2+            go :: UnifyEnv -> [TcTyVar] -> Subst+               -> [TyVarBinder] -> [TyVarBinder] -> TcM.TcM TcCoercion+            go uenv (skol_tv:skol_tvs) subst2 (bndr1:bndrs1) (bndr2:bndrs2)+              = do { let tv2  = binderVar bndr2+                         vis1 = binderFlag bndr1+                         vis2 = binderFlag bndr2++                   -- Unify the kinds, at Nominal role+                   -- See (SF1) in Note [Solving forall equalities]+                   ; kind_co <- uType (uenv `setUEnvRole` Nominal)+                                      (tyVarKind skol_tv)+                                      (substTy subst2 (tyVarKind tv2))++                   ; let subst2' = extendTvSubstAndInScope subst2 tv2                                        (mkCastTy (mkTyVarTy skol_tv) kind_co)                          -- skol_tv is already in the in-scope set, but the                          -- free vars of kind_co are not; hence "...AndInScope"-                   ; (co, wanteds2) <- go skol_tvs subst' bndrs2-                   ; return ( mkForAllCo skol_tv kind_co co-                            , wanteds1 `unionBags` wanteds2 ) }+                   ; co <- go uenv skol_tvs subst2' bndrs1 bndrs2 +                   ; return (mkNakedForAllCo skol_tv vis1 vis2 kind_co co)}+                     -- mkNaked.. because these types are not zonked, and the+                     -- assertions in mkForAllCo may fail without that zonking+             -- Done: unify phi1 ~ phi2-            go [] subst bndrs2-              = assert (null bndrs2) $-                unify loc rewriters (eqRelRole eq_rel) phi1' (substTyUnchecked subst phi2)+            go uenv [] subst2 bndrs1 bndrs2+              = assert (null bndrs1 && null bndrs2) $+                uType uenv phi1' (substTyUnchecked subst2 phi2) -            go _ _ _ = panic "cna_eq_nc_forall"  -- case (s:ss) []+            go _ _ _ _ _ = panic "can_eq_nc_forall"  -- case (s:ss) [] -            empty_subst2 = mkEmptySubst (getSubstInScope subst1)+            init_subst2 = mkEmptySubst (getSubstInScope subst1) -      ; (lvl, (all_co, wanteds)) <- pushLevelNoWorkList (ppr skol_info) $-                                    go skol_tvs empty_subst2 bndrs2+      -- Generate the constraints that live in the body of the implication+      -- See (SF5) in Note [Solving forall equalities]+      ; (lvl, (all_co, wanteds)) <- pushLevelNoWorkList (ppr skol_info)   $+                                    unifyForAllBody ev (eqRelRole eq_rel) $ \uenv ->+                                    go uenv skol_tvs init_subst2 bndrs1 bndrs2+       ; emitTvImplicationTcS lvl (getSkolemInfo skol_info) skol_tvs wanteds        ; setWantedEq orig_dest all_co@@ -532,17 +540,70 @@       ; stopWith ev "Discard given polytype equality" }   where-    unify :: CtLoc -> RewriterSet -> Role -> TcType -> TcType -> TcS (TcCoercion, Cts)-    -- This version returns the wanted constraint rather-    -- than putting it in the work list-    unify loc rewriters role ty1 ty2-      | ty1 `tcEqType` ty2-      = return (mkReflCo role ty1, emptyBag)-      | otherwise-      = do { (wanted, co) <- newWantedEq loc rewriters role ty1 ty2-           ; return (co, unitBag (mkNonCanonical wanted)) }+    split_foralls :: TcType -> TcType+                  -> ( [ForAllTyBinder], TcType+                     , [ForAllTyBinder], TcType)+    -- Split matching foralls; stop when the foralls don't match+    -- See #22537.  See (SF3) in Note [Solving forall equalities]+    -- Postcondition: the two lists of binders returned have the same length+    split_foralls s1 s2+      | Just (bndr1, s1') <- splitForAllForAllTyBinder_maybe s1+      , Just (bndr2, s2') <- splitForAllForAllTyBinder_maybe s2+      = let !(bndrs1, phi1, bndrs2, phi2) = split_foralls s1' s2'+        in (bndr1:bndrs1, phi1, bndr2:bndrs2, phi2)+    split_foralls s1 s2 = ([], s1, [], s2) +{- Note [Solving forall equalities]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+To solve an equality between foralls+   [W] (forall a. t1) ~ (forall b. t2)+the basic plan is simple: just create the implication constraint+   [W] forall a. { t1 ~ (t2[a/b]) } +The evidence we produce is a ForAllCo; see the typing rule for+ForAllCo in Note [ForAllCo] in GHC.Tc.TyCo.Rep.++There are lots of wrinkles of course:++(SF1) We must check the kinds match (at Nominal role).  So from+      [W] (forall (a:ka). t1) ~ (forall (b:kb). t2)+   we actually generate the implication+      [W] forall (a:ka). { ka ~N kb,  t1 ~ t2[a/b] }+   These kind equalities are generated by the `go` loop in `can_eq_nc_forall`.+   Why Nominal role? See the typing rule for ForAllCo.++(SF2) At Nominal role we must check that the visiblities match.+  For example+     [W] (forall a. a -> a) ~N  (forall b -> b -> b)+  should fail.  At /Representational/ role we allow this; see the+  typing rule for ForAllCo, mentioned above.++(SF3) Consider this (#22537)+     newtype P a = MkP (forall c. (a,c))+     [W] (forall a. P a) ~R (forall a b. (a,b))+  The number of foralls does not line up.  But if we just unwrap the outer+  forall a, we'll get+     [W] P a ~R forall b. (a,b)+  Now unwrap the newtype+     [W] (forall c. (a,c)) ~R (forall b. (a,b))+  and all is good.++  Conclusion: Don't fail if the number of foralls does not line up.  Instead,+  handle as many binders as are visibly apparent on both sides, and then keep+  going with unification. See `split_foralls` in `can_eq_nc_forall`.  In the+  above example, at Representational role, the unifier will proceed to unwrap+  the newtype on the RHS and we'll end up back in can_eq_nc_forall.++(SF4) Remember also that we might have forall z (a:z). blah+  so in that `go` loop, we must proceed one binder at a time (#13879)++(SF5) Rather than manually gather the constraints needed in the body of the+   implication, we use `uType`.  That way we can solve some of them on the fly,+   especially Refl ones.  We use the `unifyForAllBody` wrapper for `uType`,+   because we want to /gather/ the equality constraint (to put in the implication)+   rather than /emit/ them into the monad, as `wrapUnifierTcS` does.+-}+ {- Note [Unwrap newtypes first] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ See also Note [Decomposing newtype equalities]@@ -1537,11 +1598,11 @@ -- Note [Fundeps with instances, and equality orientation] in GHC.Tc.Solver.Dict --    NotSwapped: --        ev      :: (lhs1:ki1) ~r# (xi2:ki2)---        kind_co :: k11 ~# ki2               -- Same orientiation as ev+--        kind_co :: k11 ~# ki2               -- Same orientation as ev --        type_ev :: lhs1 ~r# (xi2 |> sym kind_co) --    Swapped --        ev      :: (xi2:ki2) ~r# (lhs1:ki1)---        kind_co :: ki2 ~# ki1               -- Same orientiation as ev+--        kind_co :: ki2 ~# ki1               -- Same orientation as ev --        type_ev :: (xi2 |> kind_co) ~r# lhs1    = do { (kind_co, rewriters, unifs_happened) <- mk_kind_eq   -- :: ki1 ~N ki2@@ -1991,7 +2052,7 @@      This is done in canEqCanLHSHetero.  (EIK2) Suppose we have [W] (a::Type) ~ (b::Type->Type). The above rewrite will produce-        [W] w   : a ~ (b |> kw)+        [W] w  : a ~ (b |> kw)         [W] kw : Type ~ (Type->Type)       But we do /not/ want to regard `w` as canonical, and use it for rewriting@@ -2001,7 +2062,7 @@      messages.  (In particular, if 'a' is a unification variable, we might      unify, losing the tracking info that it depends on solving `kw`.) -     Conclusion: if a RHS contains a corecion hole arising from fixing a hetero-kinded+     Conclusion: if a RHS contains a coercion hole arising from fixing a hetero-kinded      equality, treat the equality (`w` in this case) as non-canonical, so that        * It will not be used for unification        * It will not be used for rewriting@@ -2490,10 +2551,6 @@                                             , ppr new_rewriters ])        ; return new_ev } -#if __GLASGOW_HASKELL__ <= 810-  | otherwise-  = panic "rewriteEvidence"-#endif   where     new_pred = mkTcEqPredLikeEv old_ev nlhs nrhs     loc      = ctEvLoc old_ev
compiler/GHC/Tc/Solver/Monad.hs view
@@ -97,7 +97,7 @@     instDFunType,      -- Unification-    wrapUnifierTcS, unifyFunDeps, uPairsTcM,+    wrapUnifierTcS, unifyFunDeps, uPairsTcM, unifyForAllBody,      -- MetaTyVars     newFlexiTcSTy, instFlexiX,@@ -105,7 +105,7 @@     tcInstSkolTyVarsX,      TcLevel,-    isFilledMetaTyVar_maybe, isFilledMetaTyVar,+    isFilledMetaTyVar_maybe, isFilledMetaTyVar, isUnfilledMetaTyVar,     zonkTyCoVarsAndFV, zonkTcType, zonkTcTypes, zonkTcTyVar, zonkCo,     zonkTyCoVarsAndFVList,     zonkSimples, zonkWC,@@ -1481,6 +1481,9 @@ isFilledMetaTyVar :: TcTyVar -> TcS Bool isFilledMetaTyVar tv = wrapTcS (TcM.isFilledMetaTyVar tv) +isUnfilledMetaTyVar :: TcTyVar -> TcS Bool+isUnfilledMetaTyVar tv = wrapTcS $ TcM.isUnfilledMetaTyVar tv+ zonkTyCoVarsAndFV :: TcTyCoVarSet -> TcS TcTyCoVarSet zonkTyCoVarsAndFV tvs = liftZonkTcS (TcM.zonkTyCoVarsAndFV tvs) @@ -1644,9 +1647,9 @@ matchGlobalInst :: DynFlags                 -> Bool      -- True <=> caller is the short-cut solver                              -- See Note [Shortcut solving: overlap]-                -> Class -> [Type] -> TcS TcM.ClsInstResult-matchGlobalInst dflags short_cut cls tys-  = wrapTcS (TcM.matchGlobalInst dflags short_cut cls tys)+                -> Class -> [Type] -> CtLoc -> TcS TcM.ClsInstResult+matchGlobalInst dflags short_cut cls tys loc+  = wrapTcS $ TcM.setCtLocM loc $ TcM.matchGlobalInst dflags short_cut cls tys  tcInstSkolTyVarsX :: SkolemInfo -> Subst -> [TyVar] -> TcS (Subst, [TcTyVar]) tcInstSkolTyVarsX skol_info subst tvs = wrapTcS $ TcM.tcInstSkolTyVarsX skol_info subst tvs@@ -1991,6 +1994,22 @@   where     fvs = tyCoVarsOfType (ctEvPred ev) +unifyForAllBody :: CtEvidence -> Role -> (UnifyEnv -> TcM a)+                -> TcS (a, Cts)+-- We /return/ the equality constraints we generate,+-- rather than emitting them into the monad.+-- See See (SF5) in Note [Solving forall equalities] in GHC.Tc.Solver.Equality+unifyForAllBody ev role unify_body+  = do { (res, cts, unified, _rewriters) <- wrapUnifierX ev role unify_body+         -- Ignore the rewriters. They are used in wrapUnifierTcS only+         -- as an optimistion to prioritise the work list; but they are+         -- /also/ stored in each individual constraint we return.++       -- Kick out any inert constraint that we have unified+       ; _ <- kickOutAfterUnification unified++       ; return (res, cts) }+ wrapUnifierTcS :: CtEvidence -> Role                -> (UnifyEnv -> TcM a)  -- Some calls to uType                -> TcS (a, Bag Ct, [TcTyVar])@@ -2004,39 +2023,48 @@ -- unified the process; the (Bag Ct) are the deferred constraints.  wrapUnifierTcS ev role do_unifications-  = do { unif_count_ref <- getUnifiedRef-       ; (cos, unified, rewriters, cts) <- wrapTcS $-             do { defer_ref   <- TcM.newTcRef emptyBag-                ; unified_ref <- TcM.newTcRef []-                ; rewriters <- TcM.zonkRewriterSet (ctEvRewriters ev)-                ; let env = UE { u_role      = role-                               , u_rewriters = rewriters-                               , u_loc       = ctEvLoc ev-                               , u_defer     = defer_ref-                               , u_unified   = Just unified_ref}--                ; cos <- do_unifications env--                ; cts     <- TcM.readTcRef defer_ref-                ; unified <- TcM.readTcRef unified_ref---                -- Don't forget to update the count of variables-                -- unified, lest we forget to iterate (#24146)-                ; unless (null unified) $-                  TcM.updTcRef unif_count_ref (+ (length unified))--                ; return (cos, unified, rewriters, cts) }+  = do { (res, cts, unified, rewriters) <- wrapUnifierX ev role do_unifications         -- Emit the deferred constraints        -- See Note [Work-list ordering] in GHC.Tc.Solved.Equality+       --+       -- All the constraints in `cts` share the same rewriter set so,+       -- rather than looking at it one by one, we pass it to+       -- extendWorkListEqs; just a small optimisation.        ; unless (isEmptyBag cts) $          updWorkListTcS (extendWorkListEqs rewriters cts)         -- And kick out any inert constraint that we have unified        ; _ <- kickOutAfterUnification unified -       ; return (cos, cts, unified) }+       ; return (res, cts, unified) }++wrapUnifierX :: CtEvidence -> Role+             -> (UnifyEnv -> TcM a)  -- Some calls to uType+             -> TcS (a, Bag Ct, [TcTyVar], RewriterSet)+wrapUnifierX ev role do_unifications+  = do { unif_count_ref <- getUnifiedRef+       ; wrapTcS $+         do { defer_ref   <- TcM.newTcRef emptyBag+            ; unified_ref <- TcM.newTcRef []+            ; rewriters   <- TcM.zonkRewriterSet (ctEvRewriters ev)+            ; let env = UE { u_role      = role+                           , u_rewriters = rewriters+                           , u_loc       = ctEvLoc ev+                           , u_defer     = defer_ref+                           , u_unified   = Just unified_ref}++            ; res <- do_unifications env++            ; cts     <- TcM.readTcRef defer_ref+            ; unified <- TcM.readTcRef unified_ref++            -- Don't forget to update the count of variables+            -- unified, lest we forget to iterate (#24146)+            ; unless (null unified) $+              TcM.updTcRef unif_count_ref (+ (length unified))++            ; return (res, cts, unified, rewriters) } }   {-
compiler/GHC/Tc/Solver/Rewrite.hs view
@@ -1,7 +1,3 @@-{-# LANGUAGE BangPatterns  #-}--{-# LANGUAGE DeriveFunctor #-}- module GHC.Tc.Solver.Rewrite(    rewrite, rewriteForErrors, rewriteArgsNom,    rewriteType@@ -30,7 +26,6 @@ import GHC.Driver.DynFlags import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Tc.Solver.Monad as TcS  import GHC.Utils.Misc
compiler/GHC/Tc/Solver/Solve.hs view
@@ -33,7 +33,6 @@  import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Misc  import GHC.Driver.Session
compiler/GHC/Tc/TyCl.hs view
@@ -99,7 +99,6 @@  import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Constants (debugIsOn) import GHC.Utils.Misc @@ -1517,7 +1516,7 @@        ; traceTc "inferInitialKinds done }" empty        ; return tcs }   where-    infer_initial_kind = addLocMA (getInitialKind InitialKindInfer)+    infer_initial_kind = addLocM (getInitialKind InitialKindInfer)  -- Check type/class declarations against their standalone kind signatures or -- CUSKs, producing a generalized TcTyCon for each.@@ -1529,7 +1528,7 @@        ; return tcs }   where     check_initial_kind (ldecl, msig) =-      addLocMA (getInitialKind (InitialKindCheck msig)) ldecl+      addLocM (getInitialKind (InitialKindCheck msig)) ldecl  -- | Get the initial kind of a TyClDecl, either generalized or non-generalized, -- depending on the 'InitialKindStrategy'.@@ -1557,7 +1556,7 @@             -- See Note [Don't process associated types in getInitialKind]         ; at_tcs <- tcExtendTyVarEnv (tyConTyVars cls_tc) $-                      mapM (addLocMA (getAssocFamInitialKind cls_tc)) ats+                      mapM (addLocM (getAssocFamInitialKind cls_tc)) ats        ; return (cls_tc : at_tcs) }   where     getAssocFamInitialKind cls =@@ -1818,8 +1817,8 @@ -- Kind-check the types of arguments to a GADT data constructor. kcConGADTArgs :: NewOrData -> TcKind -> HsConDeclGADTDetails GhcRn -> TcM () kcConGADTArgs new_or_data res_kind con_args = case con_args of-  PrefixConGADT tys     ->   kcConArgTys new_or_data res_kind tys-  RecConGADT (L _ flds) _ -> kcConArgTys new_or_data res_kind $+  PrefixConGADT _ tys     -> kcConArgTys new_or_data res_kind tys+  RecConGADT _ (L _ flds) -> kcConArgTys new_or_data res_kind $                              map (hsLinear . cd_fld_type . unLoc) flds  kcConDecls :: Foldable f@@ -2622,7 +2621,7 @@                -- The (binderVars tc_bndrs) is needed bring into scope the                -- skolems bound by the class decl header (#17841)                do { ctxt <- tcHsContext hs_ctxt-                  ; fds  <- mapM (addLocMA tc_fundep) fundeps+                  ; fds  <- mapM (addLocM tc_fundep) fundeps                   ; sig_stuff <- tcClassSigs class_name sigs meths                   ; at_stuff  <- tcClassATs class_name clas ats at_defs                   ; return (ctxt, fds, sig_stuff, at_stuff) }@@ -2725,7 +2724,7 @@                                           (at_def_tycon at_def) [at_def])                         emptyNameEnv at_defs -    tc_at at = do { (fam_tc, val_infos) <- addLocMA (tcFamDecl1 (Just cls)) at+    tc_at at = do { (fam_tc, val_infos) <- addLocM (tcFamDecl1 (Just cls)) at                   ; mapM_ (checkTyFamEqnValidityInfo fam_tc) val_infos                   ; let at_defs = lookupNameEnv at_defs_map (at_fam_name at)                                   `orElse` []@@ -3002,10 +3001,6 @@          -- overlap done by dropDominatedAxioms        ; return (fam_tc, axiom_validity_infos) } } -#if __GLASGOW_HASKELL__ <= 810-  | otherwise = panic "tcFamInst1"  -- Silence pattern-exhaustiveness checker-#endif- -- | Maybe return a list of Bools that say whether a type family was declared -- injective in the corresponding type arguments. Length of the list is equal to -- the number of arguments (including implicit kind/coercion arguments).@@ -3333,7 +3328,7 @@  tcTyFamInstEqnGuts :: TyCon -> AssocInstInfo                    -> HsOuterFamEqnTyVarBndrs GhcRn     -- Implicit and explicit binders-                   -> HsTyPats GhcRn                    -- Patterns+                   -> HsFamEqnPats GhcRn                -- Patterns                    -> LHsType GhcRn                     -- RHS                    -> TcM ([TyVar], TyVarSet, [TcType], TcType)                        -- (tyvars, non_user_tvs, pats, rhs)@@ -3439,7 +3434,7 @@         -- The Nothing case cannot happen for type families, because         -- we don't call unravelFamInstPats until we've solved the         -- equalities. For data families, it shouldn't happen either,-        -- we need to fail hard and early if it does. See trac issue #15905+        -- we need to fail hard and early if it does. See issue #15905         -- for an example of this happening.  addConsistencyConstraints :: AssocInstInfo -> TcType -> TcM ()@@ -3584,7 +3579,7 @@            -> DataDefnCons (LConDecl GhcRn) -> TcM (DataDefnCons DataCon) tcConDecls dd_info rep_tycon tmpl_bndrs res_kind   = concatMapDataDefnConsTcM (tyConName rep_tycon) $ \ new_or_data ->-    addLocMA $ tcConDecl new_or_data dd_info rep_tycon tmpl_bndrs res_kind (mkTyConTagMap rep_tycon)+    addLocM $ tcConDecl new_or_data dd_info rep_tycon tmpl_bndrs res_kind (mkTyConTagMap rep_tycon)     -- mkTyConTagMap: it's important that we pay for tag allocation here,     -- once per TyCon. See Note [Constructor tag allocation], fixes #14657 @@ -3895,7 +3890,7 @@ tcConIsInfixGADT con details   = case details of            RecConGADT{} -> return False-           PrefixConGADT arg_tys       -- See Note [Infix GADT constructors]+           PrefixConGADT _ arg_tys       -- See Note [Infix GADT constructors]                | isSymOcc (getOccName con)                , [_ty1,_ty2] <- map hsScaledThing arg_tys                   -> do { fix_env <- getFixityEnv@@ -3921,9 +3916,9 @@                               -- might have a specific kind               -> HsConDeclGADTDetails GhcRn               -> TcM [(Scaled TcType, HsSrcBang)]-tcConGADTArgs exp_kind (PrefixConGADT btys)+tcConGADTArgs exp_kind (PrefixConGADT _ btys)   = mapM (tcConArg exp_kind) btys-tcConGADTArgs exp_kind (RecConGADT fields _)+tcConGADTArgs exp_kind (RecConGADT _ fields)   = tcRecConDeclFields exp_kind fields  tcConArg :: ContextKind  -- expected kind for args; always OpenKind for datatypes,@@ -4783,7 +4778,7 @@ checkNewDataCon :: DataCon -> TcM () -- Further checks for the data constructor of a newtype -- You might wonder if we need to check for an unlifted newtype--- without -XUnliftedNewTypes, such as+-- without -XUnliftedNewtypes, such as --   newtype C = MkC Int# -- But they are caught earlier, by GHC.Tc.Gen.HsType.checkDataKindSig checkNewDataCon con
compiler/GHC/Tc/TyCl/Build.hs view
@@ -184,7 +184,9 @@               -- See Note [Constructor tag allocation], fixes #14657               data_con = mkDataCon src_name declared_infix prom_info                                    src_bangs field_lbls-                                   univ_tvs ex_tvs user_tvbs eq_spec ctxt+                                   univ_tvs ex_tvs+                                   noConcreteTyVars+                                   user_tvbs eq_spec ctxt                                    arg_tys res_ty NoPromInfo rep_tycon tag                                    stupid_ctxt dc_wrk dc_rep               dc_wrk = mkDataConWorkId work_name data_con
compiler/GHC/Tc/TyCl/Class.hs view
@@ -66,7 +66,6 @@  import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain  import GHC.Data.Maybe import GHC.Data.Bag@@ -196,7 +195,7 @@                                 tcdMeths = default_binds}))   = recoverM (return emptyLHsBinds) $     setSrcSpan (getLocA class_name) $-    do  { clas <- tcLookupLocatedClass (n2l class_name)+    do  { clas <- tcLookupLocatedClass (la2la class_name)          -- We make a separate binding for each default method.         -- At one time I used a single AbsBinds for all of them, thus@@ -238,7 +237,7 @@  tcDefMeth _ _ _ _ _ prag_fn (sel_id, Nothing)   = do { -- No default method-         mapM_ (addLocMA (badDmPrag sel_id ))+         mapM_ (addLocM (badDmPrag sel_id ))                (lookupPragEnv prag_fn (idName sel_id))        ; return emptyBag } @@ -282,7 +281,7 @@               local_dm_ty = instantiateMethod clas global_dm_id (mkTyVarTys tyvars) -             lm_bind     = dm_bind { fun_id = L (la2na bind_loc) local_dm_name }+             lm_bind     = dm_bind { fun_id = L (l2l bind_loc) local_dm_name }                              -- Substitute the local_meth_name for the binder                              -- NB: the binding is always a FunBind @@ -296,9 +295,9 @@              ctxt = FunSigCtxt sel_name warn_redundant         ; let local_dm_id = mkLocalId local_dm_name ManyTy local_dm_ty-             local_dm_sig = CompleteSig { sig_bndr = local_dm_id-                                        , sig_ctxt  = ctxt-                                        , sig_loc   = getLocA hs_ty }+             local_dm_sig = CSig { sig_bndr = local_dm_id+                                 , sig_ctxt = ctxt+                                 , sig_loc  = getLocA hs_ty }         ; (ev_binds, (tc_bind, _))                <- checkConstraints skol_info tyvars [this_dict] $
compiler/GHC/Tc/TyCl/Instance.hs view
@@ -486,7 +486,8 @@ tcClsInstDecl :: LClsInstDecl GhcRn               -> TcM ([InstInfo GhcRn], [FamInst], [DerivInfo]) -- The returned DerivInfos are for any associated data families-tcClsInstDecl (L loc (ClsInstDecl { cid_poly_ty = hs_ty, cid_binds = binds+tcClsInstDecl (L loc (ClsInstDecl { cid_ext = lwarn+                                  , cid_poly_ty = hs_ty, cid_binds = binds                                   , cid_sigs = uprags, cid_tyfam_insts = ats                                   , cid_overlap_mode = overlap_mode                                   , cid_datafam_insts = adts }))@@ -541,8 +542,9 @@         ; dfun_name <- newDFunName clas inst_tys (getLocA hs_ty)                 -- Dfun location is that of instance *header* +        ; let warn = fmap unLoc lwarn         ; ispec <- newClsInst (fmap unLoc overlap_mode) dfun_name-                              tyvars theta clas inst_tys+                              tyvars theta clas inst_tys warn          ; let inst_binds = InstBindings                              { ib_binds = binds@@ -608,7 +610,7 @@          -- itself, so we make do with the location of family name        ; (co_ax_branch, co_ax_validity_info)           <- tcTyFamInstEqn fam_tc mb_clsinfo-                (L (na2la $ getLoc fam_lname) eqn)+                (L (l2l $ getLoc fam_lname) eqn)           -- (2) check for validity        ; checkConsistentFamInst mb_clsinfo fam_tc co_ax_branch@@ -915,7 +917,7 @@ tcDataFamInstHeader     :: AssocInstInfo -> SkolemInfo -> TyCon -> HsOuterFamEqnTyVarBndrs GhcRn     -> LexicalFixity -> Maybe (LHsContext GhcRn)-    -> HsTyPats GhcRn -> Maybe (LHsKind GhcRn)+    -> HsFamEqnPats GhcRn -> Maybe (LHsKind GhcRn)     -> NewOrData     -> TcM ([TcTyVar], TyVarSet, [TcType], TcKind, TcThetaType)          -- All skolem TcTyVars, all zonked so it's clear what the free vars are@@ -1330,7 +1332,7 @@              con_app_args = foldl' app_to_meth con_app_tys sc_meth_ids               app_to_meth :: HsExpr GhcTc -> Id -> HsExpr GhcTc-             app_to_meth fun meth_id = HsApp noComments (L loc' fun)+             app_to_meth fun meth_id = HsApp noExtField (L loc' fun)                                             (L loc' (wrapId arg_wrapper meth_id))               inst_tv_tys = mkTyVarTys inst_tyvars@@ -1694,20 +1696,6 @@     superclass selection, except at a smaller type.  This test is     implemented by GHC.Tc.Solver.InertSet.prohibitedSuperClassSolve -Note [Migrating away from loopy superclass solving]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-The logic from Note [Solving superclass constraints] was implemented in GHC 9.6.-However, we want to provide a migration strategy for users, to avoid suddenly-breaking their code going when upgrading to GHC 9.6. To this effect, we temporarily-continue to allow the constraint solver to create these potentially non-terminating-solutions, but emit a loud warning when doing so: see-GHC.Tc.Solver.Dict.tryLastResortProhibitedSuperclass.--Users can silence the warning by manually adding the necessary constraint to the-context. GHC will then keep this user-written Given, dropping the Given arising-from superclass expansion which has greater SC depth, as explained in-Note [Replacement vs keeping] in GHC.Tc.Solver.Dict.- Note [Silent superclass arguments] (historical interest only) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NB1: this note describes our *old* solution to the@@ -1881,13 +1869,13 @@       where         inst_loc' = noAnnSrcSpan inst_loc         error_rhs dflags = L inst_loc'-                         $ HsApp noComments error_fun (error_msg dflags)+                         $ HsApp noExtField error_fun (error_msg dflags)         error_fun    = L inst_loc' $                        wrapId (mkWpTyApps                                 [ getRuntimeRep meth_tau, meth_tau])                               nO_METHOD_BINDING_ERROR_ID         error_msg dflags = L inst_loc'-                                    (HsLit noComments (HsStringPrim NoSourceText+                                    (HsLit noExtField (HsStringPrim NoSourceText                                               (unsafeMkByteString (error_string dflags))))         meth_tau     = classMethodInstTy sel_id inst_tys         error_string dflags = showSDoc dflags@@ -2068,12 +2056,11 @@                     -- WantRCC <=> check for redundant constraints in the                     --          user-specified instance signature              inner_meth_id  = mkLocalId inner_meth_name ManyTy sig_ty-             inner_meth_sig = CompleteSig { sig_bndr = inner_meth_id-                                          , sig_ctxt = ctxt-                                          , sig_loc  = getLocA hs_sig_ty }-+             inner_meth_sig = CSig { sig_bndr = inner_meth_id+                                   , sig_ctxt = ctxt+                                   , sig_loc  = getLocA hs_sig_ty } -       ; (tc_bind, [inner_id]) <- tcPolyCheck no_prag_fn inner_meth_sig meth_bind+       ; (tc_bind, [Scaled _ inner_id]) <- tcPolyCheck no_prag_fn inner_meth_sig meth_bind         ; let export = ABE { abe_poly  = local_meth_id                           , abe_mono  = inner_id@@ -2231,7 +2218,7 @@                                       , tyConBinderForAllTyFlag tcb /= Inferred ]               rhs  = foldl' mk_vta (nlHsVar dm_name) visible_inst_tys               bind = L (noAnnSrcSpan loc)-                    $ mkTopFunBind (Generated SkipPmc) fn+                    $ mkTopFunBind (Generated OtherExpansion SkipPmc) fn                         [mkSimpleMatch (mkPrefixFunRhs fn) [] rhs]          ; liftIO (putDumpFileMaybe logger Opt_D_dump_deriv "Filling in method body"@@ -2244,7 +2231,7 @@     (_, _, _, inst_tys) = tcSplitDFunTy (idType dfun_id)      mk_vta :: LHsExpr GhcRn -> Type -> LHsExpr GhcRn-    mk_vta fun ty = noLocA (HsAppType noExtField fun noHsTok+    mk_vta fun ty = noLocA (HsAppType noExtField fun         (mkEmptyWildCardBndrs $ nlHsParTy $ noLocA $ XHsType ty))        -- NB: use visible type application        -- See Note [Default methods in instances]@@ -2437,7 +2424,7 @@ tcSpecInstPrags :: DFunId -> InstBindings GhcRn                 -> TcM ([LTcSpecPrag], TcPragEnv) tcSpecInstPrags dfun_id (InstBindings { ib_binds = binds, ib_pragmas = uprags })-  = do { spec_inst_prags <- mapM (wrapLocAM (tcSpecInst dfun_id)) $+  = do { spec_inst_prags <- mapM (wrapLocM (tcSpecInst dfun_id)) $                             filter isSpecInstLSig uprags              -- The filter removes the pragmas for methods        ; return (spec_inst_prags, mkPragEnv uprags binds) }@@ -2475,4 +2462,3 @@ inst_decl_ctxt :: SDoc -> SDoc inst_decl_ctxt doc = hang (text "In the instance declaration for")                         2 (quotes doc)-
compiler/GHC/Tc/TyCl/PatSyn.hs view
@@ -41,7 +41,6 @@ import GHC.Core.TyCo.Subst( extendTvSubstWithClone ) import GHC.Core.Predicate -import GHC.Builtin.Types.Prim import GHC.Types.Name import GHC.Types.Name.Set import GHC.Types.SrcLoc@@ -61,7 +60,7 @@ import GHC.Core.ConLike import GHC.Types.FieldLabel import GHC.Rename.Env-import GHC.Rename.Utils (wrapGenSpan, isIrrefutableHsPatRn)+import GHC.Rename.Utils (wrapGenSpan, isIrrefutableHsPat) import GHC.Data.Bag import GHC.Utils.Misc import GHC.Driver.DynFlags ( getDynFlags, xopt_FieldSelectors )@@ -86,35 +85,11 @@   = setSrcSpanA loc $     addErrCtxt (text "In the declaration for pattern synonym"                 <+> quotes (ppr name)) $-    recoverM (recoverPSB psb) $-    case (sig_fn name) of-      Nothing                 -> tcInferPatSynDecl psb prag_fn-      Just (TcPatSynSig tpsi) -> tcCheckPatSynDecl psb tpsi prag_fn-      _                       -> panic "tcPatSynDecl"--recoverPSB :: PatSynBind GhcRn GhcRn-           -> TcM (LHsBinds GhcTc, TcGblEnv)--- See Note [Pattern synonym error recovery]-recoverPSB (PSB { psb_id = L _ name-                , psb_args = details })- = do { matcher_name <- newImplicitBinder name mkMatcherOcc-      ; let placeholder = AConLike $ PatSynCon $-                          mk_placeholder matcher_name-      ; gbl_env <- tcExtendGlobalEnv [placeholder] getGblEnv-      ; return (emptyBag, gbl_env) }-  where-    (_arg_names, is_infix) = collectPatSynArgInfo details-    mk_placeholder matcher_name-      = mkPatSyn name is_infix-                        ([mkTyVarBinder SpecifiedSpec alphaTyVar], []) ([], [])-                        [] -- Arg tys-                        alphaTy-                        (matcher_name, matcher_ty, True) Nothing-                        []  -- Field labels-       where-         -- The matcher_id is used only by the desugarer, so actually-         -- and error-thunk would probably do just as well here.-         matcher_ty = mkSpecForAllTys [alphaTyVar] alphaTy+    -- See Note [Pattern synonym error recovery]+    case sig_fn name of+      Nothing                   -> tcInferPatSynDecl psb prag_fn+      Just (TcPatSynSig patsig) -> tcCheckPatSynDecl psb patsig prag_fn+      _                         -> panic "tcPatSynDecl"  {- Note [Pattern synonym error recovery] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~@@ -134,14 +109,19 @@ So we use simplifyTop to completely solve the constraint, report any errors, throw an exception. -Even in the event of such an error we can recover and carry on, just-as we do for value bindings, provided we plug in placeholder for the-pattern synonym: see recoverPSB.  The goal of the placeholder is not-to cause a raft of follow-on errors.  I've used the simplest thing for-now, but we might need to elaborate it a bit later.  (e.g.  I've given-it zero args, which may cause knock-on errors if it is used in a-pattern.) But it'll do for now.+Unlike for value bindings, we don't create a placeholder pattern+synonym binding in an attempt to recover from the error, as this placeholder+was occasionally the cause of strange follow-up errors to occur, as reported in #23467.+It seems rather difficult to come up with a satisfactory placeholder: +  - it would need to have the right number of arguments,+    with the appropriate field names (if any),+  - we could give each argument the type `forall a. a`; this would generally+    work OK in pattern occurrences of the PatSyn, but not so in expressions,+    e.g. "let x = Con y" would require (y :: forall a. a) which would cause+    confusing errors.++So, for now at least, we don't attempt to recover at all. -}  tcInferPatSynDecl :: PatSynBind GhcRn GhcRn@@ -371,15 +351,15 @@ -}  tcCheckPatSynDecl :: PatSynBind GhcRn GhcRn-                  -> TcPatSynInfo+                  -> TcPatSynSig                   -> TcPragEnv                   -> TcM (LHsBinds GhcTc, TcGblEnv) tcCheckPatSynDecl psb@PSB{ psb_id = lname@(L _ name), psb_args = details                          , psb_def = lpat, psb_dir = dir }-                  TPSI{ patsig_implicit_bndrs = implicit_bndrs-                      , patsig_univ_bndrs = explicit_univ_bndrs, patsig_req  = req_theta-                      , patsig_ex_bndrs   = explicit_ex_bndrs,   patsig_prov = prov_theta-                      , patsig_body_ty    = sig_body_ty }+                  PatSig{ patsig_implicit_bndrs = implicit_bndrs+                        , patsig_univ_bndrs = explicit_univ_bndrs, patsig_req  = req_theta+                        , patsig_ex_bndrs   = explicit_ex_bndrs,   patsig_prov = prov_theta+                        , patsig_body_ty    = sig_body_ty }                   prag_fn   = do { traceTc "tcCheckPatSynDecl" $          vcat [ ppr implicit_bndrs, ppr explicit_univ_bndrs, ppr req_theta@@ -583,7 +563,7 @@ until we see the pattern declaration itself before deciding res_ty is, and hence which variables are existential and which are universal. -And that in turn is why TcPatSynInfo has a separate field,+And that in turn is why TcPatSynSig has a separate field, patsig_implicit_bndrs, to capture the implicitly bound type variables, because we don't yet know how to split them up. @@ -808,11 +788,11 @@               args = map nlVarPat [scrutinee, cont, fail]              lwpat = noLocA $ WildPat pat_ty-             cases = if isIrrefutableHsPatRn dflags lpat+             cases = if isIrrefutableHsPat dflags lpat                      then [mkHsCaseAlt lpat  cont']                      else [mkHsCaseAlt lpat  cont',                            mkHsCaseAlt lwpat fail']-             gen = Generated SkipPmc+             gen = Generated OtherExpansion SkipPmc              body = mkLHsWrap (mkWpLet req_ev_binds) $                     L (getLoc lpat) $                     HsCase PatSyn (nlHsVar scrutinee) $@@ -820,9 +800,10 @@                       , mg_ext = MatchGroupTc [unrestricted pat_ty] res_ty gen                       }              body' = noLocA $-                     HsLam noExtField $-                     MG{ mg_alts = noLocA [mkSimpleMatch LambdaExpr-                                                         args body]+                     HsLam noAnn LamSingle $+                     MG{ mg_alts = noLocA [mkSimpleMatch (LamAlt LamSingle)+                                                         args+                                                         body]                        , mg_ext = MatchGroupTc (map unrestricted [pat_ty, cont_ty, fail_ty]) res_ty gen                        }              match = mkMatch (mkPrefixFunRhs (L loc (idName patsyn_id))) []@@ -953,9 +934,6 @@        ; traceTc "tcPatSynBuilderBind }" $ ppr builder_binds        ; return builder_binds } } } -#if __GLASGOW_HASKELL__ <= 810-  | otherwise = panic "tcPatSynBuilderBind"  -- Both cases dealt with-#endif   where     mb_match_group        = case dir of@@ -964,9 +942,9 @@            Unidirectional -> panic "tcPatSynBuilderBind"      mk_mg :: LHsExpr GhcRn -> MatchGroup GhcRn (LHsExpr GhcRn)-    mk_mg body = mkMatchGroup (Generated SkipPmc) (noLocA [builder_match])+    mk_mg body = mkMatchGroup (Generated OtherExpansion SkipPmc) (noLocA [builder_match])           where-            builder_args  = [L (na2la loc) (VarPat noExtField (L loc n))+            builder_args  = [(L (l2l loc) (VarPat noExtField (L loc n)))                             | L loc n <- args]             builder_match = mkMatch (mkPrefixFunRhs ps_lname)                                     builder_args body@@ -1054,25 +1032,30 @@         = return $ HsVar noExtField (L l var)         | otherwise         = Left (PatSynUnboundVar var)-    go1 (ParPat _ lpar pat rpar) = fmap (\e -> HsPar noAnn lpar e rpar) $ go pat+    go1 (ParPat _ pat) = fmap (HsPar noExtField) (go pat)     go1 (ListPat _ pats)       = do { exprs <- mapM go pats            ; return $ ExplicitList noExtField exprs }     go1 (TuplePat _ pats box)       = do { exprs <- mapM go pats                                          ; return $ ExplicitTuple noExtField-                                           (map (Present noAnn) exprs) box }+                                           (map (Present noExtField) exprs) box }     go1 (SumPat _ pat alt arity)    = do { expr <- go1 (unLoc pat)                                          ; return $ ExplicitSum noExtField alt arity                                                                    (noLocA expr)                                          }-    go1 (LitPat _ lit)              = return $ HsLit noComments lit+    go1 (LitPat _ lit)              = return $ HsLit noExtField lit     go1 (NPat _ (L _ n) mb_neg _)         | Just (SyntaxExprRn neg) <- mb_neg                                     = return $ unLoc $ foldl' nlHsApp (noLocA neg)-                                                       [noLocA (HsOverLit noAnn n)]-        | otherwise                 = return $ HsOverLit noAnn n+                                                       [noLocA (HsOverLit noExtField n)]+        | otherwise                 = return $ HsOverLit noExtField n     go1 (SplicePat (HsUntypedSpliceTop _ pat) _) = go1 pat     go1 (SplicePat (HsUntypedSpliceNested _) _)  = panic "tcPatToExpr: invalid nested splice"+    go1 (EmbTyPat _ tp) = return $ HsEmbTy noExtField (hstp_to_hswc tp)+      where hstp_to_hswc :: HsTyPat GhcRn -> LHsWcType GhcRn+            hstp_to_hswc (HsTP { hstp_ext = HsTPRn { hstp_nwcs = wcs }, hstp_body = hs_ty })+                        = HsWC { hswc_ext = wcs, hswc_body = hs_ty }+    go1 (InvisPat _ _tp) = panic "tcPatToExpr: invalid invisible pattern"     go1 (XPat (HsPatExpanded _ pat))= go1 pat      -- See Note [Invertible view patterns]@@ -1080,7 +1063,7 @@       Nothing      -> notInvertible p       Just inverse ->         fmap-          (\ expr -> HsApp noAnn (wrapGenSpan inverse) (wrapGenSpan expr))+          (\ expr -> HsApp noExtField (wrapGenSpan inverse) (wrapGenSpan expr))           (go1 (unLoc pat))      -- The following patterns are not invertible.@@ -1242,8 +1225,8 @@      go1 :: Pat GhcTc -> ([TyVar], [EvVar])     go1 (LazyPat _ p)      = go p-    go1 (AsPat _ _ _ p)    = go p-    go1 (ParPat _ _ p _)   = go p+    go1 (AsPat _ _ p)      = go p+    go1 (ParPat _ p)       = go p     go1 (BangPat _ p)      = go p     go1 (ListPat _ ps)     = mergeMany . map go $ ps     go1 (TuplePat _ ps _)  = mergeMany . map go $ ps
compiler/GHC/Tc/TyCl/Utils.hs view
@@ -53,7 +53,6 @@  import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Misc import GHC.Utils.FV as FV @@ -138,7 +137,8 @@      go_co (GRefl _ ty mco)       = go ty `plusNameEnv` go_mco mco      go_co (TyConAppCo _ tc cs)   = go_tc tc `plusNameEnv` go_co_s cs      go_co (AppCo co co')         = go_co co `plusNameEnv` go_co co'-     go_co (ForAllCo _ co co')    = go_co co `plusNameEnv` go_co co'+     go_co (ForAllCo { fco_kind = kind_co, fco_body = body_co })+                                  = go_co kind_co `plusNameEnv` go_co body_co      go_co (FunCo { fco_mult = m, fco_arg = a, fco_res = r })                                   = go_co m `plusNameEnv` go_co a `plusNameEnv` go_co r      go_co (CoVarCo _)            = emptyNameEnv@@ -157,7 +157,6 @@      go_prov (PhantomProv co)     = go_co co      go_prov (ProofIrrelProv co)  = go_co co      go_prov (PluginProv _)       = emptyNameEnv-     go_prov (CorePrepProv _)     = emptyNameEnv       go_tc tc | isTypeSynonymTyCon tc = unitNameEnv (tyConName tc) tc               | otherwise             = emptyNameEnv@@ -844,10 +843,10 @@ tcRecSelBinds :: [(Id, LHsBind GhcRn)] -> TcM TcGblEnv tcRecSelBinds sel_bind_prs   = tcExtendGlobalValEnv [sel_id | (L _ (XSig (IdSig sel_id))) <- sigs] $-    do { (rec_sel_binds, tcg_env) <- discardWarnings $-                                     -- See Note [Impredicative record selectors]-                                     setXOptM LangExt.ImpredicativeTypes $-                                     tcValBinds TopLevel binds sigs getGblEnv+    do { (rec_sel_binds, _, tcg_env) <- discardWarnings $+                                       -- See Note [Impredicative record selectors]+                                       setXOptM LangExt.ImpredicativeTypes $+                                       tcValBinds TopLevel binds sigs getGblEnv        ; return (tcg_env `addTypecheckedBinds` map snd rec_sel_binds) }   where     sigs = [ L (noAnnSrcSpan loc) (XSig $ IdSig sel_id)@@ -881,16 +880,23 @@     locc     = noAnnSrcSpan loc     lbl      = flLabel fl     sel_name = flSelector fl+    sel_lname = L locn sel_name+    match_ctxt = mkPrefixFunRhs sel_lname      sel_id = mkExportedLocalId rec_details sel_name sel_ty-    rec_details = RecSelId { sel_tycon      = idDetails-                           , sel_naughty    = is_naughty-                           , sel_fieldLabel = fl }      -- Find a representative constructor, con1-    cons_w_field = conLikesWithFields all_cons [lbl]+    cons_partitioned@(cons_w_field, _) = conLikesWithFields all_cons [lbl]     con1 = assert (not (null cons_w_field)) $ head cons_w_field +    -- Construct the IdDetails+    rec_details = RecSelId { sel_tycon      = idDetails+                           , sel_naughty    = is_naughty+                           , sel_fieldLabel = fl+                           , sel_cons       = cons_partitioned }+                               -- See Note [Detecting incomplete record selectors] in GHC.HsToCore.Pmc++     -- Selector type; Note [Polymorphic selectors]     (univ_tvs, _, _, _, req_theta, _, data_ty) = conLikeFullSig con1 @@ -929,12 +935,11 @@     -- make the binding: sel (C2 { fld = x }) = x     --                   sel (C7 { fld = x }) = x     --    where cons_w_field = [C2,C7]-    sel_bind = mkTopFunBind (Generated SkipPmc) sel_lname alts+    sel_bind = mkTopFunBind (Generated OtherExpansion SkipPmc) sel_lname alts       where-        alts | is_naughty = [mkSimpleMatch (mkPrefixFunRhs sel_lname)-                                           [] unit_rhs]+        alts | is_naughty = [mkSimpleMatch match_ctxt [] unit_rhs]              | otherwise =  map mk_match cons_w_field ++ deflt-    mk_match con = mkSimpleMatch (mkPrefixFunRhs sel_lname)+    mk_match con = mkSimpleMatch match_ctxt                                  [L loc' (mk_sel_pat con)]                                  (L loc' (HsVar noExtField (L locn field_var)))     mk_sel_pat con = ConPat NoExtField (L locn (getName con)) (RecCon rec_fields)@@ -947,15 +952,13 @@                         , hfbRHS                            = L loc' (VarPat noExtField (L locn field_var))                         , hfbPun = False })-    sel_lname = L locn sel_name     field_var = mkInternalName (mkBuiltinUnique 1) (getOccName sel_name) loc      -- Add catch-all default case unless the case is exhaustive     -- We do this explicitly so that we get a nice error message that     -- mentions this particular record selector     deflt | all dealt_with all_cons = []-          | otherwise = [mkSimpleMatch CaseAlt-                            [genWildPat]+          | otherwise = [mkSimpleMatch match_ctxt [genWildPat]                             (genLHsApp                                 (genHsVar (getName rEC_SEL_ERROR_ID))                                 (genLHsLit msg_lit))]@@ -1056,7 +1059,7 @@   The selector is defined like this:     $selReadPfld :: forall a. ReadP a => String -> a     $selReadPfld @a (d::ReadP a) s = readp @a d s-  Perfectly fine!  The (ReadP a) constraint lets us contruct a value of type+  Perfectly fine!  The (ReadP a) constraint lets us construct a value of type   'a' from a bare String.    Another curious case (#23038):
compiler/GHC/Tc/Types/EvTerm.hs view
@@ -38,7 +38,9 @@ evCallStack :: (MonadThings m, HasModule m, HasDynFlags m) =>     EvCallStack -> m EvExpr -- See Note [Overview of implicit CallStacks] in GHC.Tc.Types.Evidence-evCallStack cs = do+evCallStack EvCsEmpty =+  Var <$> lookupId emptyCallStackName+evCallStack (EvCsPushCall fs loc tm) = do   df            <- getDynFlags   let platform = targetPlatform df   m             <- getModule@@ -53,8 +55,6 @@                         , return $ mkIntExprInt platform (srcSpanEndCol l)                         ] -  emptyCS <- Var <$> lookupId emptyCallStackName-   pushCSVar <- lookupId pushCallStackName   let pushCS name loc rest =         mkCoreApps (Var pushCSVar) [mkCoreTup [name, loc], rest]@@ -69,6 +69,4 @@         let ip_co = unwrapIP (exprType tm)         return (pushCS nameExpr locExpr (Cast tm ip_co)) -  case cs of-    EvCsPushCall fs loc tm -> mkPush fs loc tm-    EvCsEmpty              -> return emptyCS+  mkPush fs loc tm
compiler/GHC/Tc/Utils/Backpack.hs view
@@ -79,7 +79,6 @@ import GHC.Utils.Misc ( HasDebugCallStack ) import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain  import GHC.Data.FastString import GHC.Data.Maybe@@ -524,8 +523,8 @@         tcg_rn_decls   = tcg_rn_decls   orig_tcg_env,         -- Annotations         tcg_ann_env    = tcg_ann_env    orig_tcg_env,-        -- Documentation header-        tcg_doc_hdr    = tcg_doc_hdr orig_tcg_env+        -- Documentation header and located module name+        tcg_hdr_info    = tcg_hdr_info orig_tcg_env         -- tcg_dus?         -- tcg_th_used           = tcg_th_used orig_tcg_env,         -- tcg_th_splice_used    = tcg_th_splice_used orig_tcg_env
compiler/GHC/Tc/Utils/Concrete.hs view
@@ -1,4 +1,5 @@ {-# LANGUAGE MultiWayIf #-}+{-# LANGUAGE ParallelListComp #-}  -- | Checking for representation-polymorphism using the Concrete mechanism. --@@ -8,38 +9,41 @@   ( -- * Ensuring that a type has a fixed runtime representation     hasFixedRuntimeRep   , hasFixedRuntimeRep_syntactic++  , unifyConcrete++  , idConcreteTvs   )  where  import GHC.Prelude +import GHC.Builtin.Names       ( unsafeCoercePrimName ) import GHC.Builtin.Types       ( liftedTypeKindTyCon, unliftedTypeKindTyCon )  import GHC.Core.Coercion       ( coToMCo, mkCastTyMCo                                , mkGReflRightMCo, mkNomReflCo ) import GHC.Core.TyCo.Rep       ( Type(..), MCoercion(..) ) import GHC.Core.TyCon          ( isConcreteTyCon )-import GHC.Core.Type           ( isConcreteType, typeKind, tyVarKind, coreView-                               , mkTyVarTy, mkTyConApp, mkFunTy, mkAppTy )+import GHC.Core.Type           ( isConcreteType, typeKind, mkFunTy) -import GHC.Tc.Types            ( TcM, ThStage(..), PendingStuff(..) ) import GHC.Tc.Types.Constraint ( NotConcreteError(..), NotConcreteReason(..) ) import GHC.Tc.Types.Evidence   ( Role(..), TcCoercionN, TcMCoercionN )-import GHC.Tc.Types.Origin     ( CtOrigin(..), FixedRuntimeRepContext, FixedRuntimeRepOrigin(..) )-import GHC.Tc.Utils.Monad      ( emitNotConcreteError, setTcLevel, getCtLocM, getStage, traceTc-                               , liftZonkM )-import GHC.Tc.Utils.TcType     ( TcType, TcKind, TcTypeFRR-                               , MetaInfo(..), ConcreteTvOrigin(..)-                               , isMetaTyVar, metaTyVarInfo, tcTyVarLevel )-import GHC.Tc.Utils.TcMType    ( newConcreteTyVar, isFilledMetaTyVar_maybe, writeMetaTyVar-                               , emitWantedEq )+import GHC.Tc.Types.Origin+import GHC.Tc.Utils.Monad+import GHC.Tc.Utils.TcType+import GHC.Tc.Utils.TcMType -import GHC.Types.Basic         ( TypeOrKind(..) )-import GHC.Types.Name          ( getOccName )-import GHC.Types.Name.Occurrence( occNameFS )+import GHC.Types.Basic         ( TypeOrKind(KindLevel) )+import GHC.Types.Id+import GHC.Types.Id.Info+import GHC.Types.Name+import GHC.Types.Name.Env+import GHC.Types.Var           ( tyVarKind, tyVarName )+ import GHC.Utils.Misc          ( HasDebugCallStack ) import GHC.Utils.Outputable-import GHC.Data.FastString     ( fsLit )+import GHC.Data.FastString     ( FastString, fsLit )   import Control.Monad      ( void )@@ -400,7 +404,8 @@                         -- @ki@ is concrete, and @co :: ty ~# ty'@.                         -- That is, @ty'@ has a syntactically fixed RuntimeRep                         -- in the sense of Note [Fixed RuntimeRep].-hasFixedRuntimeRep frr_ctxt ty = checkFRR_with unifyConcrete frr_ctxt ty+hasFixedRuntimeRep frr_ctxt ty =+  checkFRR_with (unifyConcrete (fsLit "cx") . ConcreteFRR) frr_ctxt ty  -- | Like 'hasFixedRuntimeRep', but we perform an eager syntactic check. --@@ -485,9 +490,9 @@ -- We assume the provided type is already at the kind-level -- (this only matters for error messages). unifyConcrete :: HasDebugCallStack-              => FixedRuntimeRepOrigin -> TcType -> TcM TcMCoercionN-unifyConcrete frr_orig ty-  = do { (ty, errs) <- makeTypeConcrete (ConcreteFRR frr_orig) ty+              => FastString -> ConcreteTvOrigin -> TcType -> TcM TcMCoercionN+unifyConcrete occ_fs conc_orig ty+  = do { (ty, errs) <- makeTypeConcrete conc_orig ty        ; case errs of            -- We were able to make the type fully concrete.          { [] -> return MRefl@@ -497,14 +502,15 @@            -- Create a new ConcreteTv metavariable @concrete_tv@            -- and unify @ty ~# concrete_tv@.          ; _  ->-    do { conc_tv <- newConcreteTyVar (ConcreteFRR frr_orig) (fsLit "cx") ki+    do { conc_tv <- newConcreteTyVar conc_orig occ_fs ki            -- NB: newConcreteTyVar asserts that 'ki' is concrete.        ; coToMCo <$> emitWantedEq orig KindLevel Nominal ty (mkTyVarTy conc_tv) } } }   where     ki :: TcKind     ki = typeKind ty     orig :: CtOrigin-    orig = FRROrigin frr_orig+    orig = case conc_orig of+      ConcreteFRR frr_orig -> FRROrigin frr_orig  -- | Ensure that the given type is concrete. --@@ -686,3 +692,36 @@      bale_out :: TcType -> NotConcreteReason -> WriterT [NotConcreteReason] TcM TcType     bale_out ty reason = do { tell [reason]; return ty }++{-***********************************************************************+%*                                                                      *+                   Concrete type variables of Ids+%*                                                                      *+%**********************************************************************-}++-- | Which type variables of this 'Id' must be concrete when instantiated?+--+-- See Note [Representation-polymorphism checking built-ins] in GHC.Tc.Gen.Head.+idConcreteTvs :: TcId -> ConcreteTyVars+idConcreteTvs id++  -- HACK for unsafeCoerce#: because of the way it is not quite wired in,+  -- as described in Note [Wiring in unsafeCoerce#] in GHC.HsToCore, we don't+  -- have access to the correct IdDetails in the typechecker (as we only patch+  -- in the correct information in the desugarer).+  -- So, for the time being, we manually inspect the type of the original,+  -- unpatched Id to retrieve which of its outer forall-d tyvars should be concrete.+  | idName id == unsafeCoercePrimName+  , (a_rep:_b_rep:a:_b:_, _) <- tcSplitForAllTyVars $ idType id+  -- NB: only check the argument representation, not the result representation.+  -- This is because the following is OK:+  --+  --   unsafeCoerceWordRep :: forall {r2} (b :: TYPE r2). Word# -> b+  --   unsafeCoerceWordRep = unsafeCoerce#+  = mkNameEnv+    [(tyVarName a_rep, ConcreteFRR $ FixedRuntimeRepOrigin (mkTyVarTy a)+                                   $ FRRRepPolyId unsafeCoercePrimName RepPolyFunction+                                   $ Argument 1 Top)]++  | otherwise+  = idDetailsConcreteTvs $ idDetails id
compiler/GHC/Tc/Utils/Env.hs view
@@ -1,6 +1,7 @@ -- (c) The University of Glasgow 2006 {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TupleSections #-} {-# OPTIONS_GHC -fno-warn-orphans #-}  -- instance MonadThings is necessarily an                                        -- orphan {-# LANGUAGE UndecidableInstances #-} -- Wrinkle in Note [Trees That Grow]@@ -70,6 +71,7 @@  import GHC.Prelude + import GHC.Driver.Env import GHC.Driver.Env.KnotVars import GHC.Driver.DynFlags@@ -87,13 +89,16 @@ import GHC.Tc.Errors.Types import GHC.Tc.Utils.Monad import GHC.Tc.Utils.TcType+import {-# SOURCE #-} GHC.Tc.Utils.TcMType ( tcCheckUsage ) import GHC.Tc.Types.LclEnv+import GHC.Tc.Types.Evidence (HsWrapper, idHsWrapper, (<.>))  import GHC.Core.InstEnv import GHC.Core.DataCon ( DataCon, dataConTyCon, flSelector ) import GHC.Core.PatSyn  ( PatSyn ) import GHC.Core.ConLike import GHC.Core.TyCon+import GHC.Core.TyCo.Rep import GHC.Core.Type import GHC.Core.Coercion.Axiom import GHC.Core.Class@@ -218,7 +223,7 @@ tcLookupLocatedGlobal :: LocatedA Name -> TcM TyThing -- c.f. GHC.IfaceToCore.tcIfaceGlobal tcLookupLocatedGlobal name-  = addLocMA tcLookupGlobal name+  = addLocM tcLookupGlobal name  tcLookupGlobal :: Name -> TcM TyThing -- The Name is almost always an ExternalName, but not always@@ -308,13 +313,13 @@         _           -> wrongThingErr WrongThingAxiom (AGlobal thing) name  tcLookupLocatedGlobalId :: LocatedA Name -> TcM Id-tcLookupLocatedGlobalId = addLocMA tcLookupId+tcLookupLocatedGlobalId = addLocM tcLookupId  tcLookupLocatedClass :: LocatedA Name -> TcM Class-tcLookupLocatedClass = addLocMA tcLookupClass+tcLookupLocatedClass = addLocM tcLookupClass  tcLookupLocatedTyCon :: LocatedN Name -> TcM TyCon-tcLookupLocatedTyCon = addLocMA tcLookupTyCon+tcLookupLocatedTyCon = addLocM tcLookupTyCon  -- Find the instance that exactly matches a type class application.  The class arguments must be precisely -- the same as in the instance declaration (modulo renaming & casts).@@ -440,7 +445,7 @@ -}  tcLookupLocated :: LocatedA Name -> TcM TcTyThing-tcLookupLocated = addLocMA tcLookup+tcLookupLocated = addLocM tcLookup  tcLookupLcl_maybe :: Name -> TcM (Maybe TcTyThing) tcLookupLcl_maybe name@@ -574,17 +579,17 @@   tcExtendLetEnv :: TopLevelFlag -> TcSigFun -> IsGroupClosed-                  -> [TcId] -> TcM a -> TcM a+                  -> [Scaled TcId] -> TcM a -> TcM (a, HsWrapper) -- Used for both top-level value bindings and nested let/where-bindings -- Adds to the TcBinderStack too tcExtendLetEnv top_lvl sig_fn (IsGroupClosed fvs fv_type_closed)                ids thing_inside-  = tcExtendBinderStack [TcIdBndr id top_lvl | id <- ids] $+  = tcExtendBinderStack [TcIdBndr id top_lvl | Scaled _ id <- ids] $     tc_extend_local_env top_lvl           [ (idName id, ATcId { tct_id   = id                               , tct_info = mk_tct_info id })-          | id <- ids ]-    thing_inside+          | Scaled _ id <- ids ] $+    foldr check_usage ((, idHsWrapper) <$> thing_inside) scaled_names   where     mk_tct_info id       | type_closed && isEmptyNameSet rhs_fvs = ClosedLet@@ -594,6 +599,11 @@         rhs_fvs     = lookupNameEnv fvs name `orElse` emptyNameSet         type_closed = isTypeClosedLetBndr id &&                       (fv_type_closed || hasCompleteSig sig_fn name)+    scaled_names = [Scaled p (idName id) | Scaled p id <- ids ]+    check_usage :: Scaled Name -> TcM (a, HsWrapper) -> TcM (a, HsWrapper)+    check_usage (Scaled p id) thing_inside = do+      ((res, inner_wrap), outer_wrap) <- tcCheckUsage id p thing_inside+      return $ (res, outer_wrap <.> inner_wrap)  tcExtendIdEnv :: [TcId] -> TcM a -> TcM a -- For lambda-bound and case-bound Ids@@ -644,8 +654,7 @@                           -- (GlobalRdrEnv handles the top level)                , tcl_th_bndrs = extendNameEnvList th_bndrs-                               [(n, thlvl) | (n, ATcId {}) <- extra_env]-                               -- We only track Ids in tcl_th_bndrs+                               [(n, thlvl) | (n, _) <- extra_env]                , tcl_env = extendNameEnvList lcl_type_env extra_env }               -- tcl_rdr and tcl_th_bndrs: extend the local LocalRdrEnv and@@ -1076,7 +1085,21 @@              | isUnboundName name -> failM  -- If the name really isn't in scope                                             -- don't report it again (#11941)              | otherwise -> failWithTc (TcRnStageRestriction (StageCheckSplice name))-           _ -> failWithTc $++           _ | isTermVarOrFieldNameSpace (nameNameSpace name) ->+               -- This code path is only reachable with RequiredTypeArguments enabled+               -- via the following chain of calls:+               --   `notFound`       called from+               --   `tcLookupGlobal` called from+               --   `tcLookup`       called from+               --   `tcTyVar`+               -- It means the user tried to use a term variable at the type level, e.g.+               --   let { a = 42; f :: a -> a; ... } in ...+               -- If you are seeing this error for any other reason, it is a bug in GHC.+               -- See Note [Demotion of unqualified variables] (W1) in GHC.Rename.Env+               failWithTc $ TcRnUnpromotableThing name TermVariablePE++             | otherwise -> failWithTc $                 mkTcRnNotInScope (getRdrName name) (NotInScopeTc (getLclEnvTypeEnv lcl_env))                        -- Take care: printing the whole gbl env can                        -- cause an infinite loop, in the case where we
compiler/GHC/Tc/Utils/Instantiate.hs view
@@ -19,7 +19,7 @@       tcInstType, tcInstTypeBndrs,      tcSkolemiseInvisibleBndrs,-     tcInstSkolTyVars, tcInstSkolTyVarsX,+     tcInstSkolTyVars, tcInstSkolTyVarsX, tcInstSkolTyVarBndrsX,      tcSkolDFunType, tcSuperSkolTyVars, tcInstSuperSkolTyVarsX,       freshenTyVarBndrs, freshenCoVarBndrsX,@@ -80,20 +80,20 @@ import GHC.Types.SourceText import GHC.Types.SrcLoc as SrcLoc import GHC.Types.Var.Env-import GHC.Types.Var.Set import GHC.Types.Id import GHC.Types.Name+import GHC.Types.Name.Env import GHC.Types.Var import qualified GHC.LanguageExtensions as LangExt  import GHC.Utils.Misc import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Outputable import GHC.Utils.Unique (sameUnique)  import GHC.Unit.State import GHC.Unit.External+import GHC.Unit.Module.Warnings  import Data.List ( mapAccumL ) import qualified Data.List.NonEmpty as NE@@ -157,9 +157,10 @@     =  ( wp, [a,b], [d1:Ord a,d2:Eq b], a->b->b )     where wp = /\a.\(d1:Ord a)./\b.\(d2:Ord b). <hole> a d1 b d2 -This second example is the reason for the recursive 'go'-function in topSkolemise: we must remove successive layers-of foralls and (=>).+This second example is the reason for the recursive 'go' function in+topSkolemise: we remove successive layers of foralls and (=>).  This+is really just an optimisation; see wrinkle (SK1) in GHC.Tc.Utils.Unify+Note [Skolemisation overview].  In general,   if      topSkolemise ty = (wrap, tvs, evs, rho)@@ -172,8 +173,8 @@ topSkolemise :: SkolemInfo              -> TcSigmaType              -> TcM ( HsWrapper-                    , [(Name,TyVar)]     -- All skolemised variables-                    , [EvVar]            -- All "given"s+                    , [(Name,TcInvisTVBinder)]     -- All skolemised variables+                    , [EvVar]                      -- All "given"s                     , TcRhoType ) -- See Note [Skolemisation] topSkolemise skolem_info ty@@ -183,13 +184,17 @@      -- Why recursive?  See Note [Skolemisation]     go subst wrap tv_prs ev_vars ty-      | (tvs, theta, inner_ty) <- tcSplitSigmaTy ty+      | (bndrs, theta, inner_ty) <- tcSplitSigmaTyBndrs ty+      , let tvs = binderVars bndrs       , not (null tvs && null theta)-      = do { (subst', tvs1) <- tcInstSkolTyVarsX skolem_info subst tvs-           ; ev_vars1       <- newEvVars (substTheta subst' theta)+      = do { (subst', bndrs1) <- tcInstSkolTyVarBndrsX skolem_info subst bndrs+           ; let tvs1 = binderVars bndrs1+           ; traceTc "topSkol" (vcat [ ppr tvs <+> vcat (map (ppr . getSrcSpan) tvs)+                                     , ppr tvs1 <+> vcat (map (ppr . getSrcSpan) tvs1) ])+           ; ev_vars1 <- newEvVars (substTheta subst' theta)            ; go subst'                 (wrap <.> mkWpTyLams tvs1 <.> mkWpEvLams ev_vars1)-                (tv_prs ++ (map tyVarName tvs `zip` tvs1))+                (tv_prs ++ (map tyVarName tvs `zip` bndrs1))                 (ev_vars ++ ev_vars1)                 inner_ty } @@ -197,7 +202,7 @@       = return (wrap, tv_prs, ev_vars, substTy subst ty)         -- substTy is a quick no-op on an empty substitution -topInstantiate ::CtOrigin -> TcSigmaType -> TcM (HsWrapper, TcRhoType)+topInstantiate :: CtOrigin -> TcSigmaType -> TcM (HsWrapper, TcRhoType) -- Instantiate outer invisible binders (both Inferred and Specified) -- If    top_instantiate ty = (wrap, inner_ty) -- then  wrap :: inner_ty "->" ty@@ -207,7 +212,10 @@   | (tvs,   body1) <- tcSplitSomeForAllTyVars isInvisibleForAllTyFlag sigma   , (theta, body2) <- tcSplitPhiTy body1   , not (null tvs && null theta)-  = do { (_, wrap1, body3) <- instantiateSigma orig tvs theta body2+  = do { (_, wrap1, body3) <- instantiateSigma orig noConcreteTyVars tvs theta body2+           -- Why 'noConcreteTyVars' here?+           -- See Note [Representation-polymorphism checking built-ins]+           -- in GHC.Tc.Gen.Head.         -- Loop, to account for types like        --       forall a. Num a => forall b. Ord b => ...@@ -217,13 +225,16 @@    | otherwise = return (idHsWrapper, sigma) -instantiateSigma :: CtOrigin -> [TyVar] -> TcThetaType -> TcSigmaType+instantiateSigma :: CtOrigin+                 -> ConcreteTyVars -- ^ concreteness information+                 -> [TyVar]+                 -> TcThetaType -> TcSigmaType                  -> TcM ([TcTyVar], HsWrapper, TcSigmaType) -- (instantiate orig tvs theta ty) -- instantiates the type variables tvs, emits the (instantiated) -- constraints theta, and returns the (instantiated) type ty-instantiateSigma orig tvs theta body_ty-  = do { (subst, inst_tvs) <- mapAccumLM newMetaTyVarX empty_subst tvs+instantiateSigma orig concs tvs theta body_ty+  = do { rec (subst, inst_tvs) <- mapAccumLM (new_meta subst) empty_subst tvs        ; let inst_theta  = substTheta subst theta              inst_body   = substTy subst body_ty              inst_tv_tys = mkTyVarTys inst_tvs@@ -235,13 +246,25 @@                        , text "theta" <+> ppr theta                        , text "type" <+> debugPprType body_ty                        , text "with" <+> vcat (map debugPprType inst_tv_tys)-                       , text "theta:" <+>  ppr inst_theta ])+                       , text "theta:" <+> ppr inst_theta ])        ; return (inst_tvs, wrap, inst_body) }   where-    free_tvs = tyCoVarsOfType body_ty `unionVarSet` tyCoVarsOfTypes theta-    in_scope = mkInScopeSet (free_tvs `delVarSetList` tvs)+    in_scope = mkInScopeSet (tyCoVarsOfType (mkSpecSigmaTy tvs theta body_ty))+               -- mkSpecSigmaTy: Inferred vs Specified is not important here;+               --                We just want an accurate free-var set     empty_subst = mkEmptySubst in_scope+    new_meta :: Subst -> Subst -> TyVar -> TcM (Subst, TcTyVar)+    new_meta final_subst subst tv+      -- Is this a type variable that must be instantiated to a concrete type?+      -- If so, create a ConcreteTv metavariable instead of a plain TauTv.+      -- See Note [Representation-polymorphism checking built-ins] in GHC.Tc.Gen.Head.+      | Just conc_orig0 <- lookupNameEnv concs (tyVarName tv)+      , let conc_orig = substConcreteTvOrigin final_subst body_ty conc_orig0+      -- See Note [substConcreteTvOrigin].+      = newConcreteTyVarX conc_orig subst tv+      | otherwise+      = newMetaTyVarX subst tv  instTyVarsWith :: CtOrigin -> [TyVar] -> [TcType] -> TcM Subst -- Use this when you want to instantiate (forall a b c. ty) with@@ -496,6 +519,13 @@ -- See Note [Skolemising type variables] tcInstSkolTyVarsX skol_info = tcInstSkolTyVarsPushLevel skol_info False +tcInstSkolTyVarBndrsX :: SkolemInfo -> Subst -> [VarBndr TyCoVar vis] -> TcM (Subst, [VarBndr TyCoVar vis])+tcInstSkolTyVarBndrsX skol_info subs bndrs = do+  (subst', bndrs') <- tcInstSkolTyVarsX skol_info subs (binderVars bndrs)+  pure (subst', zipWith mkForAllTyBinder flags bndrs')+  where+    flags = binderFlags bndrs+ tcInstSuperSkolTyVars :: SkolemInfo -> [TyVar] -> TcM (Subst, [TcTyVar]) -- See Note [Skolemising type variables] -- This version freshens the names and creates "super skolems";@@ -672,14 +702,14 @@                            -> ExpRhoType                            -> TcM (HsOverLit GhcTc) newNonTrivialOverloadedLit-  lit@(OverLit { ol_val = val, ol_ext = OverLitRn rebindable (L _ meth_name) })+  lit@(OverLit { ol_val = val, ol_ext = OverLitRn rebindable (L loc meth_name) })   res_ty   = do  { hs_lit <- mkOverLit val         ; let lit_ty = hsLitType hs_lit         ; (_, fi') <- tcSyntaxOp orig (mkRnSyntaxExpr meth_name)                                       [synKnownType lit_ty] res_ty $                       \_ _ -> return ()-        ; let L _ witness = nlHsSyntaxApps fi' [nlHsLit hs_lit]+        ; let L _ witness = mkHsSyntaxApps (l2l loc) fi' [nlHsLit hs_lit]         ; res_ty <- readExpType res_ty         ; return (lit { ol_ext = OverLitTc { ol_rebindable = rebindable                                            , ol_witness = witness@@ -688,7 +718,7 @@     orig = LiteralOrigin lit  -------------mkOverLit ::OverLitVal -> TcM (HsLit GhcTc)+mkOverLit :: OverLitVal -> TcM (HsLit (GhcPass p)) mkOverLit (HsIntegral i)   = do  { integer_ty <- tcMetaTy integerTyConName         ; return (HsInteger (il_text i)@@ -853,8 +883,8 @@ tcGetInsts = fmap tcg_insts getGblEnv  newClsInst :: Maybe OverlapMode -> Name -> [TyVar] -> ThetaType-           -> Class -> [Type] -> TcM ClsInst-newClsInst overlap_mode dfun_name tvs theta clas tys+           -> Class -> [Type] -> Maybe (WarningTxt GhcRn) -> TcM ClsInst+newClsInst overlap_mode dfun_name tvs theta clas tys warn   = do { (subst, tvs') <- freshenTyVarBndrs tvs              -- Be sure to freshen those type variables,              -- so they are sure not to appear in any lookup@@ -868,7 +898,7 @@              --     helpful to use the same names         ; oflag <- getOverlapFlag overlap_mode-       ; let cls_inst = mkLocalClsInst dfun oflag tvs' clas tys'+       ; let cls_inst = mkLocalClsInst dfun oflag tvs' clas tys' warn         ; when (isOrphan (is_orphan cls_inst)) $          addDiagnostic (TcRnOrphanInstance $ Left cls_inst)
compiler/GHC/Tc/Utils/Monad.hs view
@@ -1,8 +1,4 @@-{-# LANGUAGE BangPatterns      #-}-{-# LANGUAGE ExplicitForAll    #-}-{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE RecordWildCards   #-}-{-# LANGUAGE TypeApplications  #-}  {-# OPTIONS_GHC -fno-warn-orphans #-} @@ -61,9 +57,9 @@   addDependentFiles,    -- * Error management-  getSrcSpanM, setSrcSpan, setSrcSpanA, addLocM, addLocMA,+  getSrcSpanM, setSrcSpan, setSrcSpanA, addLocM,   inGeneratedCode, setInGeneratedCode,-  wrapLocM, wrapLocAM, wrapLocFstM, wrapLocFstMA, wrapLocSndM, wrapLocSndMA, wrapLocM_,+  wrapLocM, wrapLocFstM, wrapLocFstMA, wrapLocSndM, wrapLocSndMA, wrapLocM_,   wrapLocMA_,wrapLocMA,   getErrsVar, setErrsVar,   addErr,@@ -350,7 +346,7 @@                 tcg_merged         = [],                 tcg_dfun_n         = dfun_n_var,                 tcg_keep           = keep_var,-                tcg_doc_hdr        = Nothing,+                tcg_hdr_info        = (Nothing,Nothing),                 tcg_hpc            = False,                 tcg_main           = Nothing,                 tcg_self_boot      = NoSelfBoot,@@ -992,23 +988,20 @@ setInGeneratedCode thing_inside =   updLclCtxt (\env -> env { tcl_in_gen_code = True }) thing_inside -setSrcSpanA :: SrcSpanAnn' ann -> TcRn a -> TcRn a+setSrcSpanA :: EpAnn ann -> TcRn a -> TcRn a setSrcSpanA l = setSrcSpan (locA l) -addLocM :: (a -> TcM b) -> Located a -> TcM b-addLocM fn (L loc a) = setSrcSpan loc $ fn a--addLocMA :: (a -> TcM b) -> GenLocated (SrcSpanAnn' ann) a -> TcM b-addLocMA fn (L loc a) = setSrcSpanA loc $ fn a--wrapLocM :: (a -> TcM b) -> Located a -> TcM (Located b)-wrapLocM fn (L loc a) = setSrcSpan loc $ do { b <- fn a-                                            ; return (L loc b) }+addLocM :: (HasLoc t) => (a -> TcM b) -> GenLocated t a -> TcM b+addLocM fn (L loc a) = setSrcSpan (getHasLoc loc) $ fn a -wrapLocAM :: (a -> TcM b) -> LocatedAn an a -> TcM (Located b)-wrapLocAM fn a = wrapLocM fn (reLoc a)+wrapLocM :: (HasLoc t) =>  (a -> TcM b) -> GenLocated t a -> TcM (Located b)+wrapLocM fn (L loc a) =+  let+    loc' = getHasLoc loc+  in setSrcSpan loc' $ do { b <- fn a+                          ; return (L loc' b) } -wrapLocMA :: (a -> TcM b) -> GenLocated (SrcSpanAnn' ann) a -> TcRn (GenLocated (SrcSpanAnn' ann) b)+wrapLocMA :: (a -> TcM b) -> GenLocated (EpAnn ann) a -> TcRn (GenLocated (EpAnn ann) b) wrapLocMA fn (L loc a) = setSrcSpanA loc $ do { b <- fn a                                               ; return (L loc b) } @@ -1023,7 +1016,7 @@ --    wrapLocFstMA :: (a -> TcM (b,c)) -> LocatedN    a -> TcM (LocatedN    b, c) --    wrapLocFstMA :: (a -> TcM (b,c)) -> LocatedAn t a -> TcM (LocatedAn t b, c) -- and so on.-wrapLocFstMA :: (a -> TcM (b,c)) -> GenLocated (SrcSpanAnn' ann) a -> TcM (GenLocated (SrcSpanAnn' ann) b, c)+wrapLocFstMA :: (a -> TcM (b,c)) -> GenLocated (EpAnn ann) a -> TcM (GenLocated (EpAnn ann) b, c) wrapLocFstMA fn (L loc a) =   setSrcSpanA loc $ do     (b,c) <- fn a@@ -1040,7 +1033,7 @@ --    wrapLocSndMA :: (a -> TcM (b, c)) -> LocatedN    a -> TcM (b, LocatedN    c) --    wrapLocSndMA :: (a -> TcM (b, c)) -> LocatedAn t a -> TcM (b, LocatedAn t c) -- and so on.-wrapLocSndMA :: (a -> TcM (b, c)) -> GenLocated (SrcSpanAnn' ann) a -> TcM (b, GenLocated (SrcSpanAnn' ann) c)+wrapLocSndMA :: (a -> TcM (b, c)) -> GenLocated (EpAnn ann) a -> TcM (b, GenLocated (EpAnn ann) c) wrapLocSndMA fn (L loc a) =   setSrcSpanA loc $ do     (b,c) <- fn a@@ -1219,7 +1212,7 @@  So typically it's better to do setSrcSpan /before/ addErrCtxt. -See Note [Rebindable syntax and HsExpansion] in GHC.Hs.Expr for+See Note [Rebindable syntax and XXExprGhcRn] in GHC.Hs.Expr for more discussion of this fancy footwork, as well as Note [Generated code and pattern-match checking] in GHC.Types.Basic for the relation with pattern-match checks.@@ -1263,13 +1256,14 @@  updCtxt :: ErrCtxt -> TcLclEnv -> TcLclEnv -- Do not update the context if we are in generated code--- See Note [Rebindable syntax and HsExpansion] in GHC.Hs.Expr+-- See Note [Rebindable syntax and XXExprGhcRn] in GHC.Hs.Expr updCtxt ctxt env   | lclEnvInGeneratedCode env = env   | otherwise = addLclEnvErrCtxt ctxt env  popErrCtxt :: TcM a -> TcM a-popErrCtxt = updLclEnv (\env -> setLclEnvErrCtxt (pop $ getLclEnvErrCtxt env) env)+popErrCtxt thing_inside = updLclEnv (\env -> setLclEnvErrCtxt (pop $ getLclEnvErrCtxt env) env) $+                          thing_inside            where              pop []       = []              pop (_:msgs) = msgs@@ -1299,7 +1293,6 @@                      $ setLclEnvErrCtxt (ctl_ctxt lcl)                      $ setLclEnvBinderStack (ctl_bndrs lcl)                      $ env) thing_inside-  {- ********************************************************************* *                                                                      *
compiler/GHC/Tc/Utils/TcMType.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE LambdaCase      #-} {-# LANGUAGE MultiWayIf      #-} {-# LANGUAGE RecursiveDo     #-} {-# LANGUAGE TupleSections   #-}@@ -23,9 +24,10 @@   newFlexiTyVarTy,              -- Kind -> TcM TcType   newFlexiTyVarTys,             -- Int -> Kind -> TcM [TcType]   newOpenFlexiTyVar, newOpenFlexiTyVarTy, newOpenTypeKind,+  newOpenFlexiFRRTyVar, newOpenFlexiFRRTyVarTy,   newOpenBoxedTypeKind,   newMetaKindVar, newMetaKindVars,-  newMetaTyVarTyAtLevel, newConcreteTyVarTyAtLevel,+  newMetaTyVarTyAtLevel, newConcreteTyVarTyAtLevel, substConcreteTvOrigin,   newAnonMetaTyVar, newConcreteTyVar,   cloneMetaTyVar, cloneMetaTyVarWithInfo,   newCycleBreakerTyVar,@@ -53,10 +55,11 @@    --------------------------------   -- Instantiation-  newMetaTyVars, newMetaTyVarX, newMetaTyVarsX,+  newMetaTyVars, newMetaTyVarX, newMetaTyVarsX, newMetaTyVarBndrsX,   newMetaTyVarTyVarX,   newTyVarTyVar, cloneTyVarTyVar,-  newPatSigTyVar, newSkolemTyVar, newWildCardX,+  newConcreteTyVarX,+  newPatTyVar, newSkolemTyVar, newWildCardX,    --------------------------------   -- Expected types@@ -146,7 +149,6 @@ import GHC.Utils.Misc import GHC.Utils.Outputable import GHC.Utils.Panic-import GHC.Utils.Panic.Plain import GHC.Utils.Constants (debugIsOn)  import Control.Monad@@ -362,8 +364,8 @@ newCoercionHole loc = newCoercionHoleO (ctLocOrigin loc)  newCoercionHoleO :: CtOrigin -> TcPredType -> TcM CoercionHole-newCoercionHoleO (KindEqOrigin {}) = new_coercion_hole True-newCoercionHoleO _                 = new_coercion_hole False+newCoercionHoleO (KindEqOrigin {}) pty = new_coercion_hole True pty+newCoercionHoleO _ pty                 = new_coercion_hole False pty  new_coercion_hole :: Bool -> TcPredType -> TcM CoercionHole new_coercion_hole hetero_kind pred_ty@@ -795,19 +797,27 @@                  -> FastString -> TcKind -> TcM TcTyVar newConcreteTyVar reason fs kind   = assertPpr (isConcreteType kind) assert_msg $-    newNamedAnonMetaTyVar fs (ConcreteTv reason) kind+  do { th_stage <- getStage+     ; if+        -- See [Wrinkle: Typed Template Haskell]+        -- in Note [hasFixedRuntimeRep] in GHC.Tc.Utils.Concrete.+        | Brack _ (TcPending {}) <- th_stage+        -> newNamedAnonMetaTyVar fs TauTv kind++        | otherwise+        -> newNamedAnonMetaTyVar fs (ConcreteTv reason) kind }   where     assert_msg = text "newConcreteTyVar: non-concrete kind" <+> ppr kind -newPatSigTyVar :: Name -> Kind -> TcM TcTyVar-newPatSigTyVar name kind+newPatTyVar :: Name -> Kind -> TcM TcTyVar+newPatTyVar name kind   = do { details <- newMetaDetails TauTv        ; uniq <- newUnique        ; let name' = name `setNameUnique` uniq              tyvar = mkTcTyVar name' kind details          -- Don't use cloneMetaTyVar;          -- same reasoning as in newTyVarTyVar-       ; traceTc "newPatSigTyVar" (ppr tyvar)+       ; traceTc "newPatTyVar" (ppr tyvar)        ; return tyvar }  cloneAnonMetaTyVar :: MetaInfo -> TyVar -> TcKind -> TcM TcTyVar@@ -953,7 +963,11 @@        ; return (mkTYPEapp rr) }  -- | Create a tyvar that can be a lifted or unlifted type.--- Returns alpha :: TYPE kappa, where both alpha and kappa are fresh+-- Returns @alpha :: TYPE kappa@, where both @alpha@ and @kappa@ are fresh.+--+-- Note: you should use 'newOpenFlexiFRRTyVarTy' if you also need to ensure+-- that the representation is concrete, in the sense of Note [Concrete types]+-- in GHC.Tc.Utils.Concrete. newOpenFlexiTyVarTy :: TcM TcType newOpenFlexiTyVarTy   = do { tv <- newOpenFlexiTyVar@@ -964,6 +978,30 @@   = do { kind <- newOpenTypeKind        ; newFlexiTyVar kind } +-- | Like 'newOpenFlexiTyVar', but ensures the type variable has a+-- syntactically fixed RuntimeRep in the sense of Note [Fixed RuntimeRep]+-- in GHC.Tc.Utils.Concrete.+newOpenFlexiFRRTyVar :: FixedRuntimeRepContext -> TcM TcTyVar+newOpenFlexiFRRTyVar frr_ctxt+  = do { th_stage <- getStage+       ; case th_stage of+          { Brack _ (TcPending {}) -- See [Wrinkle: Typed Template Haskell]+              -> newOpenFlexiTyVar -- in Note [hasFixedRuntimeRep] in GHC.Tc.Utils.Concrete.+          ; _ ->+   mdo { let conc_orig = ConcreteFRR $+                          FixedRuntimeRepOrigin+                            { frr_context = frr_ctxt+                            , frr_type    = mkTyVarTy tv }+        ; rr <- mkTyVarTy <$> newConcreteTyVar conc_orig (fsLit "cx") runtimeRepTy+        ; tv <- newFlexiTyVar (mkTYPEapp rr)+        ; return tv } } }++-- | See 'newOpenFlexiFRRTyVar'.+newOpenFlexiFRRTyVarTy :: FixedRuntimeRepContext -> TcM TcType+newOpenFlexiFRRTyVarTy frr_ctxt+  = do { tv <- newOpenFlexiFRRTyVar frr_ctxt+       ; return (mkTyVarTy tv) }+ newOpenBoxedTypeKind :: TcM TcKind newOpenBoxedTypeKind   = do { lev <- newFlexiTyVarTy (mkTyConTy levityTyCon)@@ -984,14 +1022,33 @@ -- Just like newMetaTyVars, but start with an existing substitution. newMetaTyVarsX subst = mapAccumLM newMetaTyVarX subst +newMetaTyVarBndrsX :: Subst -> [VarBndr TyVar vis] -> TcM (Subst, [VarBndr TcTyVar vis])+newMetaTyVarBndrsX subst bndrs = do+  (subst, bndrs') <- newMetaTyVarsX subst (binderVars bndrs)+  pure (subst, zipWith mkForAllTyBinder flags bndrs')+  where+    flags = binderFlags bndrs+ newMetaTyVarX :: Subst -> TyVar -> TcM (Subst, TcTyVar) -- Make a new unification variable tyvar whose Name and Kind come from -- an existing TyVar. We substitute kind variables in the kind. newMetaTyVarX = new_meta_tv_x TauTv +-- | Like 'newMetaTyVarX', but for concrete type variables.+newConcreteTyVarX :: ConcreteTvOrigin -> Subst -> TyVar -> TcM (Subst, TcTyVar)+newConcreteTyVarX conc subst tv+  = do { th_stage <- getStage+       ; if+          -- See [Wrinkle: Typed Template Haskell]+          -- in Note [hasFixedRuntimeRep] in GHC.Tc.Utils.Concrete.+          | Brack _ (TcPending {}) <- th_stage+          -> new_meta_tv_x TauTv subst tv+          | otherwise+          -> new_meta_tv_x (ConcreteTv conc) subst tv }+ newMetaTyVarTyVarX :: Subst -> TyVar -> TcM (Subst, TcTyVar) -- Just like newMetaTyVarX, but make a TyVarTv-newMetaTyVarTyVarX = new_meta_tv_x TyVarTv+newMetaTyVarTyVarX subst tv = new_meta_tv_x TyVarTv subst tv  newWildCardX :: Subst -> TyVar -> TcM (Subst, TcTyVar) newWildCardX subst tv@@ -1004,16 +1061,7 @@         ; let subst1 = extendTvSubstWithClone subst tv new_tv         ; return (subst1, new_tv) }   where-    substd_kind = substTyUnchecked subst (tyVarKind tv)-      -- NOTE: #12549 is fixed so we could use-      -- substTy here, but the tc_infer_args problem-      -- is not yet fixed so leaving as unchecked for now.-      -- OLD NOTE:-      -- Unchecked because we call newMetaTyVarX from-      -- tcInstTyBinder, which is called from tcInferTyApps-      -- which does not yet take enough trouble to ensure-      -- the in-scope set is right; e.g. #12785 trips-      -- if we use substTy here+    substd_kind = substTy subst (tyVarKind tv)  newMetaTyVarTyAtLevel :: TcLevel -> TcKind -> TcM TcType newMetaTyVarTyAtLevel tc_lvl kind@@ -1027,6 +1075,91 @@         ; name    <- newMetaTyVarName (fsLit "c")         ; return (mkTyVarTy (mkTcTyVar name kind details)) } +{- Note [substConcreteTvOrigin]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+To report helpful representation-polymorphism errors to the users, we want to+indicate which type caused the error, instead of simply printing kinds.+For example, in++  coerce :: forall {r} (a :: TYPE r) (b :: TYPE r). Coercible a b => a -> b++  bad :: forall {s} (z :: TYPE s). z -> z+  bad = coerce++we want the error message to say (with additional debug info on type variables+for clarity of this explanation):++  The first argument of 'coerce' does not have a fixed runtime representation.+  Its type is:+    a0[tau] :: TYPE r0[conc]+  Could not unify s[sk] with r0[conc] because the former is not a concrete+  RuntimeRep.++This is more informative than just saying that we could not unify s[sk] with+r0[conc]; it's helpful to users to phrase it in terms of types rather than kinds+whenever possible (especially as the kind variables often have inferred Specificity).++To achieve this, we store the type on which the representation-polymorphism+check is being performed, in the field frr_type of FixedRuntimeRepOrigin.+This is all described in Note [Reporting representation-polymorphism errors] in+GHC.Tc.Types.Origin.++However, we have to be careful in the example above, in which we are+instantiating a built-in representation-polymorphic 'Id'. As described in the+Note [Representation-polymorphism checking built-ins] in GHC.Tc.Gen.Head, in such+cases we end up storing types appearing in the original type of the primop,+which means for the situation above with 'coerce' we end up with a ConcreteTvOrigin+which includes type variables bound in the original type of 'coerce':++  FixedRuntimeRepOrigin+    { frr_type = a[tv] :: TYPE r[tv]+    , frr_context = "first argument of coerce" }++When we instantiate 'coerce' in the previous example, we obtain a substitution++  [ r[tv] |-> r0[conc], a |-> a0 :: TYPE r0[conc] ]++which we need to apply to the 'frr_type' field in order for the type variables+in the error message to match up.+This is done by the call to 'substConcreteTvOrigin' in 'instantiateSigma'.++Wrinkle [Extending the substitution]++  In certain cases, we need to extend the substitution we get from 'instantiateSigma'.+  For example, suppose we have:++    bad2 :: forall {s} (z :: TYPE s). z -> z+    bad2 = coerce @z++  Then 'instantiateSigma' will only instantiate the inferred type variable 'r'+  of 'coerce', as it needs to leave 'a' un-instantiated so that the visible+  type application '@z' makes sense. In this case, we end up with a substitution++    subst:                   [ r[tv] |-> r0[conc] ]+    body_ty:                forall (a :: TYPE r[tv]) (b :: TYPE r[tv]). ...+    substTy subst body_ty:  forall (a' :: TYPE r0[conc]) (b' :: TYPE r0[conc]). ...++  Now, we still want a substitution that maps (a :: TYPE r[tv]) to+  (a' :: TYPE r0[conc]) in order to apply it to the 'frr_type', so that we don't+  mention the un-substed (a :: TYPE r[tv]) in the error message.+  To achieve this, we extend the substitution with the outermost quantified type+  variables in the leftover (partially-instantiated) type using 'substTyVarBndrs'+  to get the full substitution which we use in 'substConcreteTvOrigin'.+-}++substConcreteTvOrigin :: Subst -> Type -> ConcreteTvOrigin -> ConcreteTvOrigin+substConcreteTvOrigin subst body_ty (ConcreteFRR frr_orig)+  -- See Note [substConcreteTvOrigin], Wrinkle [Extending the substitution]+  -- for the justification of this extra complication.+  = let subst' = case splitForAllTyCoVars body_ty of+                   ([], _) -> subst+                   (bndrs, _) -> fst $ substTyVarBndrs subst bndrs+    in ConcreteFRR $ substFRROrigin subst' frr_orig++substFRROrigin :: Subst -> FixedRuntimeRepOrigin -> FixedRuntimeRepOrigin+substFRROrigin subst orig@(FixedRuntimeRepOrigin { frr_type = ty })+  = orig { frr_type = substTy subst ty }+ {- ********************************************************************* *                                                                      *           Finding variables to quantify over@@ -1450,7 +1583,7 @@      go_co dv (CoVarCo cv) = go_cv dv cv -    go_co dv (ForAllCo tcv kind_co co)+    go_co dv (ForAllCo { fco_tcv = tcv, fco_kind = kind_co, fco_body = co })       = do { dv1 <- go_co dv kind_co            ; collect_cand_qtvs_co orig_ty cur_lvl (bound `extendVarSet` tcv) dv1 co } @@ -1460,7 +1593,6 @@     go_prov dv (PhantomProv co)    = go_co dv co     go_prov dv (ProofIrrelProv co) = go_co dv co     go_prov dv (PluginProv _)      = return dv-    go_prov dv (CorePrepProv _)    = return dv      go_cv :: CandidatesQTvs -> CoVar -> TcM CandidatesQTvs     go_cv dv@(DV { dv_cvs = cvs }) cv@@ -1590,7 +1722,7 @@  Note that not *every* variable with a higher level will get generalised, either due to the monomorphism restriction or other-quirks. See, for example, the code in GHC.Tc.Solver.decideMonoTyVars+quirks. See, for example, the code in GHC.Tc.Solver.decidePromotedTyVars and in GHC.Tc.Gen.HsType.kindGeneralizeSome, both of which exclude certain otherwise-eligible variables from being generalised. @@ -2239,11 +2371,11 @@   where     go_integral int@(IL src neg i)       | isIntTy res_ty  && platformInIntRange  platform i-      = Just (HsLit noAnn (HsInt noExtField int))+      = Just (HsLit noExtField (HsInt noExtField int))       | isWordTy res_ty && platformInWordRange platform i       = Just (mkLit wordDataCon (HsWordPrim src i))       | isIntegerTy res_ty-      = Just (HsLit noAnn (HsInteger src i res_ty))+      = Just (HsLit noExtField (HsInteger src i res_ty))       | otherwise       = go_fractional (integralFractionalLit neg i)         -- The 'otherwise' case is important@@ -2264,11 +2396,11 @@             -- is less than 100, which ensures desugaring isn't slow.      go_string src s-      | isStringTy res_ty = Just (HsLit noAnn (HsString src s))+      | isStringTy res_ty = Just (HsLit noExtField (HsString src s))       | otherwise         = Nothing  mkLit :: DataCon -> HsLit GhcTc -> HsExpr GhcTc-mkLit con lit = HsApp noComments (nlHsDataCon con) (nlHsLit lit)+mkLit con lit = HsApp noExtField (nlHsDataCon con) (nlHsLit lit)  ------------------------------ hsOverLitName :: OverLitVal -> Name
+ compiler/GHC/Tc/Utils/TcMType.hs-boot view
@@ -0,0 +1,8 @@+module GHC.Tc.Utils.TcMType where++import GHC.Tc.Types+import GHC.Types.Name+import GHC.Core.TyCo.Rep+import GHC.Tc.Types.Evidence++tcCheckUsage :: Name -> Mult -> TcM a -> TcM (a, HsWrapper)
compiler/GHC/Tc/Utils/Unify.hs view
@@ -13,1688 +13,1867 @@ module GHC.Tc.Utils.Unify (   -- Full-blown subsumption   tcWrapResult, tcWrapResultO, tcWrapResultMono,-  tcTopSkolemise, tcSkolemiseScoped, tcSkolemiseExpType,-  tcSubType, tcSubTypeSigma, tcSubTypePat, tcSubTypeDS,-  tcSubTypeAmbiguity, tcSubMult,-  checkConstraints, checkTvConstraints,-  buildImplicationFor, buildTvImplication, emitResidualTvConstraint,--  -- Various unifications-  unifyType, unifyKind, unifyInvisibleType, unifyExpectedType,-  unifyTypeAndEmit, promoteTcType,-  swapOverTyVars, touchabilityAndShapeTest,-  UnifyEnv(..), updUEnvLoc, setUEnvRole,-  uType,--  ---------------------------------  -- Holes-  tcInfer,-  matchExpectedListTy,-  matchExpectedTyConApp,-  matchExpectedAppTy,-  matchExpectedFunTys,-  matchExpectedFunKind,-  matchActualFunTySigma, matchActualFunTysRho,--  checkTyEqRhs, recurseIntoTyConApp,-  PuResult(..), failCheckWith, okCheckRefl, mapCheck,-  TyEqFlags(..), TyEqFamApp(..), AreUnifying(..), LevelCheck(..), FamAppBreaker,-  famAppArgFlags, simpleUnifyCheck, checkPromoteFreeVars,-  ) where--import GHC.Prelude--import GHC.Hs--import GHC.Tc.Utils.Concrete ( hasFixedRuntimeRep, hasFixedRuntimeRep_syntactic )-import GHC.Tc.Utils.Env-import GHC.Tc.Utils.Instantiate-import GHC.Tc.Utils.Monad-import GHC.Tc.Utils.TcMType-import GHC.Tc.Utils.TcType-import GHC.Tc.Types.Evidence-import GHC.Tc.Types.Constraint-import GHC.Tc.Types.Origin-import GHC.Tc.Zonk.TcType--import GHC.Core.Type-import GHC.Core.TyCo.Rep-import GHC.Core.TyCo.FVs( isInjectiveInType )-import GHC.Core.TyCo.Ppr( debugPprType {- pprTyVar -} )-import GHC.Core.TyCon-import GHC.Core.Coercion-import GHC.Core.Multiplicity-import GHC.Core.Reduction--import qualified GHC.LanguageExtensions as LangExt--import GHC.Builtin.Types-import GHC.Types.Name-import GHC.Types.Var as Var-import GHC.Types.Var.Set-import GHC.Types.Var.Env-import GHC.Types.Basic-import GHC.Types.Unique.Set (nonDetEltsUniqSet)--import GHC.Utils.Error-import GHC.Utils.Misc-import GHC.Utils.Outputable as Outputable-import GHC.Utils.Panic-import GHC.Utils.Panic.Plain--import GHC.Driver.DynFlags-import GHC.Data.Bag-import GHC.Data.FastString( fsLit )--import Control.Monad-import Data.Monoid as DM ( Any(..) )-import qualified Data.Semigroup as S ( (<>) )--{- *********************************************************************-*                                                                      *-              matchActualFunTys-*                                                                      *-********************************************************************* -}---- | 'matchActualFunTySigma' looks for just one function arrow,--- returning an uninstantiated sigma-type.------ Invariant: the returned argument type has a syntactically fixed--- RuntimeRep in the sense of Note [Fixed RuntimeRep]--- in GHC.Tc.Utils.Concrete.------ See Note [Return arguments with a fixed RuntimeRep].-matchActualFunTySigma-  :: ExpectedFunTyOrigin-      -- ^ See Note [Herald for matchExpectedFunTys]-  -> Maybe TypedThing-      -- ^ The thing with type TcSigmaType-  -> (Arity, [Scaled TcSigmaType])-      -- ^ Total number of value args in the call, and-      -- types of values args to which function has-      --   been applied already (reversed)-      -- (Both are used only for error messages)-  -> TcRhoType-      -- ^ Type to analyse: a TcRhoType-  -> TcM (HsWrapper, Scaled TcSigmaTypeFRR, TcSigmaType)--- This function takes in a type to analyse (a RhoType) and returns--- an argument type and a result type (splitting apart a function arrow).--- The returned argument type is a SigmaType with a fixed RuntimeRep;--- as explained in Note [Return arguments with a fixed RuntimeRep].------ See Note [matchActualFunTy error handling] for the first three arguments---- If   (wrap, arg_ty, res_ty) = matchActualFunTySigma ... fun_ty--- then wrap :: fun_ty ~> (arg_ty -> res_ty)--- and NB: res_ty is an (uninstantiated) SigmaType--matchActualFunTySigma herald mb_thing err_info fun_ty-  = assertPpr (isRhoTy fun_ty) (ppr fun_ty) $-    go fun_ty-  where-    -- Does not allocate unnecessary meta variables: if the input already is-    -- a function, we just take it apart.  Not only is this efficient,-    -- it's important for higher rank: the argument might be of form-    --              (forall a. ty) -> other-    -- If allocated (fresh-meta-var1 -> fresh-meta-var2) and unified, we'd-    -- hide the forall inside a meta-variable-    go :: TcRhoType   -- The type we're processing, perhaps after-                      -- expanding type synonyms-       -> TcM (HsWrapper, Scaled TcSigmaTypeFRR, TcSigmaType)-    go ty | Just ty' <- coreView ty = go ty'--    go (FunTy { ft_af = af, ft_mult = w, ft_arg = arg_ty, ft_res = res_ty })-      = assert (isVisibleFunArg af) $-      do { hasFixedRuntimeRep_syntactic (FRRExpectedFunTy herald 1) arg_ty-         ; return (idHsWrapper, Scaled w arg_ty, res_ty) }--    go ty@(TyVarTy tv)-      | isMetaTyVar tv-      = do { cts <- readMetaTyVar tv-           ; case cts of-               Indirect ty' -> go ty'-               Flexi        -> defer ty }--       -- In all other cases we bale out into ordinary unification-       -- However unlike the meta-tyvar case, we are sure that the-       -- number of arguments doesn't match arity of the original-       -- type, so we can add a bit more context to the error message-       -- (cf #7869).-       ---       -- It is not always an error, because specialized type may have-       -- different arity, for example:-       ---       -- > f1 = f2 'a'-       -- > f2 :: Monad m => m Bool-       -- > f2 = undefined-       ---       -- But in that case we add specialized type into error context-       -- anyway, because it may be useful. See also #9605.-    go ty = addErrCtxtM (mk_ctxt ty) (defer ty)--    -------------    defer fun_ty-      = do { arg_ty <- newOpenFlexiTyVarTy-           ; res_ty <- newOpenFlexiTyVarTy-           ; mult <- newFlexiTyVarTy multiplicityTy-           ; let unif_fun_ty = tcMkVisFunTy mult arg_ty res_ty-           ; co <- unifyType mb_thing fun_ty unif_fun_ty-           ; hasFixedRuntimeRep_syntactic (FRRExpectedFunTy herald 1) arg_ty-           ; return (mkWpCastN co, Scaled mult arg_ty, res_ty) }--    -------------    mk_ctxt :: TcType -> TidyEnv -> ZonkM (TidyEnv, SDoc)-    mk_ctxt res_ty env = mkFunTysMsg env herald (reverse arg_tys_so_far)-                                     res_ty n_val_args_in_call-    (n_val_args_in_call, arg_tys_so_far) = err_info--{- Note [matchActualFunTy error handling]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-matchActualFunTySigma is made much more complicated by the-desire to produce good error messages. Consider the application-    f @Int x y-In GHC.Tc.Gen.Expr.tcArgs we deal with visible type arguments,-and then call matchActualFunTysPart for each individual value-argument. It, in turn, must instantiate any type/dictionary args,-before looking for an arrow type.--But if it doesn't find an arrow type, it wants to generate a message-like "f is applied to two arguments but its type only has one".-To do that, it needs to know about the args that tcArgs has already-munched up -- hence passing in n_val_args_in_call and arg_tys_so_far;-and hence also the accumulating so_far arg to 'go'.--This allows us (in mk_ctxt) to construct f's /instantiated/ type,-with just the values-arg arrows, which is what we really want-in the error message.--Ugh!--}---- | Like 'matchExpectedFunTys', but used when you have an "actual" type,--- for example in function application.------ INVARIANT: the returned argument types all have a syntactically fixed RuntimeRep--- in the sense of Note [Fixed RuntimeRep] in GHC.Tc.Utils.Concrete.--- See Note [Return arguments with a fixed RuntimeRep].-matchActualFunTysRho :: ExpectedFunTyOrigin -- ^ See Note [Herald for matchExpectedFunTys]-                     -> CtOrigin-                     -> Maybe TypedThing -- ^ the thing with type TcSigmaType-                     -> Arity-                     -> TcSigmaType-                     -> TcM (HsWrapper, [Scaled TcSigmaTypeFRR], TcRhoType)--- If    matchActualFunTysRho n ty = (wrap, [t1,..,tn], res_ty)--- then  wrap : ty ~> (t1 -> ... -> tn -> res_ty)---       and res_ty is a RhoType--- NB: the returned type is top-instantiated; it's a RhoType-matchActualFunTysRho herald ct_orig mb_thing n_val_args_wanted fun_ty-  = go n_val_args_wanted [] fun_ty-  where-    go n so_far fun_ty-      | not (isRhoTy fun_ty)-      = do { (wrap1, rho) <- topInstantiate ct_orig fun_ty-           ; (wrap2, arg_tys, res_ty) <- go n so_far rho-           ; return (wrap2 <.> wrap1, arg_tys, res_ty) }--    go 0 _ fun_ty = return (idHsWrapper, [], fun_ty)--    go n so_far fun_ty-      = do { (wrap_fun1, arg_ty1, res_ty1) <- matchActualFunTySigma-                                                 herald mb_thing-                                                 (n_val_args_wanted, so_far)-                                                 fun_ty-           ; (wrap_res, arg_tys, res_ty)   <- go (n-1) (arg_ty1:so_far) res_ty1-           ; let wrap_fun2 = mkWpFun idHsWrapper wrap_res arg_ty1 res_ty-           -- NB: arg_ty1 comes from matchActualFunTySigma, so it has-           -- a syntactically fixed RuntimeRep as needed to call mkWpFun.-           ; return (wrap_fun2 <.> wrap_fun1, arg_ty1:arg_tys, res_ty) }--{--************************************************************************-*                                                                      *-             matchExpected functions-*                                                                      *-************************************************************************--Note [Herald for matchExpectedFunTys]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-The 'herald' always looks like:-   "The equation(s) for 'f' have"-   "The abstraction (\x.e) takes"-   "The section (+ x) expects"-   "The function 'f' is applied to"--This is used to construct a message of form--   The abstraction `\Just 1 -> ...' takes two arguments-   but its type `Maybe a -> a' has only one--   The equation(s) for `f' have two arguments-   but its type `Maybe a -> a' has only one--   The section `(f 3)' requires 'f' to take two arguments-   but its type `Int -> Int' has only one--   The function 'f' is applied to two arguments-   but its type `Int -> Int' has only one--When visible type applications (e.g., `f @Int 1 2`, as in #13902) enter the-picture, we have a choice in deciding whether to count the type applications as-proper arguments:--   The function 'f' is applied to one visible type argument-     and two value arguments-   but its type `forall a. a -> a` has only one visible type argument-     and one value argument--Or whether to include the type applications as part of the herald itself:--   The expression 'f @Int' is applied to two arguments-   but its type `Int -> Int` has only one--The latter is easier to implement and is arguably easier to understand, so we-choose to implement that option.--Note [matchExpectedFunTys]-~~~~~~~~~~~~~~~~~~~~~~~~~~-matchExpectedFunTys checks that a sigma has the form-of an n-ary function.  It passes the decomposed type to the-thing_inside, and returns a wrapper to coerce between the two types--It's used wherever a language construct must have a functional type,-namely:-        A lambda expression-        A function definition-     An operator section--This function must be written CPS'd because it needs to fill in the-ExpTypes produced for arguments before it can fill in the ExpType-passed in.--Note [Return arguments with a fixed RuntimeRep]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-The functions--  - matchExpectedFunTys,-  - matchActualFunTySigma,-  - matchActualFunTysRho,--peel off argument types, as explained in Note [matchExpectedFunTys].-It's important that these functions return argument types that have-a fixed runtime representation, otherwise we would be in violation-of the representation-polymorphism invariants of-Note [Representation polymorphism invariants] in GHC.Core.--This is why all these functions have an additional invariant,-that the argument types they return all have a syntactically fixed RuntimeRep,-in the sense of Note [Fixed RuntimeRep] in GHC.Tc.Utils.Concrete.--Example:--  Suppose we have--    type F :: Type -> RuntimeRep-    type family F a where { F Int = LiftedRep }--    type Dual :: Type -> Type-    type family Dual a where-      Dual a = a -> ()--    f :: forall (a :: TYPE (F Int)). Dual a-    f = \ x -> ()--  The body of `f` is a lambda abstraction, so we must be able to split off-  one argument type from its type. This is handled by `matchExpectedFunTys`-  (see 'GHC.Tc.Gen.Match.tcMatchLambda'). We end up with desugared Core that-  looks like this:--    f :: forall (a :: TYPE (F Int)). Dual (a |> (TYPE F[0]))-    f = \ @(a :: TYPE (F Int)) ->-          (\ (x :: (a |> (TYPE F[0]))) -> ())-          `cast`-          (Sub (Sym (Dual[0] <(a |> (TYPE F[0]))>)))--  Two important transformations took place:--    1. We inserted casts around the argument type to ensure that it has-       a fixed runtime representation, as required by invariant (I1) from-       Note [Representation polymorphism invariants] in GHC.Core.-    2. We inserted a cast around the whole lambda to make everything line up-       with the type signature.--}---- | Use this function to split off arguments types when you have an--- \"expected\" type.------ This function skolemises at each polytype.------ Invariant: this function only applies the provided function--- to a list of argument types which all have a syntactically fixed RuntimeRep--- in the sense of Note [Fixed RuntimeRep] in GHC.Tc.Utils.Concrete.--- See Note [Return arguments with a fixed RuntimeRep].-matchExpectedFunTys :: forall a.-                       ExpectedFunTyOrigin -- See Note [Herald for matchExpectedFunTys]-                    -> UserTypeCtxt-                    -> Arity-                    -> ExpRhoType      -- Skolemised-                    -> ([Scaled ExpSigmaTypeFRR] -> ExpRhoType -> TcM a)-                    -> TcM (HsWrapper, a)--- If    matchExpectedFunTys n ty = (wrap, _)--- then  wrap : (t1 -> ... -> tn -> ty_r) ~> ty,---   where [t1, ..., tn], ty_r are passed to the thing_inside-matchExpectedFunTys herald ctx arity orig_ty thing_inside-  = case orig_ty of-      Check ty -> go [] arity ty-      _        -> defer [] arity orig_ty-  where-    -- Skolemise any foralls /before/ the zero-arg case-    -- so that we guarantee to return a rho-type-    go acc_arg_tys n ty-      | (tvs, theta, _) <- tcSplitSigmaTy ty-      , not (null tvs && null theta)-      = do { (wrap_gen, (wrap_res, result)) <- tcTopSkolemise ctx ty $ \ty' ->-                                               go acc_arg_tys n ty'-           ; return (wrap_gen <.> wrap_res, result) }--    -- No more args; do this /before/ coreView, so-    -- that we do not unnecessarily unwrap synonyms-    go acc_arg_tys 0 rho_ty-      = do { result <- thing_inside (reverse acc_arg_tys) (mkCheckExpType rho_ty)-           ; return (idHsWrapper, result) }--    go acc_arg_tys n ty-      | Just ty' <- coreView ty = go acc_arg_tys n ty'--    go acc_arg_tys n (FunTy { ft_af = af, ft_mult = mult, ft_arg = arg_ty, ft_res = res_ty })-      = assert (isVisibleFunArg af) $-        do { let arg_pos = 1 + length acc_arg_tys -- for error messages only-           ; (arg_co, arg_ty) <- hasFixedRuntimeRep (FRRExpectedFunTy herald arg_pos) arg_ty-           ; (wrap_res, result) <- go ((Scaled mult $ mkCheckExpType arg_ty) : acc_arg_tys)-                                      (n-1) res_ty-           ; let wrap_arg = mkWpCastN arg_co-                 fun_wrap = mkWpFun wrap_arg wrap_res (Scaled mult arg_ty) res_ty-           ; return (fun_wrap, result) }--    go acc_arg_tys n ty@(TyVarTy tv)-      | isMetaTyVar tv-      = do { cts <- readMetaTyVar tv-           ; case cts of-               Indirect ty' -> go acc_arg_tys n ty'-               Flexi        -> defer acc_arg_tys n (mkCheckExpType ty) }--       -- In all other cases we bale out into ordinary unification-       -- However unlike the meta-tyvar case, we are sure that the-       -- number of arguments doesn't match arity of the original-       -- type, so we can add a bit more context to the error message-       -- (cf #7869).-       ---       -- It is not always an error, because specialized type may have-       -- different arity, for example:-       ---       -- > f1 = f2 'a'-       -- > f2 :: Monad m => m Bool-       -- > f2 = undefined-       ---       -- But in that case we add specialized type into error context-       -- anyway, because it may be useful. See also #9605.-    go acc_arg_tys n ty = addErrCtxtM (mk_ctxt acc_arg_tys ty) $-                          defer acc_arg_tys n (mkCheckExpType ty)--    -------------    defer :: [Scaled ExpSigmaTypeFRR] -> Arity -> ExpRhoType -> TcM (HsWrapper, a)-    defer acc_arg_tys n fun_ty-      = do { let last_acc_arg_pos = length acc_arg_tys-           ; more_arg_tys <- mapM new_exp_arg_ty [last_acc_arg_pos + 1 .. last_acc_arg_pos + n]-           ; res_ty       <- newInferExpType-           ; result       <- thing_inside (reverse acc_arg_tys ++ more_arg_tys) res_ty-           ; more_arg_tys <- mapM (\(Scaled m t) -> Scaled m <$> readExpType t) more_arg_tys-           ; res_ty       <- readExpType res_ty-           ; let unif_fun_ty = mkScaledFunTys more_arg_tys res_ty-           ; wrap <- tcSubType AppOrigin ctx unif_fun_ty fun_ty-                         -- Not a good origin at all :-(-           ; return (wrap, result) }--    new_exp_arg_ty :: Int -> TcM (Scaled ExpSigmaTypeFRR)-    new_exp_arg_ty arg_pos -- position for error messages only-      = mkScaled <$> newFlexiTyVarTy multiplicityTy-                 <*> newInferExpTypeFRR (FRRExpectedFunTy herald arg_pos)--    -------------    mk_ctxt :: [Scaled ExpSigmaTypeFRR] -> TcType -> TidyEnv -> ZonkM (TidyEnv, SDoc)-    mk_ctxt arg_tys res_ty env-      = mkFunTysMsg env herald arg_tys' res_ty arity-      where-        arg_tys' = map (\(Scaled u v) -> Scaled u (checkingExpType "matchExpectedFunTys" v)) $-                   reverse arg_tys-            -- this is safe b/c we're called from "go"--mkFunTysMsg :: TidyEnv-            -> ExpectedFunTyOrigin-            -> [Scaled TcType] -> TcType -> Arity-            -> ZonkM (TidyEnv, SDoc)-mkFunTysMsg env herald arg_tys res_ty n_val_args_in_call-  = do { (env', fun_rho) <- zonkTidyTcType env $-                            mkScaledFunTys arg_tys res_ty--       ; let (all_arg_tys, _) = splitFunTys fun_rho-             n_fun_args = length all_arg_tys--             msg | n_val_args_in_call <= n_fun_args  -- Enough args, in the end-                 = text "In the result of a function call"-                 | otherwise-                 = hang (full_herald <> comma)-                      2 (sep [ text "but its type" <+> quotes (pprType fun_rho)-                             , if n_fun_args == 0 then text "has none"-                               else text "has only" <+> speakN n_fun_args])--       ; return (env', msg) }- where-  full_herald = pprExpectedFunTyHerald herald-            <+> speakNOf n_val_args_in_call (text "value argument")-------------------------matchExpectedListTy :: TcRhoType -> TcM (TcCoercionN, TcRhoType)--- Special case for lists-matchExpectedListTy exp_ty- = do { (co, [elt_ty]) <- matchExpectedTyConApp listTyCon exp_ty-      ; return (co, elt_ty) }------------------------matchExpectedTyConApp :: TyCon                -- T :: forall kv1 ... kvm. k1 -> ... -> kn -> *-                      -> TcRhoType            -- orig_ty-                      -> TcM (TcCoercionN,    -- T k1 k2 k3 a b c ~N orig_ty-                              [TcSigmaType])  -- Element types, k1 k2 k3 a b c---- It's used for wired-in tycons, so we call checkWiredInTyCon--- Precondition: never called with FunTyCon--- Precondition: input type :: *--- Postcondition: (T k1 k2 k3 a b c) is well-kinded--matchExpectedTyConApp tc orig_ty-  = assertPpr (isAlgTyCon tc) (ppr tc) $-    go orig_ty-  where-    go ty-       | Just ty' <- coreView ty-       = go ty'--    go ty@(TyConApp tycon args)-       | tc == tycon  -- Common case-       = return (mkNomReflCo ty, args)--    go (TyVarTy tv)-       | isMetaTyVar tv-       = do { cts <- readMetaTyVar tv-            ; case cts of-                Indirect ty -> go ty-                Flexi       -> defer }--    go _ = defer--    -- If the common case does not occur, instantiate a template-    -- T k1 .. kn t1 .. tm, and unify with the original type-    -- Doing it this way ensures that the types we return are-    -- kind-compatible with T.  For example, suppose we have-    --       matchExpectedTyConApp T (f Maybe)-    -- where data T a = MkT a-    -- Then we don't want to instantiate T's data constructors with-    --    (a::*) ~ Maybe-    -- because that'll make types that are utterly ill-kinded.-    -- This happened in #7368-    defer-      = do { (_, arg_tvs) <- newMetaTyVars (tyConTyVars tc)-           ; traceTc "matchExpectedTyConApp" (ppr tc $$ ppr (tyConTyVars tc) $$ ppr arg_tvs)-           ; let args = mkTyVarTys arg_tvs-                 tc_template = mkTyConApp tc args-           ; co <- unifyType Nothing tc_template orig_ty-           ; return (co, args) }-------------------------matchExpectedAppTy :: TcRhoType                         -- orig_ty-                   -> TcM (TcCoercion,                   -- m a ~N orig_ty-                           (TcSigmaType, TcSigmaType))  -- Returns m, a--- If the incoming type is a mutable type variable of kind k, then--- matchExpectedAppTy returns a new type variable (m: * -> k); note the *.--matchExpectedAppTy orig_ty-  = go orig_ty-  where-    go ty-      | Just ty' <- coreView ty = go ty'--      | Just (fun_ty, arg_ty) <- tcSplitAppTy_maybe ty-      = return (mkNomReflCo orig_ty, (fun_ty, arg_ty))--    go (TyVarTy tv)-      | isMetaTyVar tv-      = do { cts <- readMetaTyVar tv-           ; case cts of-               Indirect ty -> go ty-               Flexi       -> defer }--    go _ = defer--    -- Defer splitting by generating an equality constraint-    defer-      = do { ty1 <- newFlexiTyVarTy kind1-           ; ty2 <- newFlexiTyVarTy kind2-           ; co <- unifyType Nothing (mkAppTy ty1 ty2) orig_ty-           ; return (co, (ty1, ty2)) }--    orig_kind = typeKind orig_ty-    kind1 = mkVisFunTyMany liftedTypeKind orig_kind-    kind2 = liftedTypeKind    -- m :: * -> k-                              -- arg type :: *--{- **********************************************************************-*-                      fillInferResult-*-********************************************************************** -}--{- Note [inferResultToType]-~~~~~~~~~~~~~~~~~~~~~~~~~~~-expTypeToType and inferResultType convert an InferResult to a monotype.-It must be a monotype because if the InferResult isn't already filled in,-we fill it in with a unification variable (hence monotype).  So to preserve-order-independence we check for mono-type-ness even if it *is* filled in-already.--See also Note [TcLevel of ExpType] in GHC.Tc.Utils.TcType, and-Note [fillInferResult].--}---- | Fill an 'InferResult' with the given type.------ If @co = fillInferResult t1 infer_res@, then @co :: t1 ~# t2@,--- where @t2@ is the type stored in the 'ir_ref' field of @infer_res@.------ This function enforces the following invariants:------  - Level invariant.---    The stored type @t2@ is at the same level as given by the---    'ir_lvl' field.---  - FRR invariant.---    Whenever the 'ir_frr' field is not @Nothing@, @t2@ is guaranteed---    to have a syntactically fixed RuntimeRep, in the sense of---    Note [Fixed RuntimeRep] in GHC.Tc.Utils.Concrete.-fillInferResult :: TcType -> InferResult -> TcM TcCoercionN-fillInferResult act_res_ty (IR { ir_uniq = u-                               , ir_lvl  = res_lvl-                               , ir_frr  = mb_frr-                               , ir_ref  = ref })-  = do { mb_exp_res_ty <- readTcRef ref-       ; case mb_exp_res_ty of-            Just exp_res_ty-               -- We progressively refine the type stored in 'ref',-               -- for example when inferring types across multiple equations.-               ---               -- Example:-               ---               --  \ x -> case y of { True -> x ; False -> 3 :: Int }-               ---               -- When inferring the return type of this function, we will create-               -- an 'Infer' 'ExpType', which will first be filled by the type of 'x'-               -- after typechecking the first equation, and then filled again with-               -- the type 'Int', at which point we want to ensure that we unify-               -- the type of 'x' with 'Int'. This is what is happening below when-               -- we are "joining" several inferred 'ExpType's.-               -> do { traceTc "Joining inferred ExpType" $-                       ppr u <> colon <+> ppr act_res_ty <+> char '~' <+> ppr exp_res_ty-                     ; cur_lvl <- getTcLevel-                     ; unless (cur_lvl `sameDepthAs` res_lvl) $-                       ensureMonoType act_res_ty-                     ; unifyType Nothing act_res_ty exp_res_ty }-            Nothing-               -> do { traceTc "Filling inferred ExpType" $-                       ppr u <+> text ":=" <+> ppr act_res_ty--                     -- Enforce the level invariant: ensure the TcLevel of-                     -- the type we are writing to 'ref' matches 'ir_lvl'.-                     ; (prom_co, act_res_ty) <- promoteTcType res_lvl act_res_ty--                     -- Enforce the FRR invariant: ensure the type has a syntactically-                     -- fixed RuntimeRep (if necessary, i.e. 'mb_frr' is not 'Nothing').-                     ; (frr_co, act_res_ty) <--                         case mb_frr of-                           Nothing       -> return (mkNomReflCo act_res_ty, act_res_ty)-                           Just frr_orig -> hasFixedRuntimeRep frr_orig act_res_ty--                     -- Compose the two coercions.-                     ; let final_co = prom_co `mkTransCo` frr_co--                     ; writeTcRef ref (Just act_res_ty)--                     ; return final_co }-     }--{- Note [fillInferResult]-~~~~~~~~~~~~~~~~~~~~~~~~~-When inferring, we use fillInferResult to "fill in" the hole in InferResult-   data InferResult = IR { ir_uniq :: Unique-                         , ir_lvl  :: TcLevel-                         , ir_ref  :: IORef (Maybe TcType) }--There are two things to worry about:--1. What if it is under a GADT or existential pattern match?-   - GADTs: a unification variable (and Infer's hole is similar) is untouchable-   - Existentials: be careful about skolem-escape--2. What if it is filled in more than once?  E.g. multiple branches of a case-     case e of-        T1 -> e1-        T2 -> e2--Our typing rules are:--* The RHS of a existential or GADT alternative must always be a-  monotype, regardless of the number of alternatives.--* Multiple non-existential/GADT branches can have (the same)-  higher rank type (#18412).  E.g. this is OK:-      case e of-        True  -> hr-        False -> hr-  where hr:: (forall a. a->a) -> Int-  c.f. Section 7.1 of "Practical type inference for arbitrary-rank types"-       We use choice (2) in that Section.-       (GHC 8.10 and earlier used choice (1).)--  But note that-      case e of-        True  -> hr-        False -> \x -> hr x-  will fail, because we still /infer/ both branches, so the \x will get-  a (monotype) unification variable, which will fail to unify with-  (forall a. a->a)--For (1) we can detect the GADT/existential situation by seeing that-the current TcLevel is greater than that stored in ir_lvl of the Infer-ExpType.  We bump the level whenever we go past a GADT/existential match.--Then, before filling the hole use promoteTcType to promote the type-to the outer ir_lvl.  promoteTcType does this-  - create a fresh unification variable alpha at level ir_lvl-  - emits an equality alpha[ir_lvl] ~ ty-  - fills the hole with alpha-That forces the type to be a monotype (since unification variables can-only unify with monotypes); and catches skolem-escapes because the-alpha is untouchable until the equality floats out.--For (2), we simply look to see if the hole is filled already.-  - if not, we promote (as above) and fill the hole-  - if it is filled, we simply unify with the type that is-    already there--There is one wrinkle.  Suppose we have-   case e of-      T1 -> e1 :: (forall a. a->a) -> Int-      G2 -> e2-where T1 is not GADT or existential, but G2 is a GADT.  Then suppose the-T1 alternative fills the hole with (forall a. a->a) -> Int, which is fine.-But now the G2 alternative must not *just* unify with that else we'd risk-allowing through (e2 :: (forall a. a->a) -> Int).  If we'd checked G2 first-we'd have filled the hole with a unification variable, which enforces a-monotype.--So if we check G2 second, we still want to emit a constraint that restricts-the RHS to be a monotype. This is done by ensureMonoType, and it works-by simply generating a constraint (alpha ~ ty), where alpha is a fresh-unification variable.  We discard the evidence.---}----{--************************************************************************-*                                                                      *-                Subsumption checking-*                                                                      *-************************************************************************--Note [Subsumption checking: tcSubType]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-All the tcSubType calls have the form-                tcSubType actual_ty expected_ty-which checks-                actual_ty <= expected_ty--That is, that a value of type actual_ty is acceptable in-a place expecting a value of type expected_ty.  I.e. that--    actual ty   is more polymorphic than   expected_ty--It returns a wrapper function-        co_fn :: actual_ty ~ expected_ty-which takes an HsExpr of type actual_ty into one of type-expected_ty.--Note [Ambiguity check and deep subsumption]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Consider-   f :: (forall b. Eq b => a -> a) -> Int--Does `f` have an ambiguous type?   The ambiguity check usually checks-that this definition of f' would typecheck, where f' has the exact same-type as f:-   f' :: (forall b. Eq b => a -> a) -> Intp-   f' = f--This will be /rejected/ with DeepSubsumption but /accepted/ with-ShallowSubsumption.  On the other hand, this eta-expanded version f''-would be rejected both ways:-   f'' :: (forall b. Eq b => a -> a) -> Intp-   f'' x = f x--This is squishy in the same way as other examples in GHC.Tc.Validity-Note [The squishiness of the ambiguity check]--The situation in June 2022.  Since we have SimpleSubsumption at the moment,-we don't want introduce new breakage if you add -XDeepSubsumption, by-rejecting types as ambiguous that weren't ambiguous before.  So, as a-holding decision, we /always/ use SimpleSubsumption for the ambiguity check-(erring on the side accepting more programs). Hence tcSubTypeAmbiguity.--}------------------------ tcWrapResult needs both un-type-checked (for origins and error messages)--- and type-checked (for wrapping) expressions-tcWrapResult :: HsExpr GhcRn -> HsExpr GhcTc -> TcSigmaType -> ExpRhoType-             -> TcM (HsExpr GhcTc)-tcWrapResult rn_expr = tcWrapResultO (exprCtOrigin rn_expr) rn_expr--tcWrapResultO :: CtOrigin -> HsExpr GhcRn -> HsExpr GhcTc -> TcSigmaType -> ExpRhoType-               -> TcM (HsExpr GhcTc)-tcWrapResultO orig rn_expr expr actual_ty res_ty-  = do { traceTc "tcWrapResult" (vcat [ text "Actual:  " <+> ppr actual_ty-                                      , text "Expected:" <+> ppr res_ty ])-       ; wrap <- tcSubTypeNC orig GenSigCtxt (Just $ HsExprRnThing rn_expr) actual_ty res_ty-       ; return (mkHsWrap wrap expr) }--tcWrapResultMono :: HsExpr GhcRn -> HsExpr GhcTc-                 -> TcRhoType   -- Actual -- a rho-type not a sigma-type-                 -> ExpRhoType  -- Expected-                 -> TcM (HsExpr GhcTc)--- A version of tcWrapResult to use when the actual type is a--- rho-type, so nothing to instantiate; just go straight to unify.--- It means we don't need to pass in a CtOrigin-tcWrapResultMono rn_expr expr act_ty res_ty-  = assertPpr (isRhoTy act_ty) (ppr act_ty $$ ppr rn_expr) $-    do { co <- unifyExpectedType rn_expr act_ty res_ty-       ; return (mkHsWrapCo co expr) }--unifyExpectedType :: HsExpr GhcRn-                  -> TcRhoType   -- Actual -- a rho-type not a sigma-type-                  -> ExpRhoType  -- Expected-                  -> TcM TcCoercionN-unifyExpectedType rn_expr act_ty exp_ty-  = case exp_ty of-      Infer inf_res -> fillInferResult act_ty inf_res-      Check exp_ty  -> unifyType (Just $ HsExprRnThing rn_expr) act_ty exp_ty---------------------------tcSubTypePat :: CtOrigin -> UserTypeCtxt-            -> ExpSigmaType -> TcSigmaType -> TcM HsWrapper--- Used in patterns; polarity is backwards compared---   to tcSubType--- If wrap = tc_sub_type_et t1 t2---    => wrap :: t1 ~> t2-tcSubTypePat inst_orig ctxt (Check ty_actual) ty_expected-  = tc_sub_type unifyTypeET inst_orig ctxt ty_actual ty_expected--tcSubTypePat _ _ (Infer inf_res) ty_expected-  = do { co <- fillInferResult ty_expected inf_res-               -- In patterns we do not instantatiate--       ; return (mkWpCastN (mkSymCo co)) }------------------tcSubType :: CtOrigin -> UserTypeCtxt-          -> TcSigmaType  -- ^ Actual-          -> ExpRhoType   -- ^ Expected-          -> TcM HsWrapper--- Checks that 'actual' is more polymorphic than 'expected'-tcSubType orig ctxt ty_actual ty_expected-  = addSubTypeCtxt ty_actual ty_expected $-    do { traceTc "tcSubType" (vcat [pprUserTypeCtxt ctxt, ppr ty_actual, ppr ty_expected])-       ; tcSubTypeNC orig ctxt Nothing ty_actual ty_expected }------------------tcSubTypeDS :: HsExpr GhcRn-            -> TcRhoType   -- Actual -- a rho-type not a sigma-type-            -> ExpRhoType  -- Expected-            -> TcM HsWrapper--- Similar signature to unifyExpectedType; does deep subsumption--- Only one call site, in GHC.Tc.Gen.App.tcApp-tcSubTypeDS rn_expr act_rho res_ty-  = case res_ty of-      Check exp_rho -> tc_sub_type_deep (unifyType m_thing) orig-                                        GenSigCtxt act_rho exp_rho--      Infer inf_res -> do { co <- fillInferResult act_rho inf_res-                          ; return (mkWpCastN co) }-  where-    orig    = exprCtOrigin rn_expr-    m_thing = Just (HsExprRnThing rn_expr)------------------tcSubTypeNC :: CtOrigin          -- ^ Used when instantiating-            -> UserTypeCtxt      -- ^ Used when skolemising-            -> Maybe TypedThing -- ^ The expression that has type 'actual' (if known)-            -> TcSigmaType       -- ^ Actual type-            -> ExpRhoType        -- ^ Expected type-            -> TcM HsWrapper-tcSubTypeNC inst_orig ctxt m_thing ty_actual res_ty-  = case res_ty of-      Check ty_expected -> tc_sub_type (unifyType m_thing) inst_orig ctxt-                                       ty_actual ty_expected--      Infer inf_res -> do { (wrap, rho) <- topInstantiate inst_orig ty_actual-                                   -- See Note [Instantiation of InferResult]-                          ; co <- fillInferResult rho inf_res-                          ; return (mkWpCastN co <.> wrap) }------------------tcSubTypeSigma :: CtOrigin       -- where did the actual type arise / why are we-                                 -- doing this subtype check?-               -> UserTypeCtxt   -- where did the expected type arise?-               -> TcSigmaType -> TcSigmaType -> TcM HsWrapper--- External entry point, but no ExpTypes on either side--- Checks that actual <= expected--- Returns HsWrapper :: actual ~ expected-tcSubTypeSigma orig ctxt ty_actual ty_expected-  = tc_sub_type (unifyType Nothing) orig ctxt ty_actual ty_expected------------------tcSubTypeAmbiguity :: UserTypeCtxt   -- Where did this type arise-                   -> TcSigmaType -> TcSigmaType -> TcM HsWrapper--- See Note [Ambiguity check and deep subsumption]-tcSubTypeAmbiguity ctxt ty_actual ty_expected-  = tc_sub_type_shallow (unifyType Nothing)-                        (AmbiguityCheckOrigin ctxt)-                        ctxt ty_actual ty_expected------------------addSubTypeCtxt :: TcType -> ExpType -> TcM a -> TcM a-addSubTypeCtxt ty_actual ty_expected thing_inside- | isRhoTy ty_actual        -- If there is no polymorphism involved, the- , isRhoExpTy ty_expected   -- TypeEqOrigin stuff (added by the _NC functions)- = thing_inside             -- gives enough context by itself- | otherwise- = addErrCtxtM mk_msg thing_inside-  where-    mk_msg tidy_env-      = do { (tidy_env, ty_actual)   <- zonkTidyTcType tidy_env ty_actual-           ; ty_expected             <- readExpType ty_expected-                   -- A worry: might not be filled if we're debugging. Ugh.-           ; (tidy_env, ty_expected) <- zonkTidyTcType tidy_env ty_expected-           ; let msg = vcat [ hang (text "When checking that:")-                                 4 (ppr ty_actual)-                            , nest 2 (hang (text "is more polymorphic than:")-                                         2 (ppr ty_expected)) ]-           ; return (tidy_env, msg) }---{- Note [Instantiation of InferResult]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-We now always instantiate before filling in InferResult, so that-the result is a TcRhoType: see #17173 for discussion.--For example:--1. Consider-    f x = (*)-   We want to instantiate the type of (*) before returning, else we-   will infer the type-     f :: forall {a}. a -> forall b. Num b => b -> b -> b-   This is surely confusing for users.--   And worse, the monomorphism restriction won't work properly. The MR is-   dealt with in simplifyInfer, and simplifyInfer has no way of-   instantiating. This could perhaps be worked around, but it may be-   hard to know even when instantiation should happen.--2. Another reason.  Consider-       f :: (?x :: Int) => a -> a-       g y = let ?x = 3::Int in f-   Here want to instantiate f's type so that the ?x::Int constraint-  gets discharged by the enclosing implicit-parameter binding.--3. Suppose one defines plus = (+). If we instantiate lazily, we will-   infer plus :: forall a. Num a => a -> a -> a. However, the monomorphism-   restriction compels us to infer-      plus :: Integer -> Integer -> Integer-   (or similar monotype). Indeed, the only way to know whether to apply-   the monomorphism restriction at all is to instantiate--There is one place where we don't want to instantiate eagerly,-namely in GHC.Tc.Module.tcRnExpr, which implements GHCi's :type-command. See Note [Implementing :type] in GHC.Tc.Module.--}------------------tc_sub_type, tc_sub_type_deep, tc_sub_type_shallow-    :: (TcType -> TcType -> TcM TcCoercionN)  -- How to unify-    -> CtOrigin       -- Used when instantiating-    -> UserTypeCtxt   -- Used when skolemising-    -> TcSigmaType    -- Actual; a sigma-type-    -> TcSigmaType    -- Expected; also a sigma-type-    -> TcM HsWrapper--- Checks that actual_ty is more polymorphic than expected_ty--- If wrap = tc_sub_type t1 t2---    => wrap :: t1 ~> t2------ The "how to unify argument" is always a call to `uType TypeLevel orig`,--- but with different ways of constructing the CtOrigin `orig` from--- the argument types and context.-------------------------tc_sub_type unify inst_orig ctxt ty_actual ty_expected-  = do { deep_subsumption <- xoptM LangExt.DeepSubsumption-       ; if deep_subsumption-         then tc_sub_type_deep    unify inst_orig ctxt ty_actual ty_expected-         else tc_sub_type_shallow unify inst_orig ctxt ty_actual ty_expected-  }-------------------------tc_sub_type_shallow unify inst_orig ctxt ty_actual ty_expected-  | definitely_poly ty_expected   -- See Note [Don't skolemise unnecessarily]-  , definitely_mono_shallow ty_actual-  = do { traceTc "tc_sub_type (drop to equality)" $-         vcat [ text "ty_actual   =" <+> ppr ty_actual-              , text "ty_expected =" <+> ppr ty_expected ]-       ; mkWpCastN <$>-         unify ty_actual ty_expected }--  | otherwise   -- This is the general case-  = do { traceTc "tc_sub_type (general case)" $-         vcat [ text "ty_actual   =" <+> ppr ty_actual-              , text "ty_expected =" <+> ppr ty_expected ]--       ; (sk_wrap, inner_wrap)-           <- tcTopSkolemise ctxt ty_expected $ \ sk_rho ->-              do { (wrap, rho_a) <- topInstantiate inst_orig ty_actual-                 ; cow           <- unify rho_a sk_rho-                 ; return (mkWpCastN cow <.> wrap) }--       ; return (sk_wrap <.> inner_wrap) }-------------------------tc_sub_type_deep unify inst_orig ctxt ty_actual ty_expected-  | definitely_poly ty_expected      -- See Note [Don't skolemise unnecessarily]-  , definitely_mono_deep ty_actual-  = do { traceTc "tc_sub_type_deep (drop to equality)" $-         vcat [ text "ty_actual   =" <+> ppr ty_actual-              , text "ty_expected =" <+> ppr ty_expected ]-       ; mkWpCastN <$>-         unify ty_actual ty_expected }--  | otherwise   -- This is the general case-  = do { traceTc "tc_sub_type_deep (general case)" $-         vcat [ text "ty_actual   =" <+> ppr ty_actual-              , text "ty_expected =" <+> ppr ty_expected ]--       ; (sk_wrap, inner_wrap)-           <- tcDeeplySkolemise ctxt ty_expected $ \ sk_rho ->-              -- See Note [Deep subsumption]-              tc_sub_type_ds unify inst_orig ctxt ty_actual sk_rho--       ; return (sk_wrap <.> inner_wrap) }--definitely_mono_shallow :: TcType -> Bool-definitely_mono_shallow ty = isRhoTy ty-    -- isRhoTy: no top level forall or (=>)--definitely_mono_deep :: TcType -> Bool-definitely_mono_deep ty-  | not (definitely_mono_shallow ty)     = False-    -- isRhoTy: False means top level forall or (=>)-  | Just (_, res) <- tcSplitFunTy_maybe ty = definitely_mono_deep res-    -- Top level (->)-  | otherwise                              = True--definitely_poly :: TcType -> Bool--- A very conservative test:--- see Note [Don't skolemise unnecessarily]-definitely_poly ty-  | (tvs, theta, tau) <- tcSplitSigmaTy ty-  , (tv:_) <- tvs   -- At least one tyvar-  , null theta      -- No constraints; see (DP1)-  , tv `isInjectiveInType` tau-       -- The tyvar actually occurs (DP2),-       -- and occurs in an injective position (DP3).-  = True-  | otherwise-  = False--{- Note [Don't skolemise unnecessarily]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Suppose we are trying to solve-     ty_actual   <= ty_expected-    (Char->Char) <= (forall a. a->a)-We could skolemise the 'forall a', and then complain-that (Char ~ a) is insoluble; but that's a pretty obscure-error.  It's better to say that-    (Char->Char) ~ (forall a. a->a)-fails.--If we prematurely go to equality we'll reject a program we should-accept (e.g. #13752).  So the test (which is only to improve error-message) is very conservative:-- * ty_actual   is /definitely/ monomorphic: see `definitely_mono`-   This definitely_mono test comes in "shallow" and "deep" variants-- * ty_expected is /definitely/ polymorphic: see `definitely_poly`-   This definitely_poly test is more subtle than you might think.-   Here are three cases where expected_ty looks polymorphic, but-   isn't, and where it would be /wrong/ to switch to equality:--   (DP1)  (Char->Char) <= (forall a. (a~Char) => a -> a)--   (DP2)  (Char->Char) <= (forall a. Char -> Char)--   (DP3)  (Char->Char) <= (forall a. F [a] Char -> Char)-                          where type instance F [x] t = t---Note [Wrapper returned from tcSubMult]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-There is no notion of multiplicity coercion in Core, therefore the wrapper-returned by tcSubMult (and derived functions such as tcCheckUsage and-checkManyPattern) is quite unlike any other wrapper: it checks whether the-coercion produced by the constraint solver is trivial, producing a type error-if it is not. This is implemented via the WpMultCoercion wrapper, as desugared-by GHC.HsToCore.Binds.dsHsWrapper, which does the reflexivity check.--This wrapper needs to be placed in the term; otherwise, checking of the-eventual coercion won't be triggered during desugaring. But it can be put-anywhere, since it doesn't affect the desugared code.--Why do we check this in the desugarer? It's a convenient place, since it's-right after all the constraints are solved. We need the constraints to be-solved to check whether they are trivial or not.--An alternative would be to have a kind of constraint which can-only produce trivial evidence. This would allow such checks to happen-in the constraint solver (#18756).-This would be similar to the existing setup for Concrete, see-  Note [The Concrete mechanism] in GHC.Tc.Utils.Concrete-    (PHASE 1 in particular).--}--tcSubMult :: CtOrigin -> Mult -> Mult -> TcM HsWrapper-tcSubMult origin w_actual w_expected-  | Just (w1, w2) <- isMultMul w_actual =-  do { w1 <- tcSubMult origin w1 w_expected-     ; w2 <- tcSubMult origin w2 w_expected-     ; return (w1 <.> w2) }-  -- Currently, we consider p*q and sup p q to be equal.  Therefore, p*q <= r is-  -- equivalent to p <= r and q <= r.  For other cases, we approximate p <= q by p-  -- ~ q.  This is not complete, but it's sound. See also Note [Overapproximating-  -- multiplicities] in Multiplicity.-tcSubMult origin w_actual w_expected =-  case submult w_actual w_expected of-    Submult -> return WpHole-    Unknown -> tcEqMult origin w_actual w_expected--tcEqMult :: CtOrigin -> Mult -> Mult -> TcM HsWrapper-tcEqMult origin w_actual w_expected = do-  {-  -- Note that here we do not call to `submult`, so we check-  -- for strict equality.-  ; coercion <- unifyTypeAndEmit TypeLevel origin w_actual w_expected-  ; return $ if isReflCo coercion then WpHole else WpMultCoercion coercion }---{- *********************************************************************-*                                                                      *-                    Deep subsumption-*                                                                      *-********************************************************************* -}--{- Note [Deep subsumption]-~~~~~~~~~~~~~~~~~~~~~~~~~~-The DeepSubsumption extension, documented here--    https://github.com/ghc-proposals/ghc-proposals/pull/511.--makes a best-efforts attempt implement deep subsumption as it was-prior to the Simplify Subsumption proposal:--    https://github.com/ghc-proposals/ghc-proposals/pull/287--The effects are in these main places:--1. In the subsumption check, tcSubType, we must do deep skolemisation:-   see the call to tcDeeplySkolemise in tc_sub_type_deep--2. In tcPolyExpr we must do deep skolemisation:-   see the call to tcDeeplySkolemise in tcSkolemiseExpType--3. for expression type signatures (e :: ty), and functions with type-   signatures (e.g. f :: ty; f = e), we must deeply skolemise the type;-   see the call to tcDeeplySkolemise in tcSkolemiseScoped.--4. In GHC.Tc.Gen.App.tcApp we call tcSubTypeDS to match the result-   type. Without deep subsumption, unifyExpectedType would be sufficent.--In all these cases note that the deep skolemisation must be done /first/.-Consider (1)-     (forall a. Int -> a -> a)  <=  Int -> (forall b. b -> b)-We must skolemise the `forall b` before instantiating the `forall a`.-See also Note [Deep skolemisation].--Note that we /always/ use shallow subsumption in the ambiguity check.-See Note [Ambiguity check and deep subsumption].--Note [Deep skolemisation]-~~~~~~~~~~~~~~~~~~~~~~~~~-deeplySkolemise decomposes and skolemises a type, returning a type-with all its arrows visible (ie not buried under foralls)--Examples:--  deeplySkolemise (Int -> forall a. Ord a => blah)-    =  ( wp, [a], [d:Ord a], Int -> blah )-    where wp = \x:Int. /\a. \(d:Ord a). <hole> x--  deeplySkolemise  (forall a. Ord a => Maybe a -> forall b. Eq b => blah)-    =  ( wp, [a,b], [d1:Ord a,d2:Eq b], Maybe a -> blah )-    where wp = /\a.\(d1:Ord a).\(x:Maybe a)./\b.\(d2:Ord b). <hole> x--In general,-  if      deeplySkolemise ty = (wrap, tvs, evs, rho)-    and   e :: rho-  then    wrap e :: ty-    and   'wrap' binds tvs, evs--ToDo: this eta-abstraction plays fast and loose with termination,-      because it can introduce extra lambdas.  Maybe add a `seq` to-      fix this--Note [Setting the argument context]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Consider we are doing the ambiguity check for the (bogus)-  f :: (forall a b. C b => a -> a) -> Int--We'll call-   tcSubType ((forall a b. C b => a->a) -> Int )-             ((forall a b. C b => a->a) -> Int )--with a UserTypeCtxt of (FunSigCtxt "f").  Then we'll do the co/contra thing-on the argument type of the (->) -- and at that point we want to switch-to a UserTypeCtxt of GenSigCtxt.  Why?--* Error messages.  If we stick with FunSigCtxt we get errors like-     * Could not deduce: C b-       from the context: C b0-        bound by the type signature for:-            f :: forall a b. C b => a->a-  But of course f does not have that type signature!-  Example tests: T10508, T7220a, Simple14--* Implications. We may decide to build an implication for the whole-  ambiguity check, but we don't need one for each level within it,-  and TcUnify.alwaysBuildImplication checks the UserTypeCtxt.-  See Note [When to build an implication]--Note [Multiplicity in deep subsumption]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Consider-   t1 ->{mt} t2  <=   s1 ->{ms} s2--At the moment we /unify/ ms~mt, via tcEqMult.--Arguably we should use `tcSubMult`. But then if mt=m0 (a unification-variable) and ms=Many, `tcSubMult` is a no-op (since anything is a-sub-multiplicty of Many).  But then `m0` may never get unified with-anything.  It is then skolemised by the zonker; see GHC.HsToCore.Binds-Note [Free tyvars on rule LHS].  So we in RULE foldr/app in GHC.Base-we get this-- "foldr/app"     [1] forall ys m1 m2. foldr (\x{m1} \xs{m2}. (:) x xs) ys-                                       = \xs -> xs ++ ys--where we eta-expanded that (:).  But now foldr expects an argument-with ->{Many} and gets an argument with ->{m1} or ->{m2}, and Lint-complains.--The easiest solution was to use tcEqMult in tc_sub_type_ds, and-insist on equality. This is only in the DeepSubsumption code anyway.--}--tc_sub_type_ds :: (TcType -> TcType -> TcM TcCoercionN)  -- How to unify-               -> CtOrigin       -- Used when instantiating-               -> UserTypeCtxt   -- Used when skolemising-               -> TcSigmaType    -- Actual; a sigma-type-               -> TcRhoType      -- Expected; deeply skolemised-               -> TcM HsWrapper---- If wrap = tc_sub_type_ds t1 t2---    => wrap :: t1 ~> t2--- Here is where the work actually happens!--- Precondition: ty_expected is deeply skolemised--tc_sub_type_ds unify inst_orig ctxt ty_actual ty_expected-  = do { traceTc "tc_sub_type_ds" $-         vcat [ text "ty_actual   =" <+> ppr ty_actual-              , text "ty_expected =" <+> ppr ty_expected ]-       ; go ty_actual ty_expected }-  where-    -- NB: 'go' is not recursive, except for doing coreView-    go ty_a ty_e | Just ty_a' <- coreView ty_a = go ty_a' ty_e-                 | Just ty_e' <- coreView ty_e = go ty_a  ty_e'--    go (TyVarTy tv_a) ty_e-      = do { lookup_res <- isFilledMetaTyVar_maybe tv_a-           ; case lookup_res of-               Just ty_a' ->-                 do { traceTc "tc_sub_type_ds following filled meta-tyvar:"-                        (ppr tv_a <+> text "-->" <+> ppr ty_a')-                    ; tc_sub_type_ds unify inst_orig ctxt ty_a' ty_e }-               Nothing -> just_unify ty_actual ty_expected }--    go ty_a@(FunTy { ft_af = af1, ft_mult = act_mult, ft_arg = act_arg, ft_res = act_res })-       ty_e@(FunTy { ft_af = af2, ft_mult = exp_mult, ft_arg = exp_arg, ft_res = exp_res })-      | isVisibleFunArg af1, isVisibleFunArg af2-      = if (isTauTy ty_a && isTauTy ty_e)       -- Short cut common case to avoid-        then just_unify ty_actual ty_expected   -- unnecessary eta expansion-        else-        -- This is where we do the co/contra thing, and generate a WpFun, which in turn-        -- causes eta-expansion, which we don't like; hence encouraging NoDeepSubsumption-        do { arg_wrap  <- tc_sub_type_deep unify given_orig GenSigCtxt exp_arg act_arg-                          -- GenSigCtxt: See Note [Setting the argument context]-           ; res_wrap  <- tc_sub_type_ds   unify inst_orig  ctxt       act_res exp_res-           ; mult_wrap <- tcEqMult inst_orig act_mult exp_mult-                          -- See Note [Multiplicity in deep subsumption]-           ; return (mult_wrap <.>-                     mkWpFun arg_wrap res_wrap (Scaled exp_mult exp_arg) exp_res) }-                     -- arg_wrap :: exp_arg ~> act_arg-                     -- res_wrap :: act-res ~> exp_res-      where-        given_orig = GivenOrigin (SigSkol GenSigCtxt exp_arg [])--    go ty_a ty_e-      | let (tvs, theta, _) = tcSplitSigmaTy ty_a-      , not (null tvs && null theta)-      = do { (in_wrap, in_rho) <- topInstantiate inst_orig ty_a-           ; body_wrap <- tc_sub_type_ds unify inst_orig ctxt in_rho ty_e-           ; return (body_wrap <.> in_wrap) }--      | otherwise   -- Revert to unification-      = do { -- It's still possible that ty_actual has nested foralls. Instantiate-             -- these, as there's no way unification will succeed with them in.-             -- See typecheck/should_compile/T11305 for an example of when this-             -- is important. The problem is that we're checking something like-             --  a -> forall b. b -> b     <=   alpha beta gamma-             -- where we end up with alpha := (->)-             (inst_wrap, rho_a) <- deeplyInstantiate inst_orig ty_actual-           ; unify_wrap         <- just_unify rho_a ty_expected-           ; return (unify_wrap <.> inst_wrap) }--    just_unify ty_a ty_e = do { cow <- unify ty_a ty_e-                              ; return (mkWpCastN cow) }--tcDeeplySkolemise-    :: UserTypeCtxt -> TcSigmaType-    -> (TcType -> TcM result)-    -> TcM (HsWrapper, result)-        -- ^ The wrapper has type: spec_ty ~> expected_ty--- Just like tcTopSkolemise, but calls--- deeplySkolemise instead of topSkolemise--- See Note [Deep skolemisation]-tcDeeplySkolemise ctxt expected_ty thing_inside-  | isTauTy expected_ty  -- Short cut for common case-  = do { res <- thing_inside expected_ty-       ; return (idHsWrapper, res) }-  | otherwise-  = do  { -- This (unpleasant) rec block allows us to pass skol_info to deeplySkolemise;-          -- but skol_info can't be built until we have tv_prs-          rec { (wrap, tv_prs, given, rho_ty) <- deeplySkolemise skol_info expected_ty-              ; skol_info <- mkSkolemInfo (SigSkol ctxt expected_ty tv_prs) }--        ; traceTc "tcDeeplySkolemise" (ppr expected_ty $$ ppr rho_ty $$ ppr tv_prs)--        ; let skol_tvs  = map snd tv_prs-        ; (ev_binds, result)-              <- checkConstraints (getSkolemInfo skol_info) skol_tvs given $-                 thing_inside rho_ty--        ; return (wrap <.> mkWpLet ev_binds, result) }-          -- The ev_binds returned by checkConstraints is very-          -- often empty, in which case mkWpLet is a no-op--deeplySkolemise :: SkolemInfo -> TcSigmaType-                -> TcM ( HsWrapper-                       , [(Name,TyVar)]     -- All skolemised variables-                       , [EvVar]            -- All "given"s-                       , TcRhoType )--- See Note [Deep skolemisation]-deeplySkolemise skol_info ty-  = go init_subst ty-  where-    init_subst = mkEmptySubst (mkInScopeSet (tyCoVarsOfType ty))--    go subst ty-      | Just (arg_tys, tvs, theta, ty') <- tcDeepSplitSigmaTy_maybe ty-      = do { let arg_tys' = substScaledTys subst arg_tys-           ; ids1           <- newSysLocalIds (fsLit "dk") arg_tys'-           ; (subst', tvs1) <- tcInstSkolTyVarsX skol_info subst tvs-           ; ev_vars1       <- newEvVars (substTheta subst' theta)-           ; (wrap, tvs_prs2, ev_vars2, rho) <- go subst' ty'-           ; let tv_prs1 = map tyVarName tvs `zip` tvs1-           ; return ( mkWpEta ids1 (mkWpTyLams tvs1-                                    <.> mkWpEvLams ev_vars1-                                    <.> wrap)-                    , tv_prs1  ++ tvs_prs2-                    , ev_vars1 ++ ev_vars2-                    , mkScaledFunTys arg_tys' rho ) }--      | otherwise-      = return (idHsWrapper, [], [], substTy subst ty)-        -- substTy is a quick no-op on an empty substitution--deeplyInstantiate :: CtOrigin -> TcType -> TcM (HsWrapper, Type)-deeplyInstantiate orig ty-  = go init_subst ty-  where-    init_subst = mkEmptySubst (mkInScopeSet (tyCoVarsOfType ty))--    go subst ty-      | Just (arg_tys, tvs, theta, rho) <- tcDeepSplitSigmaTy_maybe ty-      = do { (subst', tvs') <- newMetaTyVarsX subst tvs-           ; let arg_tys' = substScaledTys   subst' arg_tys-                 theta'   = substTheta subst' theta-           ; ids1  <- newSysLocalIds (fsLit "di") arg_tys'-           ; wrap1 <- instCall orig (mkTyVarTys tvs') theta'-           ; (wrap2, rho2) <- go subst' rho-           ; return (mkWpEta ids1 (wrap2 <.> wrap1),-                     mkScaledFunTys arg_tys' rho2) }--      | otherwise-      = do { let ty' = substTy subst ty-           ; return (idHsWrapper, ty') }--tcDeepSplitSigmaTy_maybe-  :: TcSigmaType -> Maybe ([Scaled TcType], [TyVar], ThetaType, TcSigmaType)--- Looks for a *non-trivial* quantified type, under zero or more function arrows--- By "non-trivial" we mean either tyvars or constraints are non-empty--tcDeepSplitSigmaTy_maybe ty-  | Just (arg_ty, res_ty)           <- tcSplitFunTy_maybe ty-  , Just (arg_tys, tvs, theta, rho) <- tcDeepSplitSigmaTy_maybe res_ty-  = Just (arg_ty:arg_tys, tvs, theta, rho)--  | (tvs, theta, rho) <- tcSplitSigmaTy ty-  , not (null tvs && null theta)-  = Just ([], tvs, theta, rho)--  | otherwise = Nothing---{- *********************************************************************-*                                                                      *-                    Generalisation-*                                                                      *-********************************************************************* -}--{- Note [Skolemisation]-~~~~~~~~~~~~~~~~~~~~~~~-tcTopSkolemise takes "expected type" and strip off quantifiers to expose the-type underneath, binding the new skolems for the 'thing_inside'-The returned 'HsWrapper' has type (specific_ty -> expected_ty).--Note that for a nested type like-   forall a. Eq a => forall b. Ord b => blah-we still only build one implication constraint-   forall a b. (Eq a, Ord b) => <constraints>-This is just an optimisation, but it's why we use topSkolemise to-build the pieces from all the layers, before making a single call-to checkConstraints.--tcSkolemiseScoped is very similar, but differs in two ways:--* It deals specially with just the outer forall, bringing those type-  variables into lexical scope.  To my surprise, I found that doing-  this unconditionally in tcTopSkolemise (i.e. doing it even if we don't-  need to bring the variables into lexical scope, which is harmless)-  caused a non-trivial (1%-ish) perf hit on the compiler.--* It handles deep subumption, wheres tcTopSkolemise never looks under-  function arrows.--* It always calls checkConstraints, even if there are no skolem-  variables at all.  Reason: there might be nested deferred errors-  that must not be allowed to float to top level.-  See Note [When to build an implication] below.--}--tcTopSkolemise, tcSkolemiseScoped-    :: UserTypeCtxt -> TcSigmaType-    -> (TcType -> TcM result)-    -> TcM (HsWrapper, result)-        -- ^ The wrapper has type: spec_ty ~> expected_ty--- See Note [Skolemisation] for the differences between--- tcSkolemiseScoped and tcTopSkolemise--tcSkolemiseScoped ctxt expected_ty thing_inside-  = do { deep_subsumption <- xoptM LangExt.DeepSubsumption-       ; let skolemise | deep_subsumption = deeplySkolemise-                       | otherwise        = topSkolemise-       ; -- rec {..}: see Note [Keeping SkolemInfo inside a SkolemTv]-         --           in GHC.Tc.Utils.TcType-         rec { (wrap, tv_prs, given, rho_ty) <- skolemise skol_info expected_ty-             ; skol_info <- mkSkolemInfo (SigSkol ctxt expected_ty tv_prs) }--       ; let skol_tvs = map snd tv_prs-       ; (ev_binds, res)-             <- checkConstraints (getSkolemInfo skol_info) skol_tvs given $-                tcExtendNameTyVarEnv tv_prs               $-                thing_inside rho_ty--       ; return (wrap <.> mkWpLet ev_binds, res) }--tcTopSkolemise ctxt expected_ty thing_inside-  | isRhoTy expected_ty  -- Short cut for common case-  = do { res <- thing_inside expected_ty-       ; return (idHsWrapper, res) }-  | otherwise-  = do { -- rec {..}: see Note [Keeping SkolemInfo inside a SkolemTv]-         --           in GHC.Tc.Utils.TcType-         rec { (wrap, tv_prs, given, rho_ty) <- topSkolemise skol_info expected_ty-             ; skol_info <- mkSkolemInfo (SigSkol ctxt expected_ty tv_prs) }--       ; let skol_tvs = map snd tv_prs-       ; (ev_binds, result)-             <- checkConstraints (getSkolemInfo skol_info) skol_tvs given $-                thing_inside rho_ty--       ; return (wrap <.> mkWpLet ev_binds, result) }-         -- The ev_binds returned by checkConstraints is very-        -- often empty, in which case mkWpLet is a no-op---- | Variant of 'tcTopSkolemise' that takes an ExpType-tcSkolemiseExpType :: UserTypeCtxt -> ExpSigmaType-                   -> (ExpRhoType -> TcM result)-                   -> TcM (HsWrapper, result)-tcSkolemiseExpType _ et@(Infer {}) thing_inside-  = (idHsWrapper, ) <$> thing_inside et-tcSkolemiseExpType ctxt (Check ty) thing_inside-  = do { deep_subsumption <- xoptM LangExt.DeepSubsumption-       ; let skolemise | deep_subsumption = tcDeeplySkolemise-                       | otherwise        = tcTopSkolemise-       ; skolemise ctxt ty $ \rho_ty ->-         thing_inside (mkCheckExpType rho_ty) }--checkConstraints :: SkolemInfoAnon-                 -> [TcTyVar]           -- Skolems-                 -> [EvVar]             -- Given-                 -> TcM result-                 -> TcM (TcEvBinds, result)--checkConstraints skol_info skol_tvs given thing_inside-  = do { implication_needed <- implicationNeeded skol_info skol_tvs given--       ; if implication_needed-         then do { (tclvl, wanted, result) <- pushLevelAndCaptureConstraints thing_inside-                 ; (implics, ev_binds) <- buildImplicationFor tclvl skol_info skol_tvs given wanted-                 ; traceTc "checkConstraints" (ppr tclvl $$ ppr skol_tvs)-                 ; emitImplications implics-                 ; return (ev_binds, result) }--         else -- Fast path.  We check every function argument with tcCheckPolyExpr,-              -- which uses tcTopSkolemise and hence checkConstraints.-              -- So this fast path is well-exercised-              do { res <- thing_inside-                 ; return (emptyTcEvBinds, res) } }--checkTvConstraints :: SkolemInfo-                   -> [TcTyVar]          -- Skolem tyvars-                   -> TcM result-                   -> TcM result--checkTvConstraints skol_info skol_tvs thing_inside-  = do { (tclvl, wanted, result) <- pushLevelAndCaptureConstraints thing_inside-       ; emitResidualTvConstraint skol_info skol_tvs tclvl wanted-       ; return result }--emitResidualTvConstraint :: SkolemInfo -> [TcTyVar]-                         -> TcLevel -> WantedConstraints -> TcM ()-emitResidualTvConstraint skol_info skol_tvs tclvl wanted-  | not (isEmptyWC wanted) ||-    checkTelescopeSkol skol_info_anon-  = -- checkTelescopeSkol: in this case, /always/ emit this implication-    -- even if 'wanted' is empty. We need the implication so that we check-    -- for a bad telescope. See Note [Skolem escape and forall-types] in-    -- GHC.Tc.Gen.HsType-    do { implic <- buildTvImplication skol_info_anon skol_tvs tclvl wanted-       ; emitImplication implic }--  | otherwise  -- Empty 'wanted', emit nothing-  = return ()-  where-     skol_info_anon = getSkolemInfo skol_info--buildTvImplication :: SkolemInfoAnon -> [TcTyVar]-                   -> TcLevel -> WantedConstraints -> TcM Implication-buildTvImplication skol_info skol_tvs tclvl wanted-  = assertPpr (all (isSkolemTyVar <||> isTyVarTyVar) skol_tvs) (ppr skol_tvs) $-    do { ev_binds <- newNoTcEvBinds  -- Used for equalities only, so all the constraints-                                     -- are solved by filling in coercion holes, not-                                     -- by creating a value-level evidence binding-       ; implic   <- newImplication--       ; let implic' = implic { ic_tclvl     = tclvl-                              , ic_skols     = skol_tvs-                              , ic_given_eqs = NoGivenEqs-                              , ic_wanted    = wanted-                              , ic_binds     = ev_binds-                              , ic_info      = skol_info }--       ; checkImplicationInvariants implic'-       ; return implic' }--implicationNeeded :: SkolemInfoAnon -> [TcTyVar] -> [EvVar] -> TcM Bool--- See Note [When to build an implication]-implicationNeeded skol_info skol_tvs given-  | null skol_tvs-  , null given-  , not (alwaysBuildImplication skol_info)-  = -- Empty skolems and givens-    do { tc_lvl <- getTcLevel-       ; if not (isTopTcLevel tc_lvl)  -- No implication needed if we are-         then return False             -- already inside an implication-         else-    do { dflags <- getDynFlags       -- If any deferral can happen,-                                     -- we must build an implication-       ; return (gopt Opt_DeferTypeErrors dflags ||-                 gopt Opt_DeferTypedHoles dflags ||-                 gopt Opt_DeferOutOfScopeVariables dflags) } }--  | otherwise     -- Non-empty skolems or givens-  = return True   -- Definitely need an implication--alwaysBuildImplication :: SkolemInfoAnon -> Bool--- See Note [When to build an implication]-alwaysBuildImplication _ = False--{-  Commmented out for now while I figure out about error messages.-    See #14185--alwaysBuildImplication (SigSkol ctxt _ _)-  = case ctxt of-      FunSigCtxt {} -> True  -- RHS of a binding with a signature-      _             -> False-alwaysBuildImplication (RuleSkol {})      = True-alwaysBuildImplication (InstSkol {})      = True-alwaysBuildImplication (FamInstSkol {})   = True-alwaysBuildImplication _                  = False--}--buildImplicationFor :: TcLevel -> SkolemInfoAnon -> [TcTyVar]-                   -> [EvVar] -> WantedConstraints-                   -> TcM (Bag Implication, TcEvBinds)-buildImplicationFor tclvl skol_info skol_tvs given wanted-  | isEmptyWC wanted && null given-             -- Optimisation : if there are no wanteds, and no givens-             -- don't generate an implication at all.-             -- Reason for the (null given): we don't want to lose-             -- the "inaccessible alternative" error check-  = return (emptyBag, emptyTcEvBinds)--  | otherwise-  = assertPpr (all (isSkolemTyVar <||> isTyVarTyVar) skol_tvs) (ppr skol_tvs) $-      -- Why allow TyVarTvs? Because implicitly declared kind variables in-      -- non-CUSK type declarations are TyVarTvs, and we need to bring them-      -- into scope as a skolem in an implication. This is OK, though,-      -- because TyVarTvs will always remain tyvars, even after unification.-    do { ev_binds_var <- newTcEvBinds-       ; implic <- newImplication-       ; let implic' = implic { ic_tclvl  = tclvl-                              , ic_skols  = skol_tvs-                              , ic_given  = given-                              , ic_wanted = wanted-                              , ic_binds  = ev_binds_var-                              , ic_info   = skol_info }-       ; checkImplicationInvariants implic'--       ; return (unitBag implic', TcEvBinds ev_binds_var) }--{- Note [When to build an implication]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Suppose we have some 'skolems' and some 'givens', and we are-considering whether to wrap the constraints in their scope into an-implication.  We must /always/ so if either 'skolems' or 'givens' are-non-empty.  But what if both are empty?  You might think we could-always drop the implication.  Other things being equal, the fewer-implications the better.  Less clutter and overhead.  But we must-take care:--* If we have an unsolved [W] g :: a ~# b, and -fdefer-type-errors,-  we'll make a /term-level/ evidence binding for 'g = error "blah"'.-  We must have an EvBindsVar those bindings!, otherwise they end up as-  top-level unlifted bindings, which are verboten. This only matters-  at top level, so we check for that-  See also Note [Deferred errors for coercion holes] in GHC.Tc.Errors.-  cf #14149 for an example of what goes wrong.--* If you have-     f :: Int;  f = f_blah-     g :: Bool; g = g_blah-  If we don't build an implication for f or g (no tyvars, no givens),-  the constraints for f_blah and g_blah are solved together.  And that-  can yield /very/ confusing error messages, because we can get-      [W] C Int b1    -- from f_blah-      [W] C Int b2    -- from g_blan-  and fundpes can yield [W] b1 ~ b2, even though the two functions have-  literally nothing to do with each other.  #14185 is an example.-  Building an implication keeps them separate.--}+  tcSubType, tcSubTypeSigma, tcSubTypePat, tcSubTypeDS,+  tcSubTypeAmbiguity, tcSubMult,+  checkConstraints, checkTvConstraints,+  buildImplicationFor, buildTvImplication, emitResidualTvConstraint,++  -- Skolemisation+  DeepSubsumptionFlag(..), getDeepSubsumptionFlag,+  tcSkolemise, tcSkolemiseCompleteSig, tcSkolemiseExpectedType,++  -- Various unifications+  unifyType, unifyKind, unifyInvisibleType, unifyExpectedType,+  unifyTypeAndEmit, promoteTcType,+  swapOverTyVars, touchabilityAndShapeTest,+  UnifyEnv(..), updUEnvLoc, setUEnvRole,+  uType,++  --------------------------------+  -- Holes+  tcInfer,+  matchExpectedListTy,+  matchExpectedTyConApp,+  matchExpectedAppTy,+  matchExpectedFunTys,+  matchExpectedFunKind,+  matchActualFunTy, matchActualFunTys,++  checkTyEqRhs, recurseIntoTyConApp,+  PuResult(..), failCheckWith, okCheckRefl, mapCheck,+  TyEqFlags(..), TyEqFamApp(..), AreUnifying(..), LevelCheck(..), FamAppBreaker,+  famAppArgFlags, simpleUnifyCheck, checkPromoteFreeVars,+  ) where++import GHC.Prelude++import GHC.Hs++import GHC.Tc.Utils.Concrete ( hasFixedRuntimeRep, hasFixedRuntimeRep_syntactic )+import GHC.Tc.Utils.Env+import GHC.Tc.Utils.Instantiate+import GHC.Tc.Utils.Monad+import GHC.Tc.Utils.TcMType+import GHC.Tc.Utils.TcType+import GHC.Tc.Types.Evidence+import GHC.Tc.Types.Constraint+import GHC.Tc.Types.Origin+import GHC.Tc.Zonk.TcType++import GHC.Core.Type+import GHC.Core.TyCo.Rep+import GHC.Core.TyCo.FVs( isInjectiveInType )+import GHC.Core.TyCo.Ppr( debugPprType {- pprTyVar -} )+import GHC.Core.TyCon+import GHC.Core.Coercion+import GHC.Core.Multiplicity+import GHC.Core.Reduction++import qualified GHC.LanguageExtensions as LangExt++import GHC.Builtin.Types+import GHC.Types.Name+import GHC.Types.Id( idType )+import GHC.Types.Var as Var+import GHC.Types.Var.Set+import GHC.Types.Var.Env+import GHC.Types.Basic+import GHC.Types.Unique.Set (nonDetEltsUniqSet)++import GHC.Utils.Error+import GHC.Utils.Misc+import GHC.Utils.Outputable as Outputable+import GHC.Utils.Panic++import GHC.Driver.DynFlags+import GHC.Data.Bag+import GHC.Data.FastString( fsLit )++import Control.Monad+import Data.Monoid as DM ( Any(..) )+import qualified Data.Semigroup as S ( (<>) )++{- *********************************************************************+*                                                                      *+              matchActualFunTys+*                                                                      *+********************************************************************* -}++-- | 'matchActualFunTy' looks for just one function arrow,+-- returning an uninstantiated sigma-type.+--+-- Invariant: the returned argument type has a syntactically fixed+-- RuntimeRep in the sense of Note [Fixed RuntimeRep]+-- in GHC.Tc.Utils.Concrete.+--+-- See Note [Return arguments with a fixed RuntimeRep].+matchActualFunTy+  :: ExpectedFunTyOrigin+      -- ^ See Note [Herald for matchExpectedFunTys]+  -> Maybe TypedThing+      -- ^ The thing with type TcSigmaType+  -> (Arity, TcType)+      -- ^ Total number of value args in the call, and+      --   the original function type+      -- (Both are used only for error messages)+  -> TcRhoType+      -- ^ Type to analyse: a TcRhoType+  -> TcM (HsWrapper, Scaled TcSigmaTypeFRR, TcSigmaType)+-- This function takes in a type to analyse (a RhoType) and returns+-- an argument type and a result type (splitting apart a function arrow).+-- The returned argument type is a SigmaType with a fixed RuntimeRep;+-- as explained in Note [Return arguments with a fixed RuntimeRep].+--+-- See Note [matchActualFunTy error handling] for the first three arguments++-- If   (wrap, arg_ty, res_ty) = matchActualFunTy ... fun_ty+-- then wrap :: fun_ty ~> (arg_ty -> res_ty)+-- and NB: res_ty is an (uninstantiated) SigmaType++matchActualFunTy herald mb_thing err_info fun_ty+  = assertPpr (isRhoTy fun_ty) (ppr fun_ty) $+    go fun_ty+  where+    -- Does not allocate unnecessary meta variables: if the input already is+    -- a function, we just take it apart.  Not only is this efficient,+    -- it's important for higher rank: the argument might be of form+    --              (forall a. ty) -> other+    -- If allocated (fresh-meta-var1 -> fresh-meta-var2) and unified, we'd+    -- hide the forall inside a meta-variable+    go :: TcRhoType   -- The type we're processing, perhaps after+                      -- expanding type synonyms+       -> TcM (HsWrapper, Scaled TcSigmaTypeFRR, TcSigmaType)+    go ty | Just ty' <- coreView ty = go ty'++    go (FunTy { ft_af = af, ft_mult = w, ft_arg = arg_ty, ft_res = res_ty })+      = assert (isVisibleFunArg af) $+      do { hasFixedRuntimeRep_syntactic (FRRExpectedFunTy herald 1) arg_ty+         ; return (idHsWrapper, Scaled w arg_ty, res_ty) }++    go ty@(TyVarTy tv)+      | isMetaTyVar tv+      = do { cts <- readMetaTyVar tv+           ; case cts of+               Indirect ty' -> go ty'+               Flexi        -> defer ty }++       -- In all other cases we bale out into ordinary unification+       -- However unlike the meta-tyvar case, we are sure that the+       -- number of arguments doesn't match arity of the original+       -- type, so we can add a bit more context to the error message+       -- (cf #7869).+       --+       -- It is not always an error, because specialized type may have+       -- different arity, for example:+       --+       -- > f1 = f2 'a'+       -- > f2 :: Monad m => m Bool+       -- > f2 = undefined+       --+       -- But in that case we add specialized type into error context+       -- anyway, because it may be useful. See also #9605.+    go ty = addErrCtxtM (mk_ctxt ty) (defer ty)++    ------------+    defer fun_ty+      = do { arg_ty <- new_check_arg_ty herald 1+           ; res_ty <- newOpenFlexiTyVarTy+           ; let unif_fun_ty = mkScaledFunTys [arg_ty] res_ty+           ; co <- unifyType mb_thing fun_ty unif_fun_ty+           ; return (mkWpCastN co, arg_ty, res_ty) }++    ------------+    mk_ctxt :: TcType -> TidyEnv -> ZonkM (TidyEnv, SDoc)+    mk_ctxt _res_ty = mkFunTysMsg herald err_info++{- Note [matchActualFunTy error handling]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+matchActualFunTy is made much more complicated by the+desire to produce good error messages. Consider the application+    f @Int x y+In GHC.Tc.Gen.Head.tcInstFun we instantiate the function type, one+argument at a time.  It must instantiate any type/dictionary args,+before looking for an arrow type.++But if it doesn't find an arrow type, it wants to generate a message+like "f is applied to two arguments but its type only has one".+To do that, it needs to know about the args that tcArgs has already+munched up -- hence passing in n_val_args_in_call and arg_tys_so_far;+and hence also the accumulating so_far arg to 'go'.++This allows us (in mk_ctxt) to construct f's /instantiated/ type,+with just the values-arg arrows, which is what we really want+in the error message.++Ugh!+-}++-- | Like 'matchExpectedFunTys', but used when you have an "actual" type,+-- for example in function application.+--+-- INVARIANT: the returned argument types all have a syntactically fixed RuntimeRep+-- in the sense of Note [Fixed RuntimeRep] in GHC.Tc.Utils.Concrete.+-- See Note [Return arguments with a fixed RuntimeRep].+matchActualFunTys :: ExpectedFunTyOrigin -- ^ See Note [Herald for matchExpectedFunTys]+                  -> CtOrigin+                  -> Arity+                  -> TcSigmaType+                  -> TcM (HsWrapper, [Scaled TcSigmaTypeFRR], TcRhoType)+-- If    matchActualFunTys n ty = (wrap, [t1,..,tn], res_ty)+-- then  wrap : ty ~> (t1 -> ... -> tn -> res_ty)+--       and res_ty is a RhoType+-- NB: the returned type is top-instantiated; it's a RhoType+matchActualFunTys herald ct_orig n_val_args_wanted top_ty+  = go n_val_args_wanted [] top_ty+  where+    go n so_far fun_ty+      | not (isRhoTy fun_ty)+      = do { (wrap1, rho) <- topInstantiate ct_orig fun_ty+           ; (wrap2, arg_tys, res_ty) <- go n so_far rho+           ; return (wrap2 <.> wrap1, arg_tys, res_ty) }++    go 0 _ fun_ty = return (idHsWrapper, [], fun_ty)++    go n so_far fun_ty+      = do { (wrap_fun1, arg_ty1, res_ty1) <- matchActualFunTy+                                                 herald Nothing+                                                 (n_val_args_wanted, top_ty)+                                                 fun_ty+           ; (wrap_res, arg_tys, res_ty)   <- go (n-1) (arg_ty1:so_far) res_ty1+           ; let wrap_fun2 = mkWpFun idHsWrapper wrap_res arg_ty1 res_ty+           -- NB: arg_ty1 comes from matchActualFunTy, so it has+           -- a syntactically fixed RuntimeRep as needed to call mkWpFun.+           ; return (wrap_fun2 <.> wrap_fun1, arg_ty1:arg_tys, res_ty) }++{-+************************************************************************+*                                                                      *+          Skolemisation and matchExpectedFunTys+*                                                                      *+************************************************************************++Note [Skolemisation overview]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Suppose f :: (forall a. a->a) -> blah, and we have the application (f e)+Then we want to typecheck `e` pushing in the type `forall a. a->a`. But we+need to be careful:++* Roughly speaking, in (tcPolyExpr e (forall a b. rho)), we skolemise `a` and `b`,+  and then call (tcExpr e rho)++* But not quite!  We must be careful if `e` is a type lambda (\ @p @q -> blah).+  Then we want to line up the skolemised variables `a`,`b`+  with `p`,`q`, so we can't just call (tcExpr (\ @p @q -> blah) rho)++* A very similar situation arises with+     (\ @p @q -> blah) :: forall a b. rho+  Again, we must line up `p`, `q` with the skolemised `a` and `b`.++* Another similar situation arises with+    g :: forall a b. rho+    g @p @q x y = ....+  Here again when skolemising `a` and `b` we must be careful to match them up+  with `p` and `q`.++OK, so how exactly do we check @p binders in lambdas?  First note that we only+we only attempt to deal with @p binders when /checking/. We don't do inference for+(\ @a -> blah), not yet anyway.++For checking, there are two cases to consider:+  * Function LHS, where the function has a type signature+                  f :: forall a. a -> forall b. [b] -> blah+                  f @p x @q y = ...++  * Lambda        \ @p x @q y -> ...+                  \cases { @p x @q y -> ... }+    (\case p behaves like \cases { p -> ... }, and p is always a term pattern.)++Both ultimately handled by matchExpectedFunTys.++* Function LHS case is handled by `GHC.Tc.Gen.Bind.tcPolyCheck`:+  * It calls `tcSkolemiseCompleteSig`+  * Passes the skolemised variables into `tcFunBindMatches`+  * Which uses `matchExpectedFunTys` to decompose the function type to+    match the arguments+  * And then passes the (skolemised-variables ++ arg tys) on to `tcMatches`++* For the Lambda case there are two sub-cases:+   * An expression with a type signature: (\ @a x y -> blah) :: hs_ty+     This is handled by `GHC.Tc.Gen.Head.tcExprWithSig`, which kind-checks+     the signature and hands off to `tcExprPolyCheck` vai `tcPolyLExprSig`+     Note that the foralls at the top of hs_ty scope over the expression.++   * A higher order call: h e, where h :: poly_ty -> blah+     This is handlded by `GHC.Tc.Gen.Expr.tcPolyExpr`, which (in the+     checking case) again hands off to `tcExprPolyCheck`.  Here there is+     no type-variable scoping to worry about.++  So both sub-cases end up in `GHC.Tc.Gen.Expr.tcPolyExprCheck`+  * This skolemises the /top-level/ invisible binders, but remembers+    the binders as [ExpPatType]+  * Then it looks for a lambda, and if so, calls `tcLambdaMatches` passing in+    the skolemised binders so they can be matched up with the lambda binders.+  * Otherwise it does deep-skolemisation if DeepSubsumption is on,+    and then calls tcExpr to typecheck `e`++  The outer skolemisation in tcPolyExprCheck is done using+    * tcSkolemiseCompleteSig when there is a user-written signature+    * tcSkolemiseGeneral when the polytype just comes from the context e.g. (f e)+  The former just calls the latter, so the two cases differ only slightly:+    * Both do shallow skolemisation+    * Both go via checkConstraints, which uses implicationNeeded to decide whether+      to build an implication constraint even if there /are/ no skolems.+      See Note [When to build an implication] below.++  The difference between the two cases is that `tcSkolemiseCompleteSig`+  also brings the outer type variables into scope.  It would do no+  harm to do so in both cases, but I found that (to my surprise) doing+  so caused a non-trivial (1%-ish) perf hit on the compiler.++* `tcFunBindMatches` and `tcLambdaMatches` both use `matchExpectedFunTys`, which+  ensures that any trailing invisible binders are skolemised; and does so deeply+  if DeepSubsumption is on.++  This corresponds to the plan: "skolemise at the '=' of a function binding or+  at the '->' of a lambda binding".  (See #17594 and "Plan B2".)++Some wrinkles++(SK1) tcSkolemiseGeneral and tcSkolemiseCompleteSig make fresh type variables+      See Note [Instantiate sig with fresh variables]++(SK2) All skolemisation (even without DeepSubsumption) builds just one implication+      constraint for a nested forall like:+          forall a. Eq a => forall b. Ord b => blah+      The implication constraint will look like+          forall a b. (Eq a, Ord b) => <constraints>+      See the loop in GHC.Tc.Utils.Instantiate.topSkolemise.+      This is just an optimisation; it would be fine to generate one implication+      constraint for each nesting layer.++Some examples:++*     f :: forall a b. blah+      f @p x = rhs+  `tcPolyCheck` calls `tcSkolemiseCompleteSig` to skolemise the signature, and+  then calls `tcFunBindMatches` passing in [a_sk, b_sk], the skolemsed+  variables. The latter ultimately calls `tcMatches`, and thence `tcMatchPats`.+  The latter matches up the `a_sk` with `@p`, and discards the `b_sk`.++*     f :: forall (a::Type) (b::a). blah+      f @(p::b) x = rhs+  `tcSkolemiseCompleteSig` brings `a` and `b` into scope, bound to `a_sk` and `b_sk` resp.+  When `tcMatchPats` typechecks the pattern `@(p::b)` it'll find that `b` is in+  scope (as a result of tcSkolemiseCompleteSig) which is a bit strange.  But+  it'll then unify the kinds `Type ~ b`, which will fail as it should.++*     f :: Int -> forall (a::Type) (b::a). blah+      f x  @p = rhs+  `matchExpectedFunTys` does shallow skolemisation eagerly, so we'll skolemise the+  forall a b.  Then `tcMatchPats` will bind [p :-> a_sk], and discard `b_sk`.+  Discarding the `b_sk` means that+      f x @p = \ @q -> blah+  or  f x @p = let .. in \ @q -> blah+  will both be rejected: this is Plan B2: skolemise at the "=".++* Suppose DeepSubsumption is on+    f :: forall a. a -> forall b. b -> b -> forall z. z+    f @p x @q y = rhs+  The `tcSkolemiseCompleteSig` uses shallow skolemisation, so it only skolemises+  and brings into scope [a :-> a_sk]. Then `matchExpectedFunTys` skolemises the+  forall b, because it needs to expose two value arguments.  Finally+  `matchExpectedFunTys` concludes with deeply skolemising the remaining type.++  So we end up with `[p :-> a_sk, q :-> b_sk]`.  Notice that we must not+  deeply-skolemise /first/ or we'd get the tyvars [a_sk, b_sk, c_sk] which would+  not line up with the patterns [@p, x, @q, y]+-}++tcSkolemiseGeneral+  :: DeepSubsumptionFlag+  -> UserTypeCtxt+  -> TcType -> TcType   -- top_ty and expected_ty+        -- Here, top_ty      is the type we started to skolemise; used only in SigSkol+        -- -     expected_ty is the type we are actually skolemising+        -- matchExpectedFunTys walks down the type, skolemising as it goes,+        -- keeping the same top_ty, but successively smaller expected_tys+  -> ([(Name, TcInvisTVBinder)] -> TcType -> TcM result)+  -> TcM (HsWrapper, result)+tcSkolemiseGeneral ds_flag ctxt top_ty expected_ty thing_inside+  | definitely_mono ds_flag expected_ty+    -- Fast path for a very very common case: no skolemisation to do+    -- But still call checkConstraints in case we need an implication regardless+  = do { let sig_skol = SigSkol ctxt top_ty []+       ; (ev_binds, result) <- checkConstraints sig_skol [] [] $+                               thing_inside [] expected_ty+       ; return (mkWpLet ev_binds, result) }++  | otherwise+  = do { -- rec {..}: see Note [Keeping SkolemInfo inside a SkolemTv]+         --           in GHC.Tc.Utils.TcType+       ; rec { (wrap, tv_prs, given, rho_ty) <- case ds_flag of+                    Deep    -> deeplySkolemise skol_info expected_ty+                    Shallow -> topSkolemise skol_info expected_ty+             ; let sig_skol = SigSkol ctxt top_ty (map (fmap binderVar) tv_prs)+             ; skol_info <- mkSkolemInfo sig_skol }++       ; let skol_tvs = map (binderVar . snd) tv_prs+       ; traceTc "tcSkolemiseGeneral" (pprUserTypeCtxt ctxt <+> ppr skol_tvs <+> ppr given)+       ; (ev_binds, result) <- checkConstraints sig_skol skol_tvs given $+                               thing_inside tv_prs rho_ty++       ; return (wrap <.> mkWpLet ev_binds, result) }+         -- The ev_binds returned by checkConstraints is very+         -- often empty, in which case mkWpLet is a no-op++tcSkolemiseCompleteSig :: TcCompleteSig+                       -> ([ExpPatType] -> TcRhoType -> TcM result)+                       -> TcM (HsWrapper, result)+-- ^ The wrapper has type: spec_ty ~> expected_ty+-- See Note [Skolemisation] for the differences between+-- tcSkolemiseCompleteSig and tcTopSkolemise++tcSkolemiseCompleteSig (CSig { sig_bndr = poly_id, sig_ctxt = ctxt, sig_loc = loc })+                       thing_inside+  = do { cur_loc <- getSrcSpanM+       ; let poly_ty = idType poly_id+       ; setSrcSpan loc $   -- Sets the location for the implication constraint+         tcSkolemiseGeneral Shallow ctxt poly_ty poly_ty $ \tv_prs rho_ty ->+         setSrcSpan cur_loc $ -- Revert to the original location+         tcExtendNameTyVarEnv (map (fmap binderVar) tv_prs) $+         thing_inside (map (mkInvisExpPatType . snd) tv_prs) rho_ty }++tcSkolemiseExpectedType :: TcSigmaType+                        -> ([ExpPatType] -> TcRhoType -> TcM result)+                        -> TcM (HsWrapper, result)+-- Just like tcSkolemiseCompleteSig, except that we don't have a user-written+-- type signature, we only have a type comimg from the context.+-- Eg. f :: (forall a. blah) -> blah+--     In the call (f e) we will call tcSkolemiseExpectedType on (forall a.blah)+--     before typececking `e`+tcSkolemiseExpectedType exp_ty thing_inside+  = tcSkolemiseGeneral Shallow GenSigCtxt exp_ty exp_ty $ \tv_prs rho_ty ->+    thing_inside (map (mkInvisExpPatType . snd) tv_prs) rho_ty++tcSkolemise :: DeepSubsumptionFlag -> UserTypeCtxt -> TcSigmaType+            -> (TcRhoType -> TcM result)+            -> TcM (HsWrapper, result)+tcSkolemise ds_flag ctxt expected_ty thing_inside+  = tcSkolemiseGeneral ds_flag ctxt expected_ty expected_ty $ \_ rho_ty ->+    thing_inside rho_ty++checkConstraints :: SkolemInfoAnon+                 -> [TcTyVar]           -- Skolems+                 -> [EvVar]             -- Given+                 -> TcM result+                 -> TcM (TcEvBinds, result)+-- checkConstraints is careful to build an implication even if+-- `skol_tvs` and `given` are both empty, under certain circumstances+-- See Note [When to build an implication]+checkConstraints skol_info skol_tvs given thing_inside+  = do { implication_needed <- implicationNeeded skol_info skol_tvs given++       ; if implication_needed+         then do { (tclvl, wanted, result) <- pushLevelAndCaptureConstraints thing_inside+                 ; (implics, ev_binds) <- buildImplicationFor tclvl skol_info skol_tvs given wanted+                 ; traceTc "checkConstraints" (ppr tclvl $$ ppr skol_tvs)+                 ; emitImplications implics+                 ; return (ev_binds, result) }++         else -- Fast path.  We check every function argument with tcCheckPolyExpr,+              -- which uses tcTopSkolemise and hence checkConstraints.+              -- So this fast path is well-exercised+              do { res <- thing_inside+                 ; return (emptyTcEvBinds, res) } }++checkTvConstraints :: SkolemInfo+                   -> [TcTyVar]          -- Skolem tyvars+                   -> TcM result+                   -> TcM result++checkTvConstraints skol_info skol_tvs thing_inside+  = do { (tclvl, wanted, result) <- pushLevelAndCaptureConstraints thing_inside+       ; emitResidualTvConstraint skol_info skol_tvs tclvl wanted+       ; return result }++emitResidualTvConstraint :: SkolemInfo -> [TcTyVar]+                         -> TcLevel -> WantedConstraints -> TcM ()+emitResidualTvConstraint skol_info skol_tvs tclvl wanted+  | not (isEmptyWC wanted) ||+    checkTelescopeSkol skol_info_anon+  = -- checkTelescopeSkol: in this case, /always/ emit this implication+    -- even if 'wanted' is empty. We need the implication so that we check+    -- for a bad telescope. See Note [Skolem escape and forall-types] in+    -- GHC.Tc.Gen.HsType+    do { implic <- buildTvImplication skol_info_anon skol_tvs tclvl wanted+       ; emitImplication implic }++  | otherwise  -- Empty 'wanted', emit nothing+  = return ()+  where+     skol_info_anon = getSkolemInfo skol_info++buildTvImplication :: SkolemInfoAnon -> [TcTyVar]+                   -> TcLevel -> WantedConstraints -> TcM Implication+buildTvImplication skol_info skol_tvs tclvl wanted+  = assertPpr (all (isSkolemTyVar <||> isTyVarTyVar) skol_tvs) (ppr skol_tvs) $+    do { ev_binds <- newNoTcEvBinds  -- Used for equalities only, so all the constraints+                                     -- are solved by filling in coercion holes, not+                                     -- by creating a value-level evidence binding+       ; implic   <- newImplication++       ; let implic' = implic { ic_tclvl     = tclvl+                              , ic_skols     = skol_tvs+                              , ic_given_eqs = NoGivenEqs+                              , ic_wanted    = wanted+                              , ic_binds     = ev_binds+                              , ic_info      = skol_info }++       ; checkImplicationInvariants implic'+       ; return implic' }++implicationNeeded :: SkolemInfoAnon -> [TcTyVar] -> [EvVar] -> TcM Bool+-- See Note [When to build an implication]+implicationNeeded skol_info skol_tvs given+  | null skol_tvs+  , null given+  , not (alwaysBuildImplication skol_info)+  = -- Empty skolems and givens+    do { tc_lvl <- getTcLevel+       ; if not (isTopTcLevel tc_lvl)  -- No implication needed if we are+         then return False             -- already inside an implication+         else+    do { dflags <- getDynFlags       -- If any deferral can happen,+                                     -- we must build an implication+       ; return (gopt Opt_DeferTypeErrors dflags ||+                 gopt Opt_DeferTypedHoles dflags ||+                 gopt Opt_DeferOutOfScopeVariables dflags) } }++  | otherwise     -- Non-empty skolems or givens+  = return True   -- Definitely need an implication++alwaysBuildImplication :: SkolemInfoAnon -> Bool+-- See Note [When to build an implication]+alwaysBuildImplication _ = False++{-  Commmented out for now while I figure out about error messages.+    See #14185++alwaysBuildImplication (SigSkol ctxt _ _)+  = case ctxt of+      FunSigCtxt {} -> True  -- RHS of a binding with a signature+      _             -> False+alwaysBuildImplication (RuleSkol {})      = True+alwaysBuildImplication (InstSkol {})      = True+alwaysBuildImplication (FamInstSkol {})   = True+alwaysBuildImplication _                  = False+-}++buildImplicationFor :: TcLevel -> SkolemInfoAnon -> [TcTyVar]+                   -> [EvVar] -> WantedConstraints+                   -> TcM (Bag Implication, TcEvBinds)+buildImplicationFor tclvl skol_info skol_tvs given wanted+  | isEmptyWC wanted && null given+             -- Optimisation : if there are no wanteds, and no givens+             -- don't generate an implication at all.+             -- Reason for the (null given): we don't want to lose+             -- the "inaccessible alternative" error check+  = return (emptyBag, emptyTcEvBinds)++  | otherwise+  = assertPpr (all (isSkolemTyVar <||> isTyVarTyVar) skol_tvs) (ppr skol_tvs) $+      -- Why allow TyVarTvs? Because implicitly declared kind variables in+      -- non-CUSK type declarations are TyVarTvs, and we need to bring them+      -- into scope as a skolem in an implication. This is OK, though,+      -- because TyVarTvs will always remain tyvars, even after unification.+    do { ev_binds_var <- newTcEvBinds+       ; implic <- newImplication+       ; let implic' = implic { ic_tclvl  = tclvl+                              , ic_skols  = skol_tvs+                              , ic_given  = given+                              , ic_wanted = wanted+                              , ic_binds  = ev_binds_var+                              , ic_info   = skol_info }+       ; checkImplicationInvariants implic'++       ; return (unitBag implic', TcEvBinds ev_binds_var) }++{- Note [When to build an implication]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Suppose we have some 'skolems' and some 'givens', and we are+considering whether to wrap the constraints in their scope into an+implication.  We must /always/ do so if either 'skolems' or 'givens' are+non-empty.  But what if both are empty?  You might think we could+always drop the implication.  Other things being equal, the fewer+implications the better.  Less clutter and overhead.  But we must+take care:++* If we have an unsolved [W] g :: a ~# b, and -fdefer-type-errors,+  we'll make a /term-level/ evidence binding for 'g = error "blah"'.+  We must have an EvBindsVar those bindings!, otherwise they end up as+  top-level unlifted bindings, which are verboten. This only matters+  at top level, so we check for that+  See also Note [Deferred errors for coercion holes] in GHC.Tc.Errors.+  cf #14149 for an example of what goes wrong.++* This is /necessary/ for top level but may be /desirable/ even for+  nested bindings, because if the deferred coercion is bound too far+  out it will be reported even if that thunk (say) is not evaluated.++* If you have+     f :: Int;  f = f_blah+     g :: Bool; g = g_blah+  If we don't build an implication for f or g (no tyvars, no givens),+  the constraints for f_blah and g_blah are solved together.  And that+  can yield /very/ confusing error messages, because we can get+      [W] C Int b1    -- from f_blah+      [W] C Int b2    -- from g_blan+  and fundeps can yield [W] b1 ~ b2, even though the two functions have+  literally nothing to do with each other.  #14185 is an example.+  Building an implication keeps them separate.++Note [Herald for matchExpectedFunTys]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+The 'herald' always looks like:+   "The equation(s) for 'f' have"+   "The abstraction (\x.e) takes"+   "The section (+ x) expects"+   "The function 'f' is applied to"++This is used to construct a message of form++   The abstraction `\Just 1 -> ...' takes two arguments+   but its type `Maybe a -> a' has only one++   The equation(s) for `f' have two arguments+   but its type `Maybe a -> a' has only one++   The section `(f 3)' requires 'f' to take two arguments+   but its type `Int -> Int' has only one++   The function 'f' is applied to two arguments+   but its type `Int -> Int' has only one++When visible type applications (e.g., `f @Int 1 2`, as in #13902) enter the+picture, we have a choice in deciding whether to count the type applications as+proper arguments:++   The function 'f' is applied to one visible type argument+     and two value arguments+   but its type `forall a. a -> a` has only one visible type argument+     and one value argument++Or whether to include the type applications as part of the herald itself:++   The expression 'f @Int' is applied to two arguments+   but its type `Int -> Int` has only one++The latter is easier to implement and is arguably easier to understand, so we+choose to implement that option.++Note [matchExpectedFunTys]+~~~~~~~~~~~~~~~~~~~~~~~~~~+matchExpectedFunTys checks that a sigma has the form+of an n-ary function.  It passes the decomposed type to the+thing_inside, and returns a wrapper to coerce between the two types++It's used wherever a language construct must have a functional type,+namely:+        A lambda expression+        A function definition+     An operator section++This function must be written CPS'd because it needs to fill in the+ExpTypes produced for arguments before it can fill in the ExpType+passed in.++Note [Return arguments with a fixed RuntimeRep]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+The functions++  - matchExpectedFunTys,+  - matchActualFunTy,+  - matchActualFunTys,++peel off argument types, as explained in Note [matchExpectedFunTys].+It's important that these functions return argument types that have+a fixed runtime representation, otherwise we would be in violation+of the representation-polymorphism invariants of+Note [Representation polymorphism invariants] in GHC.Core.++This is why all these functions have an additional invariant,+that the argument types they return all have a syntactically fixed RuntimeRep,+in the sense of Note [Fixed RuntimeRep] in GHC.Tc.Utils.Concrete.++Example:++  Suppose we have++    type F :: Type -> RuntimeRep+    type family F a where { F Int = LiftedRep }++    type Dual :: Type -> Type+    type family Dual a where+      Dual a = a -> ()++    f :: forall (a :: TYPE (F Int)). Dual a+    f = \ x -> ()++  The body of `f` is a lambda abstraction, so we must be able to split off+  one argument type from its type. This is handled by `matchExpectedFunTys`+  (see 'GHC.Tc.Gen.Match.tcLambdaMatches'). We end up with desugared Core that+  looks like this:++    f :: forall (a :: TYPE (F Int)). Dual (a |> (TYPE F[0]))+    f = \ @(a :: TYPE (F Int)) ->+          (\ (x :: (a |> (TYPE F[0]))) -> ())+          `cast`+          (Sub (Sym (Dual[0] <(a |> (TYPE F[0]))>)))++  Two important transformations took place:++    1. We inserted casts around the argument type to ensure that it has+       a fixed runtime representation, as required by invariant (I1) from+       Note [Representation polymorphism invariants] in GHC.Core.+    2. We inserted a cast around the whole lambda to make everything line up+       with the type signature.+-}++-- | Use this function to split off arguments types when you have an+-- \"expected\" type.+--+-- This function skolemises at each polytype.+--+-- Invariant: this function only applies the provided function+-- to a list of argument types which all have a syntactically fixed RuntimeRep+-- in the sense of Note [Fixed RuntimeRep] in GHC.Tc.Utils.Concrete.+-- See Note [Return arguments with a fixed RuntimeRep].+matchExpectedFunTys :: forall a.+                       ExpectedFunTyOrigin  -- See Note [Herald for matchExpectedFunTys]+                    -> UserTypeCtxt+                    -> VisArity+                    -> ExpSigmaType+                    -> ([ExpPatType] -> ExpRhoType -> TcM a)+                    -> TcM (HsWrapper, a)+-- If    matchExpectedFunTys n ty = (wrap, _)+-- then  wrap : (t1 -> ... -> tn -> ty_r) ~> ty,+--   where [t1, ..., tn], ty_r are passed to the thing_inside+--+-- Unconditionally concludes by skolemising any trailing invisible+-- binders and, if DeepSubsumption is on, it does so deeply.+--+-- Postcondition:+--   If exp_ty is Check {}, then [ExpPatType] and ExpRhoType results are all Check{}+--   If exp_ty is Infer {}, then [ExpPatType] and ExpRhoType results are all Infer{}+matchExpectedFunTys herald _ arity (Infer inf_res) thing_inside+  = do { arg_tys <- mapM (new_infer_arg_ty herald) [1 .. arity]+       ; res_ty  <- newInferExpType+       ; result  <- thing_inside (map ExpFunPatTy arg_tys) res_ty+       ; arg_tys <- mapM (\(Scaled m t) -> Scaled m <$> readExpType t) arg_tys+       ; res_ty  <- readExpType res_ty+       ; co <- fillInferResult (mkScaledFunTys arg_tys res_ty) inf_res+       ; return (mkWpCastN co, result) }++matchExpectedFunTys herald ctx arity (Check top_ty) thing_inside+  = check 0 [] top_ty+  where+    check :: VisArity -> [ExpPatType] -> TcSigmaType -> TcM (HsWrapper, a)+    -- `check` is called only in the Check{} case+    -- It collects rev_pat_tys in reversed order+    -- n_so_far is the number of /visible/ arguments seen so far:+    --     i.e. length (filterOut isExpForAllPatTyInvis rev_pat_tys)++    -- Do shallow skolemisation if there are top-level invisible quantifiers+    check n_so_far rev_pat_tys ty+      | isSigmaTy ty  -- Type has invisible quantifiers+      = do { (wrap_gen, (wrap_res, result))+                 <- tcSkolemiseGeneral Shallow ctx top_ty ty $ \tv_bndrs ty' ->+                    let rev_pat_tys' = reverse (map (mkInvisExpPatType . snd) tv_bndrs)+                                       ++ rev_pat_tys+                    in check n_so_far rev_pat_tys' ty'+           ; return (wrap_gen <.> wrap_res, result) }++    -- (n_so_far == arity): no more args+    -- rho_ty has no top-level quantifiers+    -- If there is deep subsumption, do deep skolemisation+    check n_so_far rev_pat_tys rho_ty+      | n_so_far == arity+      = do { let pat_tys = reverse rev_pat_tys+           ; ds_flag <- getDeepSubsumptionFlag+           ; case ds_flag of+               Shallow -> do { res <- thing_inside pat_tys (mkCheckExpType rho_ty)+                             ; return (idHsWrapper, res) }+               Deep    -> tcSkolemiseGeneral Deep ctx top_ty rho_ty $ \_ rho_ty ->+                          -- "_" drop the /deeply/-skolemise binders+                          -- They do not line up with binders in the Match+                          thing_inside pat_tys (mkCheckExpType rho_ty) }++    -- NOW do coreView.  We didn't do it before, so that we do not unnecessarily+    -- unwrap a synonym in the returned rho_ty+    check n_so_far rev_pat_tys ty+      | Just ty' <- coreView ty = check n_so_far rev_pat_tys ty'++    -- Decompose /visible/ (forall a -> blah), to give an ExpForAllPat+    -- NB: invisible binders are handled by tcSplitSigmaTy/tcTopSkolemise above+    -- NB: visible foralls "count" for the Arity argument; they correspond+    --     to syntactically visible patterns in the source program+    -- See Note [Visible type application and abstraction] in GHC.Tc.Gen.App+    check n_so_far rev_pat_tys ty+      | Just (Bndr tv vis, body_ty) <- splitForAllForAllTyBinder_maybe ty+      = assertPpr (isVisibleForAllTyFlag vis) (ppr ty) $+        -- isSigmaTy case above has dealt with /invisible/ quantifiers,+        -- so this one must be /visible/ (= Required)+        do { let init_subst = mkEmptySubst (mkInScopeSet (tyCoVarsOfType ty))+             -- rec {..}: see Note [Keeping SkolemInfo inside a SkolemTv]+             --           in GHC.Tc.Utils.TcType+           ; rec { (subst', [tv']) <- tcInstSkolTyVarsX skol_info init_subst [tv]+                 ; let tv_prs = [(tyVarName tv, tv')]+                 ; skol_info <- mkSkolemInfo (SigSkol ctx top_ty tv_prs) }+           ; let body_ty' = substTy subst' body_ty+                 pat_ty   = ExpForAllPatTy (mkForAllTyBinder Required tv')+           ; (ev_binds, (wrap_res, result)) <- checkConstraints (getSkolemInfo skol_info) [tv'] [] $+                                               check (n_so_far+1) (pat_ty : rev_pat_tys) body_ty'+           ; let wrap_gen = mkWpVisTyLam tv' body_ty' <.> mkWpLet ev_binds+           ; return (wrap_gen <.> wrap_res, result) }++    check n_so_far rev_pat_tys (FunTy { ft_af = af, ft_mult = mult+                                      , ft_arg = arg_ty, ft_res = res_ty })+      = assert (isVisibleFunArg af) $+        do { let arg_pos = n_so_far + 1+           ; (arg_co, arg_ty) <- hasFixedRuntimeRep (FRRExpectedFunTy herald arg_pos) arg_ty+           ; (wrap_res, result) <- check arg_pos+                                         (mkCheckExpFunPatTy (Scaled mult arg_ty) : rev_pat_tys)+                                         res_ty+           ; let wrap_arg = mkWpCastN arg_co+                 fun_wrap = mkWpFun wrap_arg wrap_res (Scaled mult arg_ty) res_ty+           ; return (fun_wrap, result) }++    check n_so_far rev_pat_tys ty@(TyVarTy tv)+      | isMetaTyVar tv+      = do { cts <- readMetaTyVar tv+           ; case cts of+               Indirect ty' -> check n_so_far rev_pat_tys ty'+               Flexi        -> defer n_so_far rev_pat_tys ty }++       -- In all other cases we bale out into ordinary unification+       -- However unlike the meta-tyvar case, we are sure that the+       -- number of arguments doesn't match arity of the original+       -- type, so we can add a bit more context to the error message+       -- (cf #7869).+       --+       -- It is not always an error, because specialized type may have+       -- different arity, for example:+       --+       -- > f1 = f2 'a'+       -- > f2 :: Monad m => m Bool+       -- > f2 = undefined+       --+       -- But in that case we add specialized type into error context+       -- anyway, because it may be useful. See also #9605.+    check n_so_far rev_pat_tys res_ty+      = addErrCtxtM (mkFunTysMsg herald (arity, top_ty))  $+        defer n_so_far rev_pat_tys res_ty++    ------------+    defer :: VisArity -> [ExpPatType] -> TcRhoType -> TcM (HsWrapper, a)+    defer n_so_far rev_pat_tys fun_ty+      = do { more_arg_tys <- mapM (new_check_arg_ty herald) [n_so_far + 1 .. arity]+           ; let all_pats = reverse rev_pat_tys ++ map mkCheckExpFunPatTy more_arg_tys+           ; res_ty <- newOpenFlexiTyVarTy+           ; result <- thing_inside all_pats (mkCheckExpType res_ty)++           ; co <- unifyType Nothing (mkScaledFunTys more_arg_tys res_ty) fun_ty+           ; return (mkWpCastN co, result) }++new_infer_arg_ty :: ExpectedFunTyOrigin -> Int -> TcM (Scaled ExpSigmaTypeFRR)+new_infer_arg_ty herald arg_pos -- position for error messages only+  = do { mult     <- newFlexiTyVarTy multiplicityTy+       ; inf_hole <- newInferExpTypeFRR (FRRExpectedFunTy herald arg_pos)+       ; return (mkScaled mult inf_hole) }++new_check_arg_ty :: ExpectedFunTyOrigin -> Int -> TcM (Scaled TcType)+new_check_arg_ty herald arg_pos -- Position for error messages only+  = do { mult   <- newFlexiTyVarTy multiplicityTy+       ; arg_ty <- newOpenFlexiFRRTyVarTy (FRRExpectedFunTy herald arg_pos)+       ; return (mkScaled mult arg_ty) }++mkFunTysMsg :: ExpectedFunTyOrigin+            -> (VisArity, TcType)+            -> TidyEnv -> ZonkM (TidyEnv, SDoc)+-- See Note [Reporting application arity errors]+mkFunTysMsg herald (n_vis_args_in_call, fun_ty) env+  = do { (env', fun_ty) <- zonkTidyTcType env fun_ty++       ; let (pi_ty_bndrs, _) = splitPiTys fun_ty+             n_fun_args = count isVisiblePiTyBinder pi_ty_bndrs+             msg | n_vis_args_in_call <= n_fun_args  -- Enough args, in the end+                 = text "In the result of a function call"+                 | otherwise+                 = hang (full_herald <> comma)+                      2 (sep [ text "but its type" <+> quotes (pprSigmaType fun_ty)+                             , if n_fun_args == 0 then text "has none"+                               else text "has only" <+> speakN n_fun_args])++       ; return (env', msg) }+ where+  full_herald = pprExpectedFunTyHerald herald+            <+> speakNOf n_vis_args_in_call (text "visible argument")+             -- What are "visible" arguments? See Note [Visibility and arity] in GHC.Types.Basic+++{- Note [Reporting application arity errors]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider      f :: Int -> Int -> Int+and the call  foo = f 3 4 5+We'd like to get an error like:++    • Couldn't match expected type ‘t0 -> t’ with actual type ‘Int’+    • The function ‘f’ is applied to three visible arguments,           -- What are "visible" arguments?+        but its type ‘Int -> Int -> Int’ has only two                   -- See Note [Visibility and arity] in GHC.Types.Basic++That is what `mkFunTysMsg` tries to do.  But what is the "type of the function".+Most obviously, we can report its full, polymorphic type; that is simple and+explicable.  But sometimes a bit odd.  Consider+    f :: Bool -> t Int Int+    foo = f True 5 10+We get this error:+    • Couldn't match type ‘Int’ with ‘t0 -> t’+      Expected: Int -> t0 -> t+        Actual: Int -> Int+    • The function ‘f’ is applied to three visible arguments,+        but its type ‘Bool -> t Int Int’ has only one++That's not /quite/ right beause we can instantiate `t` to an arrow and get+two arrows (but not three!).  With that in mind, one could consider reporting+the /instantiated/ type, and GHC used to do so.  But it's more work, and in+some ways more confusing, especially when nested quantifiers are concerned, e.g.+    f :: Bool -> forall t. t Int Int++So we just keep it simple and report the original function type.+++************************************************************************+*                                                                      *+                    Other matchExpected functions+*                                                                      *+********************************************************************* -}++matchExpectedListTy :: TcRhoType -> TcM (TcCoercionN, TcRhoType)+-- Special case for lists+matchExpectedListTy exp_ty+ = do { (co, [elt_ty]) <- matchExpectedTyConApp listTyCon exp_ty+      ; return (co, elt_ty) }++---------------------+matchExpectedTyConApp :: TyCon                -- T :: forall kv1 ... kvm. k1 -> ... -> kn -> *+                      -> TcRhoType            -- orig_ty+                      -> TcM (TcCoercionN,    -- T k1 k2 k3 a b c ~N orig_ty+                              [TcSigmaType])  -- Element types, k1 k2 k3 a b c++-- It's used for wired-in tycons, so we call checkWiredInTyCon+-- Precondition: never called with FunTyCon+-- Precondition: input type :: *+-- Postcondition: (T k1 k2 k3 a b c) is well-kinded++matchExpectedTyConApp tc orig_ty+  = assertPpr (isAlgTyCon tc) (ppr tc) $+    go orig_ty+  where+    go ty+       | Just ty' <- coreView ty+       = go ty'++    go ty@(TyConApp tycon args)+       | tc == tycon  -- Common case+       = return (mkNomReflCo ty, args)++    go (TyVarTy tv)+       | isMetaTyVar tv+       = do { cts <- readMetaTyVar tv+            ; case cts of+                Indirect ty -> go ty+                Flexi       -> defer }++    go _ = defer++    -- If the common case does not occur, instantiate a template+    -- T k1 .. kn t1 .. tm, and unify with the original type+    -- Doing it this way ensures that the types we return are+    -- kind-compatible with T.  For example, suppose we have+    --       matchExpectedTyConApp T (f Maybe)+    -- where data T a = MkT a+    -- Then we don't want to instantiate T's data constructors with+    --    (a::*) ~ Maybe+    -- because that'll make types that are utterly ill-kinded.+    -- This happened in #7368+    defer+      = do { (_, arg_tvs) <- newMetaTyVars (tyConTyVars tc)+           ; traceTc "matchExpectedTyConApp" (ppr tc $$ ppr (tyConTyVars tc) $$ ppr arg_tvs)+           ; let args = mkTyVarTys arg_tvs+                 tc_template = mkTyConApp tc args+           ; co <- unifyType Nothing tc_template orig_ty+           ; return (co, args) }++----------------------+matchExpectedAppTy :: TcRhoType                         -- orig_ty+                   -> TcM (TcCoercion,                   -- m a ~N orig_ty+                           (TcSigmaType, TcSigmaType))  -- Returns m, a+-- If the incoming type is a mutable type variable of kind k, then+-- matchExpectedAppTy returns a new type variable (m: * -> k); note the *.++matchExpectedAppTy orig_ty+  = go orig_ty+  where+    go ty+      | Just ty' <- coreView ty = go ty'++      | Just (fun_ty, arg_ty) <- tcSplitAppTy_maybe ty+      = return (mkNomReflCo orig_ty, (fun_ty, arg_ty))++    go (TyVarTy tv)+      | isMetaTyVar tv+      = do { cts <- readMetaTyVar tv+           ; case cts of+               Indirect ty -> go ty+               Flexi       -> defer }++    go _ = defer++    -- Defer splitting by generating an equality constraint+    defer+      = do { ty1 <- newFlexiTyVarTy kind1+           ; ty2 <- newFlexiTyVarTy kind2+           ; co <- unifyType Nothing (mkAppTy ty1 ty2) orig_ty+           ; return (co, (ty1, ty2)) }++    orig_kind = typeKind orig_ty+    kind1 = mkVisFunTyMany liftedTypeKind orig_kind+    kind2 = liftedTypeKind    -- m :: * -> k+                              -- arg type :: *++{- **********************************************************************+*+                      fillInferResult+*+********************************************************************** -}++{- Note [inferResultToType]+~~~~~~~~~~~~~~~~~~~~~~~~~~~+expTypeToType and inferResultType convert an InferResult to a monotype.+It must be a monotype because if the InferResult isn't already filled in,+we fill it in with a unification variable (hence monotype).  So to preserve+order-independence we check for mono-type-ness even if it *is* filled in+already.++See also Note [TcLevel of ExpType] in GHC.Tc.Utils.TcType, and+Note [fillInferResult].+-}++-- | Fill an 'InferResult' with the given type.+--+-- If @co = fillInferResult t1 infer_res@, then @co :: t1 ~# t2@,+-- where @t2@ is the type stored in the 'ir_ref' field of @infer_res@.+--+-- This function enforces the following invariants:+--+--  - Level invariant.+--    The stored type @t2@ is at the same level as given by the+--    'ir_lvl' field.+--  - FRR invariant.+--    Whenever the 'ir_frr' field is not @Nothing@, @t2@ is guaranteed+--    to have a syntactically fixed RuntimeRep, in the sense of+--    Note [Fixed RuntimeRep] in GHC.Tc.Utils.Concrete.+fillInferResult :: TcType -> InferResult -> TcM TcCoercionN+fillInferResult act_res_ty (IR { ir_uniq = u+                               , ir_lvl  = res_lvl+                               , ir_frr  = mb_frr+                               , ir_ref  = ref })+  = do { mb_exp_res_ty <- readTcRef ref+       ; case mb_exp_res_ty of+            Just exp_res_ty+               -- We progressively refine the type stored in 'ref',+               -- for example when inferring types across multiple equations.+               --+               -- Example:+               --+               --  \ x -> case y of { True -> x ; False -> 3 :: Int }+               --+               -- When inferring the return type of this function, we will create+               -- an 'Infer' 'ExpType', which will first be filled by the type of 'x'+               -- after typechecking the first equation, and then filled again with+               -- the type 'Int', at which point we want to ensure that we unify+               -- the type of 'x' with 'Int'. This is what is happening below when+               -- we are "joining" several inferred 'ExpType's.+               -> do { traceTc "Joining inferred ExpType" $+                       ppr u <> colon <+> ppr act_res_ty <+> char '~' <+> ppr exp_res_ty+                     ; cur_lvl <- getTcLevel+                     ; unless (cur_lvl `sameDepthAs` res_lvl) $+                       ensureMonoType act_res_ty+                     ; unifyType Nothing act_res_ty exp_res_ty }+            Nothing+               -> do { traceTc "Filling inferred ExpType" $+                       ppr u <+> text ":=" <+> ppr act_res_ty++                     -- Enforce the level invariant: ensure the TcLevel of+                     -- the type we are writing to 'ref' matches 'ir_lvl'.+                     ; (prom_co, act_res_ty) <- promoteTcType res_lvl act_res_ty++                     -- Enforce the FRR invariant: ensure the type has a syntactically+                     -- fixed RuntimeRep (if necessary, i.e. 'mb_frr' is not 'Nothing').+                     ; (frr_co, act_res_ty) <-+                         case mb_frr of+                           Nothing       -> return (mkNomReflCo act_res_ty, act_res_ty)+                           Just frr_orig -> hasFixedRuntimeRep frr_orig act_res_ty++                     -- Compose the two coercions.+                     ; let final_co = prom_co `mkTransCo` frr_co++                     ; writeTcRef ref (Just act_res_ty)++                     ; return final_co }+     }++{- Note [fillInferResult]+~~~~~~~~~~~~~~~~~~~~~~~~~+When inferring, we use fillInferResult to "fill in" the hole in InferResult+   data InferResult = IR { ir_uniq :: Unique+                         , ir_lvl  :: TcLevel+                         , ir_ref  :: IORef (Maybe TcType) }++There are two things to worry about:++1. What if it is under a GADT or existential pattern match?+   - GADTs: a unification variable (and Infer's hole is similar) is untouchable+   - Existentials: be careful about skolem-escape++2. What if it is filled in more than once?  E.g. multiple branches of a case+     case e of+        T1 -> e1+        T2 -> e2++Our typing rules are:++* The RHS of a existential or GADT alternative must always be a+  monotype, regardless of the number of alternatives.++* Multiple non-existential/GADT branches can have (the same)+  higher rank type (#18412).  E.g. this is OK:+      case e of+        True  -> hr+        False -> hr+  where hr:: (forall a. a->a) -> Int+  c.f. Section 7.1 of "Practical type inference for arbitrary-rank types"+       We use choice (2) in that Section.+       (GHC 8.10 and earlier used choice (1).)++  But note that+      case e of+        True  -> hr+        False -> \x -> hr x+  will fail, because we still /infer/ both branches, so the \x will get+  a (monotype) unification variable, which will fail to unify with+  (forall a. a->a)++For (1) we can detect the GADT/existential situation by seeing that+the current TcLevel is greater than that stored in ir_lvl of the Infer+ExpType.  We bump the level whenever we go past a GADT/existential match.++Then, before filling the hole use promoteTcType to promote the type+to the outer ir_lvl.  promoteTcType does this+  - create a fresh unification variable alpha at level ir_lvl+  - emits an equality alpha[ir_lvl] ~ ty+  - fills the hole with alpha+That forces the type to be a monotype (since unification variables can+only unify with monotypes); and catches skolem-escapes because the+alpha is untouchable until the equality floats out.++For (2), we simply look to see if the hole is filled already.+  - if not, we promote (as above) and fill the hole+  - if it is filled, we simply unify with the type that is+    already there++There is one wrinkle.  Suppose we have+   case e of+      T1 -> e1 :: (forall a. a->a) -> Int+      G2 -> e2+where T1 is not GADT or existential, but G2 is a GADT.  Then suppose the+T1 alternative fills the hole with (forall a. a->a) -> Int, which is fine.+But now the G2 alternative must not *just* unify with that else we'd risk+allowing through (e2 :: (forall a. a->a) -> Int).  If we'd checked G2 first+we'd have filled the hole with a unification variable, which enforces a+monotype.++So if we check G2 second, we still want to emit a constraint that restricts+the RHS to be a monotype. This is done by ensureMonoType, and it works+by simply generating a constraint (alpha ~ ty), where alpha is a fresh+unification variable.  We discard the evidence.++-}++++{-+************************************************************************+*                                                                      *+                Subsumption checking+*                                                                      *+************************************************************************++Note [Subsumption checking: tcSubType]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+All the tcSubType calls have the form+                tcSubType actual_ty expected_ty+which checks+                actual_ty <= expected_ty++That is, that a value of type actual_ty is acceptable in+a place expecting a value of type expected_ty.  I.e. that++    actual ty   is more polymorphic than   expected_ty++It returns a wrapper function+        co_fn :: actual_ty ~ expected_ty+which takes an HsExpr of type actual_ty into one of type+expected_ty.++Note [Ambiguity check and deep subsumption]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider+   f :: (forall b. Eq b => a -> a) -> Int++Does `f` have an ambiguous type?   The ambiguity check usually checks+that this definition of f' would typecheck, where f' has the exact same+type as f:+   f' :: (forall b. Eq b => a -> a) -> Intp+   f' = f++This will be /rejected/ with DeepSubsumption but /accepted/ with+ShallowSubsumption.  On the other hand, this eta-expanded version f''+would be rejected both ways:+   f'' :: (forall b. Eq b => a -> a) -> Intp+   f'' x = f x++This is squishy in the same way as other examples in GHC.Tc.Validity+Note [The squishiness of the ambiguity check]++The situation in June 2022.  Since we have SimpleSubsumption at the moment,+we don't want introduce new breakage if you add -XDeepSubsumption, by+rejecting types as ambiguous that weren't ambiguous before.  So, as a+holding decision, we /always/ use SimpleSubsumption for the ambiguity check+(erring on the side accepting more programs). Hence tcSubTypeAmbiguity.+-}++++-----------------+-- tcWrapResult needs both un-type-checked (for origins and error messages)+-- and type-checked (for wrapping) expressions+tcWrapResult :: HsExpr GhcRn -> HsExpr GhcTc -> TcSigmaType -> ExpRhoType+             -> TcM (HsExpr GhcTc)+tcWrapResult rn_expr = tcWrapResultO (exprCtOrigin rn_expr) rn_expr++tcWrapResultO :: CtOrigin -> HsExpr GhcRn -> HsExpr GhcTc -> TcSigmaType -> ExpRhoType+               -> TcM (HsExpr GhcTc)+tcWrapResultO orig rn_expr expr actual_ty res_ty+  = do { traceTc "tcWrapResult" (vcat [ text "Actual:  " <+> ppr actual_ty+                                      , text "Expected:" <+> ppr res_ty ])+       ; wrap <- tcSubTypeNC orig GenSigCtxt (Just $ HsExprRnThing rn_expr) actual_ty res_ty+       ; return (mkHsWrap wrap expr) }++tcWrapResultMono :: HsExpr GhcRn -> HsExpr GhcTc+                 -> TcRhoType   -- Actual -- a rho-type not a sigma-type+                 -> ExpRhoType  -- Expected+                 -> TcM (HsExpr GhcTc)+-- A version of tcWrapResult to use when the actual type is a+-- rho-type, so nothing to instantiate; just go straight to unify.+-- It means we don't need to pass in a CtOrigin+tcWrapResultMono rn_expr expr act_ty res_ty+  = assertPpr (isRhoTy act_ty) (ppr act_ty $$ ppr rn_expr) $+    do { co <- unifyExpectedType rn_expr act_ty res_ty+       ; return (mkHsWrapCo co expr) }++unifyExpectedType :: HsExpr GhcRn+                  -> TcRhoType   -- Actual -- a rho-type not a sigma-type+                  -> ExpRhoType  -- Expected+                  -> TcM TcCoercionN+unifyExpectedType rn_expr act_ty exp_ty+  = case exp_ty of+      Infer inf_res -> fillInferResult act_ty inf_res+      Check exp_ty  -> unifyType (Just $ HsExprRnThing rn_expr) act_ty exp_ty++------------------------+tcSubTypePat :: CtOrigin -> UserTypeCtxt+            -> ExpSigmaType -> TcSigmaType -> TcM HsWrapper+-- Used in patterns; polarity is backwards compared+--   to tcSubType+-- If wrap = tc_sub_type_et t1 t2+--    => wrap :: t1 ~> t2+tcSubTypePat inst_orig ctxt (Check ty_actual) ty_expected+  = tc_sub_type unifyTypeET inst_orig ctxt ty_actual ty_expected++tcSubTypePat _ _ (Infer inf_res) ty_expected+  = do { co <- fillInferResult ty_expected inf_res+               -- In patterns we do not instantatiate++       ; return (mkWpCastN (mkSymCo co)) }++---------------+tcSubType :: CtOrigin -> UserTypeCtxt+          -> TcSigmaType  -- ^ Actual+          -> ExpRhoType   -- ^ Expected+          -> TcM HsWrapper+-- Checks that 'actual' is more polymorphic than 'expected'+tcSubType orig ctxt ty_actual ty_expected+  = addSubTypeCtxt ty_actual ty_expected $+    do { traceTc "tcSubType" (vcat [pprUserTypeCtxt ctxt, ppr ty_actual, ppr ty_expected])+       ; tcSubTypeNC orig ctxt Nothing ty_actual ty_expected }++---------------+tcSubTypeDS :: HsExpr GhcRn+            -> TcRhoType   -- Actual -- a rho-type not a sigma-type+            -> ExpRhoType  -- Expected+            -> TcM HsWrapper+-- Similar signature to unifyExpectedType; does deep subsumption+-- Only one call site, in GHC.Tc.Gen.App.tcApp+tcSubTypeDS rn_expr act_rho res_ty+  = case res_ty of+      Check exp_rho -> tc_sub_type_ds Deep (unifyType m_thing) orig+                                      GenSigCtxt act_rho exp_rho++      Infer inf_res -> do { co <- fillInferResult act_rho inf_res+                          ; return (mkWpCastN co) }+  where+    orig    = exprCtOrigin rn_expr+    m_thing = Just (HsExprRnThing rn_expr)++---------------+tcSubTypeNC :: CtOrigin          -- ^ Used when instantiating+            -> UserTypeCtxt      -- ^ Used when skolemising+            -> Maybe TypedThing -- ^ The expression that has type 'actual' (if known)+            -> TcSigmaType       -- ^ Actual type+            -> ExpRhoType        -- ^ Expected type+            -> TcM HsWrapper+tcSubTypeNC inst_orig ctxt m_thing ty_actual res_ty+  = case res_ty of+      Check ty_expected -> tc_sub_type (unifyType m_thing) inst_orig ctxt+                                       ty_actual ty_expected++      Infer inf_res -> do { (wrap, rho) <- topInstantiate inst_orig ty_actual+                                   -- See Note [Instantiation of InferResult]+                          ; co <- fillInferResult rho inf_res+                          ; return (mkWpCastN co <.> wrap) }++---------------+tcSubTypeSigma :: CtOrigin       -- where did the actual type arise / why are we+                                 -- doing this subtype check?+               -> UserTypeCtxt   -- where did the expected type arise?+               -> TcSigmaType -> TcSigmaType -> TcM HsWrapper+-- External entry point, but no ExpTypes on either side+-- Checks that actual <= expected+-- Returns HsWrapper :: actual ~ expected+tcSubTypeSigma orig ctxt ty_actual ty_expected+  = tc_sub_type (unifyType Nothing) orig ctxt ty_actual ty_expected++---------------+tcSubTypeAmbiguity :: UserTypeCtxt   -- Where did this type arise+                   -> TcSigmaType -> TcSigmaType -> TcM HsWrapper+-- See Note [Ambiguity check and deep subsumption]+tcSubTypeAmbiguity ctxt ty_actual ty_expected+  = tc_sub_type_ds Shallow (unifyType Nothing)+                           (AmbiguityCheckOrigin ctxt)+                           ctxt ty_actual ty_expected++---------------+addSubTypeCtxt :: TcType -> ExpType -> TcM a -> TcM a+addSubTypeCtxt ty_actual ty_expected thing_inside+ | isRhoTy ty_actual        -- If there is no polymorphism involved, the+ , isRhoExpTy ty_expected   -- TypeEqOrigin stuff (added by the _NC functions)+ = thing_inside             -- gives enough context by itself+ | otherwise+ = addErrCtxtM mk_msg thing_inside+  where+    mk_msg tidy_env+      = do { (tidy_env, ty_actual)   <- zonkTidyTcType tidy_env ty_actual+           ; ty_expected             <- readExpType ty_expected+                   -- A worry: might not be filled if we're debugging. Ugh.+           ; (tidy_env, ty_expected) <- zonkTidyTcType tidy_env ty_expected+           ; let msg = vcat [ hang (text "When checking that:")+                                 4 (ppr ty_actual)+                            , nest 2 (hang (text "is more polymorphic than:")+                                         2 (ppr ty_expected)) ]+           ; return (tidy_env, msg) }+++{- Note [Instantiation of InferResult]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+We now always instantiate before filling in InferResult, so that+the result is a TcRhoType: see #17173 for discussion.++For example:++1. Consider+    f x = (*)+   We want to instantiate the type of (*) before returning, else we+   will infer the type+     f :: forall {a}. a -> forall b. Num b => b -> b -> b+   This is surely confusing for users.++   And worse, the monomorphism restriction won't work properly. The MR is+   dealt with in simplifyInfer, and simplifyInfer has no way of+   instantiating. This could perhaps be worked around, but it may be+   hard to know even when instantiation should happen.++2. Another reason.  Consider+       f :: (?x :: Int) => a -> a+       g y = let ?x = 3::Int in f+   Here want to instantiate f's type so that the ?x::Int constraint+  gets discharged by the enclosing implicit-parameter binding.++3. Suppose one defines plus = (+). If we instantiate lazily, we will+   infer plus :: forall a. Num a => a -> a -> a. However, the monomorphism+   restriction compels us to infer+      plus :: Integer -> Integer -> Integer+   (or similar monotype). Indeed, the only way to know whether to apply+   the monomorphism restriction at all is to instantiate++There is one place where we don't want to instantiate eagerly,+namely in GHC.Tc.Module.tcRnExpr, which implements GHCi's :type+command. See Note [Implementing :type] in GHC.Tc.Module.+-}++---------------+tc_sub_type :: (TcType -> TcType -> TcM TcCoercionN)  -- How to unify+            -> CtOrigin       -- Used when instantiating+            -> UserTypeCtxt   -- Used when skolemising+            -> TcSigmaType    -- Actual; a sigma-type+            -> TcSigmaType    -- Expected; also a sigma-type+            -> TcM HsWrapper+-- Checks that actual_ty is more polymorphic than expected_ty+-- If wrap = tc_sub_type t1 t2+--    => wrap :: t1 ~> t2+--+-- The "how to unify argument" is always a call to `uType TypeLevel orig`,+-- but with different ways of constructing the CtOrigin `orig` from+-- the argument types and context.++----------------------+tc_sub_type unify inst_orig ctxt ty_actual ty_expected+  = do { ds_flag <- getDeepSubsumptionFlag+       ; tc_sub_type_ds ds_flag unify inst_orig ctxt ty_actual ty_expected }++----------------------+tc_sub_type_ds :: DeepSubsumptionFlag+               -> (TcType -> TcType -> TcM TcCoercionN)+               -> CtOrigin -> UserTypeCtxt -> TcSigmaType+               -> TcSigmaType -> TcM HsWrapper+-- tc_sub_type_ds is the main subsumption worker function+-- It takes an explicit DeepSubsumptionFlag+tc_sub_type_ds ds_flag unify inst_orig ctxt ty_actual ty_expected+  | definitely_poly ty_expected   -- See Note [Don't skolemise unnecessarily]+  , definitely_mono ds_flag ty_actual+  = do { traceTc "tc_sub_type (drop to equality)" $+         vcat [ text "ty_actual   =" <+> ppr ty_actual+              , text "ty_expected =" <+> ppr ty_expected ]+       ; mkWpCastN <$>+         unify ty_actual ty_expected }++  | otherwise   -- This is the general case+  = do { traceTc "tc_sub_type (general case)" $+         vcat [ text "ty_actual   =" <+> ppr ty_actual+              , text "ty_expected =" <+> ppr ty_expected ]++       ; (sk_wrap, inner_wrap)+           <- case ds_flag of+                Shallow -> -- Shallow: skolemise, instantiate and unify+                           tcSkolemise Shallow ctxt ty_expected $ \sk_rho ->+                           do { (wrap, rho_a) <- topInstantiate inst_orig ty_actual+                              ; cow           <- unify rho_a sk_rho+                              ; return (mkWpCastN cow <.> wrap) }+                Deep -> -- Deep: we have co/contra work to do+                        tcSkolemise Deep ctxt ty_expected $ \sk_rho ->+                        tc_sub_type_deep unify inst_orig ctxt ty_actual sk_rho++       ; return (sk_wrap <.> inner_wrap) }++----------------------+definitely_mono :: DeepSubsumptionFlag -> TcType -> Bool+definitely_mono ds_flag ty+  = case ds_flag of+      Shallow -> isRhoTy ty      -- isRhoTy: no top level forall or (=>)+      Deep    -> isDeepRhoTy ty  -- "deep" version: no nested forall or (=>)++definitely_poly :: TcType -> Bool+-- A very conservative test:+-- see Note [Don't skolemise unnecessarily]+definitely_poly ty+  | (tvs, theta, tau) <- tcSplitSigmaTy ty+  , (tv:_) <- tvs   -- At least one tyvar+  , null theta      -- No constraints; see (DP1)+  , tv `isInjectiveInType` tau+       -- The tyvar actually occurs (DP2),+       -- and occurs in an injective position (DP3).+  = True+  | otherwise+  = False++{- Note [Don't skolemise unnecessarily]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Suppose we are trying to solve+     ty_actual   <= ty_expected+    (Char->Char) <= (forall a. a->a)+We could skolemise the 'forall a', and then complain+that (Char ~ a) is insoluble; but that's a pretty obscure+error.  It's better to say that+    (Char->Char) ~ (forall a. a->a)+fails.++If we prematurely go to equality we'll reject a program we should+accept (e.g. #13752).  So the test (which is only to improve error+message) is very conservative:++ * ty_actual   is /definitely/ monomorphic: see `definitely_mono`+   This definitely_mono test comes in "shallow" and "deep" variants++ * ty_expected is /definitely/ polymorphic: see `definitely_poly`+   This definitely_poly test is more subtle than you might think.+   Here are three cases where expected_ty looks polymorphic, but+   isn't, and where it would be /wrong/ to switch to equality:++   (DP1)  (Char->Char) <= (forall a. (a~Char) => a -> a)++   (DP2)  (Char->Char) <= (forall a. Char -> Char)++   (DP3)  (Char->Char) <= (forall a. F [a] Char -> Char)+                          where type instance F [x] t = t+++Note [Wrapper returned from tcSubMult]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+There is no notion of multiplicity coercion in Core, therefore the wrapper+returned by tcSubMult (and derived functions such as tcCheckUsage and+checkManyPattern) is quite unlike any other wrapper: it checks whether the+coercion produced by the constraint solver is trivial, producing a type error+if it is not. This is implemented via the WpMultCoercion wrapper, as desugared+by GHC.HsToCore.Binds.dsHsWrapper, which does the reflexivity check.++This wrapper needs to be placed in the term; otherwise, checking of the+eventual coercion won't be triggered during desugaring. But it can be put+anywhere, since it doesn't affect the desugared code.++Why do we check this in the desugarer? It's a convenient place, since it's+right after all the constraints are solved. We need the constraints to be+solved to check whether they are trivial or not.++An alternative would be to have a kind of constraint which can+only produce trivial evidence. This would allow such checks to happen+in the constraint solver (#18756).+This would be similar to the existing setup for Concrete, see+  Note [The Concrete mechanism] in GHC.Tc.Utils.Concrete+    (PHASE 1 in particular).+-}++tcSubMult :: CtOrigin -> Mult -> Mult -> TcM HsWrapper+tcSubMult origin w_actual w_expected+  | Just (w1, w2) <- isMultMul w_actual =+  do { w1 <- tcSubMult origin w1 w_expected+     ; w2 <- tcSubMult origin w2 w_expected+     ; return (w1 <.> w2) }+  -- Currently, we consider p*q and sup p q to be equal.  Therefore, p*q <= r is+  -- equivalent to p <= r and q <= r.  For other cases, we approximate p <= q by p+  -- ~ q.  This is not complete, but it's sound. See also Note [Overapproximating+  -- multiplicities] in Multiplicity.+tcSubMult origin w_actual w_expected =+  case submult w_actual w_expected of+    Submult -> return WpHole+    Unknown -> tcEqMult origin w_actual w_expected++tcEqMult :: CtOrigin -> Mult -> Mult -> TcM HsWrapper+tcEqMult origin w_actual w_expected = do+  {+  -- Note that here we do not call to `submult`, so we check+  -- for strict equality.+  ; coercion <- unifyTypeAndEmit TypeLevel origin w_actual w_expected+  ; return $ if isReflCo coercion then WpHole else WpMultCoercion coercion }+++{- *********************************************************************+*                                                                      *+                    Deep subsumption+*                                                                      *+********************************************************************* -}++{- Note [Deep subsumption]+~~~~~~~~~~~~~~~~~~~~~~~~~~+The DeepSubsumption extension, documented here++    https://github.com/ghc-proposals/ghc-proposals/pull/511.++makes a best-efforts attempt implement deep subsumption as it was+prior to the Simplify Subsumption proposal:++    https://github.com/ghc-proposals/ghc-proposals/pull/287++The effects are in these main places:++1. In the subsumption check, tcSubType, we must do deep skolemisation:+   see the call to tcSkolemise Deep in tc_sub_type_deep++2. In tcPolyExpr we must do deep skolemisation:+   see the call to tcSkolemise in tcSkolemiseExpType++3. for expression type signatures (e :: ty), and functions with type+   signatures (e.g. f :: ty; f = e), we must deeply skolemise the type;+   see the call to tcDeeplySkolemise in tcSkolemiseScoped.++4. In GHC.Tc.Gen.App.tcApp we call tcSubTypeDS to match the result+   type. Without deep subsumption, unifyExpectedType would be sufficent.++In all these cases note that the deep skolemisation must be done /first/.+Consider (1)+     (forall a. Int -> a -> a)  <=  Int -> (forall b. b -> b)+We must skolemise the `forall b` before instantiating the `forall a`.+See also Note [Deep skolemisation].++Note that we /always/ use shallow subsumption in the ambiguity check.+See Note [Ambiguity check and deep subsumption].++Note [Deep skolemisation]+~~~~~~~~~~~~~~~~~~~~~~~~~+deeplySkolemise decomposes and skolemises a type, returning a type+with all its arrows visible (ie not buried under foralls)++Examples:++  deeplySkolemise (Int -> forall a. Ord a => blah)+    =  ( wp, [a], [d:Ord a], Int -> blah )+    where wp = \x:Int. /\a. \(d:Ord a). <hole> x++  deeplySkolemise  (forall a. Ord a => Maybe a -> forall b. Eq b => blah)+    =  ( wp, [a,b], [d1:Ord a,d2:Eq b], Maybe a -> blah )+    where wp = /\a.\(d1:Ord a).\(x:Maybe a)./\b.\(d2:Ord b). <hole> x++In general,+  if      deeplySkolemise ty = (wrap, tvs, evs, rho)+    and   e :: rho+  then    wrap e :: ty+    and   'wrap' binds tvs, evs++ToDo: this eta-abstraction plays fast and loose with termination,+      because it can introduce extra lambdas.  Maybe add a `seq` to+      fix this++Note [Setting the argument context]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider we are doing the ambiguity check for the (bogus)+  f :: (forall a b. C b => a -> a) -> Int++We'll call+   tcSubType ((forall a b. C b => a->a) -> Int )+             ((forall a b. C b => a->a) -> Int )++with a UserTypeCtxt of (FunSigCtxt "f").  Then we'll do the co/contra thing+on the argument type of the (->) -- and at that point we want to switch+to a UserTypeCtxt of GenSigCtxt.  Why?++* Error messages.  If we stick with FunSigCtxt we get errors like+     * Could not deduce: C b+       from the context: C b0+        bound by the type signature for:+            f :: forall a b. C b => a->a+  But of course f does not have that type signature!+  Example tests: T10508, T7220a, Simple14++* Implications. We may decide to build an implication for the whole+  ambiguity check, but we don't need one for each level within it,+  and TcUnify.alwaysBuildImplication checks the UserTypeCtxt.+  See Note [When to build an implication]++Note [Multiplicity in deep subsumption]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Consider+   t1 ->{mt} t2  <=   s1 ->{ms} s2++At the moment we /unify/ ms~mt, via tcEqMult.++Arguably we should use `tcSubMult`. But then if mt=m0 (a unification+variable) and ms=Many, `tcSubMult` is a no-op (since anything is a+sub-multiplicty of Many).  But then `m0` may never get unified with+anything.  It is then skolemised by the zonker; see GHC.HsToCore.Binds+Note [Free tyvars on rule LHS].  So we in RULE foldr/app in GHC.Base+we get this++ "foldr/app"     [1] forall ys m1 m2. foldr (\x{m1} \xs{m2}. (:) x xs) ys+                                       = \xs -> xs ++ ys++where we eta-expanded that (:).  But now foldr expects an argument+with ->{Many} and gets an argument with ->{m1} or ->{m2}, and Lint+complains.++The easiest solution was to use tcEqMult in tc_sub_type_deep, and+insist on equality. This is only in the DeepSubsumption code anyway.+-}++data DeepSubsumptionFlag = Deep | Shallow++getDeepSubsumptionFlag :: TcM DeepSubsumptionFlag+getDeepSubsumptionFlag = do { ds <- xoptM LangExt.DeepSubsumption+                            ; if ds then return Deep else return Shallow }++tc_sub_type_deep :: (TcType -> TcType -> TcM TcCoercionN)  -- How to unify+                 -> CtOrigin       -- Used when instantiating+                 -> UserTypeCtxt   -- Used when skolemising+                 -> TcSigmaType    -- Actual; a sigma-type+                 -> TcRhoType      -- Expected; deeply skolemised+                 -> TcM HsWrapper++-- If wrap = tc_sub_type_deep t1 t2+--    => wrap :: t1 ~> t2+-- Here is where the work actually happens!+-- Precondition: ty_expected is deeply skolemised++tc_sub_type_deep unify inst_orig ctxt ty_actual ty_expected+  = do { traceTc "tc_sub_type_deep" $+         vcat [ text "ty_actual   =" <+> ppr ty_actual+              , text "ty_expected =" <+> ppr ty_expected ]+       ; go ty_actual ty_expected }+  where+    -- NB: 'go' is not recursive, except for doing coreView+    go ty_a ty_e | Just ty_a' <- coreView ty_a = go ty_a' ty_e+                 | Just ty_e' <- coreView ty_e = go ty_a  ty_e'++    go (TyVarTy tv_a) ty_e+      = do { lookup_res <- isFilledMetaTyVar_maybe tv_a+           ; case lookup_res of+               Just ty_a' ->+                 do { traceTc "tc_sub_type_deep following filled meta-tyvar:"+                        (ppr tv_a <+> text "-->" <+> ppr ty_a')+                    ; tc_sub_type_deep unify inst_orig ctxt ty_a' ty_e }+               Nothing -> just_unify ty_actual ty_expected }++    go ty_a@(FunTy { ft_af = af1, ft_mult = act_mult, ft_arg = act_arg, ft_res = act_res })+       ty_e@(FunTy { ft_af = af2, ft_mult = exp_mult, ft_arg = exp_arg, ft_res = exp_res })+      | isVisibleFunArg af1, isVisibleFunArg af2+      = if (isTauTy ty_a && isTauTy ty_e)       -- Short cut common case to avoid+        then just_unify ty_actual ty_expected   -- unnecessary eta expansion+        else+        -- This is where we do the co/contra thing, and generate a WpFun, which in turn+        -- causes eta-expansion, which we don't like; hence encouraging NoDeepSubsumption+        do { arg_wrap  <- tc_sub_type_ds Deep unify given_orig GenSigCtxt exp_arg act_arg+                          -- GenSigCtxt: See Note [Setting the argument context]+           ; res_wrap  <- tc_sub_type_deep unify inst_orig ctxt act_res exp_res+           ; mult_wrap <- tcEqMult inst_orig act_mult exp_mult+                          -- See Note [Multiplicity in deep subsumption]+           ; return (mult_wrap <.>+                     mkWpFun arg_wrap res_wrap (Scaled exp_mult exp_arg) exp_res) }+                     -- arg_wrap :: exp_arg ~> act_arg+                     -- res_wrap :: act-res ~> exp_res+      where+        given_orig = GivenOrigin (SigSkol GenSigCtxt exp_arg [])++    go ty_a ty_e+      | let (tvs, theta, _) = tcSplitSigmaTy ty_a+      , not (null tvs && null theta)+      = do { (in_wrap, in_rho) <- topInstantiate inst_orig ty_a+           ; body_wrap <- tc_sub_type_deep unify inst_orig ctxt in_rho ty_e+           ; return (body_wrap <.> in_wrap) }++      | otherwise   -- Revert to unification+      = do { -- It's still possible that ty_actual has nested foralls. Instantiate+             -- these, as there's no way unification will succeed with them in.+             -- See typecheck/should_compile/T11305 for an example of when this+             -- is important. The problem is that we're checking something like+             --  a -> forall b. b -> b     <=   alpha beta gamma+             -- where we end up with alpha := (->)+             (inst_wrap, rho_a) <- deeplyInstantiate inst_orig ty_actual+           ; unify_wrap         <- just_unify rho_a ty_expected+           ; return (unify_wrap <.> inst_wrap) }++    just_unify ty_a ty_e = do { cow <- unify ty_a ty_e+                              ; return (mkWpCastN cow) }++-----------------------+deeplySkolemise :: SkolemInfo -> TcSigmaType+                -> TcM ( HsWrapper+                       , [(Name,TcInvisTVBinder)]     -- All skolemised variables+                       , [EvVar]                      -- All "given"s+                       , TcRhoType )+-- See Note [Deep skolemisation]+deeplySkolemise skol_info ty+  = go init_subst ty+  where+    init_subst = mkEmptySubst (mkInScopeSet (tyCoVarsOfType ty))++    go subst ty+      | Just (arg_tys, bndrs, theta, ty') <- tcDeepSplitSigmaTy_maybe ty+      = do { let arg_tys' = substScaledTys subst arg_tys+           ; ids1             <- newSysLocalIds (fsLit "dk") arg_tys'+           ; (subst', bndrs1) <- tcInstSkolTyVarBndrsX skol_info subst bndrs+           ; ev_vars1         <- newEvVars (substTheta subst' theta)+           ; (wrap, tvs_prs2, ev_vars2, rho) <- go subst' ty'+           ; let tvs     = binderVars bndrs+                 tvs1    = binderVars bndrs1+                 tv_prs1 = map tyVarName tvs `zip` bndrs1+           ; return ( mkWpEta ids1 (mkWpTyLams tvs1+                                    <.> mkWpEvLams ev_vars1+                                    <.> wrap)+                    , tv_prs1  ++ tvs_prs2+                    , ev_vars1 ++ ev_vars2+                    , mkScaledFunTys arg_tys' rho ) }++      | otherwise+      = return (idHsWrapper, [], [], substTy subst ty)+        -- substTy is a quick no-op on an empty substitution++deeplyInstantiate :: CtOrigin -> TcType -> TcM (HsWrapper, Type)+deeplyInstantiate orig ty+  = go init_subst ty+  where+    init_subst = mkEmptySubst (mkInScopeSet (tyCoVarsOfType ty))++    go subst ty+      | Just (arg_tys, bndrs, theta, rho) <- tcDeepSplitSigmaTy_maybe ty+      = do { let tvs = binderVars bndrs+           ; (subst', tvs') <- newMetaTyVarsX subst tvs+           ; let arg_tys' = substScaledTys   subst' arg_tys+                 theta'   = substTheta subst' theta+           ; ids1  <- newSysLocalIds (fsLit "di") arg_tys'+           ; wrap1 <- instCall orig (mkTyVarTys tvs') theta'+           ; (wrap2, rho2) <- go subst' rho+           ; return (mkWpEta ids1 (wrap2 <.> wrap1),+                     mkScaledFunTys arg_tys' rho2) }++      | otherwise+      = do { let ty' = substTy subst ty+           ; return (idHsWrapper, ty') }++tcDeepSplitSigmaTy_maybe+  :: TcSigmaType -> Maybe ([Scaled TcType], [TcInvisTVBinder], ThetaType, TcSigmaType)+-- Looks for a *non-trivial* quantified type, under zero or more function arrows+-- By "non-trivial" we mean either tyvars or constraints are non-empty+tcDeepSplitSigmaTy_maybe ty+  = go ty+  where+  go ty | Just (arg_ty, res_ty)           <- tcSplitFunTy_maybe ty+        , Just (arg_tys, tvs, theta, rho) <- go res_ty+        = Just (arg_ty:arg_tys, tvs, theta, rho)++        | (tvs, theta, rho) <- tcSplitSigmaTyBndrs ty+        , not (null tvs && null theta)+        = Just ([], tvs, theta, rho)++        | otherwise = Nothing++isDeepRhoTy :: TcType -> Bool+-- True if there are no foralls or (=>) at the top, or nested under+-- arrows to the right.  e.g+--    forall a. a                  False+--    Int -> forall a. a           False+--    (forall a. a) -> Int         True+-- Returns True iff tcDeepSplitSigmaTy_maybe returns Nothing+isDeepRhoTy ty+  | not (isRhoTy ty)                       = False  -- Foralls or (=>) at top+  | Just (_, res) <- tcSplitFunTy_maybe ty = isDeepRhoTy res+  | otherwise                              = True   -- No forall, (=>), or (->) at top  {- ************************************************************************
compiler/GHC/Tc/Validity.hs view
@@ -60,7 +60,8 @@ import qualified GHC.LanguageExtensions as LangExt  import GHC.Types.Error-import GHC.Types.Basic   ( UnboxedTupleOrSum(..), unboxedTupleOrSumExtension )+import GHC.Types.Basic   ( TypeOrKind(..), UnboxedTupleOrSum(..)+                         , unboxedTupleOrSumExtension ) import GHC.Types.Name import GHC.Types.Var.Env import GHC.Types.Var.Set@@ -287,22 +288,12 @@   | TySynCtxt {} <- ctxt  -- Do not complain about TypeError on the   = return ()             -- RHS of type synonyms. See #20181 +  | Just msg <- deepUserTypeError_maybe ty+  = do { env0 <- liftZonkM tcInitTidyEnv+       ; let (env1, tidy_msg) = tidyOpenType env0 msg+       ; failWithTcM (env1, TcRnUserTypeError tidy_msg) }   | otherwise-  = check ty-  where-  check ty-    | Just msg    <- userTypeError_maybe ty      = fail_with msg-    | Just (_,t1) <- splitForAllTyCoVar_maybe ty = check t1-    | let (_,tys) =  splitAppTys ty              = mapM_ check tys-    -- splitAppTys keeps type family applications saturated.-    -- This means we don't go looking for user type errors-    -- inside type family arguments (see #20241).--  fail_with :: Type -> TcM ()-  fail_with msg = do { env0 <- liftZonkM tcInitTidyEnv-                     ; let (env1, tidy_msg) = tidyOpenType env0 msg-                     ; failWithTcM (env1, TcRnUserTypeError tidy_msg)-                     }+  = return ()   {- Note [When we don't check for ambiguity]@@ -779,9 +770,18 @@   = check_ubx_tuple_or_sum UnboxedSumType   ve ty tys    | otherwise-  = mapM_ (check_arg_type False ve) tys+  = do { -- We require DataKinds to use a type constructor in a kind, unless it+         -- is exempted (e.g., Type, TYPE, etc., which is checked by+         -- isKindTyCon) or a `type data` type constructor.+         -- See Note [Checking for DataKinds].+         unless (isKindTyCon tc || isTypeDataTyCon tc) $+         checkDataKinds ve ty+       ; mapM_ (check_arg_type False ve) tys } -check_type _ (LitTy {}) = return ()+check_type ve ty@(LitTy {}) =+  -- Type-level literals are forbidden from appearing in kinds unless DataKinds+  -- is enabled. See Note [Checking for DataKinds].+  checkDataKinds ve ty  check_type ve (CastTy ty _) = check_type ve ty @@ -929,6 +929,10 @@         ; checkTcM ub_thing_allowed             (env, TcRnUnboxedTupleOrSumTypeFuncArg tup_or_sum (tidyType env ty)) +          -- Unboxed tuples and sums are forbidden from appearing in kinds+          -- unless DataKinds is enabled. See Note [Checking for DataKinds].+        ; checkDataKinds ve ty+         ; impred <- xoptM LangExt.ImpredicativeTypes         ; let rank' = if impred then ArbitraryRank else MonoTypeTyConArg                 -- c.f. check_arg_type@@ -997,12 +1001,29 @@  checkVdqOK :: ValidityEnv -> [TyVarBinder] -> Type -> TcM () checkVdqOK ve tvbs ty = do-  checkTcM (vdqAllowed ctxt || no_vdq)+  required_type_arguments <- xoptM LangExt.RequiredTypeArguments+  checkTcM (required_type_arguments || vdqAllowed ctxt || no_vdq)            (env, TcRnVDQInTermType (Just (tidyType env ty)))   where     no_vdq = all (isInvisibleForAllTyFlag . binderFlag) tvbs     ValidityEnv{ve_tidy_env = env, ve_ctxt = ctxt} = ve +-- | Check for a DataKinds violation in a kind context.+-- See @Note [Checking for DataKinds]@.+--+-- Note that emitting DataKinds errors from the typechecker is a fairly recent+-- addition to GHC (introduced in GHC 9.10), and in order to prevent these new+-- errors from breaking users' code, we temporarily downgrade these errors to+-- warnings. (This is why we use 'diagnosticTcM' below.) See+-- @Note [Checking for DataKinds] (Wrinkle: Migration story for DataKinds+-- typechecker errors)@.+checkDataKinds :: ValidityEnv -> Type -> TcM ()+checkDataKinds (ValidityEnv{ ve_ctxt = ctxt, ve_tidy_env = env }) ty = do+  data_kinds <- xoptM LangExt.DataKinds+  diagnosticTcM+    (not (data_kinds || typeLevelUserTypeCtxt ctxt)) $+    (env, TcRnDataKindsError KindLevel (Right (tidyType env ty)))+ {- Note [No constraints in kinds] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GHC does not allow constraints in kinds. Equality constraints@@ -1076,6 +1097,104 @@ (Eq a => Int) would be treated as a function type (FunTy), which just wouldn't do. +Note [Checking for DataKinds]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Checking whether a piece of code requires -XDataKinds or not is surprisingly+complicated, so here is a specification (adapted from #22141) for what+-XDataKinds does and does not allow. First, some definitions:++* A user-written type (i.e. part of the source text of a program) is in a+  /kind context/ if it follows a `::` in:+  * A standalone kind signature, e.g.,+      type T :: Nat -> Type+  * A kind signature in a type, e.g.:+    - forall (a :: Nat -> Type). blah+    - type F = G :: Nat -> Type+    - etc.+  * A result kind signature in a type declaration, e.g.:+    - data T a :: Nat -> Type where ...+    - type family Fam :: Nat -> Type+    - etc.++* All other contexts where types can appear are referred to as /type contexts/.++* The /kind type constructors/ are (see GHC.Core.TyCon.isKindTyCon):+  * TYPE and Type+  * CONSTRAINT and Constraint+  * LiftedRep+  * RuntimeRep, Levity, and their data constructors+  * Multiplicity and its data construtors+  * VecCount, VecElem, and their data constructors++* A `type data` type constructor is defined using the -XTypeData extension, such+  as the T in `type data T = A | B`.++* The following are rejected in type contexts unless -XDataKinds is enabled:+  * Promoted data constructors (e.g., 'Just), except for those data constructors+    listed under /kind type constructors/+  * Promoted list or tuple syntax (e.g., '[Int, Bool] or '(Int, Bool))+  * Type-level literals (e.g., 42, "hello", or 'a' at the type level)++* The following are rejected in kind contexts unless -XDataKinds is enabled:+  * Everything that is rejected in a type context.+  * Any type constructor that is not a kind type constructor or a `type data`+    type constructor (e.g., Maybe, [], Char, Nat, Symbol, etc.)++    Note that this includes rejecting occurrences of non-kind type construtors+    in type synomym (or type family) applications, even it the expansion would+    be legal. For example:++      type T a = Type+      f :: forall (x :: T Int). blah++    Here the `Int` in `T Int` is rejected even though the expansion is just+    `Type`. This is consistent with, for example, rejecting `T (forall a. a->a)`+    without -XImpredicativeTypes.++    This check only occurs in kind contexts. It is always permissible to mention+    type synonyms in a type context without enabling -XDataKinds, even if the+    type synonym expands to something that would otherwise require -XDataKinds.++Because checking for DataKinds in a kind context requires looking beneath type+synonyms, it is natural to implement these checks in checkValidType, which has+the necessary machinery to check for language extensions in the presence of+type synonyms. For the exact same reason, checkValidType is *not* a good place+to check for DataKinds in a type context, since we deliberately do not want to+look beneath type synonyms there. As a result, we check for DataKinds in two+different places in the code:++* We check for DataKinds violations in kind contexts in the typechecker. See+  checkDataKinds in this module.+* We check for DataKinds violations in type contexts in the renamer. See+  checkDataKinds in GHC.Rename.HsType and check_data_kinds in GHC.Rename.Pat.++  Note that the renamer can also catch "obvious" kind-level violations such as+  `data Dat :: Proxy 42 -> Type` (where 42 is not hidden beneath a type+  synonym), so we also catch a subset of kind-level violations in the renamer+  to allow for earlier reporting of these errors.++-----+-- Wrinkle: Migration story for DataKinds typechecker errors+-----++As mentioned above, DataKinds is checked in two different places: the renamer+and the typechecker. The checks in the renamer have been around since DataKinds+was introduced. The checks in the typechecker, on the other hand, are a fairly+recent addition, having been introduced in GHC 9.10. As such, it is possible+that there are some programs in the wild that (1) do not enable DataKinds, and+(2) were accepted by a previous GHC version, but would now be rejected by the+new DataKinds checks in the typechecker.++To prevent the new DataKinds checks in the typechecker from breaking users'+code, we temporarily allow programs to compile if they violate a DataKinds+check in the typechecker, but GHC will emit a warning if such a violation+occurs. Users can then silence the warning by enabling DataKinds in the module+where the affected code lives. It is fairly straightforward to distinguish+between DataKinds violations arising from the renamer versus the typechecker,+as TcRnDataKindsError (the error message type classifying all DataKinds errors)+stores an Either field that is Left when the error comes from the renamer and+Right when the error comes from the typechecker.+ ************************************************************************ *                                                                      * \subsection{Checking a theta or source type}@@ -1473,7 +1592,9 @@   -- Handwritten instances of KnownNat/KnownChar/KnownSymbol   -- are forbidden outside of signature files (#12837).   -- Derived instances are forbidden completely (#21087).-  | clas_nm `elem` [ knownNatClassName, knownSymbolClassName, knownCharClassName ]+     -- FIXME: DataToTag instances in signature files don't actually work yet+  | clas_nm `elem` [ knownNatClassName, knownSymbolClassName+                   , knownCharClassName, dataToTagClassName ]   , (not (hs_src == HsigFile) && hand_written_bindings) || derived_instance     -- Note [Instances of built-in classes in signature files]   = fail_with_inst_err $ IllegalSpecialClassInstance clas False@@ -1503,7 +1624,11 @@   = checkHasFieldInst clas cls_args    | isCTupleClass clas-  = failWithTc (TcRnTupleConstraintInst clas)+  = do+    -- Since we're now declaring instances for constraint tuples in+    -- GHC.Classes, this check must exclude that file.+    this_mod <- fmap tcg_mod getGblEnv+    when (this_mod /= gHC_CLASSES) (failWithTc (TcRnTupleConstraintInst clas))    -- Check language restrictions on the args to the class   | check_h98_arg_shape
compiler/GHC/Tc/Zonk/Env.hs view
@@ -1,6 +1,6 @@ {-# LANGUAGE DerivingVia #-} {-# LANGUAGE PatternSynonyms #-}-{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE NoPolyKinds #-}  -- | The 'ZonkEnv' zonking environment, and the 'ZonkT' and 'ZonkBndrT' -- monad transformers, for the final zonking to type in "GHC.Tc.Zonk.Type".
compiler/GHC/Tc/Zonk/Type.hs view
@@ -75,7 +75,6 @@ import GHC.Utils.Misc import GHC.Utils.Monad import GHC.Utils.Panic-import GHC.Utils.Panic.Plain  import GHC.Core.Multiplicity import GHC.Core@@ -330,15 +329,15 @@ -- See Note [Zonking to Type]. type ZonkBndrTcM = ZonkBndrT TcM -wrapLocZonkMA :: (a -> ZonkTcM b) -> GenLocated (SrcSpanAnn' ann) a-              -> ZonkTcM (GenLocated (SrcSpanAnn' ann) b)+wrapLocZonkMA :: (a -> ZonkTcM b) -> GenLocated (EpAnn ann) a+              -> ZonkTcM (GenLocated (EpAnn ann) b) wrapLocZonkMA fn (L loc a) = ZonkT $ \ ze ->   setSrcSpanA loc $   do { b <- runZonkT (fn a) ze      ; return (L loc b) } -wrapLocZonkBndrMA :: (a -> ZonkBndrTcM b) -> GenLocated (SrcSpanAnn' ann) a-                  -> ZonkBndrTcM (GenLocated (SrcSpanAnn' ann) b)+wrapLocZonkBndrMA :: (a -> ZonkBndrTcM b) -> GenLocated (EpAnn ann) a+                  -> ZonkBndrTcM (GenLocated (EpAnn ann) b) wrapLocZonkBndrMA fn (L loc a) = ZonkBndrT $ \ k -> ZonkT $ \ ze ->   setSrcSpanA loc $   runZonkT ( runZonkBndrT (fn a) $ \ b -> k (L loc b) ) ze@@ -719,11 +718,14 @@  zonk_bind :: HsBind GhcTc -> ZonkTcM (HsBind GhcTc) zonk_bind bind@(PatBind { pat_lhs = pat, pat_rhs = grhss+                        , pat_mult = mult_ann                         , pat_ext = (ty, ticks)})   = do  { new_pat   <- don'tBind $ zonkPat pat            -- Env already extended         ; new_grhss <- zonkGRHSs zonkLExpr grhss         ; new_ty    <- zonkTcTypeToTypeX ty+        ; new_mult  <- zonkMultAnn mult_ann         ; return (bind { pat_lhs = new_pat, pat_rhs = new_grhss+                       , pat_mult = new_mult                        , pat_ext = (new_ty, ticks) }) }  zonk_bind (VarBind { var_ext = x@@ -810,6 +812,17 @@                        , psb_def  = lpat'                        , psb_dir  = dir' } } } +zonkMultAnn :: HsMultAnn GhcTc -> ZonkTcM (HsMultAnn GhcTc)+zonkMultAnn (HsNoMultAnn mult)+  = do { mult' <- zonkTcTypeToTypeX mult+       ; return (HsNoMultAnn mult') }+zonkMultAnn (HsPct1Ann mult)+  = do { mult' <- zonkTcTypeToTypeX mult+       ; return (HsPct1Ann mult') }+zonkMultAnn (HsMultAnn mult hs_ty)+  = do { mult' <- zonkTcTypeToTypeX mult+       ; return (HsMultAnn mult' hs_ty) }+ zonkPatSynDetails :: HsPatSynDetails GhcTc                   -> ZonkTcM (HsPatSynDetails GhcTc) zonkPatSynDetails (PrefixCon _ as)@@ -851,7 +864,7 @@ ************************************************************************ -} -zonkMatchGroup :: Anno (GRHS GhcTc (LocatedA (body GhcTc))) ~ SrcAnn NoEpAnns+zonkMatchGroup :: Anno (GRHS GhcTc (LocatedA (body GhcTc))) ~ EpAnnCO                => (LocatedA (body GhcTc) -> ZonkTcM (LocatedA (body GhcTc)))                -> MatchGroup GhcTc (LocatedA (body GhcTc))                -> ZonkTcM (MatchGroup GhcTc (LocatedA (body GhcTc)))@@ -865,7 +878,7 @@                      , mg_ext = MatchGroupTc arg_tys' res_ty' origin                      }) } -zonkMatch :: Anno (GRHS GhcTc (LocatedA (body GhcTc))) ~ SrcAnn NoEpAnns+zonkMatch :: Anno (GRHS GhcTc (LocatedA (body GhcTc))) ~ EpAnnCO           => (LocatedA (body GhcTc) -> ZonkTcM (LocatedA (body GhcTc)))           -> LMatch GhcTc (LocatedA (body GhcTc))           -> ZonkTcM (LMatch GhcTc (LocatedA (body GhcTc)))@@ -876,7 +889,7 @@       ; return (L loc (match { m_pats = new_pats, m_grhss = new_grhss })) }  --------------------------------------------------------------------------zonkGRHSs :: Anno (GRHS GhcTc (LocatedA (body GhcTc))) ~ SrcAnn NoEpAnns+zonkGRHSs :: Anno (GRHS GhcTc (LocatedA (body GhcTc))) ~ EpAnnCO           => (LocatedA (body GhcTc) -> ZonkTcM (LocatedA (body GhcTc)))           -> GRHSs GhcTc (LocatedA (body GhcTc))           -> ZonkTcM (GRHSs GhcTc (LocatedA (body GhcTc)))@@ -939,23 +952,19 @@   = do  { lit' <- zonkOverLit lit         ; return (HsOverLit x lit') } -zonkExpr (HsLam x matches)-  = do new_matches <- zonkMatchGroup zonkLExpr matches-       return (HsLam x new_matches)--zonkExpr (HsLamCase x lc_variant matches)+zonkExpr (HsLam x lam_variant matches)   = do new_matches <- zonkMatchGroup zonkLExpr matches-       return (HsLamCase x lc_variant new_matches)+       return (HsLam x lam_variant new_matches)  zonkExpr (HsApp x e1 e2)   = do new_e1 <- zonkLExpr e1        new_e2 <- zonkLExpr e2        return (HsApp x new_e1 new_e2) -zonkExpr (HsAppType ty e at t)+zonkExpr (HsAppType ty e t)   = do new_e <- zonkLExpr e        new_ty <- zonkTcTypeToTypeX ty-       return (HsAppType new_ty new_e at t)+       return (HsAppType new_ty new_e t)        -- NB: the type is an HsType; can't zonk that!  zonkExpr (HsTypedBracket hsb_tc body)@@ -975,9 +984,9 @@     do { new_expr <- zonkLExpr expr        ; return (NegApp x new_expr new_op) } -zonkExpr (HsPar x lpar e rpar)+zonkExpr (HsPar x e)   = do { new_e <- zonkLExpr e-       ; return (HsPar x lpar new_e rpar) }+       ; return (HsPar x new_e) }  zonkExpr (SectionL x _ _) = dataConCantHappen x zonkExpr (SectionR x _ _) = dataConCantHappen x@@ -1016,10 +1025,10 @@             do { expr' <- zonkLExpr expr                ; return $ GRHS x guard' expr' } -zonkExpr (HsLet x tkLet binds tkIn expr)+zonkExpr (HsLet x binds expr)   = runZonkBndrT (zonkLocalBinds binds) $ \ new_binds ->     do { new_expr <- zonkLExpr expr-       ; return (HsLet x tkLet new_binds tkIn new_expr) }+       ; return (HsLet x new_binds new_expr) }  zonkExpr (HsDo ty do_or_lc (L l stmts))   = do new_stmts <- don'tBind $ zonkStmts zonkLExpr stmts@@ -1064,14 +1073,18 @@   = do new_ty <- zonkTcTypeToTypeX ty        HsStatic (fvs, new_ty) <$> zonkLExpr expr +zonkExpr (HsEmbTy x _) = dataConCantHappen x+ zonkExpr (XExpr (WrapExpr (HsWrap co_fn expr)))   = runZonkBndrT (zonkCoFn co_fn) $ \ new_co_fn ->     do new_expr <- zonkExpr expr        return (XExpr (WrapExpr (HsWrap new_co_fn new_expr))) -zonkExpr (XExpr (ExpansionExpr (HsExpanded a b)))-  = XExpr . ExpansionExpr . HsExpanded a <$> zonkExpr b+zonkExpr (XExpr (ExpandedThingTc thing e))+  = do e' <- zonkExpr e+       return $ XExpr (ExpandedThingTc thing e') + zonkExpr (XExpr (ConLikeTc con tvs tys))   = XExpr . ConLikeTc con tvs <$> mapM zonk_scale tys   where@@ -1148,22 +1161,18 @@        new_e <- zonkLExpr e        return (HsCmdApp x new_c new_e) -zonkCmd (HsCmdLam x matches)-  = do new_matches <- zonkMatchGroup zonkLCmd matches-       return (HsCmdLam x new_matches)--zonkCmd (HsCmdPar x lpar c rpar)+zonkCmd (HsCmdPar x c)   = do new_c <- zonkLCmd c-       return (HsCmdPar x lpar new_c rpar)+       return (HsCmdPar x new_c)  zonkCmd (HsCmdCase x expr ms)   = do new_expr <- zonkLExpr expr        new_ms <- zonkMatchGroup zonkLCmd ms        return (HsCmdCase x new_expr new_ms) -zonkCmd (HsCmdLamCase x lc_variant ms)+zonkCmd (HsCmdLam x lam_variant ms)   = do new_ms <- zonkMatchGroup zonkLCmd ms-       return (HsCmdLamCase x lc_variant new_ms)+       return (HsCmdLam x lam_variant new_ms)  zonkCmd (HsCmdIf x eCond ePred cThen cElse)   = runZonkBndrT (zonkSyntaxExpr eCond) $ \ new_eCond ->@@ -1172,10 +1181,10 @@        ; new_cElse <- zonkLCmd cElse        ; return (HsCmdIf x new_eCond new_ePred new_cThen new_cElse) } -zonkCmd (HsCmdLet x tkLet binds tkIn cmd)+zonkCmd (HsCmdLet x binds cmd)   = runZonkBndrT (zonkLocalBinds binds) $ \ new_binds ->     do new_cmd <- zonkLCmd cmd-       return (HsCmdLet x tkLet new_binds tkIn new_cmd)+       return (HsCmdLet x new_binds new_cmd)  zonkCmd (HsCmdDo ty (L l stmts))   = do new_stmts <- don'tBind $ zonkStmts zonkLCmd stmts@@ -1194,7 +1203,7 @@        new_ty <- zonkTcTypeToTypeX ty        new_ids <- mapSndM zonkExpr ids -       massert (isLiftedTypeKind (typeKind new_stack_tys))+       massert (definitelyLiftedType new_stack_tys)          -- desugarer assumes that this is not representation-polymorphic...          -- but indeed it should always be lifted due to the typing          -- rules for arrows@@ -1467,6 +1476,7 @@ ************************************************************************ -} + zonkPat :: LPat GhcTc -> ZonkBndrTcM (LPat GhcTc) -- Extend the environment as we go, because it's possible for one -- pattern to bind something that is used in another (inside or@@ -1474,9 +1484,9 @@ zonkPat pat = wrapLocZonkBndrMA zonk_pat pat  zonk_pat :: Pat GhcTc -> ZonkBndrTcM (Pat GhcTc)-zonk_pat (ParPat x lpar p rpar)+zonk_pat (ParPat x p)   = do  { p' <- zonkPat p-        ; return (ParPat x lpar p' rpar) }+        ; return (ParPat x p') }  zonk_pat (WildPat ty)   = do  { ty' <- noBinders $ zonkTcTypeToTypeX ty@@ -1494,10 +1504,10 @@   = do  { pat' <- zonkPat pat         ; return (BangPat x pat') } -zonk_pat (AsPat x (L loc v) at pat)+zonk_pat (AsPat x (L loc v) pat)   = do  { v'   <- zonkIdBndrX v         ; pat' <- zonkPat pat-        ; return (AsPat x (L loc v') at pat') }+        ; return (AsPat x (L loc v') pat') }  zonk_pat (ViewPat ty expr pat)   = do  { expr' <- noBinders $ zonkLExpr expr@@ -1576,6 +1586,14 @@         ; ty'   <- noBinders $ zonkTcTypeToTypeX ty         ; n'    <- zonkIdBndrX n         ; return (NPlusKPat ty' (L loc n') (L l lit1') lit2' e1' e2') }++zonk_pat (EmbTyPat ty tp)+  = do { ty' <- noBinders $ zonkTcTypeToTypeX ty+       ; return (EmbTyPat ty' tp) }++zonk_pat (InvisPat ty tp)+  = do { ty' <- noBinders $ zonkTcTypeToTypeX ty+       ; return (InvisPat ty' tp) }  zonk_pat (XPat ext) = case ext of   { ExpansionPat orig pat->
compiler/GHC/ThToHs.hs view
@@ -1,11 +1,6 @@-{-# LANGUAGE BangPatterns #-} {-# LANGUAGE ConstrainedClassMethods #-}-{-# LANGUAGE DeriveFunctor #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE MultiWayIf #-}-{-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE ViewPatterns #-} @@ -142,13 +137,13 @@ setL :: SrcSpan -> CvtM () setL loc = CvtM (\_ _ -> Right (loc, ())) -returnLA :: e -> CvtM (LocatedAn ann e)+returnLA :: (NoAnn ann) => e -> CvtM (LocatedAn ann e) returnLA x = CvtM (\_ loc -> Right (loc, L (noAnnSrcSpan loc) x))  returnJustLA :: a -> CvtM (Maybe (LocatedA a)) returnJustLA = fmap Just . returnLA -wrapParLA :: (LocatedAn ann a -> b) -> a -> CvtM b+wrapParLA :: (NoAnn ann) => (LocatedAn ann a -> b) -> a -> CvtM b wrapParLA add_par x = CvtM (\_ loc -> Right (loc, add_par (L (noAnnSrcSpan loc) x)))  wrapMsg :: ThingBeingConverted -> CvtM' ConversionFailReason a -> CvtM' RunSpliceFailReason a@@ -223,7 +218,8 @@         ; returnJustLA $ Hs.ValD noExtField $           PatBind { pat_lhs = pat'                   , pat_rhs = GRHSs emptyComments body' ds'-                  , pat_ext = noAnn+                  , pat_ext = noExtField+                  , pat_mult = HsNoMultAnn noExtField                   } }  cvtDec (TH.FunD nm cls)@@ -247,14 +243,19 @@         ; let sig' = StandaloneKindSig noAnn nm' ki'         ; returnJustLA $ Hs.KindSigD noExtField sig' } -cvtDec (TH.InfixD fx nm)+cvtDec (TH.InfixD fx th_ns_spec nm)   -- Fixity signatures are allowed for variables, constructors, and types   -- the renamer automatically looks for types during renaming, even when   -- the RdrName says it's a variable or a constructor. So, just assume   -- it's a variable or constructor and proceed.   = do { nm' <- vcNameN nm        ; returnJustLA (Hs.SigD noExtField (FixSig noAnn-                                      (FixitySig noExtField [nm'] (cvtFixity fx)))) }+                                      (FixitySig ns_spec [nm'] (cvtFixity fx)))) }+  where+    ns_spec = case th_ns_spec of+      TH.NoNamespaceSpecifier -> Hs.NoNamespaceSpecifier+      TH.TypeNamespaceSpecifier -> Hs.TypeNamespaceSpecifier noAnn+      TH.DataNamespaceSpecifier -> Hs.DataNamespaceSpecifier noAnn  cvtDec (TH.DefaultD tys)   = do  { tys' <- traverse cvtType tys@@ -301,7 +302,7 @@         ; unless (null adts')             (failWith $ DefaultDataInstDecl adts')         ; returnJustLA $ TyClD noExtField $-          ClassDecl { tcdCExt = (noAnn, NoAnnSortKey), tcdLayout = NoLayoutInfo+          ClassDecl { tcdCExt = (noAnn, EpNoLayout, NoAnnSortKey)                     , tcdCtxt = mkHsContextMaybe cxt', tcdLName = tc', tcdTyVars = tvs'                     , tcdFixity = Prefix                     , tcdFDs = fds', tcdSigs = Hs.mkClassOpSigs sigs'@@ -319,7 +320,7 @@         ; let inst_ty' = L loc $ mkHsImplicitSigType $                          mkHsQualTy ctxt loc ctxt' $ L loc ty'         ; returnJustLA $ InstD noExtField $ ClsInstD noExtField $-          ClsInstDecl { cid_ext = (noAnn, NoAnnSortKey), cid_poly_ty = inst_ty'+          ClsInstDecl { cid_ext = (Nothing, noAnn, NoAnnSortKey), cid_poly_ty = inst_ty'                       , cid_binds = binds'                       , cid_sigs = Hs.mkClassOpSigs sigs'                       , cid_tyfam_insts = ats', cid_datafam_insts = adts'@@ -328,10 +329,10 @@   where   overlap pragma =     case pragma of-      TH.Overlaps      -> Hs.Overlaps     (SourceText $ fsLit "OVERLAPS")-      TH.Overlappable  -> Hs.Overlappable (SourceText $ fsLit "OVERLAPPABLE")-      TH.Overlapping   -> Hs.Overlapping  (SourceText $ fsLit "OVERLAPPING")-      TH.Incoherent    -> Hs.Incoherent   (SourceText $ fsLit "INCOHERENT")+      TH.Overlaps      -> Hs.Overlaps     (SourceText $ fsLit "{-# OVERLAPS")+      TH.Overlappable  -> Hs.Overlappable (SourceText $ fsLit "{-# OVERLAPPABLE")+      TH.Overlapping   -> Hs.Overlapping  (SourceText $ fsLit "{-# OVERLAPPING")+      TH.Incoherent    -> Hs.Incoherent   (SourceText $ fsLit "{-# INCOHERENT")   @@ -421,7 +422,7 @@        ; let inst_ty' = L loc $ mkHsImplicitSigType $                         mkHsQualTy cxt loc cxt' $ L loc ty'        ; returnJustLA $ DerivD noExtField $-         DerivDecl { deriv_ext = noAnn+         DerivDecl { deriv_ext = (Nothing, noAnn)                    , deriv_strategy = ds'                    , deriv_type = mkHsWildCardBndrs inst_ty'                    , deriv_overlap_mode = Nothing } }@@ -562,7 +563,7 @@                                                , feqn_tycon  = nm'                                                , feqn_bndrs  = outer_bndrs                                                , feqn_pats   =-                                                (map HsValArg args') ++ args+                                                (map (HsValArg noExtField) args') ++ args                                                , feqn_fixity = Hs.Infix                                                , feqn_rhs    = rhs' } }            _ -> failWith $ InvalidTyFamInstLHS lhs@@ -604,7 +605,7 @@                -> CvtM ( LHsContext GhcPs                        , LocatedN RdrName                        , HsOuterFamEqnTyVarBndrs GhcPs-                       , HsTyPats GhcPs)+                       , HsFamEqnPats GhcPs) cvt_datainst_hdr cxt bndrs tys   = do { cxt' <- cvtContext funPrec cxt        ; bndrs' <- traverse (mapM cvt_tv) bndrs@@ -617,7 +618,7 @@           InfixT t1 nm t2 -> do { nm' <- tconNameN nm                                 ; args' <- mapM cvtType [t1,t2]                                 ; return (cxt', nm', outer_bndrs,-                                         ((map HsValArg args') ++ args)) }+                                         ((map (HsValArg noExtField) args') ++ args)) }           _ -> failWith $ InvalidTypeInstanceHeader tys }  ----------------@@ -729,7 +730,7 @@         { c'      <- mapM do_con_name c         ; args    <- mapM cvt_arg strtys         ; ty'     <- cvtType ty-        ; mk_gadt_decl c' (PrefixConGADT $ map hsLinear args) ty'}+        ; mk_gadt_decl c' (PrefixConGADT noExtField $ map hsLinear args) ty'}  cvtConstr parent_con do_con_name (RecGadtC c varstrtys ty) = case nonEmpty c of     Nothing -> failWith RecGadtNoCons@@ -738,7 +739,7 @@         ; ty'      <- cvtType ty         ; rec_flds <- mapM (cvt_id_arg parent_con) varstrtys         ; lrec_flds <- returnLA rec_flds-        ; mk_gadt_decl c' (RecConGADT lrec_flds noHsUniTok) ty' }+        ; mk_gadt_decl c' (RecConGADT noAnn lrec_flds) ty' }  mk_gadt_decl :: NonEmpty (LocatedN RdrName) -> HsConDeclGADTDetails GhcPs -> LHsType GhcPs              -> CvtM (LConDecl GhcPs)@@ -747,7 +748,6 @@        returnLA $ ConDeclGADT                    { con_g_ext  = noAnn                    , con_names  = names-                   , con_dcolon = noHsUniTok                    , con_bndrs  = bndrs                    , con_mb_cxt = Nothing                    , con_g_args = args@@ -799,7 +799,8 @@  cvtForD :: Foreign -> CvtM (ForeignDecl GhcPs) cvtForD (ImportF callconv safety from nm ty) =-  do { l <- getL+  do { ls <- getL+     ; let l = l2l ls      ; if -- the prim and javascript calling conventions do not support headers           -- and are inserted verbatim, analogous to mkImport in GHC.Parser.PostProcess           |  callconv == TH.Prim || callconv == TH.JavaScript@@ -809,7 +810,7 @@                                                       True)))           |  Just impspec <- parseCImport (L l (cvt_conv callconv)) (L l safety')                                           (mkFastString (TH.nameBase nm))-                                          from (L l $ quotedSourceText from)+                                          from (L ls $ quotedSourceText from)           -> mk_imp impspec           |  otherwise           -> failWith $ InvalidCCallImpent from }@@ -831,7 +832,8 @@ cvtForD (ExportF callconv as nm ty)   = do  { nm' <- vNameN nm         ; ty' <- cvtSigType ty-        ; l <- getL+        ; ls <- getL+        ; let l = l2l ls         ; let astxt = mkFastString as         ; let e = CExport (L l (SourceText astxt)) (L l (CExportStatic (SourceText astxt)                                                 astxt@@ -950,10 +952,16 @@        ; return Nothing        } cvtPragmaD (CompleteP cls mty)-  = do { cls'  <- wrapL $ mapM cNameN cls+  = do { cls'  <- mapM cNameN cls        ; mty'  <- traverse tconNameN mty        ; returnJustLA $ Hs.SigD noExtField                    $ CompleteMatchSig (noAnn, NoSourceText) cls' mty' }+cvtPragmaD (SCCP nm str) = do+  nm' <- vcNameN nm+  str' <- traverse (\s ->+    returnLA $ StringLiteral NoSourceText (mkFastString s) Nothing) str+  returnJustLA $ Hs.SigD noExtField+    $ SCCFunSig (noAnn, SourceText $ fsLit "{-# SCC") nm' str'  dfltActivation :: TH.Inline -> Activation dfltActivation TH.NoInline = NeverActive@@ -1003,8 +1011,7 @@       ((_:_), (_:_)) ->         failWith ImplicitParamsWithOtherBinds -cvtClause :: HsMatchContext GhcPs-          -> TH.Clause -> CvtM (Hs.LMatch GhcPs (LHsExpr GhcPs))+cvtClause :: HsMatchContextPs -> TH.Clause -> CvtM (Hs.LMatch GhcPs (LHsExpr GhcPs)) cvtClause ctxt (Clause ps body wheres)   = do  { ps' <- cvtPats ps         ; let pps = map (parenthesizePat appPrec) ps'@@ -1016,7 +1023,7 @@ cvtImplicitParamBind n e = do     n' <- wrapL (ipName n)     e' <- cvtl e-    returnLA (IPBind noAnn (reLocA n') e')+    returnLA (IPBind noAnn (reLoc n') e')  ------------------------------------------------------------------- --              Expressions@@ -1028,9 +1035,9 @@     cvt (VarE s)   = do { s' <- vName s; wrapParLA (HsVar noExtField) s' }     cvt (ConE s)   = do { s' <- cName s; wrapParLA (HsVar noExtField) s' }     cvt (LitE l)-      | overloadedLit l = go cvtOverLit (HsOverLit noComments)+      | overloadedLit l = go cvtOverLit (HsOverLit noExtField)                              (hsOverLitNeedsParens appPrec)-      | otherwise       = go cvtLit (HsLit noComments)+      | otherwise       = go cvtLit (HsLit noExtField)                              (hsLitNeedsParens appPrec)       where         go :: (Lit -> CvtM (l GhcPs))@@ -1043,10 +1050,10 @@           if is_compound_lit l' then wrapParLA gHsPar e' else pure e'     cvt (AppE e1 e2)   = do { e1' <- parenthesizeHsExpr opPrec <$> cvtl e1                             ; e2' <- parenthesizeHsExpr appPrec <$> cvtl e2-                            ; return $ HsApp noComments e1' e2' }+                            ; return $ HsApp noExtField e1' e2' }     cvt (AppTypeE e t) = do { e' <- parenthesizeHsExpr opPrec <$> cvtl e                             ; t' <- parenthesizeHsType appPrec <$> cvtType t-                            ; return $ HsAppType noExtField e' noHsTok+                            ; return $ HsAppType noAnn e'                                      $ mkHsWildCardBndrs t' }     cvt (LamE [] e)    = cvt e -- Degenerate case. We convert the body as its                                -- own expression to avoid pretty-printing@@ -1055,17 +1062,17 @@     cvt (LamE ps e)    = do { ps' <- cvtPats ps; e' <- cvtl e                             ; let pats = map (parenthesizePat appPrec) ps'                             ; th_origin <- getOrigin-                            ; wrapParLA (HsLam noExtField . mkMatchGroup th_origin)-                                        [mkSimpleMatch LambdaExpr pats e']}-    cvt (LamCaseE ms)  = do { ms' <- mapM (cvtMatch $ LamCaseAlt LamCase) ms+                            ; wrapParLA (HsLam noAnn LamSingle . mkMatchGroup th_origin)+                                        [mkSimpleMatch (LamAlt LamSingle) pats e']}+    cvt (LamCaseE ms)  = do { ms' <- mapM (cvtMatch $ LamAlt LamCase) ms                             ; th_origin <- getOrigin-                            ; wrapParLA (HsLamCase noAnn LamCase . mkMatchGroup th_origin) ms'+                            ; wrapParLA (HsLam noAnn LamCase . mkMatchGroup th_origin) ms'                             }     cvt (LamCasesE ms)       | null ms   = failWith CasesExprWithoutAlts-      | otherwise = do { ms' <- mapM (cvtClause $ LamCaseAlt LamCases) ms+      | otherwise = do { ms' <- mapM (cvtClause $ LamAlt LamCases) ms                        ; th_origin <- getOrigin-                       ; wrapParLA (HsLamCase noAnn LamCases . mkMatchGroup th_origin) ms'+                       ; wrapParLA (HsLam noAnn LamCases . mkMatchGroup th_origin) ms'                        }     cvt (TupE es)        = cvt_tup es Boxed     cvt (UnboxedTupE es) = cvt_tup es Unboxed@@ -1079,7 +1086,7 @@       | otherwise      = do { alts' <- mapM cvtpair alts                             ; return $ HsMultiIf noAnn alts' }     cvt (LetE ds e)    = do { ds' <- cvtLocalDecs LetExpression ds-                            ; e' <- cvtl e; return $ HsLet noAnn noHsTok ds' noHsTok e'}+                            ; e' <- cvtl e; return $ HsLet noAnn  ds' e'}     cvt (CaseE e ms)   = do { e' <- cvtl e; ms' <- mapM (cvtMatch CaseAlt) ms                             ; th_origin <- getOrigin                             ; wrapParLA (HsCase noAnn e' . mkMatchGroup th_origin) ms' }@@ -1090,7 +1097,7 @@                             ; return $ ArithSeq noAnn Nothing dd' }     cvt (ListE xs)       | Just s <- allCharLs xs       = do { l' <- cvtLit (StringL s)-                                          ; return (HsLit noComments l') }+                                          ; return (HsLit noExtField l') }              -- Note [Converting strings]       | otherwise       = do { xs' <- mapM cvtl xs                              ; return $ ExplicitList noAnn xs'@@ -1112,12 +1119,12 @@     cvt (InfixE Nothing  s (Just y)) = ensureValidOpExp s $                                        do { s' <- cvtl s; y' <- cvtl y                                           ; wrapParLA gHsPar $-                                                          SectionR noComments s' y' }+                                                          SectionR noExtField s' y' }                                             -- See Note [Sections in HsSyn] in GHC.Hs.Expr     cvt (InfixE (Just x) s Nothing ) = ensureValidOpExp s $                                        do { x' <- cvtl x; s' <- cvtl s                                           ; wrapParLA gHsPar $-                                                          SectionL noComments x' s' }+                                                          SectionL noExtField x' s' }      cvt (InfixE Nothing  s Nothing ) = ensureValidOpExp s $                                        do { s' <- cvtl s@@ -1153,17 +1160,19 @@                               -- constructor names - see #14627.                               { s' <- vcName s                               ; wrapParLA (HsVar noExtField) s' }-    cvt (LabelE s)       = return $ HsOverLabel noComments NoSourceText (fsLit s)-    cvt (ImplicitParamVarE n) = do { n' <- ipName n; return $ HsIPVar noComments n' }+    cvt (LabelE s)       = return $ HsOverLabel noExtField NoSourceText (fsLit s)+    cvt (ImplicitParamVarE n) = do { n' <- ipName n; return $ HsIPVar noExtField n' }     cvt (GetFieldE exp f) = do { e' <- cvtl exp-                               ; return $ HsGetField noComments e'+                               ; return $ HsGetField noExtField e'                                          (L noSrcSpanA (DotFieldOcc noAnn (L noSrcSpanA (FieldLabelString (fsLit f))))) }     cvt (ProjectionE xs) = return $ HsProjection noAnn $ fmap                                          (L noSrcSpanA . DotFieldOcc noAnn . L noSrcSpanA . FieldLabelString  . fsLit) xs     cvt (TypedSpliceE e) = do { e' <- parenthesizeHsExpr appPrec <$> cvtl e-                              ; return $ HsTypedSplice (noAnn, noAnn) e' }+                              ; return $ HsTypedSplice [] e' }     cvt (TypedBracketE e) = do { e' <- cvtl e                                ; return $ HsTypedBracket noAnn e' }+    cvt (TypeE t) = do { t' <- cvtType t+                       ; return $ HsEmbTy noAnn (mkHsWildCardBndrs t') }  {- | #16895 Ensure an infix expression's operator is a variable/constructor. Consider this example:@@ -1198,7 +1207,7 @@ -}  cvtFld :: (RdrName -> CvtM t) -> (TH.Name, TH.Exp)-       -> CvtM (LHsFieldBind GhcPs (LocatedAn NoEpAnns t) (LHsExpr GhcPs))+       -> CvtM (LHsFieldBind GhcPs (LocatedA t) (LHsExpr GhcPs)) cvtFld f (v,e)   = do  { v' <- vNameL v         ; lhs' <- traverse f v'@@ -1216,7 +1225,7 @@  cvt_tup :: [Maybe Exp] -> Boxity -> CvtM (HsExpr GhcPs) cvt_tup es boxity = do { let cvtl_maybe Nothing  = return (missingTupArg noAnn)-                             cvtl_maybe (Just e) = fmap (Present noAnn) (cvtl e)+                             cvtl_maybe (Just e) = fmap (Present noExtField) (cvtl e)                        ; es' <- mapM cvtl_maybe es                        ; return $ ExplicitTuple                                     noAnn@@ -1325,8 +1334,7 @@                           ; rec_stmt <- wrapParLA (mkRecStmt noAnn) ss'                           ; returnLA rec_stmt } -cvtMatch :: HsMatchContext GhcPs-         -> TH.Match -> CvtM (Hs.LMatch GhcPs (LHsExpr GhcPs))+cvtMatch :: HsMatchContextPs -> TH.Match -> CvtM (Hs.LMatch GhcPs (LHsExpr GhcPs)) cvtMatch ctxt (TH.Match p body decs)   = do  { p' <- cvtPat p         ; let lp = case p' of@@ -1438,7 +1446,7 @@                             ; ps' <- cvtPats ps                             ; ts' <- mapM cvtType ts                             ; let pps = map (parenthesizePat appPrec) ps'-                                  pts = map (\t -> HsConPatTyArg noHsTok (mkHsPatSigType noAnn t)) ts'+                                  pts = map (\t -> HsConPatTyArg noAnn (mkHsTyPat t)) ts'                             ; return $ ConPat                                 { pat_con_ext = noAnn                                 , pat_con = s'@@ -1464,7 +1472,7 @@ cvtp (TildeP p)        = do { p' <- cvtPat p; return $ LazyPat noAnn p' } cvtp (BangP p)         = do { p' <- cvtPat p; return $ BangPat noAnn p' } cvtp (TH.AsP s p)      = do { s' <- vNameN s; p' <- cvtPat p-                            ; return $ AsPat noAnn s' noHsTok p' }+                            ; return $ AsPat noAnn s' p' } cvtp TH.WildP          = return $ WildPat noExtField cvtp (RecP c fs)       = do { c' <- cNameN c; fs' <- mapM cvtPatFld fs                             ; return $ ConPat@@ -1477,10 +1485,13 @@                             ; return                                    $ ListPat noAnn ps'} cvtp (SigP p t)        = do { p' <- cvtPat p; t' <- cvtType t-                            ; let pp = parenthesizePat sigPrec p'-                            ; return $ SigPat noAnn pp (mkHsPatSigType noAnn t') }+                            ; return $ SigPat noAnn p' (mkHsPatSigType noAnn t') } cvtp (ViewP e p)       = do { e' <- cvtl e; p' <- cvtPat p                             ; return $ ViewPat noAnn e' p'}+cvtp (TypeP t)         = do { t' <- cvtType t+                            ; return $ EmbTyPat noAnn (mkHsTyPat t') }+cvtp (InvisP t)        = do { t' <- cvtType t+                            ; pure (InvisPat noAnn (mkHsTyPat t'))}  cvtPatFld :: (TH.Name, TH.Pat) -> CvtM (LHsRecField GhcPs (LPat GhcPs)) cvtPatFld (s,p)@@ -1525,8 +1536,8 @@   cvtFlag TH.InferredSpec  = Hs.InferredSpec  instance CvtFlag TH.BndrVis (HsBndrVis GhcPs) where-  cvtFlag TH.BndrReq   = HsBndrRequired-  cvtFlag TH.BndrInvis = HsBndrInvisible noHsTok+  cvtFlag TH.BndrReq   = HsBndrRequired noExtField+  cvtFlag TH.BndrInvis = HsBndrInvisible noAnn  cvtTvs :: CvtFlag flag flag' => [TH.TyVarBndr flag] -> CvtM [LHsTyVarBndr flag' GhcPs] cvtTvs tvs = mapM cvt_tv tvs@@ -1602,7 +1613,7 @@ cvtTypeKind typeOrKind ty   = do { (head_ty, tys') <- split_ty_app ty        ; let m_normals = mapM extract_normal tys'-                                where extract_normal (HsValArg ty) = Just ty+                                where extract_normal (HsValArg _ ty) = Just ty                                       extract_normal _ = Nothing         ; case head_ty of@@ -1639,7 +1650,7 @@                           _            -> return $                                           parenthesizeHsType sigPrec x'                  let y'' = parenthesizeHsType sigPrec y'-                 returnLA (HsFunTy noAnn (HsUnrestrictedArrow noHsUniTok) x'' y'')+                 returnLA (HsFunTy noExtField (HsUnrestrictedArrow noAnn) x'' y'')              | otherwise              -> do { fun_tc <- returnLA $ getRdrName unrestrictedFunTyCon                    ; mk_apps (HsTyVar noAnn NotPromoted fun_tc) tys' }@@ -1654,7 +1665,7 @@                                           parenthesizeHsType sigPrec x'                  let y'' = parenthesizeHsType sigPrec y'                      w'' = hsTypeToArrow w'-                 returnLA (HsFunTy noAnn w'' x'' y'')+                 returnLA (HsFunTy noExtField w'' x'' y'')              | otherwise              -> do { fun_tc <- returnLA $ getRdrName fUNTyCon                    ; mk_apps (HsTyVar noAnn NotPromoted fun_tc) tys' }@@ -1715,7 +1726,7 @@                    ; ls' <- returnLA s'                    ; mk_apps                       (HsTyVar noAnn prom ls')-                      ([HsValArg t1', HsValArg t2'] ++ tys')+                      ([HsValArg noExtField t1', HsValArg noExtField t2'] ++ tys')                    }             UInfixT t1 s t2@@ -1731,7 +1742,7 @@                    ; t2' <- cvtType t2                    ; mk_apps                       (HsTyVar noAnn IsPromoted s')-                      ([HsValArg t1', HsValArg t2'] ++ tys')+                      ([HsValArg noExtField t1', HsValArg noExtField t2'] ++ tys')                    }             PromotedUInfixT t1 s t2@@ -1796,7 +1807,7 @@            ImplicitParamT n t              -> do { n' <- wrapL $ ipName n                    ; t' <- cvtType t-                   ; returnLA (HsIParamTy noAnn (reLocA n') t')+                   ; returnLA (HsIParamTy noAnn (reLoc n') t')                    }             _ -> failWith (MalformedType typeOrKind ty)@@ -1805,9 +1816,9 @@ hsTypeToArrow :: LHsType GhcPs -> HsArrow GhcPs hsTypeToArrow w = case unLoc w of                      HsTyVar _ _ (L _ (isExact_maybe -> Just n))-                        | n == oneDataConName -> HsLinearArrow (HsPct1 noHsTok noHsUniTok)-                        | n == manyDataConName -> HsUnrestrictedArrow noHsUniTok-                     _ -> HsExplicitMult noHsTok w noHsUniTok+                        | n == oneDataConName -> HsLinearArrow noAnn+                        | n == manyDataConName -> HsUnrestrictedArrow noAnn+                     _ -> HsExplicitMult noAnn w  -- ConT/InfixT can contain both data constructor (i.e., promoted) names and -- other (i.e, unpromoted) names, as opposed to PromotedT, which can only@@ -1833,11 +1844,12 @@       go [] = pure head_ty'       go (arg:args) =         case arg of-          HsValArg ty  -> do p_ty <- add_parens ty+          HsValArg _ ty ->+                          do p_ty <- add_parens ty                              mk_apps (HsAppTy noExtField phead_ty p_ty) args           HsTypeArg at ki ->                           do p_ki <- add_parens ki-                             mk_apps (HsAppKindTy noExtField phead_ty at p_ki) args+                             mk_apps (HsAppKindTy at phead_ty p_ki) args           HsArgPar _   -> mk_apps (HsParTy noAnn phead_ty) args    go type_args@@ -1848,7 +1860,7 @@       | otherwise                   = return lt  wrap_tyarg :: LHsTypeArg GhcPs -> LHsTypeArg GhcPs-wrap_tyarg (HsValArg ty)    = HsValArg  $ parenthesizeHsType appPrec ty+wrap_tyarg (HsValArg x ty)  = HsValArg x $ parenthesizeHsType appPrec ty wrap_tyarg (HsTypeArg l ki) = HsTypeArg l $ parenthesizeHsType appPrec ki wrap_tyarg ta@(HsArgPar {}) = ta -- Already parenthesized @@ -1880,9 +1892,9 @@ split_ty_app :: TH.Type -> CvtM (TH.Type, [LHsTypeArg GhcPs]) split_ty_app ty = go ty []   where-    go (AppT f a) as' = do { a' <- cvtType a; go f (HsValArg a':as') }+    go (AppT f a) as' = do { a' <- cvtType a; go f (HsValArg noExtField a':as') }     go (AppKindT ty ki) as' = do { ki' <- cvtKind ki-                                 ; go ty (HsTypeArg noHsTok ki' : as') }+                                 ; go ty (HsTypeArg noAnn ki' : as') }     go (ParensT t) as' = do { loc <- getL; go t (HsArgPar loc: as') }     go f as           = return (f,as) 
+ compiler/GHC/Utils/Touch.hs view
@@ -0,0 +1,34 @@+{-# LANGUAGE CPP #-}++module GHC.Utils.Touch (touch) where++import GHC.Prelude++#if defined(mingw32_HOST_OS)+import System.Win32.File+import System.Win32.Time+#else+import System.Posix.Files+import System.Posix.IO+#endif++-- | Set the mtime of the given file to the current time.+touch :: FilePath -> IO ()+touch file = do+#if defined(mingw32_HOST_OS)+    hdl <- createFile file gENERIC_WRITE fILE_SHARE_NONE Nothing oPEN_ALWAYS fILE_ATTRIBUTE_NORMAL Nothing+    t <- getSystemTimeAsFileTime+    setFileTime hdl Nothing Nothing (Just t)+    closeHandle hdl+#else+#if MIN_VERSION_unix(2,8,0)+  let oflags = defaultFileFlags { noctty = True, creat = Just 0o666 }+  fd <- openFd file WriteOnly oflags+#else+  let oflags = defaultFileFlags { noctty = True }+  fd <- openFd file WriteOnly (Just 0o666) oflags+#endif+  touchFd fd+  closeFd fd+#endif+
compiler/GHC/Utils/Unique.hs view
@@ -2,12 +2,12 @@  {- Work around #23537 -On 32 bit systems, GHC's codegen around 64 bit numbers is not quite-complete. This led to panics mentioning missing cases in iselExpr64.-Now that GHC uses Word64 for its uniques, these panics have started-popping up whenever a unique is compared to many other uniques in one-function. As a workaround we use these two functions which are not-inlined on 32 bit systems, thus preventing the panics.+On 32 bit systems, GHC's codegen around 64 bit numbers used to be incomplete+before GHC 9.10. This led to panics mentioning missing cases in iselExpr64.+Now that GHC uses Word64 for its uniques, these panics have started popping up+whenever a unique is compared to many other uniques in one function. As a+workaround we use these two functions which are not inlined, on 32 bit systems+and if compiled with versions before GHC 9.9, thus preventing the panics. -}  module GHC.Utils.Unique (sameUnique, anyOfUnique) where@@ -18,7 +18,7 @@ import GHC.Types.Unique (Unique, Uniquable (getUnique))  -#if WORD_SIZE_IN_BITS == 32+#if WORD_SIZE_IN_BITS == 32 && !MIN_VERSION_GLASGOW_HASKELL(9,9,0,0) {-# NOINLINE sameUnique #-} #else {-# INLINE sameUnique #-}@@ -26,7 +26,7 @@ sameUnique :: Uniquable a => a -> a -> Bool sameUnique x y = getUnique x == getUnique y -#if WORD_SIZE_IN_BITS == 32+#if WORD_SIZE_IN_BITS == 32 && !MIN_VERSION_GLASGOW_HASKELL(9,9,0,0) {-# NOINLINE anyOfUnique #-} #else {-# INLINE anyOfUnique #-}
compiler/GHC/Wasm/ControlFlow/FromCmm.hs view
@@ -15,7 +15,6 @@  import GHC.Cmm import GHC.Cmm.Dataflow.Block-import GHC.Cmm.Dataflow.Collections import GHC.Cmm.Dominators import GHC.Cmm.Dataflow.Graph import GHC.Cmm.Dataflow.Label@@ -334,7 +333,7 @@     CmmMachOp (MO_Add width) [e, CmmLit (CmmInt (toInteger k) width)]   where width = cmmExprWidth platform e -addToList :: (IsMap map) => ([a] -> [a]) -> KeyOf map -> map [a] -> map [a]+addToList :: ([a] -> [a]) -> Label -> LabelMap [a] -> LabelMap [a] addToList consx = mapAlter add     where add Nothing = Just (consx [])           add (Just xs) = Just (consx xs)
compiler/MachRegs.h view
@@ -51,638 +51,54 @@ #elif MACHREGS_NO_REGS == 0  /* -----------------------------------------------------------------------------   Caller saves and callee-saves regs.-+   Note [Caller saves and callee-saves regs.]+   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~    Caller-saves regs have to be saved around C-calls made from STG    land, so this file defines CALLER_SAVES_<reg> for each <reg> that    is designated caller-saves in that machine's C calling convention.+   NB: Caller-saved registers not mapped to a STG register don't+       require a CALLER_SAVES_ define.     As it stands, the only registers that are ever marked caller saves-   are the RX, FX, DX and USER registers; as a result, if you+   are the RX, FX, DX, XMM and USER registers; as a result, if you    decide to caller save a system register (e.g. SP, HP, etc), note that    this code path is completely untested! -- EZY     See Note [Register parameter passing] for details.    -------------------------------------------------------------------------- */ -/* ------------------------------------------------------------------------------   The x86 register mapping--   Ok, we've only got 6 general purpose registers, a frame pointer and a-   stack pointer.  \tr{%eax} and \tr{%edx} are return values from C functions,-   hence they get trashed across ccalls and are caller saves. \tr{%ebx},-   \tr{%esi}, \tr{%edi}, \tr{%ebp} are all callee-saves.--   Reg     STG-Reg-   ----------------   ebx     Base-   ebp     Sp-   esi     R1-   edi     Hp--   Leaving SpLim out of the picture.-   -------------------------------------------------------------------------- */--#if defined(MACHREGS_i386)--#define REG(x) __asm__("%" #x)--#if !defined(not_doing_dynamic_linking)-#define REG_Base    ebx-#endif-#define REG_Sp      ebp--#if !defined(STOLEN_X86_REGS)-#define STOLEN_X86_REGS 4-#endif--#if STOLEN_X86_REGS >= 3-# define REG_R1     esi-#endif--#if STOLEN_X86_REGS >= 4-# define REG_Hp     edi-#endif-#define REG_MachSp  esp--#define REG_XMM1    xmm0-#define REG_XMM2    xmm1-#define REG_XMM3    xmm2-#define REG_XMM4    xmm3--#define REG_YMM1    ymm0-#define REG_YMM2    ymm1-#define REG_YMM3    ymm2-#define REG_YMM4    ymm3--#define REG_ZMM1    zmm0-#define REG_ZMM2    zmm1-#define REG_ZMM3    zmm2-#define REG_ZMM4    zmm3--#define MAX_REAL_VANILLA_REG 1  /* always, since it defines the entry conv */-#define MAX_REAL_FLOAT_REG   0-#define MAX_REAL_DOUBLE_REG  0-#define MAX_REAL_LONG_REG    0-#define MAX_REAL_XMM_REG     4-#define MAX_REAL_YMM_REG     4-#define MAX_REAL_ZMM_REG     4--/* ------------------------------------------------------------------------------  The x86-64 register mapping--  %rax          caller-saves, don't steal this one-  %rbx          YES-  %rcx          arg reg, caller-saves-  %rdx          arg reg, caller-saves-  %rsi          arg reg, caller-saves-  %rdi          arg reg, caller-saves-  %rbp          YES (our *prime* register)-  %rsp          (unavailable - stack pointer)-  %r8           arg reg, caller-saves-  %r9           arg reg, caller-saves-  %r10          caller-saves-  %r11          caller-saves-  %r12          YES-  %r13          YES-  %r14          YES-  %r15          YES--  %xmm0-7       arg regs, caller-saves-  %xmm8-15      caller-saves--  Use the caller-saves regs for Rn, because we don't always have to-  save those (as opposed to Sp/Hp/SpLim etc. which always have to be-  saved).--  --------------------------------------------------------------------------- */--#elif defined(MACHREGS_x86_64)--#define REG(x) __asm__("%" #x)--#define REG_Base  r13-#define REG_Sp    rbp-#define REG_Hp    r12-#define REG_R1    rbx-#define REG_R2    r14-#define REG_R3    rsi-#define REG_R4    rdi-#define REG_R5    r8-#define REG_R6    r9-#define REG_SpLim r15-#define REG_MachSp  rsp--/*-Map both Fn and Dn to register xmmn so that we can pass a function any-combination of up to six Float# or Double# arguments without touching-the stack. See Note [Overlapping global registers] for implications.-*/--#define REG_F1    xmm1-#define REG_F2    xmm2-#define REG_F3    xmm3-#define REG_F4    xmm4-#define REG_F5    xmm5-#define REG_F6    xmm6--#define REG_D1    xmm1-#define REG_D2    xmm2-#define REG_D3    xmm3-#define REG_D4    xmm4-#define REG_D5    xmm5-#define REG_D6    xmm6--#define REG_XMM1    xmm1-#define REG_XMM2    xmm2-#define REG_XMM3    xmm3-#define REG_XMM4    xmm4-#define REG_XMM5    xmm5-#define REG_XMM6    xmm6--#define REG_YMM1    ymm1-#define REG_YMM2    ymm2-#define REG_YMM3    ymm3-#define REG_YMM4    ymm4-#define REG_YMM5    ymm5-#define REG_YMM6    ymm6--#define REG_ZMM1    zmm1-#define REG_ZMM2    zmm2-#define REG_ZMM3    zmm3-#define REG_ZMM4    zmm4-#define REG_ZMM5    zmm5-#define REG_ZMM6    zmm6--#if !defined(mingw32_HOST_OS)-#define CALLER_SAVES_R3-#define CALLER_SAVES_R4-#endif-#define CALLER_SAVES_R5-#define CALLER_SAVES_R6--#define CALLER_SAVES_F1-#define CALLER_SAVES_F2-#define CALLER_SAVES_F3-#define CALLER_SAVES_F4-#define CALLER_SAVES_F5-#if !defined(mingw32_HOST_OS)-#define CALLER_SAVES_F6-#endif--#define CALLER_SAVES_D1-#define CALLER_SAVES_D2-#define CALLER_SAVES_D3-#define CALLER_SAVES_D4-#define CALLER_SAVES_D5-#if !defined(mingw32_HOST_OS)-#define CALLER_SAVES_D6-#endif--#define CALLER_SAVES_XMM1-#define CALLER_SAVES_XMM2-#define CALLER_SAVES_XMM3-#define CALLER_SAVES_XMM4-#define CALLER_SAVES_XMM5-#if !defined(mingw32_HOST_OS)-#define CALLER_SAVES_XMM6-#endif--#define CALLER_SAVES_YMM1-#define CALLER_SAVES_YMM2-#define CALLER_SAVES_YMM3-#define CALLER_SAVES_YMM4-#define CALLER_SAVES_YMM5-#if !defined(mingw32_HOST_OS)-#define CALLER_SAVES_YMM6-#endif--#define CALLER_SAVES_ZMM1-#define CALLER_SAVES_ZMM2-#define CALLER_SAVES_ZMM3-#define CALLER_SAVES_ZMM4-#define CALLER_SAVES_ZMM5-#if !defined(mingw32_HOST_OS)-#define CALLER_SAVES_ZMM6-#endif--#define MAX_REAL_VANILLA_REG 6-#define MAX_REAL_FLOAT_REG   6-#define MAX_REAL_DOUBLE_REG  6-#define MAX_REAL_LONG_REG    0-#define MAX_REAL_XMM_REG     6-#define MAX_REAL_YMM_REG     6-#define MAX_REAL_ZMM_REG     6--/* ------------------------------------------------------------------------------   The PowerPC register mapping--   0            system glue?    (caller-save, volatile)-   1            SP              (callee-save, non-volatile)-   2            AIX, powerpc64-linux:-                    RTOC        (a strange special case)-                powerpc32-linux:-                                reserved for use by system--   3-10         args/return     (caller-save, volatile)-   11,12        system glue?    (caller-save, volatile)-   13           on 64-bit:      reserved for thread state pointer-                on 32-bit:      (callee-save, non-volatile)-   14-31                        (callee-save, non-volatile)--   f0                           (caller-save, volatile)-   f1-f13       args/return     (caller-save, volatile)-   f14-f31                      (callee-save, non-volatile)--   \tr{14}--\tr{31} are wonderful callee-save registers on all ppc OSes.-   \tr{0}--\tr{12} are caller-save registers.--   \tr{%f14}--\tr{%f31} are callee-save floating-point registers.+/* Define STG <-> machine register mappings. */+#if defined(MACHREGS_i386) || defined(MACHREGS_x86_64) -   We can do the Whole Business with callee-save registers only!-   -------------------------------------------------------------------------- */+#include "MachRegs/x86.h"  #elif defined(MACHREGS_powerpc) -#define REG(x) __asm__(#x)--#define REG_R1          r14-#define REG_R2          r15-#define REG_R3          r16-#define REG_R4          r17-#define REG_R5          r18-#define REG_R6          r19-#define REG_R7          r20-#define REG_R8          r21-#define REG_R9          r22-#define REG_R10         r23--#define REG_F1          fr14-#define REG_F2          fr15-#define REG_F3          fr16-#define REG_F4          fr17-#define REG_F5          fr18-#define REG_F6          fr19--#define REG_D1          fr20-#define REG_D2          fr21-#define REG_D3          fr22-#define REG_D4          fr23-#define REG_D5          fr24-#define REG_D6          fr25--#define REG_Sp          r24-#define REG_SpLim       r25-#define REG_Hp          r26-#define REG_Base        r27--#define MAX_REAL_FLOAT_REG   6-#define MAX_REAL_DOUBLE_REG  6--/* ------------------------------------------------------------------------------   The ARM EABI register mapping--   Here we consider ARM mode (i.e. 32bit isns)-   and also CPU with full VFPv3 implementation--   ARM registers (see Chapter 5.1 in ARM IHI 0042D and-   Section 9.2.2 in ARM Software Development Toolkit Reference Guide)--   r15  PC         The Program Counter.-   r14  LR         The Link Register.-   r13  SP         The Stack Pointer.-   r12  IP         The Intra-Procedure-call scratch register.-   r11  v8/fp      Variable-register 8.-   r10  v7/sl      Variable-register 7.-   r9   v6/SB/TR   Platform register. The meaning of this register is-                   defined by the platform standard.-   r8   v5         Variable-register 5.-   r7   v4         Variable register 4.-   r6   v3         Variable register 3.-   r5   v2         Variable register 2.-   r4   v1         Variable register 1.-   r3   a4         Argument / scratch register 4.-   r2   a3         Argument / scratch register 3.-   r1   a2         Argument / result / scratch register 2.-   r0   a1         Argument / result / scratch register 1.--   VFPv2/VFPv3/NEON registers-   s0-s15/d0-d7/q0-q3    Argument / result/ scratch registers-   s16-s31/d8-d15/q4-q7  callee-saved registers (must be preserved across-                         subroutine calls)--   VFPv3/NEON registers (added to the VFPv2 registers set)-   d16-d31/q8-q15        Argument / result/ scratch registers-   ----------------------------------------------------------------------------- */+#include "MachRegs/ppc.h"  #elif defined(MACHREGS_arm) -#define REG(x) __asm__(#x)--#define REG_Base        r4-#define REG_Sp          r5-#define REG_Hp          r6-#define REG_R1          r7-#define REG_R2          r8-#define REG_R3          r9-#define REG_R4          r10-#define REG_SpLim       r11--#if !defined(arm_HOST_ARCH_PRE_ARMv6)-/* d8 */-#define REG_F1    s16-#define REG_F2    s17-/* d9 */-#define REG_F3    s18-#define REG_F4    s19--#define REG_D1    d10-#define REG_D2    d11-#endif--/* ------------------------------------------------------------------------------   The ARMv8/AArch64 ABI register mapping--   The AArch64 provides 31 64-bit general purpose registers-   and 32 128-bit SIMD/floating point registers.--   General purpose registers (see Chapter 5.1.1 in ARM IHI 0055B)--   Register | Special | Role in the procedure call standard-   ---------+---------+-------------------------------------     SP     |         | The Stack Pointer-     r30    |  LR     | The Link Register-     r29    |  FP     | The Frame Pointer-   r19-r28  |         | Callee-saved registers-     r18    |         | The Platform Register, if needed;-            |         | or temporary register-     r17    |  IP1    | The second intra-procedure-call temporary register-     r16    |  IP0    | The first intra-procedure-call scratch register-    r9-r15  |         | Temporary registers-     r8     |         | Indirect result location register-    r0-r7   |         | Parameter/result registers---   FPU/SIMD registers--   s/d/q/v0-v7    Argument / result/ scratch registers-   s/d/q/v8-v15   callee-saved registers (must be preserved across subroutine calls,-                  but only bottom 64-bit value needs to be preserved)-   s/d/q/v16-v31  temporary registers--   ----------------------------------------------------------------------------- */+#include "MachRegs/arm32.h"  #elif defined(MACHREGS_aarch64) -#define REG(x) __asm__(#x)--#define REG_Base        r19-#define REG_Sp          r20-#define REG_Hp          r21-#define REG_R1          r22-#define REG_R2          r23-#define REG_R3          r24-#define REG_R4          r25-#define REG_R5          r26-#define REG_R6          r27-#define REG_SpLim       r28--#define REG_F1          s8-#define REG_F2          s9-#define REG_F3          s10-#define REG_F4          s11--#define REG_D1          d12-#define REG_D2          d13-#define REG_D3          d14-#define REG_D4          d15--#define REG_XMM1        q4-#define REG_XMM2        q5--#define CALLER_SAVES_XMM1-#define CALLER_SAVES_XMM2--/* ------------------------------------------------------------------------------   The s390x register mapping--   Register    | Role(s)                                 | Call effect-   ------------+-------------------------------------+------------------   r0,r1       | -                                       | caller-saved-   r2          | Argument / return value                 | caller-saved-   r3,r4,r5    | Arguments                               | caller-saved-   r6          | Argument                                | callee-saved-   r7...r11    | -                                       | callee-saved-   r12         | (Commonly used as GOT pointer)          | callee-saved-   r13         | (Commonly used as literal pool pointer) | callee-saved-   r14         | Return address                          | caller-saved-   r15         | Stack pointer                           | callee-saved-   f0          | Argument / return value                 | caller-saved-   f2,f4,f6    | Arguments                               | caller-saved-   f1,f3,f5,f7 | -                                       | caller-saved-   f8...f15    | -                                       | callee-saved-   v0...v31    | -                                       | caller-saved--   Each general purpose register r0 through r15 as well as each floating-point-   register f0 through f15 is 64 bits wide. Each vector register v0 through v31-   is 128 bits wide.--   Note, the vector registers v0 through v15 overlap with the floating-point-   registers f0 through f15.--   -------------------------------------------------------------------------- */+#include "MachRegs/arm64.h"  #elif defined(MACHREGS_s390x) -#define REG(x) __asm__("%" #x)--#define REG_Base        r7-#define REG_Sp          r8-#define REG_Hp          r10-#define REG_R1          r11-#define REG_R2          r12-#define REG_R3          r13-#define REG_R4          r6-#define REG_R5          r2-#define REG_R6          r3-#define REG_R7          r4-#define REG_R8          r5-#define REG_SpLim       r9-#define REG_MachSp      r15--#define REG_F1          f8-#define REG_F2          f9-#define REG_F3          f10-#define REG_F4          f11-#define REG_F5          f0-#define REG_F6          f1--#define REG_D1          f12-#define REG_D2          f13-#define REG_D3          f14-#define REG_D4          f15-#define REG_D5          f2-#define REG_D6          f3--#define CALLER_SAVES_R5-#define CALLER_SAVES_R6-#define CALLER_SAVES_R7-#define CALLER_SAVES_R8--#define CALLER_SAVES_F5-#define CALLER_SAVES_F6--#define CALLER_SAVES_D5-#define CALLER_SAVES_D6--/* ------------------------------------------------------------------------------   The riscv64 register mapping--   Register    | Role(s)                                 | Call effect-   ------------+-----------------------------------------+--------------   zero        | Hard-wired zero                         | --   ra          | Return address                          | caller-saved-   sp          | Stack pointer                           | callee-saved-   gp          | Global pointer                          | callee-saved-   tp          | Thread pointer                          | callee-saved-   t0,t1,t2    | -                                       | caller-saved-   s0          | Frame pointer                           | callee-saved-   s1          | -                                       | callee-saved-   a0,a1       | Arguments / return values               | caller-saved-   a2..a7      | Arguments                               | caller-saved-   s2..s11     | -                                       | callee-saved-   t3..t6      | -                                       | caller-saved-   ft0..ft7    | -                                       | caller-saved-   fs0,fs1     | -                                       | callee-saved-   fa0,fa1     | Arguments / return values               | caller-saved-   fa2..fa7    | Arguments                               | caller-saved-   fs2..fs11   | -                                       | callee-saved-   ft8..ft11   | -                                       | caller-saved--   Each general purpose register as well as each floating-point-   register is 64 bits wide.--   -------------------------------------------------------------------------- */+#include "MachRegs/s390x.h"  #elif defined(MACHREGS_riscv64) -#define REG(x) __asm__(#x)--#define REG_Base        s1-#define REG_Sp          s2-#define REG_Hp          s3-#define REG_R1          s4-#define REG_R2          s5-#define REG_R3          s6-#define REG_R4          s7-#define REG_R5          s8-#define REG_R6          s9-#define REG_R7          s10-#define REG_SpLim       s11--#define REG_F1          fs0-#define REG_F2          fs1-#define REG_F3          fs2-#define REG_F4          fs3-#define REG_F5          fs4-#define REG_F6          fs5--#define REG_D1          fs6-#define REG_D2          fs7-#define REG_D3          fs8-#define REG_D4          fs9-#define REG_D5          fs10-#define REG_D6          fs11--#define MAX_REAL_FLOAT_REG   6-#define MAX_REAL_DOUBLE_REG  6+#include "MachRegs/riscv64.h"  #elif defined(MACHREGS_wasm32) -#define REG_Base           0--#define REG_R1             1-#define REG_R2             2-#define REG_R3             3-#define REG_R4             4-#define REG_R5             5-#define REG_R6             6-#define REG_R7             7-#define REG_R8             8-#define REG_R9             9-#define REG_R10            10--#define REG_F1             11-#define REG_F2             12-#define REG_F3             13-#define REG_F4             14-#define REG_F5             15-#define REG_F6             16--#define REG_D1             17-#define REG_D2             18-#define REG_D3             19-#define REG_D4             20-#define REG_D5             21-#define REG_D6             22--#define REG_L1             23--#define REG_Sp             24-#define REG_SpLim          25-#define REG_Hp             26-#define REG_HpLim          27--/* ------------------------------------------------------------------------------   The loongarch64 register mapping--   Register    | Role(s)                                 | Call effect-   ------------+-----------------------------------------+--------------   zero        | Hard-wired zero                         | --   ra          | Return address                          | caller-saved-   tp          | Thread pointer                          | --   sp          | Stack pointer                           | callee-saved-   a0,a1       | Arguments / return values               | caller-saved-   a2..a7      | Arguments                               | caller-saved-   t0..t8      | -                                       | caller-saved-   u0          | Reserve                                 | --   fp          | Frame pointer                           | callee-saved-   s0..s8      | -                                       | callee-saved-   fa0,fa1     | Arguments / return values               | caller-saved-   fa2..fa7    | Arguments                               | caller-saved-   ft0..ft15   | -                                       | caller-saved-   fs0..fs7    | -                                       | callee-saved--   Each general purpose register as well as each floating-point-   register is 64 bits wide, also, the u0 register is called r21 in some cases.+#include "MachRegs/wasm32.h" -   -------------------------------------------------------------------------- */ #elif defined(MACHREGS_loongarch64) -#define REG(x) __asm__("$" #x)--#define REG_Base        s0-#define REG_Sp          s1-#define REG_Hp          s2-#define REG_R1          s3-#define REG_R2          s4-#define REG_R3          s5-#define REG_R4          s6-#define REG_R5          s7-#define REG_SpLim       s8--#define REG_F1          fs0-#define REG_F2          fs1-#define REG_F3          fs2-#define REG_F4          fs3--#define REG_D1          fs4-#define REG_D2          fs5-#define REG_D3          fs6-#define REG_D4          fs7--#define MAX_REAL_FLOAT_REG   4-#define MAX_REAL_DOUBLE_REG  4+#include "MachRegs/loongarch64.h"  #else 
− compiler/ghc-llvm-version.h
@@ -1,11 +0,0 @@-/* compiler/ghc-llvm-version.h.  Generated from ghc-llvm-version.h.in by configure.  */-#if !defined(__GHC_LLVM_VERSION_H__)-#define __GHC_LLVM_VERSION_H__--/* The maximum supported LLVM version number */-#define sUPPORTED_LLVM_VERSION_MAX (16)--/* The minimum supported LLVM version number */-#define sUPPORTED_LLVM_VERSION_MIN (11)--#endif /* __GHC_LLVM_VERSION_H__ */
ghc-lib.cabal view
@@ -1,7 +1,7 @@ cabal-version: 3.0 build-type: Simple name: ghc-lib-version: 9.8.5.20250214+version: 9.10.1.20240511 license: BSD-3-Clause license-file: LICENSE category: Development@@ -20,12 +20,11 @@     ghc-lib/stage0/rts/build/include/ghcautoconf.h     ghc-lib/stage0/rts/build/include/ghcplatform.h     ghc-lib/stage0/rts/build/include/GhclibDerivedConstants.h-    ghc-lib/stage0/compiler/build/primop-can-fail.hs-incl     ghc-lib/stage0/compiler/build/primop-code-size.hs-incl     ghc-lib/stage0/compiler/build/primop-commutable.hs-incl     ghc-lib/stage0/compiler/build/primop-data-decl.hs-incl     ghc-lib/stage0/compiler/build/primop-fixity.hs-incl-    ghc-lib/stage0/compiler/build/primop-has-side-effects.hs-incl+    ghc-lib/stage0/compiler/build/primop-effects.hs-incl     ghc-lib/stage0/compiler/build/primop-list.hs-incl     ghc-lib/stage0/compiler/build/primop-out-of-line.hs-incl     ghc-lib/stage0/compiler/build/primop-primop-info.hs-incl@@ -36,9 +35,18 @@     ghc-lib/stage0/compiler/build/primop-vector-tys.hs-incl     ghc-lib/stage0/compiler/build/primop-vector-uniques.hs-incl     ghc-lib/stage0/compiler/build/primop-docs.hs-incl+    ghc-lib/stage0/compiler/build/primop-is-work-free.hs-incl+    ghc-lib/stage0/compiler/build/primop-is-cheap.hs-incl     ghc-lib/stage0/compiler/build/GHC/Platform/Constants.hs+    rts/include/stg/MachRegs/arm32.h+    rts/include/stg/MachRegs/arm64.h+    rts/include/stg/MachRegs/loongarch64.h+    rts/include/stg/MachRegs/ppc.h+    rts/include/stg/MachRegs/riscv64.h+    rts/include/stg/MachRegs/s390x.h+    rts/include/stg/MachRegs/wasm32.h+    rts/include/stg/MachRegs/x86.h     libraries/containers/containers/include/containers.h-    compiler/ghc-llvm-version.h     rts/include/ghcconfig.h     compiler/MachRegs.h     compiler/CodeGen.Platform.h@@ -54,16 +62,16 @@     manual: True     description: Pass -DTHREADED_RTS to the C toolchain library-    default-language: Haskell2010+    default-language:   GHC2021     exposed: False     include-dirs:         rts/include+        rts/include/stg         ghc-lib/stage0/lib         ghc-lib/stage0/compiler/build         compiler         libraries/containers/containers/include-    if impl(ghc >= 8.8.1)-        ghc-options: -fno-safe-haskell+    ghc-options: -fno-safe-haskell     if flag(threaded-rts)         ghc-options: -fobject-code -package=ghc-boot-th -optc-DTHREADED_RTS         cc-options: -DTHREADED_RTS@@ -76,11 +84,11 @@     else         build-depends: Win32     build-depends:-        base >= 4.17 && < 4.20,+        base >= 4.18 && < 4.21,         ghc-prim > 0.2 && < 0.12,         containers >= 0.6.2.1 && < 0.8,         bytestring >= 0.11.4 && < 0.13,-        time >= 1.4 && < 1.15,+        time >= 1.4 && < 1.13,         filepath >= 1 && < 1.6,         exceptions == 0.10.*,         parsec,@@ -95,8 +103,8 @@         semaphore-compat,         rts,         hpc >= 0.6 && < 0.8,-        ghc-lib-parser == 9.8.5.20250214-    build-tool-depends: alex:alex >= 3.1, happy:happy == 1.20.* || == 2.0.2 || >= 2.1.2 && < 2.2+        ghc-lib-parser == 9.10.1.20240511+    build-tool-depends: alex:alex >= 3.1, happy:happy > 1.20     other-extensions:         BangPatterns         CPP@@ -131,16 +139,12 @@         UnboxedTuples         UndecidableInstances     default-extensions:-        BangPatterns         ImplicitPrelude         MonoLocalBinds         NoImplicitPrelude-        ScopedTypeVariables-        TypeOperators     hs-source-dirs:         ghc-lib/stage0/libraries/ghc-boot/build         ghc-lib/stage0/compiler/build-        libraries/ghci         compiler     autogen-modules:         Paths_ghc_lib@@ -157,7 +161,6 @@         GHC.Cmm.BlockId,         GHC.Cmm.CLabel,         GHC.Cmm.Dataflow.Block,-        GHC.Cmm.Dataflow.Collections,         GHC.Cmm.Dataflow.Graph,         GHC.Cmm.Dataflow.Label,         GHC.Cmm.Expr,@@ -168,6 +171,7 @@         GHC.Cmm.Type,         GHC.CmmToAsm.CFG.Weight,         GHC.CmmToLlvm.Config,+        GHC.CmmToLlvm.Version.Type,         GHC.Core,         GHC.Core.Class,         GHC.Core.Coercion,@@ -327,14 +331,17 @@         GHC.Iface.Recomp.Binary,         GHC.Iface.Syntax,         GHC.Iface.Type,+        GHC.JS.Ident,+        GHC.JS.JStg.Monad,+        GHC.JS.JStg.Syntax,         GHC.JS.Make,         GHC.JS.Ppr,         GHC.JS.Syntax,         GHC.JS.Transform,-        GHC.JS.Unsat.Syntax,         GHC.LanguageExtensions,         GHC.LanguageExtensions.Type,         GHC.Lexeme,+        GHC.Linker.Config,         GHC.Linker.Static.Utils,         GHC.Linker.Types,         GHC.Parser,@@ -522,15 +529,16 @@         GHC.Utils.Trace,         GHC.Utils.Word64,         GHC.Version,+        GHCi.BinaryArray,         GHCi.BreakArray,         GHCi.FFI,         GHCi.Message,         GHCi.RemoteTypes,+        GHCi.ResolvedBCO,         GHCi.TH.Binary,         Language.Haskell.Syntax,         Language.Haskell.Syntax.Basic,         Language.Haskell.Syntax.Binds,-        Language.Haskell.Syntax.Concrete,         Language.Haskell.Syntax.Decls,         Language.Haskell.Syntax.Expr,         Language.Haskell.Syntax.Extension,@@ -565,6 +573,7 @@         GHC.Cmm.Dataflow         GHC.Cmm.DebugBlock         GHC.Cmm.Dominators+        GHC.Cmm.GenericOpt         GHC.Cmm.Graph         GHC.Cmm.Info         GHC.Cmm.Info.Build@@ -655,7 +664,13 @@         GHC.CmmToLlvm.Mangler         GHC.CmmToLlvm.Ppr         GHC.CmmToLlvm.Regs+        GHC.CmmToLlvm.Version+        GHC.CmmToLlvm.Version.Bounds         GHC.Core.LateCC+        GHC.Core.LateCC.OverloadedCalls+        GHC.Core.LateCC.TopLevelBinds+        GHC.Core.LateCC.Types+        GHC.Core.LateCC.Utils         GHC.Core.Opt.CSE         GHC.Core.Opt.CallArity         GHC.Core.Opt.CprAnal@@ -730,6 +745,7 @@         GHC.HsToCore.Foreign.JavaScript         GHC.HsToCore.Foreign.Prim         GHC.HsToCore.Foreign.Utils+        GHC.HsToCore.Foreign.Wasm         GHC.HsToCore.GuardedRHSs         GHC.HsToCore.ListComp         GHC.HsToCore.Match@@ -762,10 +778,12 @@         GHC.Iface.Tidy         GHC.Iface.Tidy.StaticPtrTable         GHC.IfaceToCore+        GHC.JS.Opt.Expr+        GHC.JS.Opt.Simple         GHC.JS.Optimizer-        GHC.Linker.Config         GHC.Linker.Deps         GHC.Linker.Dynamic+        GHC.Linker.External         GHC.Linker.ExtraObj         GHC.Linker.Loader         GHC.Linker.MacOS@@ -871,7 +889,6 @@         GHC.SysTools.Ar         GHC.SysTools.Cpp         GHC.SysTools.Elf-        GHC.SysTools.Info         GHC.SysTools.Process         GHC.SysTools.Tasks         GHC.Tc.Deriv@@ -887,6 +904,7 @@         GHC.Tc.Gen.Arrow         GHC.Tc.Gen.Bind         GHC.Tc.Gen.Default+        GHC.Tc.Gen.Do         GHC.Tc.Gen.Export         GHC.Tc.Gen.Expr         GHC.Tc.Gen.Foreign@@ -933,8 +951,7 @@         GHC.Unit.Finder         GHC.Utils.Asm         GHC.Utils.Monad.Codensity+        GHC.Utils.Touch         GHC.Utils.Unique         GHC.Wasm.ControlFlow         GHC.Wasm.ControlFlow.FromCmm-        GHCi.BinaryArray-        GHCi.ResolvedBCO
ghc-lib/stage0/compiler/build/GHC/Platform/Constants.hs view
@@ -83,6 +83,7 @@       pc_OFFSET_StgEntCounter_link :: {-# UNPACK #-} !Int,       pc_OFFSET_StgEntCounter_entry_count :: {-# UNPACK #-} !Int,       pc_SIZEOF_StgUpdateFrame_NoHdr :: {-# UNPACK #-} !Int,+      pc_SIZEOF_StgOrigThunkInfoFrame_NoHdr :: {-# UNPACK #-} !Int,       pc_SIZEOF_StgMutArrPtrs_NoHdr :: {-# UNPACK #-} !Int,       pc_OFFSET_StgMutArrPtrs_ptrs :: {-# UNPACK #-} !Int,       pc_OFFSET_StgMutArrPtrs_size :: {-# UNPACK #-} !Int,@@ -96,6 +97,7 @@       pc_OFFSET_StgStack_sp :: {-# UNPACK #-} !Int,       pc_OFFSET_StgStack_stack :: {-# UNPACK #-} !Int,       pc_OFFSET_StgUpdateFrame_updatee :: {-# UNPACK #-} !Int,+      pc_OFFSET_StgOrigThunkInfoFrame_info_ptr :: {-# UNPACK #-} !Int,       pc_OFFSET_StgFunInfoExtraFwd_arity :: {-# UNPACK #-} !Int,       pc_REP_StgFunInfoExtraFwd_arity :: {-# UNPACK #-} !Int,       pc_SIZEOF_StgFunInfoExtraRev :: {-# UNPACK #-} !Int,@@ -166,7 +168,7 @@      ,v80,v81,v82,v83,v84,v85,v86,v87,v88,v89,v90,v91,v92,v93,v94,v95      ,v96,v97,v98,v99,v100,v101,v102,v103,v104,v105,v106,v107,v108,v109,v110,v111      ,v112,v113,v114,v115,v116,v117,v118,v119,v120,v121,v122,v123,v124,v125,v126,v127-     ,v128+     ,v128,v129,v130      ] -> PlatformConstants             { pc_CONTROL_GROUP_CONST_291 = fromIntegral v0             , pc_STD_HDR_SIZE = fromIntegral v1@@ -247,56 +249,58 @@             , pc_OFFSET_StgEntCounter_link = fromIntegral v76             , pc_OFFSET_StgEntCounter_entry_count = fromIntegral v77             , pc_SIZEOF_StgUpdateFrame_NoHdr = fromIntegral v78-            , pc_SIZEOF_StgMutArrPtrs_NoHdr = fromIntegral v79-            , pc_OFFSET_StgMutArrPtrs_ptrs = fromIntegral v80-            , pc_OFFSET_StgMutArrPtrs_size = fromIntegral v81-            , pc_SIZEOF_StgSmallMutArrPtrs_NoHdr = fromIntegral v82-            , pc_OFFSET_StgSmallMutArrPtrs_ptrs = fromIntegral v83-            , pc_SIZEOF_StgArrBytes_NoHdr = fromIntegral v84-            , pc_OFFSET_StgArrBytes_bytes = fromIntegral v85-            , pc_OFFSET_StgTSO_alloc_limit = fromIntegral v86-            , pc_OFFSET_StgTSO_cccs = fromIntegral v87-            , pc_OFFSET_StgTSO_stackobj = fromIntegral v88-            , pc_OFFSET_StgStack_sp = fromIntegral v89-            , pc_OFFSET_StgStack_stack = fromIntegral v90-            , pc_OFFSET_StgUpdateFrame_updatee = fromIntegral v91-            , pc_OFFSET_StgFunInfoExtraFwd_arity = fromIntegral v92-            , pc_REP_StgFunInfoExtraFwd_arity = fromIntegral v93-            , pc_SIZEOF_StgFunInfoExtraRev = fromIntegral v94-            , pc_OFFSET_StgFunInfoExtraRev_arity = fromIntegral v95-            , pc_REP_StgFunInfoExtraRev_arity = fromIntegral v96-            , pc_MAX_SPEC_SELECTEE_SIZE = fromIntegral v97-            , pc_MAX_SPEC_AP_SIZE = fromIntegral v98-            , pc_MIN_PAYLOAD_SIZE = fromIntegral v99-            , pc_MIN_INTLIKE = fromIntegral v100-            , pc_MAX_INTLIKE = fromIntegral v101-            , pc_MIN_CHARLIKE = fromIntegral v102-            , pc_MAX_CHARLIKE = fromIntegral v103-            , pc_MUT_ARR_PTRS_CARD_BITS = fromIntegral v104-            , pc_MAX_Vanilla_REG = fromIntegral v105-            , pc_MAX_Float_REG = fromIntegral v106-            , pc_MAX_Double_REG = fromIntegral v107-            , pc_MAX_Long_REG = fromIntegral v108-            , pc_MAX_XMM_REG = fromIntegral v109-            , pc_MAX_Real_Vanilla_REG = fromIntegral v110-            , pc_MAX_Real_Float_REG = fromIntegral v111-            , pc_MAX_Real_Double_REG = fromIntegral v112-            , pc_MAX_Real_XMM_REG = fromIntegral v113-            , pc_MAX_Real_Long_REG = fromIntegral v114-            , pc_RESERVED_C_STACK_BYTES = fromIntegral v115-            , pc_RESERVED_STACK_WORDS = fromIntegral v116-            , pc_AP_STACK_SPLIM = fromIntegral v117-            , pc_WORD_SIZE = fromIntegral v118-            , pc_CINT_SIZE = fromIntegral v119-            , pc_CLONG_SIZE = fromIntegral v120-            , pc_CLONG_LONG_SIZE = fromIntegral v121-            , pc_BITMAP_BITS_SHIFT = fromIntegral v122-            , pc_TAG_BITS = fromIntegral v123-            , pc_LDV_SHIFT = fromIntegral v124-            , pc_ILDV_CREATE_MASK = v125-            , pc_ILDV_STATE_CREATE = v126-            , pc_ILDV_STATE_USE = v127-            , pc_USE_INLINE_SRT_FIELD = 0 < v128+            , pc_SIZEOF_StgOrigThunkInfoFrame_NoHdr = fromIntegral v79+            , pc_SIZEOF_StgMutArrPtrs_NoHdr = fromIntegral v80+            , pc_OFFSET_StgMutArrPtrs_ptrs = fromIntegral v81+            , pc_OFFSET_StgMutArrPtrs_size = fromIntegral v82+            , pc_SIZEOF_StgSmallMutArrPtrs_NoHdr = fromIntegral v83+            , pc_OFFSET_StgSmallMutArrPtrs_ptrs = fromIntegral v84+            , pc_SIZEOF_StgArrBytes_NoHdr = fromIntegral v85+            , pc_OFFSET_StgArrBytes_bytes = fromIntegral v86+            , pc_OFFSET_StgTSO_alloc_limit = fromIntegral v87+            , pc_OFFSET_StgTSO_cccs = fromIntegral v88+            , pc_OFFSET_StgTSO_stackobj = fromIntegral v89+            , pc_OFFSET_StgStack_sp = fromIntegral v90+            , pc_OFFSET_StgStack_stack = fromIntegral v91+            , pc_OFFSET_StgUpdateFrame_updatee = fromIntegral v92+            , pc_OFFSET_StgOrigThunkInfoFrame_info_ptr = fromIntegral v93+            , pc_OFFSET_StgFunInfoExtraFwd_arity = fromIntegral v94+            , pc_REP_StgFunInfoExtraFwd_arity = fromIntegral v95+            , pc_SIZEOF_StgFunInfoExtraRev = fromIntegral v96+            , pc_OFFSET_StgFunInfoExtraRev_arity = fromIntegral v97+            , pc_REP_StgFunInfoExtraRev_arity = fromIntegral v98+            , pc_MAX_SPEC_SELECTEE_SIZE = fromIntegral v99+            , pc_MAX_SPEC_AP_SIZE = fromIntegral v100+            , pc_MIN_PAYLOAD_SIZE = fromIntegral v101+            , pc_MIN_INTLIKE = fromIntegral v102+            , pc_MAX_INTLIKE = fromIntegral v103+            , pc_MIN_CHARLIKE = fromIntegral v104+            , pc_MAX_CHARLIKE = fromIntegral v105+            , pc_MUT_ARR_PTRS_CARD_BITS = fromIntegral v106+            , pc_MAX_Vanilla_REG = fromIntegral v107+            , pc_MAX_Float_REG = fromIntegral v108+            , pc_MAX_Double_REG = fromIntegral v109+            , pc_MAX_Long_REG = fromIntegral v110+            , pc_MAX_XMM_REG = fromIntegral v111+            , pc_MAX_Real_Vanilla_REG = fromIntegral v112+            , pc_MAX_Real_Float_REG = fromIntegral v113+            , pc_MAX_Real_Double_REG = fromIntegral v114+            , pc_MAX_Real_XMM_REG = fromIntegral v115+            , pc_MAX_Real_Long_REG = fromIntegral v116+            , pc_RESERVED_C_STACK_BYTES = fromIntegral v117+            , pc_RESERVED_STACK_WORDS = fromIntegral v118+            , pc_AP_STACK_SPLIM = fromIntegral v119+            , pc_WORD_SIZE = fromIntegral v120+            , pc_CINT_SIZE = fromIntegral v121+            , pc_CLONG_SIZE = fromIntegral v122+            , pc_CLONG_LONG_SIZE = fromIntegral v123+            , pc_BITMAP_BITS_SHIFT = fromIntegral v124+            , pc_TAG_BITS = fromIntegral v125+            , pc_LDV_SHIFT = fromIntegral v126+            , pc_ILDV_CREATE_MASK = v127+            , pc_ILDV_STATE_CREATE = v128+            , pc_ILDV_STATE_USE = v129+            , pc_USE_INLINE_SRT_FIELD = 0 < v130             }     _ -> error "Invalid platform constants" 
− ghc-lib/stage0/compiler/build/primop-can-fail.hs-incl
@@ -1,261 +0,0 @@-primOpCanFail Int8QuotOp = True-primOpCanFail Int8RemOp = True-primOpCanFail Int8QuotRemOp = True-primOpCanFail Word8QuotOp = True-primOpCanFail Word8RemOp = True-primOpCanFail Word8QuotRemOp = True-primOpCanFail Int16QuotOp = True-primOpCanFail Int16RemOp = True-primOpCanFail Int16QuotRemOp = True-primOpCanFail Word16QuotOp = True-primOpCanFail Word16RemOp = True-primOpCanFail Word16QuotRemOp = True-primOpCanFail Int32QuotOp = True-primOpCanFail Int32RemOp = True-primOpCanFail Int32QuotRemOp = True-primOpCanFail Word32QuotOp = True-primOpCanFail Word32RemOp = True-primOpCanFail Word32QuotRemOp = True-primOpCanFail Int64QuotOp = True-primOpCanFail Int64RemOp = True-primOpCanFail Word64QuotOp = True-primOpCanFail Word64RemOp = True-primOpCanFail IntQuotOp = True-primOpCanFail IntRemOp = True-primOpCanFail IntQuotRemOp = True-primOpCanFail WordQuotOp = True-primOpCanFail WordRemOp = True-primOpCanFail WordQuotRemOp = True-primOpCanFail WordQuotRem2Op = True-primOpCanFail DoubleDivOp = True-primOpCanFail DoubleLogOp = True-primOpCanFail DoubleLog1POp = True-primOpCanFail DoubleAsinOp = True-primOpCanFail DoubleAcosOp = True-primOpCanFail FloatDivOp = True-primOpCanFail FloatLogOp = True-primOpCanFail FloatLog1POp = True-primOpCanFail FloatAsinOp = True-primOpCanFail FloatAcosOp = True-primOpCanFail ReadArrayOp = True-primOpCanFail WriteArrayOp = True-primOpCanFail IndexArrayOp = True-primOpCanFail CopyArrayOp = True-primOpCanFail CopyMutableArrayOp = True-primOpCanFail CloneArrayOp = True-primOpCanFail CloneMutableArrayOp = True-primOpCanFail FreezeArrayOp = True-primOpCanFail ThawArrayOp = True-primOpCanFail CasArrayOp = True-primOpCanFail ReadSmallArrayOp = True-primOpCanFail WriteSmallArrayOp = True-primOpCanFail IndexSmallArrayOp = True-primOpCanFail CopySmallArrayOp = True-primOpCanFail CopySmallMutableArrayOp = True-primOpCanFail CloneSmallArrayOp = True-primOpCanFail CloneSmallMutableArrayOp = True-primOpCanFail FreezeSmallArrayOp = True-primOpCanFail ThawSmallArrayOp = True-primOpCanFail CasSmallArrayOp = True-primOpCanFail IndexByteArrayOp_Char = True-primOpCanFail IndexByteArrayOp_WideChar = True-primOpCanFail IndexByteArrayOp_Int = True-primOpCanFail IndexByteArrayOp_Word = True-primOpCanFail IndexByteArrayOp_Addr = True-primOpCanFail IndexByteArrayOp_Float = True-primOpCanFail IndexByteArrayOp_Double = True-primOpCanFail IndexByteArrayOp_StablePtr = True-primOpCanFail IndexByteArrayOp_Int8 = True-primOpCanFail IndexByteArrayOp_Word8 = True-primOpCanFail IndexByteArrayOp_Int16 = True-primOpCanFail IndexByteArrayOp_Word16 = True-primOpCanFail IndexByteArrayOp_Int32 = True-primOpCanFail IndexByteArrayOp_Word32 = True-primOpCanFail IndexByteArrayOp_Int64 = True-primOpCanFail IndexByteArrayOp_Word64 = True-primOpCanFail IndexByteArrayOp_Word8AsChar = True-primOpCanFail IndexByteArrayOp_Word8AsWideChar = True-primOpCanFail IndexByteArrayOp_Word8AsInt = True-primOpCanFail IndexByteArrayOp_Word8AsWord = True-primOpCanFail IndexByteArrayOp_Word8AsAddr = True-primOpCanFail IndexByteArrayOp_Word8AsFloat = True-primOpCanFail IndexByteArrayOp_Word8AsDouble = True-primOpCanFail IndexByteArrayOp_Word8AsStablePtr = True-primOpCanFail IndexByteArrayOp_Word8AsInt16 = True-primOpCanFail IndexByteArrayOp_Word8AsWord16 = True-primOpCanFail IndexByteArrayOp_Word8AsInt32 = True-primOpCanFail IndexByteArrayOp_Word8AsWord32 = True-primOpCanFail IndexByteArrayOp_Word8AsInt64 = True-primOpCanFail IndexByteArrayOp_Word8AsWord64 = True-primOpCanFail ReadByteArrayOp_Char = True-primOpCanFail ReadByteArrayOp_WideChar = True-primOpCanFail ReadByteArrayOp_Int = True-primOpCanFail ReadByteArrayOp_Word = True-primOpCanFail ReadByteArrayOp_Addr = True-primOpCanFail ReadByteArrayOp_Float = True-primOpCanFail ReadByteArrayOp_Double = True-primOpCanFail ReadByteArrayOp_StablePtr = True-primOpCanFail ReadByteArrayOp_Int8 = True-primOpCanFail ReadByteArrayOp_Word8 = True-primOpCanFail ReadByteArrayOp_Int16 = True-primOpCanFail ReadByteArrayOp_Word16 = True-primOpCanFail ReadByteArrayOp_Int32 = True-primOpCanFail ReadByteArrayOp_Word32 = True-primOpCanFail ReadByteArrayOp_Int64 = True-primOpCanFail ReadByteArrayOp_Word64 = True-primOpCanFail ReadByteArrayOp_Word8AsChar = True-primOpCanFail ReadByteArrayOp_Word8AsWideChar = True-primOpCanFail ReadByteArrayOp_Word8AsInt = True-primOpCanFail ReadByteArrayOp_Word8AsWord = True-primOpCanFail ReadByteArrayOp_Word8AsAddr = True-primOpCanFail ReadByteArrayOp_Word8AsFloat = True-primOpCanFail ReadByteArrayOp_Word8AsDouble = True-primOpCanFail ReadByteArrayOp_Word8AsStablePtr = True-primOpCanFail ReadByteArrayOp_Word8AsInt16 = True-primOpCanFail ReadByteArrayOp_Word8AsWord16 = True-primOpCanFail ReadByteArrayOp_Word8AsInt32 = True-primOpCanFail ReadByteArrayOp_Word8AsWord32 = True-primOpCanFail ReadByteArrayOp_Word8AsInt64 = True-primOpCanFail ReadByteArrayOp_Word8AsWord64 = True-primOpCanFail WriteByteArrayOp_Char = True-primOpCanFail WriteByteArrayOp_WideChar = True-primOpCanFail WriteByteArrayOp_Int = True-primOpCanFail WriteByteArrayOp_Word = True-primOpCanFail WriteByteArrayOp_Addr = True-primOpCanFail WriteByteArrayOp_Float = True-primOpCanFail WriteByteArrayOp_Double = True-primOpCanFail WriteByteArrayOp_StablePtr = True-primOpCanFail WriteByteArrayOp_Int8 = True-primOpCanFail WriteByteArrayOp_Word8 = True-primOpCanFail WriteByteArrayOp_Int16 = True-primOpCanFail WriteByteArrayOp_Word16 = True-primOpCanFail WriteByteArrayOp_Int32 = True-primOpCanFail WriteByteArrayOp_Word32 = True-primOpCanFail WriteByteArrayOp_Int64 = True-primOpCanFail WriteByteArrayOp_Word64 = True-primOpCanFail WriteByteArrayOp_Word8AsChar = True-primOpCanFail WriteByteArrayOp_Word8AsWideChar = True-primOpCanFail WriteByteArrayOp_Word8AsInt = True-primOpCanFail WriteByteArrayOp_Word8AsWord = True-primOpCanFail WriteByteArrayOp_Word8AsAddr = True-primOpCanFail WriteByteArrayOp_Word8AsFloat = True-primOpCanFail WriteByteArrayOp_Word8AsDouble = True-primOpCanFail WriteByteArrayOp_Word8AsStablePtr = True-primOpCanFail WriteByteArrayOp_Word8AsInt16 = True-primOpCanFail WriteByteArrayOp_Word8AsWord16 = True-primOpCanFail WriteByteArrayOp_Word8AsInt32 = True-primOpCanFail WriteByteArrayOp_Word8AsWord32 = True-primOpCanFail WriteByteArrayOp_Word8AsInt64 = True-primOpCanFail WriteByteArrayOp_Word8AsWord64 = True-primOpCanFail CompareByteArraysOp = True-primOpCanFail CopyByteArrayOp = True-primOpCanFail CopyMutableByteArrayOp = True-primOpCanFail CopyMutableByteArrayNonOverlappingOp = True-primOpCanFail CopyByteArrayToAddrOp = True-primOpCanFail CopyMutableByteArrayToAddrOp = True-primOpCanFail CopyAddrToByteArrayOp = True-primOpCanFail CopyAddrToAddrOp = True-primOpCanFail CopyAddrToAddrNonOverlappingOp = True-primOpCanFail SetByteArrayOp = True-primOpCanFail SetAddrRangeOp = True-primOpCanFail AtomicReadByteArrayOp_Int = True-primOpCanFail AtomicWriteByteArrayOp_Int = True-primOpCanFail CasByteArrayOp_Int = True-primOpCanFail CasByteArrayOp_Int8 = True-primOpCanFail CasByteArrayOp_Int16 = True-primOpCanFail CasByteArrayOp_Int32 = True-primOpCanFail CasByteArrayOp_Int64 = True-primOpCanFail FetchAddByteArrayOp_Int = True-primOpCanFail FetchSubByteArrayOp_Int = True-primOpCanFail FetchAndByteArrayOp_Int = True-primOpCanFail FetchNandByteArrayOp_Int = True-primOpCanFail FetchOrByteArrayOp_Int = True-primOpCanFail FetchXorByteArrayOp_Int = True-primOpCanFail IndexOffAddrOp_Char = True-primOpCanFail IndexOffAddrOp_WideChar = True-primOpCanFail IndexOffAddrOp_Int = True-primOpCanFail IndexOffAddrOp_Word = True-primOpCanFail IndexOffAddrOp_Addr = True-primOpCanFail IndexOffAddrOp_Float = True-primOpCanFail IndexOffAddrOp_Double = True-primOpCanFail IndexOffAddrOp_StablePtr = True-primOpCanFail IndexOffAddrOp_Int8 = True-primOpCanFail IndexOffAddrOp_Word8 = True-primOpCanFail IndexOffAddrOp_Int16 = True-primOpCanFail IndexOffAddrOp_Word16 = True-primOpCanFail IndexOffAddrOp_Int32 = True-primOpCanFail IndexOffAddrOp_Word32 = True-primOpCanFail IndexOffAddrOp_Int64 = True-primOpCanFail IndexOffAddrOp_Word64 = True-primOpCanFail ReadOffAddrOp_Char = True-primOpCanFail ReadOffAddrOp_WideChar = True-primOpCanFail ReadOffAddrOp_Int = True-primOpCanFail ReadOffAddrOp_Word = True-primOpCanFail ReadOffAddrOp_Addr = True-primOpCanFail ReadOffAddrOp_Float = True-primOpCanFail ReadOffAddrOp_Double = True-primOpCanFail ReadOffAddrOp_StablePtr = True-primOpCanFail ReadOffAddrOp_Int8 = True-primOpCanFail ReadOffAddrOp_Word8 = True-primOpCanFail ReadOffAddrOp_Int16 = True-primOpCanFail ReadOffAddrOp_Word16 = True-primOpCanFail ReadOffAddrOp_Int32 = True-primOpCanFail ReadOffAddrOp_Word32 = True-primOpCanFail ReadOffAddrOp_Int64 = True-primOpCanFail ReadOffAddrOp_Word64 = True-primOpCanFail WriteOffAddrOp_Char = True-primOpCanFail WriteOffAddrOp_WideChar = True-primOpCanFail WriteOffAddrOp_Int = True-primOpCanFail WriteOffAddrOp_Word = True-primOpCanFail WriteOffAddrOp_Addr = True-primOpCanFail WriteOffAddrOp_Float = True-primOpCanFail WriteOffAddrOp_Double = True-primOpCanFail WriteOffAddrOp_StablePtr = True-primOpCanFail WriteOffAddrOp_Int8 = True-primOpCanFail WriteOffAddrOp_Word8 = True-primOpCanFail WriteOffAddrOp_Int16 = True-primOpCanFail WriteOffAddrOp_Word16 = True-primOpCanFail WriteOffAddrOp_Int32 = True-primOpCanFail WriteOffAddrOp_Word32 = True-primOpCanFail WriteOffAddrOp_Int64 = True-primOpCanFail WriteOffAddrOp_Word64 = True-primOpCanFail InterlockedExchange_Addr = True-primOpCanFail InterlockedExchange_Word = True-primOpCanFail CasAddrOp_Addr = True-primOpCanFail CasAddrOp_Word = True-primOpCanFail CasAddrOp_Word8 = True-primOpCanFail CasAddrOp_Word16 = True-primOpCanFail CasAddrOp_Word32 = True-primOpCanFail CasAddrOp_Word64 = True-primOpCanFail FetchAddAddrOp_Word = True-primOpCanFail FetchSubAddrOp_Word = True-primOpCanFail FetchAndAddrOp_Word = True-primOpCanFail FetchNandAddrOp_Word = True-primOpCanFail FetchOrAddrOp_Word = True-primOpCanFail FetchXorAddrOp_Word = True-primOpCanFail AtomicReadAddrOp_Word = True-primOpCanFail AtomicWriteAddrOp_Word = True-primOpCanFail AtomicModifyMutVar2Op = True-primOpCanFail AtomicModifyMutVar_Op = True-primOpCanFail RaiseOp = True-primOpCanFail RaiseUnderflowOp = True-primOpCanFail RaiseOverflowOp = True-primOpCanFail RaiseDivZeroOp = True-primOpCanFail ReallyUnsafePtrEqualityOp = True-primOpCanFail (VecInsertOp _ _ _) = True-primOpCanFail (VecDivOp _ _ _) = True-primOpCanFail (VecQuotOp _ _ _) = True-primOpCanFail (VecRemOp _ _ _) = True-primOpCanFail (VecIndexByteArrayOp _ _ _) = True-primOpCanFail (VecReadByteArrayOp _ _ _) = True-primOpCanFail (VecWriteByteArrayOp _ _ _) = True-primOpCanFail (VecIndexOffAddrOp _ _ _) = True-primOpCanFail (VecReadOffAddrOp _ _ _) = True-primOpCanFail (VecWriteOffAddrOp _ _ _) = True-primOpCanFail (VecIndexScalarByteArrayOp _ _ _) = True-primOpCanFail (VecReadScalarByteArrayOp _ _ _) = True-primOpCanFail (VecWriteScalarByteArrayOp _ _ _) = True-primOpCanFail (VecIndexScalarOffAddrOp _ _ _) = True-primOpCanFail (VecReadScalarOffAddrOp _ _ _) = True-primOpCanFail (VecWriteScalarOffAddrOp _ _ _) = True-primOpCanFail _ = False
ghc-lib/stage0/compiler/build/primop-code-size.hs-incl view
@@ -52,6 +52,8 @@ primOpCodeSize FloatAtanhOp =  primOpCodeSizeForeignCall  primOpCodeSize FloatPowerOp =  primOpCodeSizeForeignCall  primOpCodeSize WriteArrayOp = 2+primOpCodeSize UnsafeFreezeByteArrayOp = 0+primOpCodeSize UnsafeThawByteArrayOp = 0 primOpCodeSize CopyByteArrayOp =  primOpCodeSizeForeignCall + 4 primOpCodeSize CopyMutableByteArrayOp =  primOpCodeSizeForeignCall + 4  primOpCodeSize CopyMutableByteArrayNonOverlappingOp =  primOpCodeSizeForeignCall + 4 @@ -68,9 +70,9 @@ primOpCodeSize RaiseUnderflowOp =  primOpCodeSizeForeignCall  primOpCodeSize RaiseOverflowOp =  primOpCodeSizeForeignCall  primOpCodeSize RaiseDivZeroOp =  primOpCodeSizeForeignCall -primOpCodeSize TouchOp =  0 +primOpCodeSize TouchOp = 0 primOpCodeSize ParOp =  primOpCodeSizeForeignCall  primOpCodeSize SparkOp =  primOpCodeSizeForeignCall  primOpCodeSize AddrToAnyOp = 0 primOpCodeSize AnyToAddrOp = 0-primOpCodeSize _ =  primOpCodeSizeDefault +primOpCodeSize _thisOp =  primOpCodeSizeDefault 
ghc-lib/stage0/compiler/build/primop-commutable.hs-incl view
@@ -55,4 +55,4 @@ commutableOp FloatMulOp = True commutableOp (VecAddOp _ _ _) = True commutableOp (VecMulOp _ _ _) = True-commutableOp _ = False+commutableOp _thisOp = False
ghc-lib/stage0/compiler/build/primop-data-decl.hs-incl view
@@ -292,6 +292,8 @@    | DoublePowerOp    | DoubleDecode_2IntOp    | DoubleDecode_Int64Op+   | CastDoubleToWord64Op+   | CastWord64ToDoubleOp    | FloatGtOp    | FloatGeOp    | FloatEqOp@@ -325,6 +327,8 @@    | FloatPowerOp    | FloatToDoubleOp    | FloatDecode_IntOp+   | CastFloatToWord32Op+   | CastWord32ToFloatOp    | FloatFMAdd    | FloatFMSub    | FloatFNMAdd@@ -375,6 +379,7 @@    | ShrinkMutableByteArrayOp_Char    | ResizeMutableByteArrayOp_Char    | UnsafeFreezeByteArrayOp+   | UnsafeThawByteArrayOp    | SizeofByteArrayOp    | SizeofMutableByteArrayOp    | GetSizeofMutableByteArrayOp@@ -519,6 +524,20 @@    | IndexOffAddrOp_Word32    | IndexOffAddrOp_Int64    | IndexOffAddrOp_Word64+   | IndexOffAddrOp_Word8AsChar+   | IndexOffAddrOp_Word8AsWideChar+   | IndexOffAddrOp_Word8AsInt+   | IndexOffAddrOp_Word8AsWord+   | IndexOffAddrOp_Word8AsAddr+   | IndexOffAddrOp_Word8AsFloat+   | IndexOffAddrOp_Word8AsDouble+   | IndexOffAddrOp_Word8AsStablePtr+   | IndexOffAddrOp_Word8AsInt16+   | IndexOffAddrOp_Word8AsWord16+   | IndexOffAddrOp_Word8AsInt32+   | IndexOffAddrOp_Word8AsWord32+   | IndexOffAddrOp_Word8AsInt64+   | IndexOffAddrOp_Word8AsWord64    | ReadOffAddrOp_Char    | ReadOffAddrOp_WideChar    | ReadOffAddrOp_Int@@ -535,6 +554,20 @@    | ReadOffAddrOp_Word32    | ReadOffAddrOp_Int64    | ReadOffAddrOp_Word64+   | ReadOffAddrOp_Word8AsChar+   | ReadOffAddrOp_Word8AsWideChar+   | ReadOffAddrOp_Word8AsInt+   | ReadOffAddrOp_Word8AsWord+   | ReadOffAddrOp_Word8AsAddr+   | ReadOffAddrOp_Word8AsFloat+   | ReadOffAddrOp_Word8AsDouble+   | ReadOffAddrOp_Word8AsStablePtr+   | ReadOffAddrOp_Word8AsInt16+   | ReadOffAddrOp_Word8AsWord16+   | ReadOffAddrOp_Word8AsInt32+   | ReadOffAddrOp_Word8AsWord32+   | ReadOffAddrOp_Word8AsInt64+   | ReadOffAddrOp_Word8AsWord64    | WriteOffAddrOp_Char    | WriteOffAddrOp_WideChar    | WriteOffAddrOp_Int@@ -551,6 +584,20 @@    | WriteOffAddrOp_Word32    | WriteOffAddrOp_Int64    | WriteOffAddrOp_Word64+   | WriteOffAddrOp_Word8AsChar+   | WriteOffAddrOp_Word8AsWideChar+   | WriteOffAddrOp_Word8AsInt+   | WriteOffAddrOp_Word8AsWord+   | WriteOffAddrOp_Word8AsAddr+   | WriteOffAddrOp_Word8AsFloat+   | WriteOffAddrOp_Word8AsDouble+   | WriteOffAddrOp_Word8AsStablePtr+   | WriteOffAddrOp_Word8AsInt16+   | WriteOffAddrOp_Word8AsWord16+   | WriteOffAddrOp_Word8AsInt32+   | WriteOffAddrOp_Word8AsWord32+   | WriteOffAddrOp_Word8AsInt64+   | WriteOffAddrOp_Word8AsWord64    | InterlockedExchange_Addr    | InterlockedExchange_Word    | CasAddrOp_Addr@@ -649,7 +696,8 @@    | GetSparkOp    | NumSparks    | KeepAliveOp-   | DataToTagOp+   | DataToTagSmallOp+   | DataToTagLargeOp    | TagToEnumOp    | AddrToAnyOp    | AnyToAddrOp
ghc-lib/stage0/compiler/build/primop-docs.hs-incl view
@@ -63,8 +63,12 @@   , ("**##","Exponentiation.")   , ("decodeDouble_2Int#","Convert to integer.\n    First component of the result is -1 or 1, indicating the sign of the\n    mantissa. The next two are the high and low 32 bits of the mantissa\n    respectively, and the last is the exponent.")   , ("decodeDouble_Int64#","Decode 'Double#' into mantissa and base-2 exponent.")+  , ("castDoubleToWord64#","Bitcast a 'Double#' into a 'Word64#'")+  , ("castWord64ToDouble#","Bitcast a 'Word64#' into a 'Double#'")   , ("float2Int#","Truncates a 'Float#' value to the nearest 'Int#'.\n    Results are undefined if the truncation if truncation yields\n    a value outside the range of 'Int#'.")   , ("decodeFloat_Int#","Convert to integers.\n    First 'Int#' in result is the mantissa; second is the exponent.")+  , ("castFloatToWord32#","Bitcast a 'Float#' into a 'Word32#'")+  , ("castWord32ToFloat#","Bitcast a 'Word32#' into a 'Float#'")   , ("fmaddFloat#","Fused multiply-add operation @x*y+z@. See \"GHC.Prim#fma\".")   , ("fmsubFloat#","Fused multiply-subtract operation @x*y-z@. See \"GHC.Prim#fma\".")   , ("fnmaddFloat#","Fused negate-multiply-add operation @-x*y+z@. See \"GHC.Prim#fma\".")@@ -117,6 +121,7 @@   , ("shrinkMutableByteArray#","Shrink mutable byte array to new specified size (in bytes), in\n    the specified state thread. The new size argument must be less than or\n    equal to the current size as reported by 'getSizeofMutableByteArray#'.\n\n    Assuming the non-profiling RTS, this primitive compiles to an O(1)\n    operation in C--, modifying the array in-place. Backends bypassing C--\n    representation (such as JavaScript) might behave differently.\n\n    @since 0.4.0.0")   , ("resizeMutableByteArray#","Resize mutable byte array to new specified size (in bytes), shrinking or growing it.\n    The returned 'MutableByteArray#' is either the original\n    'MutableByteArray#' resized in-place or, if not possible, a newly\n    allocated (unpinned) 'MutableByteArray#' (with the original content\n    copied over).\n\n    To avoid undefined behaviour, the original 'MutableByteArray#' shall\n    not be accessed anymore after a 'resizeMutableByteArray#' has been\n    performed.  Moreover, no reference to the old one should be kept in order\n    to allow garbage collection of the original 'MutableByteArray#' in\n    case a new 'MutableByteArray#' had to be allocated.\n\n    @since 0.4.0.0")   , ("unsafeFreezeByteArray#","Make a mutable byte array immutable, without copying.")+  , ("unsafeThawByteArray#","Make an immutable byte array mutable, without copying.\n\n    @since 0.12.0.0")   , ("sizeofByteArray#","Return the size of the array in bytes.")   , ("sizeofMutableByteArray#","Return the size of the array in bytes. __Deprecated__, it is\n   unsafe in the presence of 'shrinkMutableByteArray#' and 'resizeMutableByteArray#'\n   operations on the same mutable byte\n   array.")   , ("getSizeofMutableByteArray#","Return the number of elements in the array, correctly accounting for\n   the effect of 'shrinkMutableByteArray#' and 'resizeMutableByteArray#'.\n\n   @since 0.5.0.0")@@ -210,7 +215,7 @@   , ("writeWord8ArrayAsWord32#","Write a 32-bit unsigned integer; offset in bytes.")   , ("writeWord8ArrayAsInt64#","Write a 64-bit signed integer; offset in bytes.")   , ("writeWord8ArrayAsWord64#","Write a 64-bit unsigned integer; offset in bytes.")-  , ("compareByteArrays#","@'compareByteArrays#' src1 src1_ofs src2 src2_ofs n@ compares\n    @n@ bytes starting at offset @src1_ofs@ in the first\n    'ByteArray#' @src1@ to the range of @n@ bytes\n    (i.e. same length) starting at offset @src2_ofs@ of the second\n    'ByteArray#' @src2@.  Both arrays must fully contain the\n    specified ranges, but this is not checked.  Returns an 'Int#'\n    less than, equal to, or greater than zero if the range is found,\n    respectively, to be byte-wise lexicographically less than, to\n    match, or be greater than the second range.")+  , ("compareByteArrays#","@'compareByteArrays#' src1 src1_ofs src2 src2_ofs n@ compares\n    @n@ bytes starting at offset @src1_ofs@ in the first\n    'ByteArray#' @src1@ to the range of @n@ bytes\n    (i.e. same length) starting at offset @src2_ofs@ of the second\n    'ByteArray#' @src2@.  Both arrays must fully contain the\n    specified ranges, but this is not checked.  Returns an 'Int#'\n    less than, equal to, or greater than zero if the range is found,\n    respectively, to be byte-wise lexicographically less than, to\n    match, or be greater than the second range.\n\n    @since 0.5.2.0")   , ("copyByteArray#"," @'copyByteArray#' src src_ofs dst dst_ofs len@ copies the range\n    starting at offset @src_ofs@ of length @len@ from the\n    'ByteArray#' @src@ to the 'MutableByteArray#' @dst@\n    starting at offset @dst_ofs@.  Both arrays must fully contain\n    the specified ranges, but this is not checked.  The two arrays must\n    not be the same array in different states, but this is not checked\n    either.\n  ")   , ("copyMutableByteArray#"," @'copyMutableByteArray#' src src_ofs dst dst_ofs len@ copies the\n    range starting at offset @src_ofs@ of length @len@ from the\n    'MutableByteArray#' @src@ to the 'MutableByteArray#' @dst@\n    starting at offset @dst_ofs@.  Both arrays must fully contain the\n    specified ranges, but this is not checked.  The regions are\n    allowed to overlap, although this is only possible when the same\n    array is provided as both the source and the destination.\n  ")   , ("copyMutableByteArrayNonOverlapping#"," @'copyMutableByteArrayNonOverlapping#' src src_ofs dst dst_ofs len@\n    copies the range starting at offset @src_ofs@ of length @len@ from\n    the 'MutableByteArray#' @src@ to the 'MutableByteArray#' @dst@\n    starting at offset @dst_ofs@.  Both arrays must fully contain the\n    specified ranges, but this is not checked.  The regions are /not/\n    allowed to overlap, but this is also not checked.\n\n    @since 0.11.0\n  ")@@ -256,6 +261,20 @@   , ("indexWord32OffAddr#","Read a 32-bit unsigned integer; offset in 4-byte words.\n\nOn some platforms, the access may fail\nfor an insufficiently aligned @Addr#@.")   , ("indexInt64OffAddr#","Read a 64-bit signed integer; offset in 8-byte words.\n\nOn some platforms, the access may fail\nfor an insufficiently aligned @Addr#@.")   , ("indexWord64OffAddr#","Read a 64-bit unsigned integer; offset in 8-byte words.\n\nOn some platforms, the access may fail\nfor an insufficiently aligned @Addr#@.")+  , ("indexWord8OffAddrAsChar#","Read an 8-bit character; offset in bytes.")+  , ("indexWord8OffAddrAsWideChar#","Read a 32-bit character; offset in bytes.")+  , ("indexWord8OffAddrAsInt#","Read a word-sized integer; offset in bytes.")+  , ("indexWord8OffAddrAsWord#","Read a word-sized unsigned integer; offset in bytes.")+  , ("indexWord8OffAddrAsAddr#","Read a machine address; offset in bytes.")+  , ("indexWord8OffAddrAsFloat#","Read a single-precision floating-point value; offset in bytes.")+  , ("indexWord8OffAddrAsDouble#","Read a double-precision floating-point value; offset in bytes.")+  , ("indexWord8OffAddrAsStablePtr#","Read a 'StablePtr#' value; offset in bytes.")+  , ("indexWord8OffAddrAsInt16#","Read a 16-bit signed integer; offset in bytes.")+  , ("indexWord8OffAddrAsWord16#","Read a 16-bit unsigned integer; offset in bytes.")+  , ("indexWord8OffAddrAsInt32#","Read a 32-bit signed integer; offset in bytes.")+  , ("indexWord8OffAddrAsWord32#","Read a 32-bit unsigned integer; offset in bytes.")+  , ("indexWord8OffAddrAsInt64#","Read a 64-bit signed integer; offset in bytes.")+  , ("indexWord8OffAddrAsWord64#","Read a 64-bit unsigned integer; offset in bytes.")   , ("readCharOffAddr#","Read an 8-bit character; offset in bytes.\n\n")   , ("readWideCharOffAddr#","Read a 32-bit character; offset in 4-byte words.\n\nOn some platforms, the access may fail\nfor an insufficiently aligned @Addr#@.")   , ("readIntOffAddr#","Read a word-sized integer; offset in machine words.\n\nOn some platforms, the access may fail\nfor an insufficiently aligned @Addr#@.")@@ -272,6 +291,20 @@   , ("readWord32OffAddr#","Read a 32-bit unsigned integer; offset in 4-byte words.\n\nOn some platforms, the access may fail\nfor an insufficiently aligned @Addr#@.")   , ("readInt64OffAddr#","Read a 64-bit signed integer; offset in 8-byte words.\n\nOn some platforms, the access may fail\nfor an insufficiently aligned @Addr#@.")   , ("readWord64OffAddr#","Read a 64-bit unsigned integer; offset in 8-byte words.\n\nOn some platforms, the access may fail\nfor an insufficiently aligned @Addr#@.")+  , ("readWord8OffAddrAsChar#","Read an 8-bit character; offset in bytes.")+  , ("readWord8OffAddrAsWideChar#","Read a 32-bit character; offset in bytes.")+  , ("readWord8OffAddrAsInt#","Read a word-sized integer; offset in bytes.")+  , ("readWord8OffAddrAsWord#","Read a word-sized unsigned integer; offset in bytes.")+  , ("readWord8OffAddrAsAddr#","Read a machine address; offset in bytes.")+  , ("readWord8OffAddrAsFloat#","Read a single-precision floating-point value; offset in bytes.")+  , ("readWord8OffAddrAsDouble#","Read a double-precision floating-point value; offset in bytes.")+  , ("readWord8OffAddrAsStablePtr#","Read a 'StablePtr#' value; offset in bytes.")+  , ("readWord8OffAddrAsInt16#","Read a 16-bit signed integer; offset in bytes.")+  , ("readWord8OffAddrAsWord16#","Read a 16-bit unsigned integer; offset in bytes.")+  , ("readWord8OffAddrAsInt32#","Read a 32-bit signed integer; offset in bytes.")+  , ("readWord8OffAddrAsWord32#","Read a 32-bit unsigned integer; offset in bytes.")+  , ("readWord8OffAddrAsInt64#","Read a 64-bit signed integer; offset in bytes.")+  , ("readWord8OffAddrAsWord64#","Read a 64-bit unsigned integer; offset in bytes.")   , ("writeCharOffAddr#","Write an 8-bit character; offset in bytes.\n\n")   , ("writeWideCharOffAddr#","Write a 32-bit character; offset in 4-byte words.\n\nOn some platforms, the access may fail\nfor an insufficiently aligned @Addr#@.")   , ("writeIntOffAddr#","Write a word-sized integer; offset in machine words.\n\nOn some platforms, the access may fail\nfor an insufficiently aligned @Addr#@.")@@ -288,6 +321,20 @@   , ("writeWord32OffAddr#","Write a 32-bit unsigned integer; offset in 4-byte words.\n\nOn some platforms, the access may fail\nfor an insufficiently aligned @Addr#@.")   , ("writeInt64OffAddr#","Write a 64-bit signed integer; offset in 8-byte words.\n\nOn some platforms, the access may fail\nfor an insufficiently aligned @Addr#@.")   , ("writeWord64OffAddr#","Write a 64-bit unsigned integer; offset in 8-byte words.\n\nOn some platforms, the access may fail\nfor an insufficiently aligned @Addr#@.")+  , ("writeWord8OffAddrAsChar#","Write an 8-bit character; offset in bytes.")+  , ("writeWord8OffAddrAsWideChar#","Write a 32-bit character; offset in bytes.")+  , ("writeWord8OffAddrAsInt#","Write a word-sized integer; offset in bytes.")+  , ("writeWord8OffAddrAsWord#","Write a word-sized unsigned integer; offset in bytes.")+  , ("writeWord8OffAddrAsAddr#","Write a machine address; offset in bytes.")+  , ("writeWord8OffAddrAsFloat#","Write a single-precision floating-point value; offset in bytes.")+  , ("writeWord8OffAddrAsDouble#","Write a double-precision floating-point value; offset in bytes.")+  , ("writeWord8OffAddrAsStablePtr#","Write a 'StablePtr#' value; offset in bytes.")+  , ("writeWord8OffAddrAsInt16#","Write a 16-bit signed integer; offset in bytes.")+  , ("writeWord8OffAddrAsWord16#","Write a 16-bit unsigned integer; offset in bytes.")+  , ("writeWord8OffAddrAsInt32#","Write a 32-bit signed integer; offset in bytes.")+  , ("writeWord8OffAddrAsWord32#","Write a 32-bit unsigned integer; offset in bytes.")+  , ("writeWord8OffAddrAsInt64#","Write a 64-bit signed integer; offset in bytes.")+  , ("writeWord8OffAddrAsWord64#","Write a 64-bit unsigned integer; offset in bytes.")   , ("atomicExchangeAddrAddr#","The atomic exchange operation. Atomically exchanges the value at the first address\n    with the Addr# given as second argument. Implies a read barrier.")   , ("atomicExchangeWordAddr#","The atomic exchange operation. Atomically exchanges the value at the address\n    with the given value. Returns the old value. Implies a read barrier.")   , ("atomicCasAddrAddr#"," Compare and swap on a word-sized memory location.\n\n     Use as: \\s -> atomicCasAddrAddr# location expected desired s\n\n     This version always returns the old value read. This follows the normal\n     protocol for CAS operations (and matches the underlying instruction on\n     most architectures).\n\n     Implies a full memory barrier.")@@ -364,7 +411,8 @@   , ("reallyUnsafePtrEquality#"," Returns @1#@ if the given pointers are equal and @0#@ otherwise. ")   , ("numSparks#"," Returns the number of sparks in the local spark pool. ")   , ("keepAlive#"," @'keepAlive#' x s k@ keeps the value @x@ alive during the execution\n     of the computation @k@.\n\n     Note that the result type here isn't quite as unrestricted as the\n     polymorphic type might suggest; see the section \\\"RuntimeRep polymorphism\n     in continuation-style primops\\\" for details. ")-  , ("dataToTag#"," Evaluates the argument and returns the tag of the result.\n     Tags are Zero-indexed; the first constructor has tag zero. ")+  , ("dataToTagSmall#"," Used internally to implement @dataToTag#@: Use that function instead!\n     This one normally offers /no advantage/ and comes with no stability\n     guarantees: it may change its type, its name, or its behavior\n     with /no warning/ between compiler releases.\n\n     It is expected that this function will be un-exposed in a future\n     release of ghc.\n\n     For more details, look at @Note [DataToTag overview]@\n     in GHC.Tc.Instance.Class in the source code for\n     /the specific compiler version you are using./\n   ")+  , ("dataToTagLarge#"," Used internally to implement @dataToTag#@: Use that function instead!\n     This one offers /no advantage/ and comes with no stability\n     guarantees: it may change its type, its name, or its behavior\n     with /no warning/ between compiler releases.\n\n     It is expected that this function will be un-exposed in a future\n     release of ghc.\n\n     For more details, look at @Note [DataToTag overview]@\n     in GHC.Tc.Instance.Class in the source code for\n     /the specific compiler version you are using./\n   ")   , ("BCO"," Primitive bytecode type. ")   , ("addrToAny#"," Convert an 'Addr#' to a followable Any type. ")   , ("anyToAddr#"," Retrieve the address of any Haskell value. This is\n     essentially an 'unsafeCoerce#', but if implemented as such\n     the core lint pass complains and fails to compile.\n     As a primop, it is opaque to core/stg, and only appears\n     in cmm (where the copy propagation pass will get rid of it).\n     Note that \"a\" must be a value, not a thunk! It's too late\n     for strictness analysis to enforce this, so you're on your\n     own to guarantee this. Also note that 'Addr#' is not a GC\n     pointer - up to you to guarantee that it does not become\n     a dangling pointer immediately after you get it.")@@ -374,7 +422,7 @@   , ("closureSize#"," @'closureSize#' closure@ returns the size of the given closure in\n     machine words. ")   , ("getCurrentCCS#"," Returns the current 'CostCentreStack' (value is @NULL@ if\n     not profiling).  Takes a dummy argument which can be used to\n     avoid the call to 'getCurrentCCS#' being floated out by the\n     simplifier, which would result in an uninformative stack\n     (\"CAF\"). ")   , ("clearCCS#"," Run the supplied IO action with an empty CCS.  For example, this\n     is used by the interpreter to run an interpreted computation\n     without the call stack showing that it was invoked from GHC. ")-  , ("whereFrom#"," Returns the @InfoProvEnt @ for the info table of the given object\n     (value is @NULL@ if the table does not exist or there is no information\n     about the closure).")+  , ("whereFrom#"," Fills the given buffer with the @InfoProvEnt@ for the info table of the\n     given object. Returns @1#@ on success and @0#@ otherwise.")   , ("FUN","The builtin function type, written in infix form as @a % m -> b@.\n   Values of this type are functions taking inputs of type @a@ and\n   producing outputs of type @b@. The multiplicity of the input is\n   @m@.\n\n   Note that @'FUN' m a b@ permits representation polymorphism in both\n   @a@ and @b@, so that types like @'Int#' -> 'Int#'@ can still be\n   well-kinded.\n  ")   , ("realWorld#"," The token used in the implementation of the IO monad as a state monad.\n     It does not pass any information at runtime.\n     See also 'GHC.Magic.runRW#'. ")   , ("void#"," This is an alias for the unboxed unit tuple constructor.\n     In earlier versions of GHC, 'void#' was a value\n     of the primitive type 'Void#', which is now defined to be @(# #)@.\n   ")
+ ghc-lib/stage0/compiler/build/primop-effects.hs-incl view
@@ -0,0 +1,410 @@+primOpEffect Int8QuotOp = CanFail+primOpEffect Int8RemOp = CanFail+primOpEffect Int8QuotRemOp = CanFail+primOpEffect Word8QuotOp = CanFail+primOpEffect Word8RemOp = CanFail+primOpEffect Word8QuotRemOp = CanFail+primOpEffect Int16QuotOp = CanFail+primOpEffect Int16RemOp = CanFail+primOpEffect Int16QuotRemOp = CanFail+primOpEffect Word16QuotOp = CanFail+primOpEffect Word16RemOp = CanFail+primOpEffect Word16QuotRemOp = CanFail+primOpEffect Int32QuotOp = CanFail+primOpEffect Int32RemOp = CanFail+primOpEffect Int32QuotRemOp = CanFail+primOpEffect Word32QuotOp = CanFail+primOpEffect Word32RemOp = CanFail+primOpEffect Word32QuotRemOp = CanFail+primOpEffect Int64QuotOp = CanFail+primOpEffect Int64RemOp = CanFail+primOpEffect Word64QuotOp = CanFail+primOpEffect Word64RemOp = CanFail+primOpEffect IntQuotOp = CanFail+primOpEffect IntRemOp = CanFail+primOpEffect IntQuotRemOp = CanFail+primOpEffect WordQuotOp = CanFail+primOpEffect WordRemOp = CanFail+primOpEffect WordQuotRemOp = CanFail+primOpEffect WordQuotRem2Op = CanFail+primOpEffect DoubleDivOp = CanFail+primOpEffect DoubleLogOp = CanFail+primOpEffect DoubleLog1POp = CanFail+primOpEffect DoubleAsinOp = CanFail+primOpEffect DoubleAcosOp = CanFail+primOpEffect FloatDivOp = CanFail+primOpEffect FloatLogOp = CanFail+primOpEffect FloatLog1POp = CanFail+primOpEffect FloatAsinOp = CanFail+primOpEffect FloatAcosOp = CanFail+primOpEffect NewArrayOp = ReadWriteEffect+primOpEffect ReadArrayOp = ReadWriteEffect+primOpEffect WriteArrayOp = ReadWriteEffect+primOpEffect IndexArrayOp = CanFail+primOpEffect UnsafeFreezeArrayOp = ReadWriteEffect+primOpEffect UnsafeThawArrayOp = ReadWriteEffect+primOpEffect CopyArrayOp = ReadWriteEffect+primOpEffect CopyMutableArrayOp = ReadWriteEffect+primOpEffect CloneArrayOp = ReadWriteEffect+primOpEffect CloneMutableArrayOp = ReadWriteEffect+primOpEffect FreezeArrayOp = ReadWriteEffect+primOpEffect ThawArrayOp = ReadWriteEffect+primOpEffect CasArrayOp = ReadWriteEffect+primOpEffect NewSmallArrayOp = ReadWriteEffect+primOpEffect ShrinkSmallMutableArrayOp_Char = ReadWriteEffect+primOpEffect ReadSmallArrayOp = ReadWriteEffect+primOpEffect WriteSmallArrayOp = ReadWriteEffect+primOpEffect IndexSmallArrayOp = CanFail+primOpEffect UnsafeFreezeSmallArrayOp = ReadWriteEffect+primOpEffect UnsafeThawSmallArrayOp = ReadWriteEffect+primOpEffect CopySmallArrayOp = ReadWriteEffect+primOpEffect CopySmallMutableArrayOp = ReadWriteEffect+primOpEffect CloneSmallArrayOp = ReadWriteEffect+primOpEffect CloneSmallMutableArrayOp = ReadWriteEffect+primOpEffect FreezeSmallArrayOp = ReadWriteEffect+primOpEffect ThawSmallArrayOp = ReadWriteEffect+primOpEffect CasSmallArrayOp = ReadWriteEffect+primOpEffect NewByteArrayOp_Char = ReadWriteEffect+primOpEffect NewPinnedByteArrayOp_Char = ReadWriteEffect+primOpEffect NewAlignedPinnedByteArrayOp_Char = ReadWriteEffect+primOpEffect ShrinkMutableByteArrayOp_Char = ReadWriteEffect+primOpEffect ResizeMutableByteArrayOp_Char = ReadWriteEffect+primOpEffect UnsafeFreezeByteArrayOp = NoEffect+primOpEffect UnsafeThawByteArrayOp = NoEffect+primOpEffect IndexByteArrayOp_Char = CanFail+primOpEffect IndexByteArrayOp_WideChar = CanFail+primOpEffect IndexByteArrayOp_Int = CanFail+primOpEffect IndexByteArrayOp_Word = CanFail+primOpEffect IndexByteArrayOp_Addr = CanFail+primOpEffect IndexByteArrayOp_Float = CanFail+primOpEffect IndexByteArrayOp_Double = CanFail+primOpEffect IndexByteArrayOp_StablePtr = CanFail+primOpEffect IndexByteArrayOp_Int8 = CanFail+primOpEffect IndexByteArrayOp_Word8 = CanFail+primOpEffect IndexByteArrayOp_Int16 = CanFail+primOpEffect IndexByteArrayOp_Word16 = CanFail+primOpEffect IndexByteArrayOp_Int32 = CanFail+primOpEffect IndexByteArrayOp_Word32 = CanFail+primOpEffect IndexByteArrayOp_Int64 = CanFail+primOpEffect IndexByteArrayOp_Word64 = CanFail+primOpEffect IndexByteArrayOp_Word8AsChar = CanFail+primOpEffect IndexByteArrayOp_Word8AsWideChar = CanFail+primOpEffect IndexByteArrayOp_Word8AsInt = CanFail+primOpEffect IndexByteArrayOp_Word8AsWord = CanFail+primOpEffect IndexByteArrayOp_Word8AsAddr = CanFail+primOpEffect IndexByteArrayOp_Word8AsFloat = CanFail+primOpEffect IndexByteArrayOp_Word8AsDouble = CanFail+primOpEffect IndexByteArrayOp_Word8AsStablePtr = CanFail+primOpEffect IndexByteArrayOp_Word8AsInt16 = CanFail+primOpEffect IndexByteArrayOp_Word8AsWord16 = CanFail+primOpEffect IndexByteArrayOp_Word8AsInt32 = CanFail+primOpEffect IndexByteArrayOp_Word8AsWord32 = CanFail+primOpEffect IndexByteArrayOp_Word8AsInt64 = CanFail+primOpEffect IndexByteArrayOp_Word8AsWord64 = CanFail+primOpEffect ReadByteArrayOp_Char = ReadWriteEffect+primOpEffect ReadByteArrayOp_WideChar = ReadWriteEffect+primOpEffect ReadByteArrayOp_Int = ReadWriteEffect+primOpEffect ReadByteArrayOp_Word = ReadWriteEffect+primOpEffect ReadByteArrayOp_Addr = ReadWriteEffect+primOpEffect ReadByteArrayOp_Float = ReadWriteEffect+primOpEffect ReadByteArrayOp_Double = ReadWriteEffect+primOpEffect ReadByteArrayOp_StablePtr = ReadWriteEffect+primOpEffect ReadByteArrayOp_Int8 = ReadWriteEffect+primOpEffect ReadByteArrayOp_Word8 = ReadWriteEffect+primOpEffect ReadByteArrayOp_Int16 = ReadWriteEffect+primOpEffect ReadByteArrayOp_Word16 = ReadWriteEffect+primOpEffect ReadByteArrayOp_Int32 = ReadWriteEffect+primOpEffect ReadByteArrayOp_Word32 = ReadWriteEffect+primOpEffect ReadByteArrayOp_Int64 = ReadWriteEffect+primOpEffect ReadByteArrayOp_Word64 = ReadWriteEffect+primOpEffect ReadByteArrayOp_Word8AsChar = ReadWriteEffect+primOpEffect ReadByteArrayOp_Word8AsWideChar = ReadWriteEffect+primOpEffect ReadByteArrayOp_Word8AsInt = ReadWriteEffect+primOpEffect ReadByteArrayOp_Word8AsWord = ReadWriteEffect+primOpEffect ReadByteArrayOp_Word8AsAddr = ReadWriteEffect+primOpEffect ReadByteArrayOp_Word8AsFloat = ReadWriteEffect+primOpEffect ReadByteArrayOp_Word8AsDouble = ReadWriteEffect+primOpEffect ReadByteArrayOp_Word8AsStablePtr = ReadWriteEffect+primOpEffect ReadByteArrayOp_Word8AsInt16 = ReadWriteEffect+primOpEffect ReadByteArrayOp_Word8AsWord16 = ReadWriteEffect+primOpEffect ReadByteArrayOp_Word8AsInt32 = ReadWriteEffect+primOpEffect ReadByteArrayOp_Word8AsWord32 = ReadWriteEffect+primOpEffect ReadByteArrayOp_Word8AsInt64 = ReadWriteEffect+primOpEffect ReadByteArrayOp_Word8AsWord64 = ReadWriteEffect+primOpEffect WriteByteArrayOp_Char = ReadWriteEffect+primOpEffect WriteByteArrayOp_WideChar = ReadWriteEffect+primOpEffect WriteByteArrayOp_Int = ReadWriteEffect+primOpEffect WriteByteArrayOp_Word = ReadWriteEffect+primOpEffect WriteByteArrayOp_Addr = ReadWriteEffect+primOpEffect WriteByteArrayOp_Float = ReadWriteEffect+primOpEffect WriteByteArrayOp_Double = ReadWriteEffect+primOpEffect WriteByteArrayOp_StablePtr = ReadWriteEffect+primOpEffect WriteByteArrayOp_Int8 = ReadWriteEffect+primOpEffect WriteByteArrayOp_Word8 = ReadWriteEffect+primOpEffect WriteByteArrayOp_Int16 = ReadWriteEffect+primOpEffect WriteByteArrayOp_Word16 = ReadWriteEffect+primOpEffect WriteByteArrayOp_Int32 = ReadWriteEffect+primOpEffect WriteByteArrayOp_Word32 = ReadWriteEffect+primOpEffect WriteByteArrayOp_Int64 = ReadWriteEffect+primOpEffect WriteByteArrayOp_Word64 = ReadWriteEffect+primOpEffect WriteByteArrayOp_Word8AsChar = ReadWriteEffect+primOpEffect WriteByteArrayOp_Word8AsWideChar = ReadWriteEffect+primOpEffect WriteByteArrayOp_Word8AsInt = ReadWriteEffect+primOpEffect WriteByteArrayOp_Word8AsWord = ReadWriteEffect+primOpEffect WriteByteArrayOp_Word8AsAddr = ReadWriteEffect+primOpEffect WriteByteArrayOp_Word8AsFloat = ReadWriteEffect+primOpEffect WriteByteArrayOp_Word8AsDouble = ReadWriteEffect+primOpEffect WriteByteArrayOp_Word8AsStablePtr = ReadWriteEffect+primOpEffect WriteByteArrayOp_Word8AsInt16 = ReadWriteEffect+primOpEffect WriteByteArrayOp_Word8AsWord16 = ReadWriteEffect+primOpEffect WriteByteArrayOp_Word8AsInt32 = ReadWriteEffect+primOpEffect WriteByteArrayOp_Word8AsWord32 = ReadWriteEffect+primOpEffect WriteByteArrayOp_Word8AsInt64 = ReadWriteEffect+primOpEffect WriteByteArrayOp_Word8AsWord64 = ReadWriteEffect+primOpEffect CompareByteArraysOp = CanFail+primOpEffect CopyByteArrayOp = ReadWriteEffect+primOpEffect CopyMutableByteArrayOp = ReadWriteEffect+primOpEffect CopyMutableByteArrayNonOverlappingOp = ReadWriteEffect+primOpEffect CopyByteArrayToAddrOp = ReadWriteEffect+primOpEffect CopyMutableByteArrayToAddrOp = ReadWriteEffect+primOpEffect CopyAddrToByteArrayOp = ReadWriteEffect+primOpEffect CopyAddrToAddrOp = ReadWriteEffect+primOpEffect CopyAddrToAddrNonOverlappingOp = ReadWriteEffect+primOpEffect SetByteArrayOp = ReadWriteEffect+primOpEffect SetAddrRangeOp = ReadWriteEffect+primOpEffect AtomicReadByteArrayOp_Int = ReadWriteEffect+primOpEffect AtomicWriteByteArrayOp_Int = ReadWriteEffect+primOpEffect CasByteArrayOp_Int = ReadWriteEffect+primOpEffect CasByteArrayOp_Int8 = ReadWriteEffect+primOpEffect CasByteArrayOp_Int16 = ReadWriteEffect+primOpEffect CasByteArrayOp_Int32 = ReadWriteEffect+primOpEffect CasByteArrayOp_Int64 = ReadWriteEffect+primOpEffect FetchAddByteArrayOp_Int = ReadWriteEffect+primOpEffect FetchSubByteArrayOp_Int = ReadWriteEffect+primOpEffect FetchAndByteArrayOp_Int = ReadWriteEffect+primOpEffect FetchNandByteArrayOp_Int = ReadWriteEffect+primOpEffect FetchOrByteArrayOp_Int = ReadWriteEffect+primOpEffect FetchXorByteArrayOp_Int = ReadWriteEffect+primOpEffect IndexOffAddrOp_Char = CanFail+primOpEffect IndexOffAddrOp_WideChar = CanFail+primOpEffect IndexOffAddrOp_Int = CanFail+primOpEffect IndexOffAddrOp_Word = CanFail+primOpEffect IndexOffAddrOp_Addr = CanFail+primOpEffect IndexOffAddrOp_Float = CanFail+primOpEffect IndexOffAddrOp_Double = CanFail+primOpEffect IndexOffAddrOp_StablePtr = CanFail+primOpEffect IndexOffAddrOp_Int8 = CanFail+primOpEffect IndexOffAddrOp_Word8 = CanFail+primOpEffect IndexOffAddrOp_Int16 = CanFail+primOpEffect IndexOffAddrOp_Word16 = CanFail+primOpEffect IndexOffAddrOp_Int32 = CanFail+primOpEffect IndexOffAddrOp_Word32 = CanFail+primOpEffect IndexOffAddrOp_Int64 = CanFail+primOpEffect IndexOffAddrOp_Word64 = CanFail+primOpEffect IndexOffAddrOp_Word8AsChar = CanFail+primOpEffect IndexOffAddrOp_Word8AsWideChar = CanFail+primOpEffect IndexOffAddrOp_Word8AsInt = CanFail+primOpEffect IndexOffAddrOp_Word8AsWord = CanFail+primOpEffect IndexOffAddrOp_Word8AsAddr = CanFail+primOpEffect IndexOffAddrOp_Word8AsFloat = CanFail+primOpEffect IndexOffAddrOp_Word8AsDouble = CanFail+primOpEffect IndexOffAddrOp_Word8AsStablePtr = CanFail+primOpEffect IndexOffAddrOp_Word8AsInt16 = CanFail+primOpEffect IndexOffAddrOp_Word8AsWord16 = CanFail+primOpEffect IndexOffAddrOp_Word8AsInt32 = CanFail+primOpEffect IndexOffAddrOp_Word8AsWord32 = CanFail+primOpEffect IndexOffAddrOp_Word8AsInt64 = CanFail+primOpEffect IndexOffAddrOp_Word8AsWord64 = CanFail+primOpEffect ReadOffAddrOp_Char = ReadWriteEffect+primOpEffect ReadOffAddrOp_WideChar = ReadWriteEffect+primOpEffect ReadOffAddrOp_Int = ReadWriteEffect+primOpEffect ReadOffAddrOp_Word = ReadWriteEffect+primOpEffect ReadOffAddrOp_Addr = ReadWriteEffect+primOpEffect ReadOffAddrOp_Float = ReadWriteEffect+primOpEffect ReadOffAddrOp_Double = ReadWriteEffect+primOpEffect ReadOffAddrOp_StablePtr = ReadWriteEffect+primOpEffect ReadOffAddrOp_Int8 = ReadWriteEffect+primOpEffect ReadOffAddrOp_Word8 = ReadWriteEffect+primOpEffect ReadOffAddrOp_Int16 = ReadWriteEffect+primOpEffect ReadOffAddrOp_Word16 = ReadWriteEffect+primOpEffect ReadOffAddrOp_Int32 = ReadWriteEffect+primOpEffect ReadOffAddrOp_Word32 = ReadWriteEffect+primOpEffect ReadOffAddrOp_Int64 = ReadWriteEffect+primOpEffect ReadOffAddrOp_Word64 = ReadWriteEffect+primOpEffect ReadOffAddrOp_Word8AsChar = ReadWriteEffect+primOpEffect ReadOffAddrOp_Word8AsWideChar = ReadWriteEffect+primOpEffect ReadOffAddrOp_Word8AsInt = ReadWriteEffect+primOpEffect ReadOffAddrOp_Word8AsWord = ReadWriteEffect+primOpEffect ReadOffAddrOp_Word8AsAddr = ReadWriteEffect+primOpEffect ReadOffAddrOp_Word8AsFloat = ReadWriteEffect+primOpEffect ReadOffAddrOp_Word8AsDouble = ReadWriteEffect+primOpEffect ReadOffAddrOp_Word8AsStablePtr = ReadWriteEffect+primOpEffect ReadOffAddrOp_Word8AsInt16 = ReadWriteEffect+primOpEffect ReadOffAddrOp_Word8AsWord16 = ReadWriteEffect+primOpEffect ReadOffAddrOp_Word8AsInt32 = ReadWriteEffect+primOpEffect ReadOffAddrOp_Word8AsWord32 = ReadWriteEffect+primOpEffect ReadOffAddrOp_Word8AsInt64 = ReadWriteEffect+primOpEffect ReadOffAddrOp_Word8AsWord64 = ReadWriteEffect+primOpEffect WriteOffAddrOp_Char = ReadWriteEffect+primOpEffect WriteOffAddrOp_WideChar = ReadWriteEffect+primOpEffect WriteOffAddrOp_Int = ReadWriteEffect+primOpEffect WriteOffAddrOp_Word = ReadWriteEffect+primOpEffect WriteOffAddrOp_Addr = ReadWriteEffect+primOpEffect WriteOffAddrOp_Float = ReadWriteEffect+primOpEffect WriteOffAddrOp_Double = ReadWriteEffect+primOpEffect WriteOffAddrOp_StablePtr = ReadWriteEffect+primOpEffect WriteOffAddrOp_Int8 = ReadWriteEffect+primOpEffect WriteOffAddrOp_Word8 = ReadWriteEffect+primOpEffect WriteOffAddrOp_Int16 = ReadWriteEffect+primOpEffect WriteOffAddrOp_Word16 = ReadWriteEffect+primOpEffect WriteOffAddrOp_Int32 = ReadWriteEffect+primOpEffect WriteOffAddrOp_Word32 = ReadWriteEffect+primOpEffect WriteOffAddrOp_Int64 = ReadWriteEffect+primOpEffect WriteOffAddrOp_Word64 = ReadWriteEffect+primOpEffect WriteOffAddrOp_Word8AsChar = ReadWriteEffect+primOpEffect WriteOffAddrOp_Word8AsWideChar = ReadWriteEffect+primOpEffect WriteOffAddrOp_Word8AsInt = ReadWriteEffect+primOpEffect WriteOffAddrOp_Word8AsWord = ReadWriteEffect+primOpEffect WriteOffAddrOp_Word8AsAddr = ReadWriteEffect+primOpEffect WriteOffAddrOp_Word8AsFloat = ReadWriteEffect+primOpEffect WriteOffAddrOp_Word8AsDouble = ReadWriteEffect+primOpEffect WriteOffAddrOp_Word8AsStablePtr = ReadWriteEffect+primOpEffect WriteOffAddrOp_Word8AsInt16 = ReadWriteEffect+primOpEffect WriteOffAddrOp_Word8AsWord16 = ReadWriteEffect+primOpEffect WriteOffAddrOp_Word8AsInt32 = ReadWriteEffect+primOpEffect WriteOffAddrOp_Word8AsWord32 = ReadWriteEffect+primOpEffect WriteOffAddrOp_Word8AsInt64 = ReadWriteEffect+primOpEffect WriteOffAddrOp_Word8AsWord64 = ReadWriteEffect+primOpEffect InterlockedExchange_Addr = ReadWriteEffect+primOpEffect InterlockedExchange_Word = ReadWriteEffect+primOpEffect CasAddrOp_Addr = ReadWriteEffect+primOpEffect CasAddrOp_Word = ReadWriteEffect+primOpEffect CasAddrOp_Word8 = ReadWriteEffect+primOpEffect CasAddrOp_Word16 = ReadWriteEffect+primOpEffect CasAddrOp_Word32 = ReadWriteEffect+primOpEffect CasAddrOp_Word64 = ReadWriteEffect+primOpEffect FetchAddAddrOp_Word = ReadWriteEffect+primOpEffect FetchSubAddrOp_Word = ReadWriteEffect+primOpEffect FetchAndAddrOp_Word = ReadWriteEffect+primOpEffect FetchNandAddrOp_Word = ReadWriteEffect+primOpEffect FetchOrAddrOp_Word = ReadWriteEffect+primOpEffect FetchXorAddrOp_Word = ReadWriteEffect+primOpEffect AtomicReadAddrOp_Word = ReadWriteEffect+primOpEffect AtomicWriteAddrOp_Word = ReadWriteEffect+primOpEffect NewMutVarOp = ReadWriteEffect+primOpEffect ReadMutVarOp = ReadWriteEffect+primOpEffect WriteMutVarOp = ReadWriteEffect+primOpEffect AtomicSwapMutVarOp = ReadWriteEffect+primOpEffect AtomicModifyMutVar2Op = ReadWriteEffect+primOpEffect AtomicModifyMutVar_Op = ReadWriteEffect+primOpEffect CasMutVarOp = ReadWriteEffect+primOpEffect CatchOp = ReadWriteEffect+primOpEffect RaiseOp = ThrowsException+primOpEffect RaiseUnderflowOp = ThrowsException+primOpEffect RaiseOverflowOp = ThrowsException+primOpEffect RaiseDivZeroOp = ThrowsException+primOpEffect RaiseIOOp = ThrowsException+primOpEffect MaskAsyncExceptionsOp = ReadWriteEffect+primOpEffect MaskUninterruptibleOp = ReadWriteEffect+primOpEffect UnmaskAsyncExceptionsOp = ReadWriteEffect+primOpEffect MaskStatus = ReadWriteEffect+primOpEffect NewPromptTagOp = ReadWriteEffect+primOpEffect PromptOp = ReadWriteEffect+primOpEffect Control0Op = ReadWriteEffect+primOpEffect AtomicallyOp = ReadWriteEffect+primOpEffect RetryOp = ReadWriteEffect+primOpEffect CatchRetryOp = ReadWriteEffect+primOpEffect CatchSTMOp = ReadWriteEffect+primOpEffect NewTVarOp = ReadWriteEffect+primOpEffect ReadTVarOp = ReadWriteEffect+primOpEffect ReadTVarIOOp = ReadWriteEffect+primOpEffect WriteTVarOp = ReadWriteEffect+primOpEffect NewMVarOp = ReadWriteEffect+primOpEffect TakeMVarOp = ReadWriteEffect+primOpEffect TryTakeMVarOp = ReadWriteEffect+primOpEffect PutMVarOp = ReadWriteEffect+primOpEffect TryPutMVarOp = ReadWriteEffect+primOpEffect ReadMVarOp = ReadWriteEffect+primOpEffect TryReadMVarOp = ReadWriteEffect+primOpEffect IsEmptyMVarOp = ReadWriteEffect+primOpEffect NewIOPortOp = ReadWriteEffect+primOpEffect ReadIOPortOp = ReadWriteEffect+primOpEffect WriteIOPortOp = ReadWriteEffect+primOpEffect DelayOp = ReadWriteEffect+primOpEffect WaitReadOp = ReadWriteEffect+primOpEffect WaitWriteOp = ReadWriteEffect+primOpEffect ForkOp = ReadWriteEffect+primOpEffect ForkOnOp = ReadWriteEffect+primOpEffect KillThreadOp = ReadWriteEffect+primOpEffect YieldOp = ReadWriteEffect+primOpEffect MyThreadIdOp = ReadWriteEffect+primOpEffect LabelThreadOp = ReadWriteEffect+primOpEffect IsCurrentThreadBoundOp = ReadWriteEffect+primOpEffect NoDuplicateOp = ReadWriteEffect+primOpEffect ThreadStatusOp = ReadWriteEffect+primOpEffect ListThreadsOp = ReadWriteEffect+primOpEffect MkWeakOp = ReadWriteEffect+primOpEffect MkWeakNoFinalizerOp = ReadWriteEffect+primOpEffect AddCFinalizerToWeakOp = ReadWriteEffect+primOpEffect DeRefWeakOp = ReadWriteEffect+primOpEffect FinalizeWeakOp = ReadWriteEffect+primOpEffect TouchOp = ReadWriteEffect+primOpEffect MakeStablePtrOp = ReadWriteEffect+primOpEffect DeRefStablePtrOp = ReadWriteEffect+primOpEffect EqStablePtrOp = ReadWriteEffect+primOpEffect MakeStableNameOp = ReadWriteEffect+primOpEffect CompactNewOp = ReadWriteEffect+primOpEffect CompactResizeOp = ReadWriteEffect+primOpEffect CompactAllocateBlockOp = ReadWriteEffect+primOpEffect CompactFixupPointersOp = ReadWriteEffect+primOpEffect CompactAdd = ReadWriteEffect+primOpEffect CompactAddWithSharing = ReadWriteEffect+primOpEffect CompactSize = ReadWriteEffect+primOpEffect ReallyUnsafePtrEqualityOp = CanFail+primOpEffect ParOp = ReadWriteEffect+primOpEffect SparkOp = ReadWriteEffect+primOpEffect SeqOp = ThrowsException+primOpEffect GetSparkOp = ReadWriteEffect+primOpEffect NumSparks = ReadWriteEffect+primOpEffect KeepAliveOp = ReadWriteEffect+primOpEffect DataToTagSmallOp = ThrowsException+primOpEffect DataToTagLargeOp = ThrowsException+primOpEffect TagToEnumOp = CanFail+primOpEffect NewBCOOp = ReadWriteEffect+primOpEffect TraceEventOp = ReadWriteEffect+primOpEffect TraceEventBinaryOp = ReadWriteEffect+primOpEffect TraceMarkerOp = ReadWriteEffect+primOpEffect SetThreadAllocationCounter = ReadWriteEffect+primOpEffect (VecInsertOp _ _ _) = CanFail+primOpEffect (VecDivOp _ _ _) = CanFail+primOpEffect (VecQuotOp _ _ _) = CanFail+primOpEffect (VecRemOp _ _ _) = CanFail+primOpEffect (VecIndexByteArrayOp _ _ _) = CanFail+primOpEffect (VecReadByteArrayOp _ _ _) = ReadWriteEffect+primOpEffect (VecWriteByteArrayOp _ _ _) = ReadWriteEffect+primOpEffect (VecIndexOffAddrOp _ _ _) = CanFail+primOpEffect (VecReadOffAddrOp _ _ _) = ReadWriteEffect+primOpEffect (VecWriteOffAddrOp _ _ _) = ReadWriteEffect+primOpEffect (VecIndexScalarByteArrayOp _ _ _) = CanFail+primOpEffect (VecReadScalarByteArrayOp _ _ _) = ReadWriteEffect+primOpEffect (VecWriteScalarByteArrayOp _ _ _) = ReadWriteEffect+primOpEffect (VecIndexScalarOffAddrOp _ _ _) = CanFail+primOpEffect (VecReadScalarOffAddrOp _ _ _) = ReadWriteEffect+primOpEffect (VecWriteScalarOffAddrOp _ _ _) = ReadWriteEffect+primOpEffect PrefetchByteArrayOp3 = ReadWriteEffect+primOpEffect PrefetchMutableByteArrayOp3 = ReadWriteEffect+primOpEffect PrefetchAddrOp3 = ReadWriteEffect+primOpEffect PrefetchValueOp3 = ReadWriteEffect+primOpEffect PrefetchByteArrayOp2 = ReadWriteEffect+primOpEffect PrefetchMutableByteArrayOp2 = ReadWriteEffect+primOpEffect PrefetchAddrOp2 = ReadWriteEffect+primOpEffect PrefetchValueOp2 = ReadWriteEffect+primOpEffect PrefetchByteArrayOp1 = ReadWriteEffect+primOpEffect PrefetchMutableByteArrayOp1 = ReadWriteEffect+primOpEffect PrefetchAddrOp1 = ReadWriteEffect+primOpEffect PrefetchValueOp1 = ReadWriteEffect+primOpEffect PrefetchByteArrayOp0 = ReadWriteEffect+primOpEffect PrefetchMutableByteArrayOp0 = ReadWriteEffect+primOpEffect PrefetchAddrOp0 = ReadWriteEffect+primOpEffect PrefetchValueOp0 = ReadWriteEffect+primOpEffect _thisOp = NoEffect
ghc-lib/stage0/compiler/build/primop-fixity.hs-incl view
@@ -17,4 +17,4 @@ primOpFixity DoubleSubOp = Just (Fixity NoSourceText 6 InfixL) primOpFixity DoubleMulOp = Just (Fixity NoSourceText 7 InfixL) primOpFixity DoubleDivOp = Just (Fixity NoSourceText 7 InfixL)-primOpFixity _ = Nothing+primOpFixity _thisOp = Nothing
− ghc-lib/stage0/compiler/build/primop-has-side-effects.hs-incl
@@ -1,261 +0,0 @@-primOpHasSideEffects NewArrayOp = True-primOpHasSideEffects ReadArrayOp = True-primOpHasSideEffects WriteArrayOp = True-primOpHasSideEffects UnsafeFreezeArrayOp = True-primOpHasSideEffects UnsafeThawArrayOp = True-primOpHasSideEffects CopyArrayOp = True-primOpHasSideEffects CopyMutableArrayOp = True-primOpHasSideEffects CloneArrayOp = True-primOpHasSideEffects CloneMutableArrayOp = True-primOpHasSideEffects FreezeArrayOp = True-primOpHasSideEffects ThawArrayOp = True-primOpHasSideEffects CasArrayOp = True-primOpHasSideEffects NewSmallArrayOp = True-primOpHasSideEffects ShrinkSmallMutableArrayOp_Char = True-primOpHasSideEffects ReadSmallArrayOp = True-primOpHasSideEffects WriteSmallArrayOp = True-primOpHasSideEffects UnsafeFreezeSmallArrayOp = True-primOpHasSideEffects UnsafeThawSmallArrayOp = True-primOpHasSideEffects CopySmallArrayOp = True-primOpHasSideEffects CopySmallMutableArrayOp = True-primOpHasSideEffects CloneSmallArrayOp = True-primOpHasSideEffects CloneSmallMutableArrayOp = True-primOpHasSideEffects FreezeSmallArrayOp = True-primOpHasSideEffects ThawSmallArrayOp = True-primOpHasSideEffects CasSmallArrayOp = True-primOpHasSideEffects NewByteArrayOp_Char = True-primOpHasSideEffects NewPinnedByteArrayOp_Char = True-primOpHasSideEffects NewAlignedPinnedByteArrayOp_Char = True-primOpHasSideEffects ShrinkMutableByteArrayOp_Char = True-primOpHasSideEffects ResizeMutableByteArrayOp_Char = True-primOpHasSideEffects UnsafeFreezeByteArrayOp = True-primOpHasSideEffects ReadByteArrayOp_Char = True-primOpHasSideEffects ReadByteArrayOp_WideChar = True-primOpHasSideEffects ReadByteArrayOp_Int = True-primOpHasSideEffects ReadByteArrayOp_Word = True-primOpHasSideEffects ReadByteArrayOp_Addr = True-primOpHasSideEffects ReadByteArrayOp_Float = True-primOpHasSideEffects ReadByteArrayOp_Double = True-primOpHasSideEffects ReadByteArrayOp_StablePtr = True-primOpHasSideEffects ReadByteArrayOp_Int8 = True-primOpHasSideEffects ReadByteArrayOp_Word8 = True-primOpHasSideEffects ReadByteArrayOp_Int16 = True-primOpHasSideEffects ReadByteArrayOp_Word16 = True-primOpHasSideEffects ReadByteArrayOp_Int32 = True-primOpHasSideEffects ReadByteArrayOp_Word32 = True-primOpHasSideEffects ReadByteArrayOp_Int64 = True-primOpHasSideEffects ReadByteArrayOp_Word64 = True-primOpHasSideEffects ReadByteArrayOp_Word8AsChar = True-primOpHasSideEffects ReadByteArrayOp_Word8AsWideChar = True-primOpHasSideEffects ReadByteArrayOp_Word8AsInt = True-primOpHasSideEffects ReadByteArrayOp_Word8AsWord = True-primOpHasSideEffects ReadByteArrayOp_Word8AsAddr = True-primOpHasSideEffects ReadByteArrayOp_Word8AsFloat = True-primOpHasSideEffects ReadByteArrayOp_Word8AsDouble = True-primOpHasSideEffects ReadByteArrayOp_Word8AsStablePtr = True-primOpHasSideEffects ReadByteArrayOp_Word8AsInt16 = True-primOpHasSideEffects ReadByteArrayOp_Word8AsWord16 = True-primOpHasSideEffects ReadByteArrayOp_Word8AsInt32 = True-primOpHasSideEffects ReadByteArrayOp_Word8AsWord32 = True-primOpHasSideEffects ReadByteArrayOp_Word8AsInt64 = True-primOpHasSideEffects ReadByteArrayOp_Word8AsWord64 = True-primOpHasSideEffects WriteByteArrayOp_Char = True-primOpHasSideEffects WriteByteArrayOp_WideChar = True-primOpHasSideEffects WriteByteArrayOp_Int = True-primOpHasSideEffects WriteByteArrayOp_Word = True-primOpHasSideEffects WriteByteArrayOp_Addr = True-primOpHasSideEffects WriteByteArrayOp_Float = True-primOpHasSideEffects WriteByteArrayOp_Double = True-primOpHasSideEffects WriteByteArrayOp_StablePtr = True-primOpHasSideEffects WriteByteArrayOp_Int8 = True-primOpHasSideEffects WriteByteArrayOp_Word8 = True-primOpHasSideEffects WriteByteArrayOp_Int16 = True-primOpHasSideEffects WriteByteArrayOp_Word16 = True-primOpHasSideEffects WriteByteArrayOp_Int32 = True-primOpHasSideEffects WriteByteArrayOp_Word32 = True-primOpHasSideEffects WriteByteArrayOp_Int64 = True-primOpHasSideEffects WriteByteArrayOp_Word64 = True-primOpHasSideEffects WriteByteArrayOp_Word8AsChar = True-primOpHasSideEffects WriteByteArrayOp_Word8AsWideChar = True-primOpHasSideEffects WriteByteArrayOp_Word8AsInt = True-primOpHasSideEffects WriteByteArrayOp_Word8AsWord = True-primOpHasSideEffects WriteByteArrayOp_Word8AsAddr = True-primOpHasSideEffects WriteByteArrayOp_Word8AsFloat = True-primOpHasSideEffects WriteByteArrayOp_Word8AsDouble = True-primOpHasSideEffects WriteByteArrayOp_Word8AsStablePtr = True-primOpHasSideEffects WriteByteArrayOp_Word8AsInt16 = True-primOpHasSideEffects WriteByteArrayOp_Word8AsWord16 = True-primOpHasSideEffects WriteByteArrayOp_Word8AsInt32 = True-primOpHasSideEffects WriteByteArrayOp_Word8AsWord32 = True-primOpHasSideEffects WriteByteArrayOp_Word8AsInt64 = True-primOpHasSideEffects WriteByteArrayOp_Word8AsWord64 = True-primOpHasSideEffects CopyByteArrayOp = True-primOpHasSideEffects CopyMutableByteArrayOp = True-primOpHasSideEffects CopyMutableByteArrayNonOverlappingOp = True-primOpHasSideEffects CopyByteArrayToAddrOp = True-primOpHasSideEffects CopyMutableByteArrayToAddrOp = True-primOpHasSideEffects CopyAddrToByteArrayOp = True-primOpHasSideEffects CopyAddrToAddrOp = True-primOpHasSideEffects CopyAddrToAddrNonOverlappingOp = True-primOpHasSideEffects SetByteArrayOp = True-primOpHasSideEffects SetAddrRangeOp = True-primOpHasSideEffects AtomicReadByteArrayOp_Int = True-primOpHasSideEffects AtomicWriteByteArrayOp_Int = True-primOpHasSideEffects CasByteArrayOp_Int = True-primOpHasSideEffects CasByteArrayOp_Int8 = True-primOpHasSideEffects CasByteArrayOp_Int16 = True-primOpHasSideEffects CasByteArrayOp_Int32 = True-primOpHasSideEffects CasByteArrayOp_Int64 = True-primOpHasSideEffects FetchAddByteArrayOp_Int = True-primOpHasSideEffects FetchSubByteArrayOp_Int = True-primOpHasSideEffects FetchAndByteArrayOp_Int = True-primOpHasSideEffects FetchNandByteArrayOp_Int = True-primOpHasSideEffects FetchOrByteArrayOp_Int = True-primOpHasSideEffects FetchXorByteArrayOp_Int = True-primOpHasSideEffects ReadOffAddrOp_Char = True-primOpHasSideEffects ReadOffAddrOp_WideChar = True-primOpHasSideEffects ReadOffAddrOp_Int = True-primOpHasSideEffects ReadOffAddrOp_Word = True-primOpHasSideEffects ReadOffAddrOp_Addr = True-primOpHasSideEffects ReadOffAddrOp_Float = True-primOpHasSideEffects ReadOffAddrOp_Double = True-primOpHasSideEffects ReadOffAddrOp_StablePtr = True-primOpHasSideEffects ReadOffAddrOp_Int8 = True-primOpHasSideEffects ReadOffAddrOp_Word8 = True-primOpHasSideEffects ReadOffAddrOp_Int16 = True-primOpHasSideEffects ReadOffAddrOp_Word16 = True-primOpHasSideEffects ReadOffAddrOp_Int32 = True-primOpHasSideEffects ReadOffAddrOp_Word32 = True-primOpHasSideEffects ReadOffAddrOp_Int64 = True-primOpHasSideEffects ReadOffAddrOp_Word64 = True-primOpHasSideEffects WriteOffAddrOp_Char = True-primOpHasSideEffects WriteOffAddrOp_WideChar = True-primOpHasSideEffects WriteOffAddrOp_Int = True-primOpHasSideEffects WriteOffAddrOp_Word = True-primOpHasSideEffects WriteOffAddrOp_Addr = True-primOpHasSideEffects WriteOffAddrOp_Float = True-primOpHasSideEffects WriteOffAddrOp_Double = True-primOpHasSideEffects WriteOffAddrOp_StablePtr = True-primOpHasSideEffects WriteOffAddrOp_Int8 = True-primOpHasSideEffects WriteOffAddrOp_Word8 = True-primOpHasSideEffects WriteOffAddrOp_Int16 = True-primOpHasSideEffects WriteOffAddrOp_Word16 = True-primOpHasSideEffects WriteOffAddrOp_Int32 = True-primOpHasSideEffects WriteOffAddrOp_Word32 = True-primOpHasSideEffects WriteOffAddrOp_Int64 = True-primOpHasSideEffects WriteOffAddrOp_Word64 = True-primOpHasSideEffects InterlockedExchange_Addr = True-primOpHasSideEffects InterlockedExchange_Word = True-primOpHasSideEffects CasAddrOp_Addr = True-primOpHasSideEffects CasAddrOp_Word = True-primOpHasSideEffects CasAddrOp_Word8 = True-primOpHasSideEffects CasAddrOp_Word16 = True-primOpHasSideEffects CasAddrOp_Word32 = True-primOpHasSideEffects CasAddrOp_Word64 = True-primOpHasSideEffects FetchAddAddrOp_Word = True-primOpHasSideEffects FetchSubAddrOp_Word = True-primOpHasSideEffects FetchAndAddrOp_Word = True-primOpHasSideEffects FetchNandAddrOp_Word = True-primOpHasSideEffects FetchOrAddrOp_Word = True-primOpHasSideEffects FetchXorAddrOp_Word = True-primOpHasSideEffects AtomicReadAddrOp_Word = True-primOpHasSideEffects AtomicWriteAddrOp_Word = True-primOpHasSideEffects NewMutVarOp = True-primOpHasSideEffects ReadMutVarOp = True-primOpHasSideEffects WriteMutVarOp = True-primOpHasSideEffects AtomicSwapMutVarOp = True-primOpHasSideEffects AtomicModifyMutVar2Op = True-primOpHasSideEffects AtomicModifyMutVar_Op = True-primOpHasSideEffects CasMutVarOp = True-primOpHasSideEffects CatchOp = True-primOpHasSideEffects RaiseIOOp = True-primOpHasSideEffects MaskAsyncExceptionsOp = True-primOpHasSideEffects MaskUninterruptibleOp = True-primOpHasSideEffects UnmaskAsyncExceptionsOp = True-primOpHasSideEffects MaskStatus = True-primOpHasSideEffects NewPromptTagOp = True-primOpHasSideEffects PromptOp = True-primOpHasSideEffects Control0Op = True-primOpHasSideEffects AtomicallyOp = True-primOpHasSideEffects RetryOp = True-primOpHasSideEffects CatchRetryOp = True-primOpHasSideEffects CatchSTMOp = True-primOpHasSideEffects NewTVarOp = True-primOpHasSideEffects ReadTVarOp = True-primOpHasSideEffects ReadTVarIOOp = True-primOpHasSideEffects WriteTVarOp = True-primOpHasSideEffects NewMVarOp = True-primOpHasSideEffects TakeMVarOp = True-primOpHasSideEffects TryTakeMVarOp = True-primOpHasSideEffects PutMVarOp = True-primOpHasSideEffects TryPutMVarOp = True-primOpHasSideEffects ReadMVarOp = True-primOpHasSideEffects TryReadMVarOp = True-primOpHasSideEffects IsEmptyMVarOp = True-primOpHasSideEffects NewIOPortOp = True-primOpHasSideEffects ReadIOPortOp = True-primOpHasSideEffects WriteIOPortOp = True-primOpHasSideEffects DelayOp = True-primOpHasSideEffects WaitReadOp = True-primOpHasSideEffects WaitWriteOp = True-primOpHasSideEffects ForkOp = True-primOpHasSideEffects ForkOnOp = True-primOpHasSideEffects KillThreadOp = True-primOpHasSideEffects YieldOp = True-primOpHasSideEffects MyThreadIdOp = True-primOpHasSideEffects LabelThreadOp = True-primOpHasSideEffects IsCurrentThreadBoundOp = True-primOpHasSideEffects NoDuplicateOp = True-primOpHasSideEffects ThreadStatusOp = True-primOpHasSideEffects ListThreadsOp = True-primOpHasSideEffects MkWeakOp = True-primOpHasSideEffects MkWeakNoFinalizerOp = True-primOpHasSideEffects AddCFinalizerToWeakOp = True-primOpHasSideEffects DeRefWeakOp = True-primOpHasSideEffects FinalizeWeakOp = True-primOpHasSideEffects TouchOp = True-primOpHasSideEffects MakeStablePtrOp = True-primOpHasSideEffects DeRefStablePtrOp = True-primOpHasSideEffects EqStablePtrOp = True-primOpHasSideEffects MakeStableNameOp = True-primOpHasSideEffects CompactNewOp = True-primOpHasSideEffects CompactResizeOp = True-primOpHasSideEffects CompactAllocateBlockOp = True-primOpHasSideEffects CompactFixupPointersOp = True-primOpHasSideEffects CompactAdd = True-primOpHasSideEffects CompactAddWithSharing = True-primOpHasSideEffects CompactSize = True-primOpHasSideEffects ParOp = True-primOpHasSideEffects SparkOp = True-primOpHasSideEffects GetSparkOp = True-primOpHasSideEffects NumSparks = True-primOpHasSideEffects NewBCOOp = True-primOpHasSideEffects TraceEventOp = True-primOpHasSideEffects TraceEventBinaryOp = True-primOpHasSideEffects TraceMarkerOp = True-primOpHasSideEffects SetThreadAllocationCounter = True-primOpHasSideEffects (VecReadByteArrayOp _ _ _) = True-primOpHasSideEffects (VecWriteByteArrayOp _ _ _) = True-primOpHasSideEffects (VecReadOffAddrOp _ _ _) = True-primOpHasSideEffects (VecWriteOffAddrOp _ _ _) = True-primOpHasSideEffects (VecReadScalarByteArrayOp _ _ _) = True-primOpHasSideEffects (VecWriteScalarByteArrayOp _ _ _) = True-primOpHasSideEffects (VecReadScalarOffAddrOp _ _ _) = True-primOpHasSideEffects (VecWriteScalarOffAddrOp _ _ _) = True-primOpHasSideEffects PrefetchByteArrayOp3 = True-primOpHasSideEffects PrefetchMutableByteArrayOp3 = True-primOpHasSideEffects PrefetchAddrOp3 = True-primOpHasSideEffects PrefetchValueOp3 = True-primOpHasSideEffects PrefetchByteArrayOp2 = True-primOpHasSideEffects PrefetchMutableByteArrayOp2 = True-primOpHasSideEffects PrefetchAddrOp2 = True-primOpHasSideEffects PrefetchValueOp2 = True-primOpHasSideEffects PrefetchByteArrayOp1 = True-primOpHasSideEffects PrefetchMutableByteArrayOp1 = True-primOpHasSideEffects PrefetchAddrOp1 = True-primOpHasSideEffects PrefetchValueOp1 = True-primOpHasSideEffects PrefetchByteArrayOp0 = True-primOpHasSideEffects PrefetchMutableByteArrayOp0 = True-primOpHasSideEffects PrefetchAddrOp0 = True-primOpHasSideEffects PrefetchValueOp0 = True-primOpHasSideEffects _ = False
+ ghc-lib/stage0/compiler/build/primop-is-cheap.hs-incl view
@@ -0,0 +1,3 @@+primOpIsCheap DataToTagSmallOp = True+primOpIsCheap DataToTagLargeOp = True+primOpIsCheap _thisOp =  primOpOkForSpeculation _thisOp 
+ ghc-lib/stage0/compiler/build/primop-is-work-free.hs-incl view
@@ -0,0 +1,8 @@+primOpIsWorkFree RaiseOp = True+primOpIsWorkFree RaiseUnderflowOp = True+primOpIsWorkFree RaiseOverflowOp = True+primOpIsWorkFree RaiseDivZeroOp = True+primOpIsWorkFree RaiseIOOp = True+primOpIsWorkFree TouchOp = False+primOpIsWorkFree SeqOp = True+primOpIsWorkFree _thisOp =  primOpCodeSize _thisOp == 0 
ghc-lib/stage0/compiler/build/primop-list.hs-incl view
@@ -291,6 +291,8 @@    , DoublePowerOp    , DoubleDecode_2IntOp    , DoubleDecode_Int64Op+   , CastDoubleToWord64Op+   , CastWord64ToDoubleOp    , FloatGtOp    , FloatGeOp    , FloatEqOp@@ -324,6 +326,8 @@    , FloatPowerOp    , FloatToDoubleOp    , FloatDecode_IntOp+   , CastFloatToWord32Op+   , CastWord32ToFloatOp    , FloatFMAdd    , FloatFMSub    , FloatFNMAdd@@ -374,6 +378,7 @@    , ShrinkMutableByteArrayOp_Char    , ResizeMutableByteArrayOp_Char    , UnsafeFreezeByteArrayOp+   , UnsafeThawByteArrayOp    , SizeofByteArrayOp    , SizeofMutableByteArrayOp    , GetSizeofMutableByteArrayOp@@ -518,6 +523,20 @@    , IndexOffAddrOp_Word32    , IndexOffAddrOp_Int64    , IndexOffAddrOp_Word64+   , IndexOffAddrOp_Word8AsChar+   , IndexOffAddrOp_Word8AsWideChar+   , IndexOffAddrOp_Word8AsInt+   , IndexOffAddrOp_Word8AsWord+   , IndexOffAddrOp_Word8AsAddr+   , IndexOffAddrOp_Word8AsFloat+   , IndexOffAddrOp_Word8AsDouble+   , IndexOffAddrOp_Word8AsStablePtr+   , IndexOffAddrOp_Word8AsInt16+   , IndexOffAddrOp_Word8AsWord16+   , IndexOffAddrOp_Word8AsInt32+   , IndexOffAddrOp_Word8AsWord32+   , IndexOffAddrOp_Word8AsInt64+   , IndexOffAddrOp_Word8AsWord64    , ReadOffAddrOp_Char    , ReadOffAddrOp_WideChar    , ReadOffAddrOp_Int@@ -534,6 +553,20 @@    , ReadOffAddrOp_Word32    , ReadOffAddrOp_Int64    , ReadOffAddrOp_Word64+   , ReadOffAddrOp_Word8AsChar+   , ReadOffAddrOp_Word8AsWideChar+   , ReadOffAddrOp_Word8AsInt+   , ReadOffAddrOp_Word8AsWord+   , ReadOffAddrOp_Word8AsAddr+   , ReadOffAddrOp_Word8AsFloat+   , ReadOffAddrOp_Word8AsDouble+   , ReadOffAddrOp_Word8AsStablePtr+   , ReadOffAddrOp_Word8AsInt16+   , ReadOffAddrOp_Word8AsWord16+   , ReadOffAddrOp_Word8AsInt32+   , ReadOffAddrOp_Word8AsWord32+   , ReadOffAddrOp_Word8AsInt64+   , ReadOffAddrOp_Word8AsWord64    , WriteOffAddrOp_Char    , WriteOffAddrOp_WideChar    , WriteOffAddrOp_Int@@ -550,6 +583,20 @@    , WriteOffAddrOp_Word32    , WriteOffAddrOp_Int64    , WriteOffAddrOp_Word64+   , WriteOffAddrOp_Word8AsChar+   , WriteOffAddrOp_Word8AsWideChar+   , WriteOffAddrOp_Word8AsInt+   , WriteOffAddrOp_Word8AsWord+   , WriteOffAddrOp_Word8AsAddr+   , WriteOffAddrOp_Word8AsFloat+   , WriteOffAddrOp_Word8AsDouble+   , WriteOffAddrOp_Word8AsStablePtr+   , WriteOffAddrOp_Word8AsInt16+   , WriteOffAddrOp_Word8AsWord16+   , WriteOffAddrOp_Word8AsInt32+   , WriteOffAddrOp_Word8AsWord32+   , WriteOffAddrOp_Word8AsInt64+   , WriteOffAddrOp_Word8AsWord64    , InterlockedExchange_Addr    , InterlockedExchange_Word    , CasAddrOp_Addr@@ -648,7 +695,8 @@    , GetSparkOp    , NumSparks    , KeepAliveOp-   , DataToTagOp+   , DataToTagSmallOp+   , DataToTagLargeOp    , TagToEnumOp    , AddrToAnyOp    , AnyToAddrOp
ghc-lib/stage0/compiler/build/primop-out-of-line.hs-incl view
@@ -109,4 +109,4 @@ primOpOutOfLine TraceEventBinaryOp = True primOpOutOfLine TraceMarkerOp = True primOpOutOfLine SetThreadAllocationCounter = True-primOpOutOfLine _ = False+primOpOutOfLine _thisOp = False
ghc-lib/stage0/compiler/build/primop-primop-info.hs-incl view
@@ -291,6 +291,8 @@ primOpInfo DoublePowerOp = mkGenPrimOp (fsLit "**##")  [] [doublePrimTy, doublePrimTy] (doublePrimTy) primOpInfo DoubleDecode_2IntOp = mkGenPrimOp (fsLit "decodeDouble_2Int#")  [] [doublePrimTy] ((mkTupleTy Unboxed [intPrimTy, wordPrimTy, wordPrimTy, intPrimTy])) primOpInfo DoubleDecode_Int64Op = mkGenPrimOp (fsLit "decodeDouble_Int64#")  [] [doublePrimTy] ((mkTupleTy Unboxed [int64PrimTy, intPrimTy]))+primOpInfo CastDoubleToWord64Op = mkGenPrimOp (fsLit "castDoubleToWord64#")  [] [doublePrimTy] (word64PrimTy)+primOpInfo CastWord64ToDoubleOp = mkGenPrimOp (fsLit "castWord64ToDouble#")  [] [word64PrimTy] (doublePrimTy) primOpInfo FloatGtOp = mkCompare (fsLit "gtFloat#") floatPrimTy primOpInfo FloatGeOp = mkCompare (fsLit "geFloat#") floatPrimTy primOpInfo FloatEqOp = mkCompare (fsLit "eqFloat#") floatPrimTy@@ -324,6 +326,8 @@ primOpInfo FloatPowerOp = mkGenPrimOp (fsLit "powerFloat#")  [] [floatPrimTy, floatPrimTy] (floatPrimTy) primOpInfo FloatToDoubleOp = mkGenPrimOp (fsLit "float2Double#")  [] [floatPrimTy] (doublePrimTy) primOpInfo FloatDecode_IntOp = mkGenPrimOp (fsLit "decodeFloat_Int#")  [] [floatPrimTy] ((mkTupleTy Unboxed [intPrimTy, intPrimTy]))+primOpInfo CastFloatToWord32Op = mkGenPrimOp (fsLit "castFloatToWord32#")  [] [floatPrimTy] (word32PrimTy)+primOpInfo CastWord32ToFloatOp = mkGenPrimOp (fsLit "castWord32ToFloat#")  [] [word32PrimTy] (floatPrimTy) primOpInfo FloatFMAdd = mkGenPrimOp (fsLit "fmaddFloat#")  [] [floatPrimTy, floatPrimTy, floatPrimTy] (floatPrimTy) primOpInfo FloatFMSub = mkGenPrimOp (fsLit "fmsubFloat#")  [] [floatPrimTy, floatPrimTy, floatPrimTy] (floatPrimTy) primOpInfo FloatFNMAdd = mkGenPrimOp (fsLit "fnmaddFloat#")  [] [floatPrimTy, floatPrimTy, floatPrimTy] (floatPrimTy)@@ -374,6 +378,7 @@ primOpInfo ShrinkMutableByteArrayOp_Char = mkGenPrimOp (fsLit "shrinkMutableByteArray#")  [deltaTyVarSpec] [mkMutableByteArrayPrimTy deltaTy, intPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy) primOpInfo ResizeMutableByteArrayOp_Char = mkGenPrimOp (fsLit "resizeMutableByteArray#")  [deltaTyVarSpec] [mkMutableByteArrayPrimTy deltaTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkMutableByteArrayPrimTy deltaTy])) primOpInfo UnsafeFreezeByteArrayOp = mkGenPrimOp (fsLit "unsafeFreezeByteArray#")  [deltaTyVarSpec] [mkMutableByteArrayPrimTy deltaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, byteArrayPrimTy]))+primOpInfo UnsafeThawByteArrayOp = mkGenPrimOp (fsLit "unsafeThawByteArray#")  [deltaTyVarSpec] [byteArrayPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkMutableByteArrayPrimTy deltaTy])) primOpInfo SizeofByteArrayOp = mkGenPrimOp (fsLit "sizeofByteArray#")  [] [byteArrayPrimTy] (intPrimTy) primOpInfo SizeofMutableByteArrayOp = mkGenPrimOp (fsLit "sizeofMutableByteArray#")  [deltaTyVarSpec] [mkMutableByteArrayPrimTy deltaTy] (intPrimTy) primOpInfo GetSizeofMutableByteArrayOp = mkGenPrimOp (fsLit "getSizeofMutableByteArray#")  [deltaTyVarSpec] [mkMutableByteArrayPrimTy deltaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy]))@@ -518,6 +523,20 @@ primOpInfo IndexOffAddrOp_Word32 = mkGenPrimOp (fsLit "indexWord32OffAddr#")  [] [addrPrimTy, intPrimTy] (word32PrimTy) primOpInfo IndexOffAddrOp_Int64 = mkGenPrimOp (fsLit "indexInt64OffAddr#")  [] [addrPrimTy, intPrimTy] (int64PrimTy) primOpInfo IndexOffAddrOp_Word64 = mkGenPrimOp (fsLit "indexWord64OffAddr#")  [] [addrPrimTy, intPrimTy] (word64PrimTy)+primOpInfo IndexOffAddrOp_Word8AsChar = mkGenPrimOp (fsLit "indexWord8OffAddrAsChar#")  [] [addrPrimTy, intPrimTy] (charPrimTy)+primOpInfo IndexOffAddrOp_Word8AsWideChar = mkGenPrimOp (fsLit "indexWord8OffAddrAsWideChar#")  [] [addrPrimTy, intPrimTy] (charPrimTy)+primOpInfo IndexOffAddrOp_Word8AsInt = mkGenPrimOp (fsLit "indexWord8OffAddrAsInt#")  [] [addrPrimTy, intPrimTy] (intPrimTy)+primOpInfo IndexOffAddrOp_Word8AsWord = mkGenPrimOp (fsLit "indexWord8OffAddrAsWord#")  [] [addrPrimTy, intPrimTy] (wordPrimTy)+primOpInfo IndexOffAddrOp_Word8AsAddr = mkGenPrimOp (fsLit "indexWord8OffAddrAsAddr#")  [] [addrPrimTy, intPrimTy] (addrPrimTy)+primOpInfo IndexOffAddrOp_Word8AsFloat = mkGenPrimOp (fsLit "indexWord8OffAddrAsFloat#")  [] [addrPrimTy, intPrimTy] (floatPrimTy)+primOpInfo IndexOffAddrOp_Word8AsDouble = mkGenPrimOp (fsLit "indexWord8OffAddrAsDouble#")  [] [addrPrimTy, intPrimTy] (doublePrimTy)+primOpInfo IndexOffAddrOp_Word8AsStablePtr = mkGenPrimOp (fsLit "indexWord8OffAddrAsStablePtr#")  [alphaTyVarSpec] [addrPrimTy, intPrimTy] (mkStablePtrPrimTy alphaTy)+primOpInfo IndexOffAddrOp_Word8AsInt16 = mkGenPrimOp (fsLit "indexWord8OffAddrAsInt16#")  [] [addrPrimTy, intPrimTy] (int16PrimTy)+primOpInfo IndexOffAddrOp_Word8AsWord16 = mkGenPrimOp (fsLit "indexWord8OffAddrAsWord16#")  [] [addrPrimTy, intPrimTy] (word16PrimTy)+primOpInfo IndexOffAddrOp_Word8AsInt32 = mkGenPrimOp (fsLit "indexWord8OffAddrAsInt32#")  [] [addrPrimTy, intPrimTy] (int32PrimTy)+primOpInfo IndexOffAddrOp_Word8AsWord32 = mkGenPrimOp (fsLit "indexWord8OffAddrAsWord32#")  [] [addrPrimTy, intPrimTy] (word32PrimTy)+primOpInfo IndexOffAddrOp_Word8AsInt64 = mkGenPrimOp (fsLit "indexWord8OffAddrAsInt64#")  [] [addrPrimTy, intPrimTy] (int64PrimTy)+primOpInfo IndexOffAddrOp_Word8AsWord64 = mkGenPrimOp (fsLit "indexWord8OffAddrAsWord64#")  [] [addrPrimTy, intPrimTy] (word64PrimTy) primOpInfo ReadOffAddrOp_Char = mkGenPrimOp (fsLit "readCharOffAddr#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, charPrimTy])) primOpInfo ReadOffAddrOp_WideChar = mkGenPrimOp (fsLit "readWideCharOffAddr#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, charPrimTy])) primOpInfo ReadOffAddrOp_Int = mkGenPrimOp (fsLit "readIntOffAddr#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy]))@@ -534,6 +553,20 @@ primOpInfo ReadOffAddrOp_Word32 = mkGenPrimOp (fsLit "readWord32OffAddr#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, word32PrimTy])) primOpInfo ReadOffAddrOp_Int64 = mkGenPrimOp (fsLit "readInt64OffAddr#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, int64PrimTy])) primOpInfo ReadOffAddrOp_Word64 = mkGenPrimOp (fsLit "readWord64OffAddr#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, word64PrimTy]))+primOpInfo ReadOffAddrOp_Word8AsChar = mkGenPrimOp (fsLit "readWord8OffAddrAsChar#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, charPrimTy]))+primOpInfo ReadOffAddrOp_Word8AsWideChar = mkGenPrimOp (fsLit "readWord8OffAddrAsWideChar#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, charPrimTy]))+primOpInfo ReadOffAddrOp_Word8AsInt = mkGenPrimOp (fsLit "readWord8OffAddrAsInt#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy]))+primOpInfo ReadOffAddrOp_Word8AsWord = mkGenPrimOp (fsLit "readWord8OffAddrAsWord#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, wordPrimTy]))+primOpInfo ReadOffAddrOp_Word8AsAddr = mkGenPrimOp (fsLit "readWord8OffAddrAsAddr#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, addrPrimTy]))+primOpInfo ReadOffAddrOp_Word8AsFloat = mkGenPrimOp (fsLit "readWord8OffAddrAsFloat#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, floatPrimTy]))+primOpInfo ReadOffAddrOp_Word8AsDouble = mkGenPrimOp (fsLit "readWord8OffAddrAsDouble#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, doublePrimTy]))+primOpInfo ReadOffAddrOp_Word8AsStablePtr = mkGenPrimOp (fsLit "readWord8OffAddrAsStablePtr#")  [deltaTyVarSpec, alphaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, mkStablePtrPrimTy alphaTy]))+primOpInfo ReadOffAddrOp_Word8AsInt16 = mkGenPrimOp (fsLit "readWord8OffAddrAsInt16#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, int16PrimTy]))+primOpInfo ReadOffAddrOp_Word8AsWord16 = mkGenPrimOp (fsLit "readWord8OffAddrAsWord16#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, word16PrimTy]))+primOpInfo ReadOffAddrOp_Word8AsInt32 = mkGenPrimOp (fsLit "readWord8OffAddrAsInt32#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, int32PrimTy]))+primOpInfo ReadOffAddrOp_Word8AsWord32 = mkGenPrimOp (fsLit "readWord8OffAddrAsWord32#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, word32PrimTy]))+primOpInfo ReadOffAddrOp_Word8AsInt64 = mkGenPrimOp (fsLit "readWord8OffAddrAsInt64#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, int64PrimTy]))+primOpInfo ReadOffAddrOp_Word8AsWord64 = mkGenPrimOp (fsLit "readWord8OffAddrAsWord64#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, word64PrimTy])) primOpInfo WriteOffAddrOp_Char = mkGenPrimOp (fsLit "writeCharOffAddr#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, charPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy) primOpInfo WriteOffAddrOp_WideChar = mkGenPrimOp (fsLit "writeWideCharOffAddr#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, charPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy) primOpInfo WriteOffAddrOp_Int = mkGenPrimOp (fsLit "writeIntOffAddr#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, intPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)@@ -550,6 +583,20 @@ primOpInfo WriteOffAddrOp_Word32 = mkGenPrimOp (fsLit "writeWord32OffAddr#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, word32PrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy) primOpInfo WriteOffAddrOp_Int64 = mkGenPrimOp (fsLit "writeInt64OffAddr#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, int64PrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy) primOpInfo WriteOffAddrOp_Word64 = mkGenPrimOp (fsLit "writeWord64OffAddr#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, word64PrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo WriteOffAddrOp_Word8AsChar = mkGenPrimOp (fsLit "writeWord8OffAddrAsChar#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, charPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo WriteOffAddrOp_Word8AsWideChar = mkGenPrimOp (fsLit "writeWord8OffAddrAsWideChar#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, charPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo WriteOffAddrOp_Word8AsInt = mkGenPrimOp (fsLit "writeWord8OffAddrAsInt#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, intPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo WriteOffAddrOp_Word8AsWord = mkGenPrimOp (fsLit "writeWord8OffAddrAsWord#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, wordPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo WriteOffAddrOp_Word8AsAddr = mkGenPrimOp (fsLit "writeWord8OffAddrAsAddr#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, addrPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo WriteOffAddrOp_Word8AsFloat = mkGenPrimOp (fsLit "writeWord8OffAddrAsFloat#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, floatPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo WriteOffAddrOp_Word8AsDouble = mkGenPrimOp (fsLit "writeWord8OffAddrAsDouble#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, doublePrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo WriteOffAddrOp_Word8AsStablePtr = mkGenPrimOp (fsLit "writeWord8OffAddrAsStablePtr#")  [alphaTyVarSpec, deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStablePtrPrimTy alphaTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo WriteOffAddrOp_Word8AsInt16 = mkGenPrimOp (fsLit "writeWord8OffAddrAsInt16#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, int16PrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo WriteOffAddrOp_Word8AsWord16 = mkGenPrimOp (fsLit "writeWord8OffAddrAsWord16#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, word16PrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo WriteOffAddrOp_Word8AsInt32 = mkGenPrimOp (fsLit "writeWord8OffAddrAsInt32#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, int32PrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo WriteOffAddrOp_Word8AsWord32 = mkGenPrimOp (fsLit "writeWord8OffAddrAsWord32#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, word32PrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo WriteOffAddrOp_Word8AsInt64 = mkGenPrimOp (fsLit "writeWord8OffAddrAsInt64#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, int64PrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)+primOpInfo WriteOffAddrOp_Word8AsWord64 = mkGenPrimOp (fsLit "writeWord8OffAddrAsWord64#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, word64PrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy) primOpInfo InterlockedExchange_Addr = mkGenPrimOp (fsLit "atomicExchangeAddrAddr#")  [deltaTyVarSpec] [addrPrimTy, addrPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, addrPrimTy])) primOpInfo InterlockedExchange_Word = mkGenPrimOp (fsLit "atomicExchangeWordAddr#")  [deltaTyVarSpec] [addrPrimTy, wordPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, wordPrimTy])) primOpInfo CasAddrOp_Addr = mkGenPrimOp (fsLit "atomicCasAddrAddr#")  [deltaTyVarSpec] [addrPrimTy, addrPrimTy, addrPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, addrPrimTy]))@@ -648,7 +695,8 @@ primOpInfo GetSparkOp = mkGenPrimOp (fsLit "getSpark#")  [deltaTyVarSpec, alphaTyVarSpec] [mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy, alphaTy])) primOpInfo NumSparks = mkGenPrimOp (fsLit "numSparks#")  [deltaTyVarSpec] [mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy])) primOpInfo KeepAliveOp = mkGenPrimOp (fsLit "keepAlive#")  [levity1TyVarInf, runtimeRep2TyVarInf, levPolyAlphaTyVarSpec, deltaTyVarSpec, openBetaTyVarSpec] [levPolyAlphaTy, mkStatePrimTy deltaTy, (mkVisFunTyMany (mkStatePrimTy deltaTy) (openBetaTy))] (openBetaTy)-primOpInfo DataToTagOp = mkGenPrimOp (fsLit "dataToTag#")  [alphaTyVarSpec] [alphaTy] (intPrimTy)+primOpInfo DataToTagSmallOp = mkGenPrimOp (fsLit "dataToTagSmall#")  [levity1TyVarInf, levPolyAlphaTyVarSpec] [levPolyAlphaTy] (intPrimTy)+primOpInfo DataToTagLargeOp = mkGenPrimOp (fsLit "dataToTagLarge#")  [levity1TyVarInf, levPolyAlphaTyVarSpec] [levPolyAlphaTy] (intPrimTy) primOpInfo TagToEnumOp = mkGenPrimOp (fsLit "tagToEnum#")  [alphaTyVarSpec] [intPrimTy] (alphaTy) primOpInfo AddrToAnyOp = mkGenPrimOp (fsLit "addrToAny#")  [levity1TyVarInf, levPolyAlphaTyVarSpec] [addrPrimTy] ((mkTupleTy Unboxed [levPolyAlphaTy])) primOpInfo AnyToAddrOp = mkGenPrimOp (fsLit "anyToAddr#")  [alphaTyVarSpec] [alphaTy, mkStatePrimTy realWorldTy] ((mkTupleTy Unboxed [mkStatePrimTy realWorldTy, addrPrimTy]))@@ -660,7 +708,7 @@ primOpInfo GetCCSOfOp = mkGenPrimOp (fsLit "getCCSOf#")  [alphaTyVarSpec, deltaTyVarSpec] [alphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, addrPrimTy])) primOpInfo GetCurrentCCSOp = mkGenPrimOp (fsLit "getCurrentCCS#")  [alphaTyVarSpec, deltaTyVarSpec] [alphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, addrPrimTy])) primOpInfo ClearCCSOp = mkGenPrimOp (fsLit "clearCCS#")  [deltaTyVarSpec, alphaTyVarSpec] [(mkVisFunTyMany (mkStatePrimTy deltaTy) ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, alphaTy]))), mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, alphaTy]))-primOpInfo WhereFromOp = mkGenPrimOp (fsLit "whereFrom#")  [alphaTyVarSpec, deltaTyVarSpec] [alphaTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, addrPrimTy]))+primOpInfo WhereFromOp = mkGenPrimOp (fsLit "whereFrom#")  [alphaTyVarSpec, deltaTyVarSpec] [alphaTy, addrPrimTy, mkStatePrimTy deltaTy] ((mkTupleTy Unboxed [mkStatePrimTy deltaTy, intPrimTy])) primOpInfo TraceEventOp = mkGenPrimOp (fsLit "traceEvent#")  [deltaTyVarSpec] [addrPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy) primOpInfo TraceEventBinaryOp = mkGenPrimOp (fsLit "traceBinaryEvent#")  [deltaTyVarSpec] [addrPrimTy, intPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy) primOpInfo TraceMarkerOp = mkGenPrimOp (fsLit "traceMarker#")  [deltaTyVarSpec] [addrPrimTy, mkStatePrimTy deltaTy] (mkStatePrimTy deltaTy)
ghc-lib/stage0/compiler/build/primop-strictness.hs-incl view
@@ -11,7 +11,7 @@ primOpStrictness MaskAsyncExceptionsOp =  \ _arity -> mkClosedDmdSig [strictOnceApply1Dmd,topDmd] topDiv  primOpStrictness MaskUninterruptibleOp =  \ _arity -> mkClosedDmdSig [strictOnceApply1Dmd,topDmd] topDiv  primOpStrictness UnmaskAsyncExceptionsOp =  \ _arity -> mkClosedDmdSig [strictOnceApply1Dmd,topDmd] topDiv -primOpStrictness PromptOp =  \ _arity -> mkClosedDmdSig [topDmd, lazyApply1Dmd, topDmd] topDiv +primOpStrictness PromptOp =  \ _arity -> mkClosedDmdSig [topDmd, strictOnceApply1Dmd, topDmd] topDiv  primOpStrictness Control0Op =  \ _arity -> mkClosedDmdSig [topDmd, lazyApply2Dmd, topDmd] topDiv  primOpStrictness AtomicallyOp =  \ _arity -> mkClosedDmdSig [strictManyApply1Dmd,topDmd] topDiv  primOpStrictness RetryOp =  \ _arity -> mkClosedDmdSig [topDmd] botDiv @@ -27,5 +27,6 @@                                               , lazyApply1Dmd                                               , topDmd ] topDiv  primOpStrictness KeepAliveOp =  \ _arity -> mkClosedDmdSig [topDmd, topDmd, strictOnceApply1Dmd] topDiv -primOpStrictness DataToTagOp =  \ _arity -> mkClosedDmdSig [evalDmd] topDiv -primOpStrictness _ =  \ arity -> mkClosedDmdSig (replicate arity topDmd) topDiv +primOpStrictness DataToTagSmallOp =  \ _arity -> mkClosedDmdSig [evalDmd] topDiv +primOpStrictness DataToTagLargeOp =  \ _arity -> mkClosedDmdSig [evalDmd] topDiv +primOpStrictness _thisOp =  \ arity -> mkClosedDmdSig (replicate arity topDmd) topDiv 
ghc-lib/stage0/compiler/build/primop-tag.hs-incl view
@@ -1,1328 +1,1376 @@ maxPrimOpTag :: Int-maxPrimOpTag = 1324-primOpTag :: PrimOp -> Int-primOpTag CharGtOp = 0-primOpTag CharGeOp = 1-primOpTag CharEqOp = 2-primOpTag CharNeOp = 3-primOpTag CharLtOp = 4-primOpTag CharLeOp = 5-primOpTag OrdOp = 6-primOpTag Int8ToIntOp = 7-primOpTag IntToInt8Op = 8-primOpTag Int8NegOp = 9-primOpTag Int8AddOp = 10-primOpTag Int8SubOp = 11-primOpTag Int8MulOp = 12-primOpTag Int8QuotOp = 13-primOpTag Int8RemOp = 14-primOpTag Int8QuotRemOp = 15-primOpTag Int8SllOp = 16-primOpTag Int8SraOp = 17-primOpTag Int8SrlOp = 18-primOpTag Int8ToWord8Op = 19-primOpTag Int8EqOp = 20-primOpTag Int8GeOp = 21-primOpTag Int8GtOp = 22-primOpTag Int8LeOp = 23-primOpTag Int8LtOp = 24-primOpTag Int8NeOp = 25-primOpTag Word8ToWordOp = 26-primOpTag WordToWord8Op = 27-primOpTag Word8AddOp = 28-primOpTag Word8SubOp = 29-primOpTag Word8MulOp = 30-primOpTag Word8QuotOp = 31-primOpTag Word8RemOp = 32-primOpTag Word8QuotRemOp = 33-primOpTag Word8AndOp = 34-primOpTag Word8OrOp = 35-primOpTag Word8XorOp = 36-primOpTag Word8NotOp = 37-primOpTag Word8SllOp = 38-primOpTag Word8SrlOp = 39-primOpTag Word8ToInt8Op = 40-primOpTag Word8EqOp = 41-primOpTag Word8GeOp = 42-primOpTag Word8GtOp = 43-primOpTag Word8LeOp = 44-primOpTag Word8LtOp = 45-primOpTag Word8NeOp = 46-primOpTag Int16ToIntOp = 47-primOpTag IntToInt16Op = 48-primOpTag Int16NegOp = 49-primOpTag Int16AddOp = 50-primOpTag Int16SubOp = 51-primOpTag Int16MulOp = 52-primOpTag Int16QuotOp = 53-primOpTag Int16RemOp = 54-primOpTag Int16QuotRemOp = 55-primOpTag Int16SllOp = 56-primOpTag Int16SraOp = 57-primOpTag Int16SrlOp = 58-primOpTag Int16ToWord16Op = 59-primOpTag Int16EqOp = 60-primOpTag Int16GeOp = 61-primOpTag Int16GtOp = 62-primOpTag Int16LeOp = 63-primOpTag Int16LtOp = 64-primOpTag Int16NeOp = 65-primOpTag Word16ToWordOp = 66-primOpTag WordToWord16Op = 67-primOpTag Word16AddOp = 68-primOpTag Word16SubOp = 69-primOpTag Word16MulOp = 70-primOpTag Word16QuotOp = 71-primOpTag Word16RemOp = 72-primOpTag Word16QuotRemOp = 73-primOpTag Word16AndOp = 74-primOpTag Word16OrOp = 75-primOpTag Word16XorOp = 76-primOpTag Word16NotOp = 77-primOpTag Word16SllOp = 78-primOpTag Word16SrlOp = 79-primOpTag Word16ToInt16Op = 80-primOpTag Word16EqOp = 81-primOpTag Word16GeOp = 82-primOpTag Word16GtOp = 83-primOpTag Word16LeOp = 84-primOpTag Word16LtOp = 85-primOpTag Word16NeOp = 86-primOpTag Int32ToIntOp = 87-primOpTag IntToInt32Op = 88-primOpTag Int32NegOp = 89-primOpTag Int32AddOp = 90-primOpTag Int32SubOp = 91-primOpTag Int32MulOp = 92-primOpTag Int32QuotOp = 93-primOpTag Int32RemOp = 94-primOpTag Int32QuotRemOp = 95-primOpTag Int32SllOp = 96-primOpTag Int32SraOp = 97-primOpTag Int32SrlOp = 98-primOpTag Int32ToWord32Op = 99-primOpTag Int32EqOp = 100-primOpTag Int32GeOp = 101-primOpTag Int32GtOp = 102-primOpTag Int32LeOp = 103-primOpTag Int32LtOp = 104-primOpTag Int32NeOp = 105-primOpTag Word32ToWordOp = 106-primOpTag WordToWord32Op = 107-primOpTag Word32AddOp = 108-primOpTag Word32SubOp = 109-primOpTag Word32MulOp = 110-primOpTag Word32QuotOp = 111-primOpTag Word32RemOp = 112-primOpTag Word32QuotRemOp = 113-primOpTag Word32AndOp = 114-primOpTag Word32OrOp = 115-primOpTag Word32XorOp = 116-primOpTag Word32NotOp = 117-primOpTag Word32SllOp = 118-primOpTag Word32SrlOp = 119-primOpTag Word32ToInt32Op = 120-primOpTag Word32EqOp = 121-primOpTag Word32GeOp = 122-primOpTag Word32GtOp = 123-primOpTag Word32LeOp = 124-primOpTag Word32LtOp = 125-primOpTag Word32NeOp = 126-primOpTag Int64ToIntOp = 127-primOpTag IntToInt64Op = 128-primOpTag Int64NegOp = 129-primOpTag Int64AddOp = 130-primOpTag Int64SubOp = 131-primOpTag Int64MulOp = 132-primOpTag Int64QuotOp = 133-primOpTag Int64RemOp = 134-primOpTag Int64SllOp = 135-primOpTag Int64SraOp = 136-primOpTag Int64SrlOp = 137-primOpTag Int64ToWord64Op = 138-primOpTag Int64EqOp = 139-primOpTag Int64GeOp = 140-primOpTag Int64GtOp = 141-primOpTag Int64LeOp = 142-primOpTag Int64LtOp = 143-primOpTag Int64NeOp = 144-primOpTag Word64ToWordOp = 145-primOpTag WordToWord64Op = 146-primOpTag Word64AddOp = 147-primOpTag Word64SubOp = 148-primOpTag Word64MulOp = 149-primOpTag Word64QuotOp = 150-primOpTag Word64RemOp = 151-primOpTag Word64AndOp = 152-primOpTag Word64OrOp = 153-primOpTag Word64XorOp = 154-primOpTag Word64NotOp = 155-primOpTag Word64SllOp = 156-primOpTag Word64SrlOp = 157-primOpTag Word64ToInt64Op = 158-primOpTag Word64EqOp = 159-primOpTag Word64GeOp = 160-primOpTag Word64GtOp = 161-primOpTag Word64LeOp = 162-primOpTag Word64LtOp = 163-primOpTag Word64NeOp = 164-primOpTag IntAddOp = 165-primOpTag IntSubOp = 166-primOpTag IntMulOp = 167-primOpTag IntMul2Op = 168-primOpTag IntMulMayOfloOp = 169-primOpTag IntQuotOp = 170-primOpTag IntRemOp = 171-primOpTag IntQuotRemOp = 172-primOpTag IntAndOp = 173-primOpTag IntOrOp = 174-primOpTag IntXorOp = 175-primOpTag IntNotOp = 176-primOpTag IntNegOp = 177-primOpTag IntAddCOp = 178-primOpTag IntSubCOp = 179-primOpTag IntGtOp = 180-primOpTag IntGeOp = 181-primOpTag IntEqOp = 182-primOpTag IntNeOp = 183-primOpTag IntLtOp = 184-primOpTag IntLeOp = 185-primOpTag ChrOp = 186-primOpTag IntToWordOp = 187-primOpTag IntToFloatOp = 188-primOpTag IntToDoubleOp = 189-primOpTag WordToFloatOp = 190-primOpTag WordToDoubleOp = 191-primOpTag IntSllOp = 192-primOpTag IntSraOp = 193-primOpTag IntSrlOp = 194-primOpTag WordAddOp = 195-primOpTag WordAddCOp = 196-primOpTag WordSubCOp = 197-primOpTag WordAdd2Op = 198-primOpTag WordSubOp = 199-primOpTag WordMulOp = 200-primOpTag WordMul2Op = 201-primOpTag WordQuotOp = 202-primOpTag WordRemOp = 203-primOpTag WordQuotRemOp = 204-primOpTag WordQuotRem2Op = 205-primOpTag WordAndOp = 206-primOpTag WordOrOp = 207-primOpTag WordXorOp = 208-primOpTag WordNotOp = 209-primOpTag WordSllOp = 210-primOpTag WordSrlOp = 211-primOpTag WordToIntOp = 212-primOpTag WordGtOp = 213-primOpTag WordGeOp = 214-primOpTag WordEqOp = 215-primOpTag WordNeOp = 216-primOpTag WordLtOp = 217-primOpTag WordLeOp = 218-primOpTag PopCnt8Op = 219-primOpTag PopCnt16Op = 220-primOpTag PopCnt32Op = 221-primOpTag PopCnt64Op = 222-primOpTag PopCntOp = 223-primOpTag Pdep8Op = 224-primOpTag Pdep16Op = 225-primOpTag Pdep32Op = 226-primOpTag Pdep64Op = 227-primOpTag PdepOp = 228-primOpTag Pext8Op = 229-primOpTag Pext16Op = 230-primOpTag Pext32Op = 231-primOpTag Pext64Op = 232-primOpTag PextOp = 233-primOpTag Clz8Op = 234-primOpTag Clz16Op = 235-primOpTag Clz32Op = 236-primOpTag Clz64Op = 237-primOpTag ClzOp = 238-primOpTag Ctz8Op = 239-primOpTag Ctz16Op = 240-primOpTag Ctz32Op = 241-primOpTag Ctz64Op = 242-primOpTag CtzOp = 243-primOpTag BSwap16Op = 244-primOpTag BSwap32Op = 245-primOpTag BSwap64Op = 246-primOpTag BSwapOp = 247-primOpTag BRev8Op = 248-primOpTag BRev16Op = 249-primOpTag BRev32Op = 250-primOpTag BRev64Op = 251-primOpTag BRevOp = 252-primOpTag Narrow8IntOp = 253-primOpTag Narrow16IntOp = 254-primOpTag Narrow32IntOp = 255-primOpTag Narrow8WordOp = 256-primOpTag Narrow16WordOp = 257-primOpTag Narrow32WordOp = 258-primOpTag DoubleGtOp = 259-primOpTag DoubleGeOp = 260-primOpTag DoubleEqOp = 261-primOpTag DoubleNeOp = 262-primOpTag DoubleLtOp = 263-primOpTag DoubleLeOp = 264-primOpTag DoubleAddOp = 265-primOpTag DoubleSubOp = 266-primOpTag DoubleMulOp = 267-primOpTag DoubleDivOp = 268-primOpTag DoubleNegOp = 269-primOpTag DoubleFabsOp = 270-primOpTag DoubleToIntOp = 271-primOpTag DoubleToFloatOp = 272-primOpTag DoubleExpOp = 273-primOpTag DoubleExpM1Op = 274-primOpTag DoubleLogOp = 275-primOpTag DoubleLog1POp = 276-primOpTag DoubleSqrtOp = 277-primOpTag DoubleSinOp = 278-primOpTag DoubleCosOp = 279-primOpTag DoubleTanOp = 280-primOpTag DoubleAsinOp = 281-primOpTag DoubleAcosOp = 282-primOpTag DoubleAtanOp = 283-primOpTag DoubleSinhOp = 284-primOpTag DoubleCoshOp = 285-primOpTag DoubleTanhOp = 286-primOpTag DoubleAsinhOp = 287-primOpTag DoubleAcoshOp = 288-primOpTag DoubleAtanhOp = 289-primOpTag DoublePowerOp = 290-primOpTag DoubleDecode_2IntOp = 291-primOpTag DoubleDecode_Int64Op = 292-primOpTag FloatGtOp = 293-primOpTag FloatGeOp = 294-primOpTag FloatEqOp = 295-primOpTag FloatNeOp = 296-primOpTag FloatLtOp = 297-primOpTag FloatLeOp = 298-primOpTag FloatAddOp = 299-primOpTag FloatSubOp = 300-primOpTag FloatMulOp = 301-primOpTag FloatDivOp = 302-primOpTag FloatNegOp = 303-primOpTag FloatFabsOp = 304-primOpTag FloatToIntOp = 305-primOpTag FloatExpOp = 306-primOpTag FloatExpM1Op = 307-primOpTag FloatLogOp = 308-primOpTag FloatLog1POp = 309-primOpTag FloatSqrtOp = 310-primOpTag FloatSinOp = 311-primOpTag FloatCosOp = 312-primOpTag FloatTanOp = 313-primOpTag FloatAsinOp = 314-primOpTag FloatAcosOp = 315-primOpTag FloatAtanOp = 316-primOpTag FloatSinhOp = 317-primOpTag FloatCoshOp = 318-primOpTag FloatTanhOp = 319-primOpTag FloatAsinhOp = 320-primOpTag FloatAcoshOp = 321-primOpTag FloatAtanhOp = 322-primOpTag FloatPowerOp = 323-primOpTag FloatToDoubleOp = 324-primOpTag FloatDecode_IntOp = 325-primOpTag FloatFMAdd = 326-primOpTag FloatFMSub = 327-primOpTag FloatFNMAdd = 328-primOpTag FloatFNMSub = 329-primOpTag DoubleFMAdd = 330-primOpTag DoubleFMSub = 331-primOpTag DoubleFNMAdd = 332-primOpTag DoubleFNMSub = 333-primOpTag NewArrayOp = 334-primOpTag ReadArrayOp = 335-primOpTag WriteArrayOp = 336-primOpTag SizeofArrayOp = 337-primOpTag SizeofMutableArrayOp = 338-primOpTag IndexArrayOp = 339-primOpTag UnsafeFreezeArrayOp = 340-primOpTag UnsafeThawArrayOp = 341-primOpTag CopyArrayOp = 342-primOpTag CopyMutableArrayOp = 343-primOpTag CloneArrayOp = 344-primOpTag CloneMutableArrayOp = 345-primOpTag FreezeArrayOp = 346-primOpTag ThawArrayOp = 347-primOpTag CasArrayOp = 348-primOpTag NewSmallArrayOp = 349-primOpTag ShrinkSmallMutableArrayOp_Char = 350-primOpTag ReadSmallArrayOp = 351-primOpTag WriteSmallArrayOp = 352-primOpTag SizeofSmallArrayOp = 353-primOpTag SizeofSmallMutableArrayOp = 354-primOpTag GetSizeofSmallMutableArrayOp = 355-primOpTag IndexSmallArrayOp = 356-primOpTag UnsafeFreezeSmallArrayOp = 357-primOpTag UnsafeThawSmallArrayOp = 358-primOpTag CopySmallArrayOp = 359-primOpTag CopySmallMutableArrayOp = 360-primOpTag CloneSmallArrayOp = 361-primOpTag CloneSmallMutableArrayOp = 362-primOpTag FreezeSmallArrayOp = 363-primOpTag ThawSmallArrayOp = 364-primOpTag CasSmallArrayOp = 365-primOpTag NewByteArrayOp_Char = 366-primOpTag NewPinnedByteArrayOp_Char = 367-primOpTag NewAlignedPinnedByteArrayOp_Char = 368-primOpTag MutableByteArrayIsPinnedOp = 369-primOpTag ByteArrayIsPinnedOp = 370-primOpTag ByteArrayContents_Char = 371-primOpTag MutableByteArrayContents_Char = 372-primOpTag ShrinkMutableByteArrayOp_Char = 373-primOpTag ResizeMutableByteArrayOp_Char = 374-primOpTag UnsafeFreezeByteArrayOp = 375-primOpTag SizeofByteArrayOp = 376-primOpTag SizeofMutableByteArrayOp = 377-primOpTag GetSizeofMutableByteArrayOp = 378-primOpTag IndexByteArrayOp_Char = 379-primOpTag IndexByteArrayOp_WideChar = 380-primOpTag IndexByteArrayOp_Int = 381-primOpTag IndexByteArrayOp_Word = 382-primOpTag IndexByteArrayOp_Addr = 383-primOpTag IndexByteArrayOp_Float = 384-primOpTag IndexByteArrayOp_Double = 385-primOpTag IndexByteArrayOp_StablePtr = 386-primOpTag IndexByteArrayOp_Int8 = 387-primOpTag IndexByteArrayOp_Word8 = 388-primOpTag IndexByteArrayOp_Int16 = 389-primOpTag IndexByteArrayOp_Word16 = 390-primOpTag IndexByteArrayOp_Int32 = 391-primOpTag IndexByteArrayOp_Word32 = 392-primOpTag IndexByteArrayOp_Int64 = 393-primOpTag IndexByteArrayOp_Word64 = 394-primOpTag IndexByteArrayOp_Word8AsChar = 395-primOpTag IndexByteArrayOp_Word8AsWideChar = 396-primOpTag IndexByteArrayOp_Word8AsInt = 397-primOpTag IndexByteArrayOp_Word8AsWord = 398-primOpTag IndexByteArrayOp_Word8AsAddr = 399-primOpTag IndexByteArrayOp_Word8AsFloat = 400-primOpTag IndexByteArrayOp_Word8AsDouble = 401-primOpTag IndexByteArrayOp_Word8AsStablePtr = 402-primOpTag IndexByteArrayOp_Word8AsInt16 = 403-primOpTag IndexByteArrayOp_Word8AsWord16 = 404-primOpTag IndexByteArrayOp_Word8AsInt32 = 405-primOpTag IndexByteArrayOp_Word8AsWord32 = 406-primOpTag IndexByteArrayOp_Word8AsInt64 = 407-primOpTag IndexByteArrayOp_Word8AsWord64 = 408-primOpTag ReadByteArrayOp_Char = 409-primOpTag ReadByteArrayOp_WideChar = 410-primOpTag ReadByteArrayOp_Int = 411-primOpTag ReadByteArrayOp_Word = 412-primOpTag ReadByteArrayOp_Addr = 413-primOpTag ReadByteArrayOp_Float = 414-primOpTag ReadByteArrayOp_Double = 415-primOpTag ReadByteArrayOp_StablePtr = 416-primOpTag ReadByteArrayOp_Int8 = 417-primOpTag ReadByteArrayOp_Word8 = 418-primOpTag ReadByteArrayOp_Int16 = 419-primOpTag ReadByteArrayOp_Word16 = 420-primOpTag ReadByteArrayOp_Int32 = 421-primOpTag ReadByteArrayOp_Word32 = 422-primOpTag ReadByteArrayOp_Int64 = 423-primOpTag ReadByteArrayOp_Word64 = 424-primOpTag ReadByteArrayOp_Word8AsChar = 425-primOpTag ReadByteArrayOp_Word8AsWideChar = 426-primOpTag ReadByteArrayOp_Word8AsInt = 427-primOpTag ReadByteArrayOp_Word8AsWord = 428-primOpTag ReadByteArrayOp_Word8AsAddr = 429-primOpTag ReadByteArrayOp_Word8AsFloat = 430-primOpTag ReadByteArrayOp_Word8AsDouble = 431-primOpTag ReadByteArrayOp_Word8AsStablePtr = 432-primOpTag ReadByteArrayOp_Word8AsInt16 = 433-primOpTag ReadByteArrayOp_Word8AsWord16 = 434-primOpTag ReadByteArrayOp_Word8AsInt32 = 435-primOpTag ReadByteArrayOp_Word8AsWord32 = 436-primOpTag ReadByteArrayOp_Word8AsInt64 = 437-primOpTag ReadByteArrayOp_Word8AsWord64 = 438-primOpTag WriteByteArrayOp_Char = 439-primOpTag WriteByteArrayOp_WideChar = 440-primOpTag WriteByteArrayOp_Int = 441-primOpTag WriteByteArrayOp_Word = 442-primOpTag WriteByteArrayOp_Addr = 443-primOpTag WriteByteArrayOp_Float = 444-primOpTag WriteByteArrayOp_Double = 445-primOpTag WriteByteArrayOp_StablePtr = 446-primOpTag WriteByteArrayOp_Int8 = 447-primOpTag WriteByteArrayOp_Word8 = 448-primOpTag WriteByteArrayOp_Int16 = 449-primOpTag WriteByteArrayOp_Word16 = 450-primOpTag WriteByteArrayOp_Int32 = 451-primOpTag WriteByteArrayOp_Word32 = 452-primOpTag WriteByteArrayOp_Int64 = 453-primOpTag WriteByteArrayOp_Word64 = 454-primOpTag WriteByteArrayOp_Word8AsChar = 455-primOpTag WriteByteArrayOp_Word8AsWideChar = 456-primOpTag WriteByteArrayOp_Word8AsInt = 457-primOpTag WriteByteArrayOp_Word8AsWord = 458-primOpTag WriteByteArrayOp_Word8AsAddr = 459-primOpTag WriteByteArrayOp_Word8AsFloat = 460-primOpTag WriteByteArrayOp_Word8AsDouble = 461-primOpTag WriteByteArrayOp_Word8AsStablePtr = 462-primOpTag WriteByteArrayOp_Word8AsInt16 = 463-primOpTag WriteByteArrayOp_Word8AsWord16 = 464-primOpTag WriteByteArrayOp_Word8AsInt32 = 465-primOpTag WriteByteArrayOp_Word8AsWord32 = 466-primOpTag WriteByteArrayOp_Word8AsInt64 = 467-primOpTag WriteByteArrayOp_Word8AsWord64 = 468-primOpTag CompareByteArraysOp = 469-primOpTag CopyByteArrayOp = 470-primOpTag CopyMutableByteArrayOp = 471-primOpTag CopyMutableByteArrayNonOverlappingOp = 472-primOpTag CopyByteArrayToAddrOp = 473-primOpTag CopyMutableByteArrayToAddrOp = 474-primOpTag CopyAddrToByteArrayOp = 475-primOpTag CopyAddrToAddrOp = 476-primOpTag CopyAddrToAddrNonOverlappingOp = 477-primOpTag SetByteArrayOp = 478-primOpTag SetAddrRangeOp = 479-primOpTag AtomicReadByteArrayOp_Int = 480-primOpTag AtomicWriteByteArrayOp_Int = 481-primOpTag CasByteArrayOp_Int = 482-primOpTag CasByteArrayOp_Int8 = 483-primOpTag CasByteArrayOp_Int16 = 484-primOpTag CasByteArrayOp_Int32 = 485-primOpTag CasByteArrayOp_Int64 = 486-primOpTag FetchAddByteArrayOp_Int = 487-primOpTag FetchSubByteArrayOp_Int = 488-primOpTag FetchAndByteArrayOp_Int = 489-primOpTag FetchNandByteArrayOp_Int = 490-primOpTag FetchOrByteArrayOp_Int = 491-primOpTag FetchXorByteArrayOp_Int = 492-primOpTag AddrAddOp = 493-primOpTag AddrSubOp = 494-primOpTag AddrRemOp = 495-primOpTag AddrToIntOp = 496-primOpTag IntToAddrOp = 497-primOpTag AddrGtOp = 498-primOpTag AddrGeOp = 499-primOpTag AddrEqOp = 500-primOpTag AddrNeOp = 501-primOpTag AddrLtOp = 502-primOpTag AddrLeOp = 503-primOpTag IndexOffAddrOp_Char = 504-primOpTag IndexOffAddrOp_WideChar = 505-primOpTag IndexOffAddrOp_Int = 506-primOpTag IndexOffAddrOp_Word = 507-primOpTag IndexOffAddrOp_Addr = 508-primOpTag IndexOffAddrOp_Float = 509-primOpTag IndexOffAddrOp_Double = 510-primOpTag IndexOffAddrOp_StablePtr = 511-primOpTag IndexOffAddrOp_Int8 = 512-primOpTag IndexOffAddrOp_Word8 = 513-primOpTag IndexOffAddrOp_Int16 = 514-primOpTag IndexOffAddrOp_Word16 = 515-primOpTag IndexOffAddrOp_Int32 = 516-primOpTag IndexOffAddrOp_Word32 = 517-primOpTag IndexOffAddrOp_Int64 = 518-primOpTag IndexOffAddrOp_Word64 = 519-primOpTag ReadOffAddrOp_Char = 520-primOpTag ReadOffAddrOp_WideChar = 521-primOpTag ReadOffAddrOp_Int = 522-primOpTag ReadOffAddrOp_Word = 523-primOpTag ReadOffAddrOp_Addr = 524-primOpTag ReadOffAddrOp_Float = 525-primOpTag ReadOffAddrOp_Double = 526-primOpTag ReadOffAddrOp_StablePtr = 527-primOpTag ReadOffAddrOp_Int8 = 528-primOpTag ReadOffAddrOp_Word8 = 529-primOpTag ReadOffAddrOp_Int16 = 530-primOpTag ReadOffAddrOp_Word16 = 531-primOpTag ReadOffAddrOp_Int32 = 532-primOpTag ReadOffAddrOp_Word32 = 533-primOpTag ReadOffAddrOp_Int64 = 534-primOpTag ReadOffAddrOp_Word64 = 535-primOpTag WriteOffAddrOp_Char = 536-primOpTag WriteOffAddrOp_WideChar = 537-primOpTag WriteOffAddrOp_Int = 538-primOpTag WriteOffAddrOp_Word = 539-primOpTag WriteOffAddrOp_Addr = 540-primOpTag WriteOffAddrOp_Float = 541-primOpTag WriteOffAddrOp_Double = 542-primOpTag WriteOffAddrOp_StablePtr = 543-primOpTag WriteOffAddrOp_Int8 = 544-primOpTag WriteOffAddrOp_Word8 = 545-primOpTag WriteOffAddrOp_Int16 = 546-primOpTag WriteOffAddrOp_Word16 = 547-primOpTag WriteOffAddrOp_Int32 = 548-primOpTag WriteOffAddrOp_Word32 = 549-primOpTag WriteOffAddrOp_Int64 = 550-primOpTag WriteOffAddrOp_Word64 = 551-primOpTag InterlockedExchange_Addr = 552-primOpTag InterlockedExchange_Word = 553-primOpTag CasAddrOp_Addr = 554-primOpTag CasAddrOp_Word = 555-primOpTag CasAddrOp_Word8 = 556-primOpTag CasAddrOp_Word16 = 557-primOpTag CasAddrOp_Word32 = 558-primOpTag CasAddrOp_Word64 = 559-primOpTag FetchAddAddrOp_Word = 560-primOpTag FetchSubAddrOp_Word = 561-primOpTag FetchAndAddrOp_Word = 562-primOpTag FetchNandAddrOp_Word = 563-primOpTag FetchOrAddrOp_Word = 564-primOpTag FetchXorAddrOp_Word = 565-primOpTag AtomicReadAddrOp_Word = 566-primOpTag AtomicWriteAddrOp_Word = 567-primOpTag NewMutVarOp = 568-primOpTag ReadMutVarOp = 569-primOpTag WriteMutVarOp = 570-primOpTag AtomicSwapMutVarOp = 571-primOpTag AtomicModifyMutVar2Op = 572-primOpTag AtomicModifyMutVar_Op = 573-primOpTag CasMutVarOp = 574-primOpTag CatchOp = 575-primOpTag RaiseOp = 576-primOpTag RaiseUnderflowOp = 577-primOpTag RaiseOverflowOp = 578-primOpTag RaiseDivZeroOp = 579-primOpTag RaiseIOOp = 580-primOpTag MaskAsyncExceptionsOp = 581-primOpTag MaskUninterruptibleOp = 582-primOpTag UnmaskAsyncExceptionsOp = 583-primOpTag MaskStatus = 584-primOpTag NewPromptTagOp = 585-primOpTag PromptOp = 586-primOpTag Control0Op = 587-primOpTag AtomicallyOp = 588-primOpTag RetryOp = 589-primOpTag CatchRetryOp = 590-primOpTag CatchSTMOp = 591-primOpTag NewTVarOp = 592-primOpTag ReadTVarOp = 593-primOpTag ReadTVarIOOp = 594-primOpTag WriteTVarOp = 595-primOpTag NewMVarOp = 596-primOpTag TakeMVarOp = 597-primOpTag TryTakeMVarOp = 598-primOpTag PutMVarOp = 599-primOpTag TryPutMVarOp = 600-primOpTag ReadMVarOp = 601-primOpTag TryReadMVarOp = 602-primOpTag IsEmptyMVarOp = 603-primOpTag NewIOPortOp = 604-primOpTag ReadIOPortOp = 605-primOpTag WriteIOPortOp = 606-primOpTag DelayOp = 607-primOpTag WaitReadOp = 608-primOpTag WaitWriteOp = 609-primOpTag ForkOp = 610-primOpTag ForkOnOp = 611-primOpTag KillThreadOp = 612-primOpTag YieldOp = 613-primOpTag MyThreadIdOp = 614-primOpTag LabelThreadOp = 615-primOpTag IsCurrentThreadBoundOp = 616-primOpTag NoDuplicateOp = 617-primOpTag GetThreadLabelOp = 618-primOpTag ThreadStatusOp = 619-primOpTag ListThreadsOp = 620-primOpTag MkWeakOp = 621-primOpTag MkWeakNoFinalizerOp = 622-primOpTag AddCFinalizerToWeakOp = 623-primOpTag DeRefWeakOp = 624-primOpTag FinalizeWeakOp = 625-primOpTag TouchOp = 626-primOpTag MakeStablePtrOp = 627-primOpTag DeRefStablePtrOp = 628-primOpTag EqStablePtrOp = 629-primOpTag MakeStableNameOp = 630-primOpTag StableNameToIntOp = 631-primOpTag CompactNewOp = 632-primOpTag CompactResizeOp = 633-primOpTag CompactContainsOp = 634-primOpTag CompactContainsAnyOp = 635-primOpTag CompactGetFirstBlockOp = 636-primOpTag CompactGetNextBlockOp = 637-primOpTag CompactAllocateBlockOp = 638-primOpTag CompactFixupPointersOp = 639-primOpTag CompactAdd = 640-primOpTag CompactAddWithSharing = 641-primOpTag CompactSize = 642-primOpTag ReallyUnsafePtrEqualityOp = 643-primOpTag ParOp = 644-primOpTag SparkOp = 645-primOpTag SeqOp = 646-primOpTag GetSparkOp = 647-primOpTag NumSparks = 648-primOpTag KeepAliveOp = 649-primOpTag DataToTagOp = 650-primOpTag TagToEnumOp = 651-primOpTag AddrToAnyOp = 652-primOpTag AnyToAddrOp = 653-primOpTag MkApUpd0_Op = 654-primOpTag NewBCOOp = 655-primOpTag UnpackClosureOp = 656-primOpTag ClosureSizeOp = 657-primOpTag GetApStackValOp = 658-primOpTag GetCCSOfOp = 659-primOpTag GetCurrentCCSOp = 660-primOpTag ClearCCSOp = 661-primOpTag WhereFromOp = 662-primOpTag TraceEventOp = 663-primOpTag TraceEventBinaryOp = 664-primOpTag TraceMarkerOp = 665-primOpTag SetThreadAllocationCounter = 666-primOpTag (VecBroadcastOp IntVec 16 W8) = 667-primOpTag (VecBroadcastOp IntVec 8 W16) = 668-primOpTag (VecBroadcastOp IntVec 4 W32) = 669-primOpTag (VecBroadcastOp IntVec 2 W64) = 670-primOpTag (VecBroadcastOp IntVec 32 W8) = 671-primOpTag (VecBroadcastOp IntVec 16 W16) = 672-primOpTag (VecBroadcastOp IntVec 8 W32) = 673-primOpTag (VecBroadcastOp IntVec 4 W64) = 674-primOpTag (VecBroadcastOp IntVec 64 W8) = 675-primOpTag (VecBroadcastOp IntVec 32 W16) = 676-primOpTag (VecBroadcastOp IntVec 16 W32) = 677-primOpTag (VecBroadcastOp IntVec 8 W64) = 678-primOpTag (VecBroadcastOp WordVec 16 W8) = 679-primOpTag (VecBroadcastOp WordVec 8 W16) = 680-primOpTag (VecBroadcastOp WordVec 4 W32) = 681-primOpTag (VecBroadcastOp WordVec 2 W64) = 682-primOpTag (VecBroadcastOp WordVec 32 W8) = 683-primOpTag (VecBroadcastOp WordVec 16 W16) = 684-primOpTag (VecBroadcastOp WordVec 8 W32) = 685-primOpTag (VecBroadcastOp WordVec 4 W64) = 686-primOpTag (VecBroadcastOp WordVec 64 W8) = 687-primOpTag (VecBroadcastOp WordVec 32 W16) = 688-primOpTag (VecBroadcastOp WordVec 16 W32) = 689-primOpTag (VecBroadcastOp WordVec 8 W64) = 690-primOpTag (VecBroadcastOp FloatVec 4 W32) = 691-primOpTag (VecBroadcastOp FloatVec 2 W64) = 692-primOpTag (VecBroadcastOp FloatVec 8 W32) = 693-primOpTag (VecBroadcastOp FloatVec 4 W64) = 694-primOpTag (VecBroadcastOp FloatVec 16 W32) = 695-primOpTag (VecBroadcastOp FloatVec 8 W64) = 696-primOpTag (VecPackOp IntVec 16 W8) = 697-primOpTag (VecPackOp IntVec 8 W16) = 698-primOpTag (VecPackOp IntVec 4 W32) = 699-primOpTag (VecPackOp IntVec 2 W64) = 700-primOpTag (VecPackOp IntVec 32 W8) = 701-primOpTag (VecPackOp IntVec 16 W16) = 702-primOpTag (VecPackOp IntVec 8 W32) = 703-primOpTag (VecPackOp IntVec 4 W64) = 704-primOpTag (VecPackOp IntVec 64 W8) = 705-primOpTag (VecPackOp IntVec 32 W16) = 706-primOpTag (VecPackOp IntVec 16 W32) = 707-primOpTag (VecPackOp IntVec 8 W64) = 708-primOpTag (VecPackOp WordVec 16 W8) = 709-primOpTag (VecPackOp WordVec 8 W16) = 710-primOpTag (VecPackOp WordVec 4 W32) = 711-primOpTag (VecPackOp WordVec 2 W64) = 712-primOpTag (VecPackOp WordVec 32 W8) = 713-primOpTag (VecPackOp WordVec 16 W16) = 714-primOpTag (VecPackOp WordVec 8 W32) = 715-primOpTag (VecPackOp WordVec 4 W64) = 716-primOpTag (VecPackOp WordVec 64 W8) = 717-primOpTag (VecPackOp WordVec 32 W16) = 718-primOpTag (VecPackOp WordVec 16 W32) = 719-primOpTag (VecPackOp WordVec 8 W64) = 720-primOpTag (VecPackOp FloatVec 4 W32) = 721-primOpTag (VecPackOp FloatVec 2 W64) = 722-primOpTag (VecPackOp FloatVec 8 W32) = 723-primOpTag (VecPackOp FloatVec 4 W64) = 724-primOpTag (VecPackOp FloatVec 16 W32) = 725-primOpTag (VecPackOp FloatVec 8 W64) = 726-primOpTag (VecUnpackOp IntVec 16 W8) = 727-primOpTag (VecUnpackOp IntVec 8 W16) = 728-primOpTag (VecUnpackOp IntVec 4 W32) = 729-primOpTag (VecUnpackOp IntVec 2 W64) = 730-primOpTag (VecUnpackOp IntVec 32 W8) = 731-primOpTag (VecUnpackOp IntVec 16 W16) = 732-primOpTag (VecUnpackOp IntVec 8 W32) = 733-primOpTag (VecUnpackOp IntVec 4 W64) = 734-primOpTag (VecUnpackOp IntVec 64 W8) = 735-primOpTag (VecUnpackOp IntVec 32 W16) = 736-primOpTag (VecUnpackOp IntVec 16 W32) = 737-primOpTag (VecUnpackOp IntVec 8 W64) = 738-primOpTag (VecUnpackOp WordVec 16 W8) = 739-primOpTag (VecUnpackOp WordVec 8 W16) = 740-primOpTag (VecUnpackOp WordVec 4 W32) = 741-primOpTag (VecUnpackOp WordVec 2 W64) = 742-primOpTag (VecUnpackOp WordVec 32 W8) = 743-primOpTag (VecUnpackOp WordVec 16 W16) = 744-primOpTag (VecUnpackOp WordVec 8 W32) = 745-primOpTag (VecUnpackOp WordVec 4 W64) = 746-primOpTag (VecUnpackOp WordVec 64 W8) = 747-primOpTag (VecUnpackOp WordVec 32 W16) = 748-primOpTag (VecUnpackOp WordVec 16 W32) = 749-primOpTag (VecUnpackOp WordVec 8 W64) = 750-primOpTag (VecUnpackOp FloatVec 4 W32) = 751-primOpTag (VecUnpackOp FloatVec 2 W64) = 752-primOpTag (VecUnpackOp FloatVec 8 W32) = 753-primOpTag (VecUnpackOp FloatVec 4 W64) = 754-primOpTag (VecUnpackOp FloatVec 16 W32) = 755-primOpTag (VecUnpackOp FloatVec 8 W64) = 756-primOpTag (VecInsertOp IntVec 16 W8) = 757-primOpTag (VecInsertOp IntVec 8 W16) = 758-primOpTag (VecInsertOp IntVec 4 W32) = 759-primOpTag (VecInsertOp IntVec 2 W64) = 760-primOpTag (VecInsertOp IntVec 32 W8) = 761-primOpTag (VecInsertOp IntVec 16 W16) = 762-primOpTag (VecInsertOp IntVec 8 W32) = 763-primOpTag (VecInsertOp IntVec 4 W64) = 764-primOpTag (VecInsertOp IntVec 64 W8) = 765-primOpTag (VecInsertOp IntVec 32 W16) = 766-primOpTag (VecInsertOp IntVec 16 W32) = 767-primOpTag (VecInsertOp IntVec 8 W64) = 768-primOpTag (VecInsertOp WordVec 16 W8) = 769-primOpTag (VecInsertOp WordVec 8 W16) = 770-primOpTag (VecInsertOp WordVec 4 W32) = 771-primOpTag (VecInsertOp WordVec 2 W64) = 772-primOpTag (VecInsertOp WordVec 32 W8) = 773-primOpTag (VecInsertOp WordVec 16 W16) = 774-primOpTag (VecInsertOp WordVec 8 W32) = 775-primOpTag (VecInsertOp WordVec 4 W64) = 776-primOpTag (VecInsertOp WordVec 64 W8) = 777-primOpTag (VecInsertOp WordVec 32 W16) = 778-primOpTag (VecInsertOp WordVec 16 W32) = 779-primOpTag (VecInsertOp WordVec 8 W64) = 780-primOpTag (VecInsertOp FloatVec 4 W32) = 781-primOpTag (VecInsertOp FloatVec 2 W64) = 782-primOpTag (VecInsertOp FloatVec 8 W32) = 783-primOpTag (VecInsertOp FloatVec 4 W64) = 784-primOpTag (VecInsertOp FloatVec 16 W32) = 785-primOpTag (VecInsertOp FloatVec 8 W64) = 786-primOpTag (VecAddOp IntVec 16 W8) = 787-primOpTag (VecAddOp IntVec 8 W16) = 788-primOpTag (VecAddOp IntVec 4 W32) = 789-primOpTag (VecAddOp IntVec 2 W64) = 790-primOpTag (VecAddOp IntVec 32 W8) = 791-primOpTag (VecAddOp IntVec 16 W16) = 792-primOpTag (VecAddOp IntVec 8 W32) = 793-primOpTag (VecAddOp IntVec 4 W64) = 794-primOpTag (VecAddOp IntVec 64 W8) = 795-primOpTag (VecAddOp IntVec 32 W16) = 796-primOpTag (VecAddOp IntVec 16 W32) = 797-primOpTag (VecAddOp IntVec 8 W64) = 798-primOpTag (VecAddOp WordVec 16 W8) = 799-primOpTag (VecAddOp WordVec 8 W16) = 800-primOpTag (VecAddOp WordVec 4 W32) = 801-primOpTag (VecAddOp WordVec 2 W64) = 802-primOpTag (VecAddOp WordVec 32 W8) = 803-primOpTag (VecAddOp WordVec 16 W16) = 804-primOpTag (VecAddOp WordVec 8 W32) = 805-primOpTag (VecAddOp WordVec 4 W64) = 806-primOpTag (VecAddOp WordVec 64 W8) = 807-primOpTag (VecAddOp WordVec 32 W16) = 808-primOpTag (VecAddOp WordVec 16 W32) = 809-primOpTag (VecAddOp WordVec 8 W64) = 810-primOpTag (VecAddOp FloatVec 4 W32) = 811-primOpTag (VecAddOp FloatVec 2 W64) = 812-primOpTag (VecAddOp FloatVec 8 W32) = 813-primOpTag (VecAddOp FloatVec 4 W64) = 814-primOpTag (VecAddOp FloatVec 16 W32) = 815-primOpTag (VecAddOp FloatVec 8 W64) = 816-primOpTag (VecSubOp IntVec 16 W8) = 817-primOpTag (VecSubOp IntVec 8 W16) = 818-primOpTag (VecSubOp IntVec 4 W32) = 819-primOpTag (VecSubOp IntVec 2 W64) = 820-primOpTag (VecSubOp IntVec 32 W8) = 821-primOpTag (VecSubOp IntVec 16 W16) = 822-primOpTag (VecSubOp IntVec 8 W32) = 823-primOpTag (VecSubOp IntVec 4 W64) = 824-primOpTag (VecSubOp IntVec 64 W8) = 825-primOpTag (VecSubOp IntVec 32 W16) = 826-primOpTag (VecSubOp IntVec 16 W32) = 827-primOpTag (VecSubOp IntVec 8 W64) = 828-primOpTag (VecSubOp WordVec 16 W8) = 829-primOpTag (VecSubOp WordVec 8 W16) = 830-primOpTag (VecSubOp WordVec 4 W32) = 831-primOpTag (VecSubOp WordVec 2 W64) = 832-primOpTag (VecSubOp WordVec 32 W8) = 833-primOpTag (VecSubOp WordVec 16 W16) = 834-primOpTag (VecSubOp WordVec 8 W32) = 835-primOpTag (VecSubOp WordVec 4 W64) = 836-primOpTag (VecSubOp WordVec 64 W8) = 837-primOpTag (VecSubOp WordVec 32 W16) = 838-primOpTag (VecSubOp WordVec 16 W32) = 839-primOpTag (VecSubOp WordVec 8 W64) = 840-primOpTag (VecSubOp FloatVec 4 W32) = 841-primOpTag (VecSubOp FloatVec 2 W64) = 842-primOpTag (VecSubOp FloatVec 8 W32) = 843-primOpTag (VecSubOp FloatVec 4 W64) = 844-primOpTag (VecSubOp FloatVec 16 W32) = 845-primOpTag (VecSubOp FloatVec 8 W64) = 846-primOpTag (VecMulOp IntVec 16 W8) = 847-primOpTag (VecMulOp IntVec 8 W16) = 848-primOpTag (VecMulOp IntVec 4 W32) = 849-primOpTag (VecMulOp IntVec 2 W64) = 850-primOpTag (VecMulOp IntVec 32 W8) = 851-primOpTag (VecMulOp IntVec 16 W16) = 852-primOpTag (VecMulOp IntVec 8 W32) = 853-primOpTag (VecMulOp IntVec 4 W64) = 854-primOpTag (VecMulOp IntVec 64 W8) = 855-primOpTag (VecMulOp IntVec 32 W16) = 856-primOpTag (VecMulOp IntVec 16 W32) = 857-primOpTag (VecMulOp IntVec 8 W64) = 858-primOpTag (VecMulOp WordVec 16 W8) = 859-primOpTag (VecMulOp WordVec 8 W16) = 860-primOpTag (VecMulOp WordVec 4 W32) = 861-primOpTag (VecMulOp WordVec 2 W64) = 862-primOpTag (VecMulOp WordVec 32 W8) = 863-primOpTag (VecMulOp WordVec 16 W16) = 864-primOpTag (VecMulOp WordVec 8 W32) = 865-primOpTag (VecMulOp WordVec 4 W64) = 866-primOpTag (VecMulOp WordVec 64 W8) = 867-primOpTag (VecMulOp WordVec 32 W16) = 868-primOpTag (VecMulOp WordVec 16 W32) = 869-primOpTag (VecMulOp WordVec 8 W64) = 870-primOpTag (VecMulOp FloatVec 4 W32) = 871-primOpTag (VecMulOp FloatVec 2 W64) = 872-primOpTag (VecMulOp FloatVec 8 W32) = 873-primOpTag (VecMulOp FloatVec 4 W64) = 874-primOpTag (VecMulOp FloatVec 16 W32) = 875-primOpTag (VecMulOp FloatVec 8 W64) = 876-primOpTag (VecDivOp FloatVec 4 W32) = 877-primOpTag (VecDivOp FloatVec 2 W64) = 878-primOpTag (VecDivOp FloatVec 8 W32) = 879-primOpTag (VecDivOp FloatVec 4 W64) = 880-primOpTag (VecDivOp FloatVec 16 W32) = 881-primOpTag (VecDivOp FloatVec 8 W64) = 882-primOpTag (VecQuotOp IntVec 16 W8) = 883-primOpTag (VecQuotOp IntVec 8 W16) = 884-primOpTag (VecQuotOp IntVec 4 W32) = 885-primOpTag (VecQuotOp IntVec 2 W64) = 886-primOpTag (VecQuotOp IntVec 32 W8) = 887-primOpTag (VecQuotOp IntVec 16 W16) = 888-primOpTag (VecQuotOp IntVec 8 W32) = 889-primOpTag (VecQuotOp IntVec 4 W64) = 890-primOpTag (VecQuotOp IntVec 64 W8) = 891-primOpTag (VecQuotOp IntVec 32 W16) = 892-primOpTag (VecQuotOp IntVec 16 W32) = 893-primOpTag (VecQuotOp IntVec 8 W64) = 894-primOpTag (VecQuotOp WordVec 16 W8) = 895-primOpTag (VecQuotOp WordVec 8 W16) = 896-primOpTag (VecQuotOp WordVec 4 W32) = 897-primOpTag (VecQuotOp WordVec 2 W64) = 898-primOpTag (VecQuotOp WordVec 32 W8) = 899-primOpTag (VecQuotOp WordVec 16 W16) = 900-primOpTag (VecQuotOp WordVec 8 W32) = 901-primOpTag (VecQuotOp WordVec 4 W64) = 902-primOpTag (VecQuotOp WordVec 64 W8) = 903-primOpTag (VecQuotOp WordVec 32 W16) = 904-primOpTag (VecQuotOp WordVec 16 W32) = 905-primOpTag (VecQuotOp WordVec 8 W64) = 906-primOpTag (VecRemOp IntVec 16 W8) = 907-primOpTag (VecRemOp IntVec 8 W16) = 908-primOpTag (VecRemOp IntVec 4 W32) = 909-primOpTag (VecRemOp IntVec 2 W64) = 910-primOpTag (VecRemOp IntVec 32 W8) = 911-primOpTag (VecRemOp IntVec 16 W16) = 912-primOpTag (VecRemOp IntVec 8 W32) = 913-primOpTag (VecRemOp IntVec 4 W64) = 914-primOpTag (VecRemOp IntVec 64 W8) = 915-primOpTag (VecRemOp IntVec 32 W16) = 916-primOpTag (VecRemOp IntVec 16 W32) = 917-primOpTag (VecRemOp IntVec 8 W64) = 918-primOpTag (VecRemOp WordVec 16 W8) = 919-primOpTag (VecRemOp WordVec 8 W16) = 920-primOpTag (VecRemOp WordVec 4 W32) = 921-primOpTag (VecRemOp WordVec 2 W64) = 922-primOpTag (VecRemOp WordVec 32 W8) = 923-primOpTag (VecRemOp WordVec 16 W16) = 924-primOpTag (VecRemOp WordVec 8 W32) = 925-primOpTag (VecRemOp WordVec 4 W64) = 926-primOpTag (VecRemOp WordVec 64 W8) = 927-primOpTag (VecRemOp WordVec 32 W16) = 928-primOpTag (VecRemOp WordVec 16 W32) = 929-primOpTag (VecRemOp WordVec 8 W64) = 930-primOpTag (VecNegOp IntVec 16 W8) = 931-primOpTag (VecNegOp IntVec 8 W16) = 932-primOpTag (VecNegOp IntVec 4 W32) = 933-primOpTag (VecNegOp IntVec 2 W64) = 934-primOpTag (VecNegOp IntVec 32 W8) = 935-primOpTag (VecNegOp IntVec 16 W16) = 936-primOpTag (VecNegOp IntVec 8 W32) = 937-primOpTag (VecNegOp IntVec 4 W64) = 938-primOpTag (VecNegOp IntVec 64 W8) = 939-primOpTag (VecNegOp IntVec 32 W16) = 940-primOpTag (VecNegOp IntVec 16 W32) = 941-primOpTag (VecNegOp IntVec 8 W64) = 942-primOpTag (VecNegOp FloatVec 4 W32) = 943-primOpTag (VecNegOp FloatVec 2 W64) = 944-primOpTag (VecNegOp FloatVec 8 W32) = 945-primOpTag (VecNegOp FloatVec 4 W64) = 946-primOpTag (VecNegOp FloatVec 16 W32) = 947-primOpTag (VecNegOp FloatVec 8 W64) = 948-primOpTag (VecIndexByteArrayOp IntVec 16 W8) = 949-primOpTag (VecIndexByteArrayOp IntVec 8 W16) = 950-primOpTag (VecIndexByteArrayOp IntVec 4 W32) = 951-primOpTag (VecIndexByteArrayOp IntVec 2 W64) = 952-primOpTag (VecIndexByteArrayOp IntVec 32 W8) = 953-primOpTag (VecIndexByteArrayOp IntVec 16 W16) = 954-primOpTag (VecIndexByteArrayOp IntVec 8 W32) = 955-primOpTag (VecIndexByteArrayOp IntVec 4 W64) = 956-primOpTag (VecIndexByteArrayOp IntVec 64 W8) = 957-primOpTag (VecIndexByteArrayOp IntVec 32 W16) = 958-primOpTag (VecIndexByteArrayOp IntVec 16 W32) = 959-primOpTag (VecIndexByteArrayOp IntVec 8 W64) = 960-primOpTag (VecIndexByteArrayOp WordVec 16 W8) = 961-primOpTag (VecIndexByteArrayOp WordVec 8 W16) = 962-primOpTag (VecIndexByteArrayOp WordVec 4 W32) = 963-primOpTag (VecIndexByteArrayOp WordVec 2 W64) = 964-primOpTag (VecIndexByteArrayOp WordVec 32 W8) = 965-primOpTag (VecIndexByteArrayOp WordVec 16 W16) = 966-primOpTag (VecIndexByteArrayOp WordVec 8 W32) = 967-primOpTag (VecIndexByteArrayOp WordVec 4 W64) = 968-primOpTag (VecIndexByteArrayOp WordVec 64 W8) = 969-primOpTag (VecIndexByteArrayOp WordVec 32 W16) = 970-primOpTag (VecIndexByteArrayOp WordVec 16 W32) = 971-primOpTag (VecIndexByteArrayOp WordVec 8 W64) = 972-primOpTag (VecIndexByteArrayOp FloatVec 4 W32) = 973-primOpTag (VecIndexByteArrayOp FloatVec 2 W64) = 974-primOpTag (VecIndexByteArrayOp FloatVec 8 W32) = 975-primOpTag (VecIndexByteArrayOp FloatVec 4 W64) = 976-primOpTag (VecIndexByteArrayOp FloatVec 16 W32) = 977-primOpTag (VecIndexByteArrayOp FloatVec 8 W64) = 978-primOpTag (VecReadByteArrayOp IntVec 16 W8) = 979-primOpTag (VecReadByteArrayOp IntVec 8 W16) = 980-primOpTag (VecReadByteArrayOp IntVec 4 W32) = 981-primOpTag (VecReadByteArrayOp IntVec 2 W64) = 982-primOpTag (VecReadByteArrayOp IntVec 32 W8) = 983-primOpTag (VecReadByteArrayOp IntVec 16 W16) = 984-primOpTag (VecReadByteArrayOp IntVec 8 W32) = 985-primOpTag (VecReadByteArrayOp IntVec 4 W64) = 986-primOpTag (VecReadByteArrayOp IntVec 64 W8) = 987-primOpTag (VecReadByteArrayOp IntVec 32 W16) = 988-primOpTag (VecReadByteArrayOp IntVec 16 W32) = 989-primOpTag (VecReadByteArrayOp IntVec 8 W64) = 990-primOpTag (VecReadByteArrayOp WordVec 16 W8) = 991-primOpTag (VecReadByteArrayOp WordVec 8 W16) = 992-primOpTag (VecReadByteArrayOp WordVec 4 W32) = 993-primOpTag (VecReadByteArrayOp WordVec 2 W64) = 994-primOpTag (VecReadByteArrayOp WordVec 32 W8) = 995-primOpTag (VecReadByteArrayOp WordVec 16 W16) = 996-primOpTag (VecReadByteArrayOp WordVec 8 W32) = 997-primOpTag (VecReadByteArrayOp WordVec 4 W64) = 998-primOpTag (VecReadByteArrayOp WordVec 64 W8) = 999-primOpTag (VecReadByteArrayOp WordVec 32 W16) = 1000-primOpTag (VecReadByteArrayOp WordVec 16 W32) = 1001-primOpTag (VecReadByteArrayOp WordVec 8 W64) = 1002-primOpTag (VecReadByteArrayOp FloatVec 4 W32) = 1003-primOpTag (VecReadByteArrayOp FloatVec 2 W64) = 1004-primOpTag (VecReadByteArrayOp FloatVec 8 W32) = 1005-primOpTag (VecReadByteArrayOp FloatVec 4 W64) = 1006-primOpTag (VecReadByteArrayOp FloatVec 16 W32) = 1007-primOpTag (VecReadByteArrayOp FloatVec 8 W64) = 1008-primOpTag (VecWriteByteArrayOp IntVec 16 W8) = 1009-primOpTag (VecWriteByteArrayOp IntVec 8 W16) = 1010-primOpTag (VecWriteByteArrayOp IntVec 4 W32) = 1011-primOpTag (VecWriteByteArrayOp IntVec 2 W64) = 1012-primOpTag (VecWriteByteArrayOp IntVec 32 W8) = 1013-primOpTag (VecWriteByteArrayOp IntVec 16 W16) = 1014-primOpTag (VecWriteByteArrayOp IntVec 8 W32) = 1015-primOpTag (VecWriteByteArrayOp IntVec 4 W64) = 1016-primOpTag (VecWriteByteArrayOp IntVec 64 W8) = 1017-primOpTag (VecWriteByteArrayOp IntVec 32 W16) = 1018-primOpTag (VecWriteByteArrayOp IntVec 16 W32) = 1019-primOpTag (VecWriteByteArrayOp IntVec 8 W64) = 1020-primOpTag (VecWriteByteArrayOp WordVec 16 W8) = 1021-primOpTag (VecWriteByteArrayOp WordVec 8 W16) = 1022-primOpTag (VecWriteByteArrayOp WordVec 4 W32) = 1023-primOpTag (VecWriteByteArrayOp WordVec 2 W64) = 1024-primOpTag (VecWriteByteArrayOp WordVec 32 W8) = 1025-primOpTag (VecWriteByteArrayOp WordVec 16 W16) = 1026-primOpTag (VecWriteByteArrayOp WordVec 8 W32) = 1027-primOpTag (VecWriteByteArrayOp WordVec 4 W64) = 1028-primOpTag (VecWriteByteArrayOp WordVec 64 W8) = 1029-primOpTag (VecWriteByteArrayOp WordVec 32 W16) = 1030-primOpTag (VecWriteByteArrayOp WordVec 16 W32) = 1031-primOpTag (VecWriteByteArrayOp WordVec 8 W64) = 1032-primOpTag (VecWriteByteArrayOp FloatVec 4 W32) = 1033-primOpTag (VecWriteByteArrayOp FloatVec 2 W64) = 1034-primOpTag (VecWriteByteArrayOp FloatVec 8 W32) = 1035-primOpTag (VecWriteByteArrayOp FloatVec 4 W64) = 1036-primOpTag (VecWriteByteArrayOp FloatVec 16 W32) = 1037-primOpTag (VecWriteByteArrayOp FloatVec 8 W64) = 1038-primOpTag (VecIndexOffAddrOp IntVec 16 W8) = 1039-primOpTag (VecIndexOffAddrOp IntVec 8 W16) = 1040-primOpTag (VecIndexOffAddrOp IntVec 4 W32) = 1041-primOpTag (VecIndexOffAddrOp IntVec 2 W64) = 1042-primOpTag (VecIndexOffAddrOp IntVec 32 W8) = 1043-primOpTag (VecIndexOffAddrOp IntVec 16 W16) = 1044-primOpTag (VecIndexOffAddrOp IntVec 8 W32) = 1045-primOpTag (VecIndexOffAddrOp IntVec 4 W64) = 1046-primOpTag (VecIndexOffAddrOp IntVec 64 W8) = 1047-primOpTag (VecIndexOffAddrOp IntVec 32 W16) = 1048-primOpTag (VecIndexOffAddrOp IntVec 16 W32) = 1049-primOpTag (VecIndexOffAddrOp IntVec 8 W64) = 1050-primOpTag (VecIndexOffAddrOp WordVec 16 W8) = 1051-primOpTag (VecIndexOffAddrOp WordVec 8 W16) = 1052-primOpTag (VecIndexOffAddrOp WordVec 4 W32) = 1053-primOpTag (VecIndexOffAddrOp WordVec 2 W64) = 1054-primOpTag (VecIndexOffAddrOp WordVec 32 W8) = 1055-primOpTag (VecIndexOffAddrOp WordVec 16 W16) = 1056-primOpTag (VecIndexOffAddrOp WordVec 8 W32) = 1057-primOpTag (VecIndexOffAddrOp WordVec 4 W64) = 1058-primOpTag (VecIndexOffAddrOp WordVec 64 W8) = 1059-primOpTag (VecIndexOffAddrOp WordVec 32 W16) = 1060-primOpTag (VecIndexOffAddrOp WordVec 16 W32) = 1061-primOpTag (VecIndexOffAddrOp WordVec 8 W64) = 1062-primOpTag (VecIndexOffAddrOp FloatVec 4 W32) = 1063-primOpTag (VecIndexOffAddrOp FloatVec 2 W64) = 1064-primOpTag (VecIndexOffAddrOp FloatVec 8 W32) = 1065-primOpTag (VecIndexOffAddrOp FloatVec 4 W64) = 1066-primOpTag (VecIndexOffAddrOp FloatVec 16 W32) = 1067-primOpTag (VecIndexOffAddrOp FloatVec 8 W64) = 1068-primOpTag (VecReadOffAddrOp IntVec 16 W8) = 1069-primOpTag (VecReadOffAddrOp IntVec 8 W16) = 1070-primOpTag (VecReadOffAddrOp IntVec 4 W32) = 1071-primOpTag (VecReadOffAddrOp IntVec 2 W64) = 1072-primOpTag (VecReadOffAddrOp IntVec 32 W8) = 1073-primOpTag (VecReadOffAddrOp IntVec 16 W16) = 1074-primOpTag (VecReadOffAddrOp IntVec 8 W32) = 1075-primOpTag (VecReadOffAddrOp IntVec 4 W64) = 1076-primOpTag (VecReadOffAddrOp IntVec 64 W8) = 1077-primOpTag (VecReadOffAddrOp IntVec 32 W16) = 1078-primOpTag (VecReadOffAddrOp IntVec 16 W32) = 1079-primOpTag (VecReadOffAddrOp IntVec 8 W64) = 1080-primOpTag (VecReadOffAddrOp WordVec 16 W8) = 1081-primOpTag (VecReadOffAddrOp WordVec 8 W16) = 1082-primOpTag (VecReadOffAddrOp WordVec 4 W32) = 1083-primOpTag (VecReadOffAddrOp WordVec 2 W64) = 1084-primOpTag (VecReadOffAddrOp WordVec 32 W8) = 1085-primOpTag (VecReadOffAddrOp WordVec 16 W16) = 1086-primOpTag (VecReadOffAddrOp WordVec 8 W32) = 1087-primOpTag (VecReadOffAddrOp WordVec 4 W64) = 1088-primOpTag (VecReadOffAddrOp WordVec 64 W8) = 1089-primOpTag (VecReadOffAddrOp WordVec 32 W16) = 1090-primOpTag (VecReadOffAddrOp WordVec 16 W32) = 1091-primOpTag (VecReadOffAddrOp WordVec 8 W64) = 1092-primOpTag (VecReadOffAddrOp FloatVec 4 W32) = 1093-primOpTag (VecReadOffAddrOp FloatVec 2 W64) = 1094-primOpTag (VecReadOffAddrOp FloatVec 8 W32) = 1095-primOpTag (VecReadOffAddrOp FloatVec 4 W64) = 1096-primOpTag (VecReadOffAddrOp FloatVec 16 W32) = 1097-primOpTag (VecReadOffAddrOp FloatVec 8 W64) = 1098-primOpTag (VecWriteOffAddrOp IntVec 16 W8) = 1099-primOpTag (VecWriteOffAddrOp IntVec 8 W16) = 1100-primOpTag (VecWriteOffAddrOp IntVec 4 W32) = 1101-primOpTag (VecWriteOffAddrOp IntVec 2 W64) = 1102-primOpTag (VecWriteOffAddrOp IntVec 32 W8) = 1103-primOpTag (VecWriteOffAddrOp IntVec 16 W16) = 1104-primOpTag (VecWriteOffAddrOp IntVec 8 W32) = 1105-primOpTag (VecWriteOffAddrOp IntVec 4 W64) = 1106-primOpTag (VecWriteOffAddrOp IntVec 64 W8) = 1107-primOpTag (VecWriteOffAddrOp IntVec 32 W16) = 1108-primOpTag (VecWriteOffAddrOp IntVec 16 W32) = 1109-primOpTag (VecWriteOffAddrOp IntVec 8 W64) = 1110-primOpTag (VecWriteOffAddrOp WordVec 16 W8) = 1111-primOpTag (VecWriteOffAddrOp WordVec 8 W16) = 1112-primOpTag (VecWriteOffAddrOp WordVec 4 W32) = 1113-primOpTag (VecWriteOffAddrOp WordVec 2 W64) = 1114-primOpTag (VecWriteOffAddrOp WordVec 32 W8) = 1115-primOpTag (VecWriteOffAddrOp WordVec 16 W16) = 1116-primOpTag (VecWriteOffAddrOp WordVec 8 W32) = 1117-primOpTag (VecWriteOffAddrOp WordVec 4 W64) = 1118-primOpTag (VecWriteOffAddrOp WordVec 64 W8) = 1119-primOpTag (VecWriteOffAddrOp WordVec 32 W16) = 1120-primOpTag (VecWriteOffAddrOp WordVec 16 W32) = 1121-primOpTag (VecWriteOffAddrOp WordVec 8 W64) = 1122-primOpTag (VecWriteOffAddrOp FloatVec 4 W32) = 1123-primOpTag (VecWriteOffAddrOp FloatVec 2 W64) = 1124-primOpTag (VecWriteOffAddrOp FloatVec 8 W32) = 1125-primOpTag (VecWriteOffAddrOp FloatVec 4 W64) = 1126-primOpTag (VecWriteOffAddrOp FloatVec 16 W32) = 1127-primOpTag (VecWriteOffAddrOp FloatVec 8 W64) = 1128-primOpTag (VecIndexScalarByteArrayOp IntVec 16 W8) = 1129-primOpTag (VecIndexScalarByteArrayOp IntVec 8 W16) = 1130-primOpTag (VecIndexScalarByteArrayOp IntVec 4 W32) = 1131-primOpTag (VecIndexScalarByteArrayOp IntVec 2 W64) = 1132-primOpTag (VecIndexScalarByteArrayOp IntVec 32 W8) = 1133-primOpTag (VecIndexScalarByteArrayOp IntVec 16 W16) = 1134-primOpTag (VecIndexScalarByteArrayOp IntVec 8 W32) = 1135-primOpTag (VecIndexScalarByteArrayOp IntVec 4 W64) = 1136-primOpTag (VecIndexScalarByteArrayOp IntVec 64 W8) = 1137-primOpTag (VecIndexScalarByteArrayOp IntVec 32 W16) = 1138-primOpTag (VecIndexScalarByteArrayOp IntVec 16 W32) = 1139-primOpTag (VecIndexScalarByteArrayOp IntVec 8 W64) = 1140-primOpTag (VecIndexScalarByteArrayOp WordVec 16 W8) = 1141-primOpTag (VecIndexScalarByteArrayOp WordVec 8 W16) = 1142-primOpTag (VecIndexScalarByteArrayOp WordVec 4 W32) = 1143-primOpTag (VecIndexScalarByteArrayOp WordVec 2 W64) = 1144-primOpTag (VecIndexScalarByteArrayOp WordVec 32 W8) = 1145-primOpTag (VecIndexScalarByteArrayOp WordVec 16 W16) = 1146-primOpTag (VecIndexScalarByteArrayOp WordVec 8 W32) = 1147-primOpTag (VecIndexScalarByteArrayOp WordVec 4 W64) = 1148-primOpTag (VecIndexScalarByteArrayOp WordVec 64 W8) = 1149-primOpTag (VecIndexScalarByteArrayOp WordVec 32 W16) = 1150-primOpTag (VecIndexScalarByteArrayOp WordVec 16 W32) = 1151-primOpTag (VecIndexScalarByteArrayOp WordVec 8 W64) = 1152-primOpTag (VecIndexScalarByteArrayOp FloatVec 4 W32) = 1153-primOpTag (VecIndexScalarByteArrayOp FloatVec 2 W64) = 1154-primOpTag (VecIndexScalarByteArrayOp FloatVec 8 W32) = 1155-primOpTag (VecIndexScalarByteArrayOp FloatVec 4 W64) = 1156-primOpTag (VecIndexScalarByteArrayOp FloatVec 16 W32) = 1157-primOpTag (VecIndexScalarByteArrayOp FloatVec 8 W64) = 1158-primOpTag (VecReadScalarByteArrayOp IntVec 16 W8) = 1159-primOpTag (VecReadScalarByteArrayOp IntVec 8 W16) = 1160-primOpTag (VecReadScalarByteArrayOp IntVec 4 W32) = 1161-primOpTag (VecReadScalarByteArrayOp IntVec 2 W64) = 1162-primOpTag (VecReadScalarByteArrayOp IntVec 32 W8) = 1163-primOpTag (VecReadScalarByteArrayOp IntVec 16 W16) = 1164-primOpTag (VecReadScalarByteArrayOp IntVec 8 W32) = 1165-primOpTag (VecReadScalarByteArrayOp IntVec 4 W64) = 1166-primOpTag (VecReadScalarByteArrayOp IntVec 64 W8) = 1167-primOpTag (VecReadScalarByteArrayOp IntVec 32 W16) = 1168-primOpTag (VecReadScalarByteArrayOp IntVec 16 W32) = 1169-primOpTag (VecReadScalarByteArrayOp IntVec 8 W64) = 1170-primOpTag (VecReadScalarByteArrayOp WordVec 16 W8) = 1171-primOpTag (VecReadScalarByteArrayOp WordVec 8 W16) = 1172-primOpTag (VecReadScalarByteArrayOp WordVec 4 W32) = 1173-primOpTag (VecReadScalarByteArrayOp WordVec 2 W64) = 1174-primOpTag (VecReadScalarByteArrayOp WordVec 32 W8) = 1175-primOpTag (VecReadScalarByteArrayOp WordVec 16 W16) = 1176-primOpTag (VecReadScalarByteArrayOp WordVec 8 W32) = 1177-primOpTag (VecReadScalarByteArrayOp WordVec 4 W64) = 1178-primOpTag (VecReadScalarByteArrayOp WordVec 64 W8) = 1179-primOpTag (VecReadScalarByteArrayOp WordVec 32 W16) = 1180-primOpTag (VecReadScalarByteArrayOp WordVec 16 W32) = 1181-primOpTag (VecReadScalarByteArrayOp WordVec 8 W64) = 1182-primOpTag (VecReadScalarByteArrayOp FloatVec 4 W32) = 1183-primOpTag (VecReadScalarByteArrayOp FloatVec 2 W64) = 1184-primOpTag (VecReadScalarByteArrayOp FloatVec 8 W32) = 1185-primOpTag (VecReadScalarByteArrayOp FloatVec 4 W64) = 1186-primOpTag (VecReadScalarByteArrayOp FloatVec 16 W32) = 1187-primOpTag (VecReadScalarByteArrayOp FloatVec 8 W64) = 1188-primOpTag (VecWriteScalarByteArrayOp IntVec 16 W8) = 1189-primOpTag (VecWriteScalarByteArrayOp IntVec 8 W16) = 1190-primOpTag (VecWriteScalarByteArrayOp IntVec 4 W32) = 1191-primOpTag (VecWriteScalarByteArrayOp IntVec 2 W64) = 1192-primOpTag (VecWriteScalarByteArrayOp IntVec 32 W8) = 1193-primOpTag (VecWriteScalarByteArrayOp IntVec 16 W16) = 1194-primOpTag (VecWriteScalarByteArrayOp IntVec 8 W32) = 1195-primOpTag (VecWriteScalarByteArrayOp IntVec 4 W64) = 1196-primOpTag (VecWriteScalarByteArrayOp IntVec 64 W8) = 1197-primOpTag (VecWriteScalarByteArrayOp IntVec 32 W16) = 1198-primOpTag (VecWriteScalarByteArrayOp IntVec 16 W32) = 1199-primOpTag (VecWriteScalarByteArrayOp IntVec 8 W64) = 1200-primOpTag (VecWriteScalarByteArrayOp WordVec 16 W8) = 1201-primOpTag (VecWriteScalarByteArrayOp WordVec 8 W16) = 1202-primOpTag (VecWriteScalarByteArrayOp WordVec 4 W32) = 1203-primOpTag (VecWriteScalarByteArrayOp WordVec 2 W64) = 1204-primOpTag (VecWriteScalarByteArrayOp WordVec 32 W8) = 1205-primOpTag (VecWriteScalarByteArrayOp WordVec 16 W16) = 1206-primOpTag (VecWriteScalarByteArrayOp WordVec 8 W32) = 1207-primOpTag (VecWriteScalarByteArrayOp WordVec 4 W64) = 1208-primOpTag (VecWriteScalarByteArrayOp WordVec 64 W8) = 1209-primOpTag (VecWriteScalarByteArrayOp WordVec 32 W16) = 1210-primOpTag (VecWriteScalarByteArrayOp WordVec 16 W32) = 1211-primOpTag (VecWriteScalarByteArrayOp WordVec 8 W64) = 1212-primOpTag (VecWriteScalarByteArrayOp FloatVec 4 W32) = 1213-primOpTag (VecWriteScalarByteArrayOp FloatVec 2 W64) = 1214-primOpTag (VecWriteScalarByteArrayOp FloatVec 8 W32) = 1215-primOpTag (VecWriteScalarByteArrayOp FloatVec 4 W64) = 1216-primOpTag (VecWriteScalarByteArrayOp FloatVec 16 W32) = 1217-primOpTag (VecWriteScalarByteArrayOp FloatVec 8 W64) = 1218-primOpTag (VecIndexScalarOffAddrOp IntVec 16 W8) = 1219-primOpTag (VecIndexScalarOffAddrOp IntVec 8 W16) = 1220-primOpTag (VecIndexScalarOffAddrOp IntVec 4 W32) = 1221-primOpTag (VecIndexScalarOffAddrOp IntVec 2 W64) = 1222-primOpTag (VecIndexScalarOffAddrOp IntVec 32 W8) = 1223-primOpTag (VecIndexScalarOffAddrOp IntVec 16 W16) = 1224-primOpTag (VecIndexScalarOffAddrOp IntVec 8 W32) = 1225-primOpTag (VecIndexScalarOffAddrOp IntVec 4 W64) = 1226-primOpTag (VecIndexScalarOffAddrOp IntVec 64 W8) = 1227-primOpTag (VecIndexScalarOffAddrOp IntVec 32 W16) = 1228-primOpTag (VecIndexScalarOffAddrOp IntVec 16 W32) = 1229-primOpTag (VecIndexScalarOffAddrOp IntVec 8 W64) = 1230-primOpTag (VecIndexScalarOffAddrOp WordVec 16 W8) = 1231-primOpTag (VecIndexScalarOffAddrOp WordVec 8 W16) = 1232-primOpTag (VecIndexScalarOffAddrOp WordVec 4 W32) = 1233-primOpTag (VecIndexScalarOffAddrOp WordVec 2 W64) = 1234-primOpTag (VecIndexScalarOffAddrOp WordVec 32 W8) = 1235-primOpTag (VecIndexScalarOffAddrOp WordVec 16 W16) = 1236-primOpTag (VecIndexScalarOffAddrOp WordVec 8 W32) = 1237-primOpTag (VecIndexScalarOffAddrOp WordVec 4 W64) = 1238-primOpTag (VecIndexScalarOffAddrOp WordVec 64 W8) = 1239-primOpTag (VecIndexScalarOffAddrOp WordVec 32 W16) = 1240-primOpTag (VecIndexScalarOffAddrOp WordVec 16 W32) = 1241-primOpTag (VecIndexScalarOffAddrOp WordVec 8 W64) = 1242-primOpTag (VecIndexScalarOffAddrOp FloatVec 4 W32) = 1243-primOpTag (VecIndexScalarOffAddrOp FloatVec 2 W64) = 1244-primOpTag (VecIndexScalarOffAddrOp FloatVec 8 W32) = 1245-primOpTag (VecIndexScalarOffAddrOp FloatVec 4 W64) = 1246-primOpTag (VecIndexScalarOffAddrOp FloatVec 16 W32) = 1247-primOpTag (VecIndexScalarOffAddrOp FloatVec 8 W64) = 1248-primOpTag (VecReadScalarOffAddrOp IntVec 16 W8) = 1249-primOpTag (VecReadScalarOffAddrOp IntVec 8 W16) = 1250-primOpTag (VecReadScalarOffAddrOp IntVec 4 W32) = 1251-primOpTag (VecReadScalarOffAddrOp IntVec 2 W64) = 1252-primOpTag (VecReadScalarOffAddrOp IntVec 32 W8) = 1253-primOpTag (VecReadScalarOffAddrOp IntVec 16 W16) = 1254-primOpTag (VecReadScalarOffAddrOp IntVec 8 W32) = 1255-primOpTag (VecReadScalarOffAddrOp IntVec 4 W64) = 1256-primOpTag (VecReadScalarOffAddrOp IntVec 64 W8) = 1257-primOpTag (VecReadScalarOffAddrOp IntVec 32 W16) = 1258-primOpTag (VecReadScalarOffAddrOp IntVec 16 W32) = 1259-primOpTag (VecReadScalarOffAddrOp IntVec 8 W64) = 1260-primOpTag (VecReadScalarOffAddrOp WordVec 16 W8) = 1261-primOpTag (VecReadScalarOffAddrOp WordVec 8 W16) = 1262-primOpTag (VecReadScalarOffAddrOp WordVec 4 W32) = 1263-primOpTag (VecReadScalarOffAddrOp WordVec 2 W64) = 1264-primOpTag (VecReadScalarOffAddrOp WordVec 32 W8) = 1265-primOpTag (VecReadScalarOffAddrOp WordVec 16 W16) = 1266-primOpTag (VecReadScalarOffAddrOp WordVec 8 W32) = 1267-primOpTag (VecReadScalarOffAddrOp WordVec 4 W64) = 1268-primOpTag (VecReadScalarOffAddrOp WordVec 64 W8) = 1269-primOpTag (VecReadScalarOffAddrOp WordVec 32 W16) = 1270-primOpTag (VecReadScalarOffAddrOp WordVec 16 W32) = 1271-primOpTag (VecReadScalarOffAddrOp WordVec 8 W64) = 1272-primOpTag (VecReadScalarOffAddrOp FloatVec 4 W32) = 1273-primOpTag (VecReadScalarOffAddrOp FloatVec 2 W64) = 1274-primOpTag (VecReadScalarOffAddrOp FloatVec 8 W32) = 1275-primOpTag (VecReadScalarOffAddrOp FloatVec 4 W64) = 1276-primOpTag (VecReadScalarOffAddrOp FloatVec 16 W32) = 1277-primOpTag (VecReadScalarOffAddrOp FloatVec 8 W64) = 1278-primOpTag (VecWriteScalarOffAddrOp IntVec 16 W8) = 1279-primOpTag (VecWriteScalarOffAddrOp IntVec 8 W16) = 1280-primOpTag (VecWriteScalarOffAddrOp IntVec 4 W32) = 1281-primOpTag (VecWriteScalarOffAddrOp IntVec 2 W64) = 1282-primOpTag (VecWriteScalarOffAddrOp IntVec 32 W8) = 1283-primOpTag (VecWriteScalarOffAddrOp IntVec 16 W16) = 1284-primOpTag (VecWriteScalarOffAddrOp IntVec 8 W32) = 1285-primOpTag (VecWriteScalarOffAddrOp IntVec 4 W64) = 1286-primOpTag (VecWriteScalarOffAddrOp IntVec 64 W8) = 1287-primOpTag (VecWriteScalarOffAddrOp IntVec 32 W16) = 1288-primOpTag (VecWriteScalarOffAddrOp IntVec 16 W32) = 1289-primOpTag (VecWriteScalarOffAddrOp IntVec 8 W64) = 1290-primOpTag (VecWriteScalarOffAddrOp WordVec 16 W8) = 1291-primOpTag (VecWriteScalarOffAddrOp WordVec 8 W16) = 1292-primOpTag (VecWriteScalarOffAddrOp WordVec 4 W32) = 1293-primOpTag (VecWriteScalarOffAddrOp WordVec 2 W64) = 1294-primOpTag (VecWriteScalarOffAddrOp WordVec 32 W8) = 1295-primOpTag (VecWriteScalarOffAddrOp WordVec 16 W16) = 1296-primOpTag (VecWriteScalarOffAddrOp WordVec 8 W32) = 1297-primOpTag (VecWriteScalarOffAddrOp WordVec 4 W64) = 1298-primOpTag (VecWriteScalarOffAddrOp WordVec 64 W8) = 1299-primOpTag (VecWriteScalarOffAddrOp WordVec 32 W16) = 1300-primOpTag (VecWriteScalarOffAddrOp WordVec 16 W32) = 1301-primOpTag (VecWriteScalarOffAddrOp WordVec 8 W64) = 1302-primOpTag (VecWriteScalarOffAddrOp FloatVec 4 W32) = 1303-primOpTag (VecWriteScalarOffAddrOp FloatVec 2 W64) = 1304-primOpTag (VecWriteScalarOffAddrOp FloatVec 8 W32) = 1305-primOpTag (VecWriteScalarOffAddrOp FloatVec 4 W64) = 1306-primOpTag (VecWriteScalarOffAddrOp FloatVec 16 W32) = 1307-primOpTag (VecWriteScalarOffAddrOp FloatVec 8 W64) = 1308-primOpTag PrefetchByteArrayOp3 = 1309-primOpTag PrefetchMutableByteArrayOp3 = 1310-primOpTag PrefetchAddrOp3 = 1311-primOpTag PrefetchValueOp3 = 1312-primOpTag PrefetchByteArrayOp2 = 1313-primOpTag PrefetchMutableByteArrayOp2 = 1314-primOpTag PrefetchAddrOp2 = 1315-primOpTag PrefetchValueOp2 = 1316-primOpTag PrefetchByteArrayOp1 = 1317-primOpTag PrefetchMutableByteArrayOp1 = 1318-primOpTag PrefetchAddrOp1 = 1319-primOpTag PrefetchValueOp1 = 1320-primOpTag PrefetchByteArrayOp0 = 1321-primOpTag PrefetchMutableByteArrayOp0 = 1322-primOpTag PrefetchAddrOp0 = 1323-primOpTag PrefetchValueOp0 = 1324+maxPrimOpTag = 1372+primOpTag :: PrimOp -> Int+primOpTag CharGtOp = 0+primOpTag CharGeOp = 1+primOpTag CharEqOp = 2+primOpTag CharNeOp = 3+primOpTag CharLtOp = 4+primOpTag CharLeOp = 5+primOpTag OrdOp = 6+primOpTag Int8ToIntOp = 7+primOpTag IntToInt8Op = 8+primOpTag Int8NegOp = 9+primOpTag Int8AddOp = 10+primOpTag Int8SubOp = 11+primOpTag Int8MulOp = 12+primOpTag Int8QuotOp = 13+primOpTag Int8RemOp = 14+primOpTag Int8QuotRemOp = 15+primOpTag Int8SllOp = 16+primOpTag Int8SraOp = 17+primOpTag Int8SrlOp = 18+primOpTag Int8ToWord8Op = 19+primOpTag Int8EqOp = 20+primOpTag Int8GeOp = 21+primOpTag Int8GtOp = 22+primOpTag Int8LeOp = 23+primOpTag Int8LtOp = 24+primOpTag Int8NeOp = 25+primOpTag Word8ToWordOp = 26+primOpTag WordToWord8Op = 27+primOpTag Word8AddOp = 28+primOpTag Word8SubOp = 29+primOpTag Word8MulOp = 30+primOpTag Word8QuotOp = 31+primOpTag Word8RemOp = 32+primOpTag Word8QuotRemOp = 33+primOpTag Word8AndOp = 34+primOpTag Word8OrOp = 35+primOpTag Word8XorOp = 36+primOpTag Word8NotOp = 37+primOpTag Word8SllOp = 38+primOpTag Word8SrlOp = 39+primOpTag Word8ToInt8Op = 40+primOpTag Word8EqOp = 41+primOpTag Word8GeOp = 42+primOpTag Word8GtOp = 43+primOpTag Word8LeOp = 44+primOpTag Word8LtOp = 45+primOpTag Word8NeOp = 46+primOpTag Int16ToIntOp = 47+primOpTag IntToInt16Op = 48+primOpTag Int16NegOp = 49+primOpTag Int16AddOp = 50+primOpTag Int16SubOp = 51+primOpTag Int16MulOp = 52+primOpTag Int16QuotOp = 53+primOpTag Int16RemOp = 54+primOpTag Int16QuotRemOp = 55+primOpTag Int16SllOp = 56+primOpTag Int16SraOp = 57+primOpTag Int16SrlOp = 58+primOpTag Int16ToWord16Op = 59+primOpTag Int16EqOp = 60+primOpTag Int16GeOp = 61+primOpTag Int16GtOp = 62+primOpTag Int16LeOp = 63+primOpTag Int16LtOp = 64+primOpTag Int16NeOp = 65+primOpTag Word16ToWordOp = 66+primOpTag WordToWord16Op = 67+primOpTag Word16AddOp = 68+primOpTag Word16SubOp = 69+primOpTag Word16MulOp = 70+primOpTag Word16QuotOp = 71+primOpTag Word16RemOp = 72+primOpTag Word16QuotRemOp = 73+primOpTag Word16AndOp = 74+primOpTag Word16OrOp = 75+primOpTag Word16XorOp = 76+primOpTag Word16NotOp = 77+primOpTag Word16SllOp = 78+primOpTag Word16SrlOp = 79+primOpTag Word16ToInt16Op = 80+primOpTag Word16EqOp = 81+primOpTag Word16GeOp = 82+primOpTag Word16GtOp = 83+primOpTag Word16LeOp = 84+primOpTag Word16LtOp = 85+primOpTag Word16NeOp = 86+primOpTag Int32ToIntOp = 87+primOpTag IntToInt32Op = 88+primOpTag Int32NegOp = 89+primOpTag Int32AddOp = 90+primOpTag Int32SubOp = 91+primOpTag Int32MulOp = 92+primOpTag Int32QuotOp = 93+primOpTag Int32RemOp = 94+primOpTag Int32QuotRemOp = 95+primOpTag Int32SllOp = 96+primOpTag Int32SraOp = 97+primOpTag Int32SrlOp = 98+primOpTag Int32ToWord32Op = 99+primOpTag Int32EqOp = 100+primOpTag Int32GeOp = 101+primOpTag Int32GtOp = 102+primOpTag Int32LeOp = 103+primOpTag Int32LtOp = 104+primOpTag Int32NeOp = 105+primOpTag Word32ToWordOp = 106+primOpTag WordToWord32Op = 107+primOpTag Word32AddOp = 108+primOpTag Word32SubOp = 109+primOpTag Word32MulOp = 110+primOpTag Word32QuotOp = 111+primOpTag Word32RemOp = 112+primOpTag Word32QuotRemOp = 113+primOpTag Word32AndOp = 114+primOpTag Word32OrOp = 115+primOpTag Word32XorOp = 116+primOpTag Word32NotOp = 117+primOpTag Word32SllOp = 118+primOpTag Word32SrlOp = 119+primOpTag Word32ToInt32Op = 120+primOpTag Word32EqOp = 121+primOpTag Word32GeOp = 122+primOpTag Word32GtOp = 123+primOpTag Word32LeOp = 124+primOpTag Word32LtOp = 125+primOpTag Word32NeOp = 126+primOpTag Int64ToIntOp = 127+primOpTag IntToInt64Op = 128+primOpTag Int64NegOp = 129+primOpTag Int64AddOp = 130+primOpTag Int64SubOp = 131+primOpTag Int64MulOp = 132+primOpTag Int64QuotOp = 133+primOpTag Int64RemOp = 134+primOpTag Int64SllOp = 135+primOpTag Int64SraOp = 136+primOpTag Int64SrlOp = 137+primOpTag Int64ToWord64Op = 138+primOpTag Int64EqOp = 139+primOpTag Int64GeOp = 140+primOpTag Int64GtOp = 141+primOpTag Int64LeOp = 142+primOpTag Int64LtOp = 143+primOpTag Int64NeOp = 144+primOpTag Word64ToWordOp = 145+primOpTag WordToWord64Op = 146+primOpTag Word64AddOp = 147+primOpTag Word64SubOp = 148+primOpTag Word64MulOp = 149+primOpTag Word64QuotOp = 150+primOpTag Word64RemOp = 151+primOpTag Word64AndOp = 152+primOpTag Word64OrOp = 153+primOpTag Word64XorOp = 154+primOpTag Word64NotOp = 155+primOpTag Word64SllOp = 156+primOpTag Word64SrlOp = 157+primOpTag Word64ToInt64Op = 158+primOpTag Word64EqOp = 159+primOpTag Word64GeOp = 160+primOpTag Word64GtOp = 161+primOpTag Word64LeOp = 162+primOpTag Word64LtOp = 163+primOpTag Word64NeOp = 164+primOpTag IntAddOp = 165+primOpTag IntSubOp = 166+primOpTag IntMulOp = 167+primOpTag IntMul2Op = 168+primOpTag IntMulMayOfloOp = 169+primOpTag IntQuotOp = 170+primOpTag IntRemOp = 171+primOpTag IntQuotRemOp = 172+primOpTag IntAndOp = 173+primOpTag IntOrOp = 174+primOpTag IntXorOp = 175+primOpTag IntNotOp = 176+primOpTag IntNegOp = 177+primOpTag IntAddCOp = 178+primOpTag IntSubCOp = 179+primOpTag IntGtOp = 180+primOpTag IntGeOp = 181+primOpTag IntEqOp = 182+primOpTag IntNeOp = 183+primOpTag IntLtOp = 184+primOpTag IntLeOp = 185+primOpTag ChrOp = 186+primOpTag IntToWordOp = 187+primOpTag IntToFloatOp = 188+primOpTag IntToDoubleOp = 189+primOpTag WordToFloatOp = 190+primOpTag WordToDoubleOp = 191+primOpTag IntSllOp = 192+primOpTag IntSraOp = 193+primOpTag IntSrlOp = 194+primOpTag WordAddOp = 195+primOpTag WordAddCOp = 196+primOpTag WordSubCOp = 197+primOpTag WordAdd2Op = 198+primOpTag WordSubOp = 199+primOpTag WordMulOp = 200+primOpTag WordMul2Op = 201+primOpTag WordQuotOp = 202+primOpTag WordRemOp = 203+primOpTag WordQuotRemOp = 204+primOpTag WordQuotRem2Op = 205+primOpTag WordAndOp = 206+primOpTag WordOrOp = 207+primOpTag WordXorOp = 208+primOpTag WordNotOp = 209+primOpTag WordSllOp = 210+primOpTag WordSrlOp = 211+primOpTag WordToIntOp = 212+primOpTag WordGtOp = 213+primOpTag WordGeOp = 214+primOpTag WordEqOp = 215+primOpTag WordNeOp = 216+primOpTag WordLtOp = 217+primOpTag WordLeOp = 218+primOpTag PopCnt8Op = 219+primOpTag PopCnt16Op = 220+primOpTag PopCnt32Op = 221+primOpTag PopCnt64Op = 222+primOpTag PopCntOp = 223+primOpTag Pdep8Op = 224+primOpTag Pdep16Op = 225+primOpTag Pdep32Op = 226+primOpTag Pdep64Op = 227+primOpTag PdepOp = 228+primOpTag Pext8Op = 229+primOpTag Pext16Op = 230+primOpTag Pext32Op = 231+primOpTag Pext64Op = 232+primOpTag PextOp = 233+primOpTag Clz8Op = 234+primOpTag Clz16Op = 235+primOpTag Clz32Op = 236+primOpTag Clz64Op = 237+primOpTag ClzOp = 238+primOpTag Ctz8Op = 239+primOpTag Ctz16Op = 240+primOpTag Ctz32Op = 241+primOpTag Ctz64Op = 242+primOpTag CtzOp = 243+primOpTag BSwap16Op = 244+primOpTag BSwap32Op = 245+primOpTag BSwap64Op = 246+primOpTag BSwapOp = 247+primOpTag BRev8Op = 248+primOpTag BRev16Op = 249+primOpTag BRev32Op = 250+primOpTag BRev64Op = 251+primOpTag BRevOp = 252+primOpTag Narrow8IntOp = 253+primOpTag Narrow16IntOp = 254+primOpTag Narrow32IntOp = 255+primOpTag Narrow8WordOp = 256+primOpTag Narrow16WordOp = 257+primOpTag Narrow32WordOp = 258+primOpTag DoubleGtOp = 259+primOpTag DoubleGeOp = 260+primOpTag DoubleEqOp = 261+primOpTag DoubleNeOp = 262+primOpTag DoubleLtOp = 263+primOpTag DoubleLeOp = 264+primOpTag DoubleAddOp = 265+primOpTag DoubleSubOp = 266+primOpTag DoubleMulOp = 267+primOpTag DoubleDivOp = 268+primOpTag DoubleNegOp = 269+primOpTag DoubleFabsOp = 270+primOpTag DoubleToIntOp = 271+primOpTag DoubleToFloatOp = 272+primOpTag DoubleExpOp = 273+primOpTag DoubleExpM1Op = 274+primOpTag DoubleLogOp = 275+primOpTag DoubleLog1POp = 276+primOpTag DoubleSqrtOp = 277+primOpTag DoubleSinOp = 278+primOpTag DoubleCosOp = 279+primOpTag DoubleTanOp = 280+primOpTag DoubleAsinOp = 281+primOpTag DoubleAcosOp = 282+primOpTag DoubleAtanOp = 283+primOpTag DoubleSinhOp = 284+primOpTag DoubleCoshOp = 285+primOpTag DoubleTanhOp = 286+primOpTag DoubleAsinhOp = 287+primOpTag DoubleAcoshOp = 288+primOpTag DoubleAtanhOp = 289+primOpTag DoublePowerOp = 290+primOpTag DoubleDecode_2IntOp = 291+primOpTag DoubleDecode_Int64Op = 292+primOpTag CastDoubleToWord64Op = 293+primOpTag CastWord64ToDoubleOp = 294+primOpTag FloatGtOp = 295+primOpTag FloatGeOp = 296+primOpTag FloatEqOp = 297+primOpTag FloatNeOp = 298+primOpTag FloatLtOp = 299+primOpTag FloatLeOp = 300+primOpTag FloatAddOp = 301+primOpTag FloatSubOp = 302+primOpTag FloatMulOp = 303+primOpTag FloatDivOp = 304+primOpTag FloatNegOp = 305+primOpTag FloatFabsOp = 306+primOpTag FloatToIntOp = 307+primOpTag FloatExpOp = 308+primOpTag FloatExpM1Op = 309+primOpTag FloatLogOp = 310+primOpTag FloatLog1POp = 311+primOpTag FloatSqrtOp = 312+primOpTag FloatSinOp = 313+primOpTag FloatCosOp = 314+primOpTag FloatTanOp = 315+primOpTag FloatAsinOp = 316+primOpTag FloatAcosOp = 317+primOpTag FloatAtanOp = 318+primOpTag FloatSinhOp = 319+primOpTag FloatCoshOp = 320+primOpTag FloatTanhOp = 321+primOpTag FloatAsinhOp = 322+primOpTag FloatAcoshOp = 323+primOpTag FloatAtanhOp = 324+primOpTag FloatPowerOp = 325+primOpTag FloatToDoubleOp = 326+primOpTag FloatDecode_IntOp = 327+primOpTag CastFloatToWord32Op = 328+primOpTag CastWord32ToFloatOp = 329+primOpTag FloatFMAdd = 330+primOpTag FloatFMSub = 331+primOpTag FloatFNMAdd = 332+primOpTag FloatFNMSub = 333+primOpTag DoubleFMAdd = 334+primOpTag DoubleFMSub = 335+primOpTag DoubleFNMAdd = 336+primOpTag DoubleFNMSub = 337+primOpTag NewArrayOp = 338+primOpTag ReadArrayOp = 339+primOpTag WriteArrayOp = 340+primOpTag SizeofArrayOp = 341+primOpTag SizeofMutableArrayOp = 342+primOpTag IndexArrayOp = 343+primOpTag UnsafeFreezeArrayOp = 344+primOpTag UnsafeThawArrayOp = 345+primOpTag CopyArrayOp = 346+primOpTag CopyMutableArrayOp = 347+primOpTag CloneArrayOp = 348+primOpTag CloneMutableArrayOp = 349+primOpTag FreezeArrayOp = 350+primOpTag ThawArrayOp = 351+primOpTag CasArrayOp = 352+primOpTag NewSmallArrayOp = 353+primOpTag ShrinkSmallMutableArrayOp_Char = 354+primOpTag ReadSmallArrayOp = 355+primOpTag WriteSmallArrayOp = 356+primOpTag SizeofSmallArrayOp = 357+primOpTag SizeofSmallMutableArrayOp = 358+primOpTag GetSizeofSmallMutableArrayOp = 359+primOpTag IndexSmallArrayOp = 360+primOpTag UnsafeFreezeSmallArrayOp = 361+primOpTag UnsafeThawSmallArrayOp = 362+primOpTag CopySmallArrayOp = 363+primOpTag CopySmallMutableArrayOp = 364+primOpTag CloneSmallArrayOp = 365+primOpTag CloneSmallMutableArrayOp = 366+primOpTag FreezeSmallArrayOp = 367+primOpTag ThawSmallArrayOp = 368+primOpTag CasSmallArrayOp = 369+primOpTag NewByteArrayOp_Char = 370+primOpTag NewPinnedByteArrayOp_Char = 371+primOpTag NewAlignedPinnedByteArrayOp_Char = 372+primOpTag MutableByteArrayIsPinnedOp = 373+primOpTag ByteArrayIsPinnedOp = 374+primOpTag ByteArrayContents_Char = 375+primOpTag MutableByteArrayContents_Char = 376+primOpTag ShrinkMutableByteArrayOp_Char = 377+primOpTag ResizeMutableByteArrayOp_Char = 378+primOpTag UnsafeFreezeByteArrayOp = 379+primOpTag UnsafeThawByteArrayOp = 380+primOpTag SizeofByteArrayOp = 381+primOpTag SizeofMutableByteArrayOp = 382+primOpTag GetSizeofMutableByteArrayOp = 383+primOpTag IndexByteArrayOp_Char = 384+primOpTag IndexByteArrayOp_WideChar = 385+primOpTag IndexByteArrayOp_Int = 386+primOpTag IndexByteArrayOp_Word = 387+primOpTag IndexByteArrayOp_Addr = 388+primOpTag IndexByteArrayOp_Float = 389+primOpTag IndexByteArrayOp_Double = 390+primOpTag IndexByteArrayOp_StablePtr = 391+primOpTag IndexByteArrayOp_Int8 = 392+primOpTag IndexByteArrayOp_Word8 = 393+primOpTag IndexByteArrayOp_Int16 = 394+primOpTag IndexByteArrayOp_Word16 = 395+primOpTag IndexByteArrayOp_Int32 = 396+primOpTag IndexByteArrayOp_Word32 = 397+primOpTag IndexByteArrayOp_Int64 = 398+primOpTag IndexByteArrayOp_Word64 = 399+primOpTag IndexByteArrayOp_Word8AsChar = 400+primOpTag IndexByteArrayOp_Word8AsWideChar = 401+primOpTag IndexByteArrayOp_Word8AsInt = 402+primOpTag IndexByteArrayOp_Word8AsWord = 403+primOpTag IndexByteArrayOp_Word8AsAddr = 404+primOpTag IndexByteArrayOp_Word8AsFloat = 405+primOpTag IndexByteArrayOp_Word8AsDouble = 406+primOpTag IndexByteArrayOp_Word8AsStablePtr = 407+primOpTag IndexByteArrayOp_Word8AsInt16 = 408+primOpTag IndexByteArrayOp_Word8AsWord16 = 409+primOpTag IndexByteArrayOp_Word8AsInt32 = 410+primOpTag IndexByteArrayOp_Word8AsWord32 = 411+primOpTag IndexByteArrayOp_Word8AsInt64 = 412+primOpTag IndexByteArrayOp_Word8AsWord64 = 413+primOpTag ReadByteArrayOp_Char = 414+primOpTag ReadByteArrayOp_WideChar = 415+primOpTag ReadByteArrayOp_Int = 416+primOpTag ReadByteArrayOp_Word = 417+primOpTag ReadByteArrayOp_Addr = 418+primOpTag ReadByteArrayOp_Float = 419+primOpTag ReadByteArrayOp_Double = 420+primOpTag ReadByteArrayOp_StablePtr = 421+primOpTag ReadByteArrayOp_Int8 = 422+primOpTag ReadByteArrayOp_Word8 = 423+primOpTag ReadByteArrayOp_Int16 = 424+primOpTag ReadByteArrayOp_Word16 = 425+primOpTag ReadByteArrayOp_Int32 = 426+primOpTag ReadByteArrayOp_Word32 = 427+primOpTag ReadByteArrayOp_Int64 = 428+primOpTag ReadByteArrayOp_Word64 = 429+primOpTag ReadByteArrayOp_Word8AsChar = 430+primOpTag ReadByteArrayOp_Word8AsWideChar = 431+primOpTag ReadByteArrayOp_Word8AsInt = 432+primOpTag ReadByteArrayOp_Word8AsWord = 433+primOpTag ReadByteArrayOp_Word8AsAddr = 434+primOpTag ReadByteArrayOp_Word8AsFloat = 435+primOpTag ReadByteArrayOp_Word8AsDouble = 436+primOpTag ReadByteArrayOp_Word8AsStablePtr = 437+primOpTag ReadByteArrayOp_Word8AsInt16 = 438+primOpTag ReadByteArrayOp_Word8AsWord16 = 439+primOpTag ReadByteArrayOp_Word8AsInt32 = 440+primOpTag ReadByteArrayOp_Word8AsWord32 = 441+primOpTag ReadByteArrayOp_Word8AsInt64 = 442+primOpTag ReadByteArrayOp_Word8AsWord64 = 443+primOpTag WriteByteArrayOp_Char = 444+primOpTag WriteByteArrayOp_WideChar = 445+primOpTag WriteByteArrayOp_Int = 446+primOpTag WriteByteArrayOp_Word = 447+primOpTag WriteByteArrayOp_Addr = 448+primOpTag WriteByteArrayOp_Float = 449+primOpTag WriteByteArrayOp_Double = 450+primOpTag WriteByteArrayOp_StablePtr = 451+primOpTag WriteByteArrayOp_Int8 = 452+primOpTag WriteByteArrayOp_Word8 = 453+primOpTag WriteByteArrayOp_Int16 = 454+primOpTag WriteByteArrayOp_Word16 = 455+primOpTag WriteByteArrayOp_Int32 = 456+primOpTag WriteByteArrayOp_Word32 = 457+primOpTag WriteByteArrayOp_Int64 = 458+primOpTag WriteByteArrayOp_Word64 = 459+primOpTag WriteByteArrayOp_Word8AsChar = 460+primOpTag WriteByteArrayOp_Word8AsWideChar = 461+primOpTag WriteByteArrayOp_Word8AsInt = 462+primOpTag WriteByteArrayOp_Word8AsWord = 463+primOpTag WriteByteArrayOp_Word8AsAddr = 464+primOpTag WriteByteArrayOp_Word8AsFloat = 465+primOpTag WriteByteArrayOp_Word8AsDouble = 466+primOpTag WriteByteArrayOp_Word8AsStablePtr = 467+primOpTag WriteByteArrayOp_Word8AsInt16 = 468+primOpTag WriteByteArrayOp_Word8AsWord16 = 469+primOpTag WriteByteArrayOp_Word8AsInt32 = 470+primOpTag WriteByteArrayOp_Word8AsWord32 = 471+primOpTag WriteByteArrayOp_Word8AsInt64 = 472+primOpTag WriteByteArrayOp_Word8AsWord64 = 473+primOpTag CompareByteArraysOp = 474+primOpTag CopyByteArrayOp = 475+primOpTag CopyMutableByteArrayOp = 476+primOpTag CopyMutableByteArrayNonOverlappingOp = 477+primOpTag CopyByteArrayToAddrOp = 478+primOpTag CopyMutableByteArrayToAddrOp = 479+primOpTag CopyAddrToByteArrayOp = 480+primOpTag CopyAddrToAddrOp = 481+primOpTag CopyAddrToAddrNonOverlappingOp = 482+primOpTag SetByteArrayOp = 483+primOpTag SetAddrRangeOp = 484+primOpTag AtomicReadByteArrayOp_Int = 485+primOpTag AtomicWriteByteArrayOp_Int = 486+primOpTag CasByteArrayOp_Int = 487+primOpTag CasByteArrayOp_Int8 = 488+primOpTag CasByteArrayOp_Int16 = 489+primOpTag CasByteArrayOp_Int32 = 490+primOpTag CasByteArrayOp_Int64 = 491+primOpTag FetchAddByteArrayOp_Int = 492+primOpTag FetchSubByteArrayOp_Int = 493+primOpTag FetchAndByteArrayOp_Int = 494+primOpTag FetchNandByteArrayOp_Int = 495+primOpTag FetchOrByteArrayOp_Int = 496+primOpTag FetchXorByteArrayOp_Int = 497+primOpTag AddrAddOp = 498+primOpTag AddrSubOp = 499+primOpTag AddrRemOp = 500+primOpTag AddrToIntOp = 501+primOpTag IntToAddrOp = 502+primOpTag AddrGtOp = 503+primOpTag AddrGeOp = 504+primOpTag AddrEqOp = 505+primOpTag AddrNeOp = 506+primOpTag AddrLtOp = 507+primOpTag AddrLeOp = 508+primOpTag IndexOffAddrOp_Char = 509+primOpTag IndexOffAddrOp_WideChar = 510+primOpTag IndexOffAddrOp_Int = 511+primOpTag IndexOffAddrOp_Word = 512+primOpTag IndexOffAddrOp_Addr = 513+primOpTag IndexOffAddrOp_Float = 514+primOpTag IndexOffAddrOp_Double = 515+primOpTag IndexOffAddrOp_StablePtr = 516+primOpTag IndexOffAddrOp_Int8 = 517+primOpTag IndexOffAddrOp_Word8 = 518+primOpTag IndexOffAddrOp_Int16 = 519+primOpTag IndexOffAddrOp_Word16 = 520+primOpTag IndexOffAddrOp_Int32 = 521+primOpTag IndexOffAddrOp_Word32 = 522+primOpTag IndexOffAddrOp_Int64 = 523+primOpTag IndexOffAddrOp_Word64 = 524+primOpTag IndexOffAddrOp_Word8AsChar = 525+primOpTag IndexOffAddrOp_Word8AsWideChar = 526+primOpTag IndexOffAddrOp_Word8AsInt = 527+primOpTag IndexOffAddrOp_Word8AsWord = 528+primOpTag IndexOffAddrOp_Word8AsAddr = 529+primOpTag IndexOffAddrOp_Word8AsFloat = 530+primOpTag IndexOffAddrOp_Word8AsDouble = 531+primOpTag IndexOffAddrOp_Word8AsStablePtr = 532+primOpTag IndexOffAddrOp_Word8AsInt16 = 533+primOpTag IndexOffAddrOp_Word8AsWord16 = 534+primOpTag IndexOffAddrOp_Word8AsInt32 = 535+primOpTag IndexOffAddrOp_Word8AsWord32 = 536+primOpTag IndexOffAddrOp_Word8AsInt64 = 537+primOpTag IndexOffAddrOp_Word8AsWord64 = 538+primOpTag ReadOffAddrOp_Char = 539+primOpTag ReadOffAddrOp_WideChar = 540+primOpTag ReadOffAddrOp_Int = 541+primOpTag ReadOffAddrOp_Word = 542+primOpTag ReadOffAddrOp_Addr = 543+primOpTag ReadOffAddrOp_Float = 544+primOpTag ReadOffAddrOp_Double = 545+primOpTag ReadOffAddrOp_StablePtr = 546+primOpTag ReadOffAddrOp_Int8 = 547+primOpTag ReadOffAddrOp_Word8 = 548+primOpTag ReadOffAddrOp_Int16 = 549+primOpTag ReadOffAddrOp_Word16 = 550+primOpTag ReadOffAddrOp_Int32 = 551+primOpTag ReadOffAddrOp_Word32 = 552+primOpTag ReadOffAddrOp_Int64 = 553+primOpTag ReadOffAddrOp_Word64 = 554+primOpTag ReadOffAddrOp_Word8AsChar = 555+primOpTag ReadOffAddrOp_Word8AsWideChar = 556+primOpTag ReadOffAddrOp_Word8AsInt = 557+primOpTag ReadOffAddrOp_Word8AsWord = 558+primOpTag ReadOffAddrOp_Word8AsAddr = 559+primOpTag ReadOffAddrOp_Word8AsFloat = 560+primOpTag ReadOffAddrOp_Word8AsDouble = 561+primOpTag ReadOffAddrOp_Word8AsStablePtr = 562+primOpTag ReadOffAddrOp_Word8AsInt16 = 563+primOpTag ReadOffAddrOp_Word8AsWord16 = 564+primOpTag ReadOffAddrOp_Word8AsInt32 = 565+primOpTag ReadOffAddrOp_Word8AsWord32 = 566+primOpTag ReadOffAddrOp_Word8AsInt64 = 567+primOpTag ReadOffAddrOp_Word8AsWord64 = 568+primOpTag WriteOffAddrOp_Char = 569+primOpTag WriteOffAddrOp_WideChar = 570+primOpTag WriteOffAddrOp_Int = 571+primOpTag WriteOffAddrOp_Word = 572+primOpTag WriteOffAddrOp_Addr = 573+primOpTag WriteOffAddrOp_Float = 574+primOpTag WriteOffAddrOp_Double = 575+primOpTag WriteOffAddrOp_StablePtr = 576+primOpTag WriteOffAddrOp_Int8 = 577+primOpTag WriteOffAddrOp_Word8 = 578+primOpTag WriteOffAddrOp_Int16 = 579+primOpTag WriteOffAddrOp_Word16 = 580+primOpTag WriteOffAddrOp_Int32 = 581+primOpTag WriteOffAddrOp_Word32 = 582+primOpTag WriteOffAddrOp_Int64 = 583+primOpTag WriteOffAddrOp_Word64 = 584+primOpTag WriteOffAddrOp_Word8AsChar = 585+primOpTag WriteOffAddrOp_Word8AsWideChar = 586+primOpTag WriteOffAddrOp_Word8AsInt = 587+primOpTag WriteOffAddrOp_Word8AsWord = 588+primOpTag WriteOffAddrOp_Word8AsAddr = 589+primOpTag WriteOffAddrOp_Word8AsFloat = 590+primOpTag WriteOffAddrOp_Word8AsDouble = 591+primOpTag WriteOffAddrOp_Word8AsStablePtr = 592+primOpTag WriteOffAddrOp_Word8AsInt16 = 593+primOpTag WriteOffAddrOp_Word8AsWord16 = 594+primOpTag WriteOffAddrOp_Word8AsInt32 = 595+primOpTag WriteOffAddrOp_Word8AsWord32 = 596+primOpTag WriteOffAddrOp_Word8AsInt64 = 597+primOpTag WriteOffAddrOp_Word8AsWord64 = 598+primOpTag InterlockedExchange_Addr = 599+primOpTag InterlockedExchange_Word = 600+primOpTag CasAddrOp_Addr = 601+primOpTag CasAddrOp_Word = 602+primOpTag CasAddrOp_Word8 = 603+primOpTag CasAddrOp_Word16 = 604+primOpTag CasAddrOp_Word32 = 605+primOpTag CasAddrOp_Word64 = 606+primOpTag FetchAddAddrOp_Word = 607+primOpTag FetchSubAddrOp_Word = 608+primOpTag FetchAndAddrOp_Word = 609+primOpTag FetchNandAddrOp_Word = 610+primOpTag FetchOrAddrOp_Word = 611+primOpTag FetchXorAddrOp_Word = 612+primOpTag AtomicReadAddrOp_Word = 613+primOpTag AtomicWriteAddrOp_Word = 614+primOpTag NewMutVarOp = 615+primOpTag ReadMutVarOp = 616+primOpTag WriteMutVarOp = 617+primOpTag AtomicSwapMutVarOp = 618+primOpTag AtomicModifyMutVar2Op = 619+primOpTag AtomicModifyMutVar_Op = 620+primOpTag CasMutVarOp = 621+primOpTag CatchOp = 622+primOpTag RaiseOp = 623+primOpTag RaiseUnderflowOp = 624+primOpTag RaiseOverflowOp = 625+primOpTag RaiseDivZeroOp = 626+primOpTag RaiseIOOp = 627+primOpTag MaskAsyncExceptionsOp = 628+primOpTag MaskUninterruptibleOp = 629+primOpTag UnmaskAsyncExceptionsOp = 630+primOpTag MaskStatus = 631+primOpTag NewPromptTagOp = 632+primOpTag PromptOp = 633+primOpTag Control0Op = 634+primOpTag AtomicallyOp = 635+primOpTag RetryOp = 636+primOpTag CatchRetryOp = 637+primOpTag CatchSTMOp = 638+primOpTag NewTVarOp = 639+primOpTag ReadTVarOp = 640+primOpTag ReadTVarIOOp = 641+primOpTag WriteTVarOp = 642+primOpTag NewMVarOp = 643+primOpTag TakeMVarOp = 644+primOpTag TryTakeMVarOp = 645+primOpTag PutMVarOp = 646+primOpTag TryPutMVarOp = 647+primOpTag ReadMVarOp = 648+primOpTag TryReadMVarOp = 649+primOpTag IsEmptyMVarOp = 650+primOpTag NewIOPortOp = 651+primOpTag ReadIOPortOp = 652+primOpTag WriteIOPortOp = 653+primOpTag DelayOp = 654+primOpTag WaitReadOp = 655+primOpTag WaitWriteOp = 656+primOpTag ForkOp = 657+primOpTag ForkOnOp = 658+primOpTag KillThreadOp = 659+primOpTag YieldOp = 660+primOpTag MyThreadIdOp = 661+primOpTag LabelThreadOp = 662+primOpTag IsCurrentThreadBoundOp = 663+primOpTag NoDuplicateOp = 664+primOpTag GetThreadLabelOp = 665+primOpTag ThreadStatusOp = 666+primOpTag ListThreadsOp = 667+primOpTag MkWeakOp = 668+primOpTag MkWeakNoFinalizerOp = 669+primOpTag AddCFinalizerToWeakOp = 670+primOpTag DeRefWeakOp = 671+primOpTag FinalizeWeakOp = 672+primOpTag TouchOp = 673+primOpTag MakeStablePtrOp = 674+primOpTag DeRefStablePtrOp = 675+primOpTag EqStablePtrOp = 676+primOpTag MakeStableNameOp = 677+primOpTag StableNameToIntOp = 678+primOpTag CompactNewOp = 679+primOpTag CompactResizeOp = 680+primOpTag CompactContainsOp = 681+primOpTag CompactContainsAnyOp = 682+primOpTag CompactGetFirstBlockOp = 683+primOpTag CompactGetNextBlockOp = 684+primOpTag CompactAllocateBlockOp = 685+primOpTag CompactFixupPointersOp = 686+primOpTag CompactAdd = 687+primOpTag CompactAddWithSharing = 688+primOpTag CompactSize = 689+primOpTag ReallyUnsafePtrEqualityOp = 690+primOpTag ParOp = 691+primOpTag SparkOp = 692+primOpTag SeqOp = 693+primOpTag GetSparkOp = 694+primOpTag NumSparks = 695+primOpTag KeepAliveOp = 696+primOpTag DataToTagSmallOp = 697+primOpTag DataToTagLargeOp = 698+primOpTag TagToEnumOp = 699+primOpTag AddrToAnyOp = 700+primOpTag AnyToAddrOp = 701+primOpTag MkApUpd0_Op = 702+primOpTag NewBCOOp = 703+primOpTag UnpackClosureOp = 704+primOpTag ClosureSizeOp = 705+primOpTag GetApStackValOp = 706+primOpTag GetCCSOfOp = 707+primOpTag GetCurrentCCSOp = 708+primOpTag ClearCCSOp = 709+primOpTag WhereFromOp = 710+primOpTag TraceEventOp = 711+primOpTag TraceEventBinaryOp = 712+primOpTag TraceMarkerOp = 713+primOpTag SetThreadAllocationCounter = 714+primOpTag (VecBroadcastOp IntVec 16 W8) = 715+primOpTag (VecBroadcastOp IntVec 8 W16) = 716+primOpTag (VecBroadcastOp IntVec 4 W32) = 717+primOpTag (VecBroadcastOp IntVec 2 W64) = 718+primOpTag (VecBroadcastOp IntVec 32 W8) = 719+primOpTag (VecBroadcastOp IntVec 16 W16) = 720+primOpTag (VecBroadcastOp IntVec 8 W32) = 721+primOpTag (VecBroadcastOp IntVec 4 W64) = 722+primOpTag (VecBroadcastOp IntVec 64 W8) = 723+primOpTag (VecBroadcastOp IntVec 32 W16) = 724+primOpTag (VecBroadcastOp IntVec 16 W32) = 725+primOpTag (VecBroadcastOp IntVec 8 W64) = 726+primOpTag (VecBroadcastOp WordVec 16 W8) = 727+primOpTag (VecBroadcastOp WordVec 8 W16) = 728+primOpTag (VecBroadcastOp WordVec 4 W32) = 729+primOpTag (VecBroadcastOp WordVec 2 W64) = 730+primOpTag (VecBroadcastOp WordVec 32 W8) = 731+primOpTag (VecBroadcastOp WordVec 16 W16) = 732+primOpTag (VecBroadcastOp WordVec 8 W32) = 733+primOpTag (VecBroadcastOp WordVec 4 W64) = 734+primOpTag (VecBroadcastOp WordVec 64 W8) = 735+primOpTag (VecBroadcastOp WordVec 32 W16) = 736+primOpTag (VecBroadcastOp WordVec 16 W32) = 737+primOpTag (VecBroadcastOp WordVec 8 W64) = 738+primOpTag (VecBroadcastOp FloatVec 4 W32) = 739+primOpTag (VecBroadcastOp FloatVec 2 W64) = 740+primOpTag (VecBroadcastOp FloatVec 8 W32) = 741+primOpTag (VecBroadcastOp FloatVec 4 W64) = 742+primOpTag (VecBroadcastOp FloatVec 16 W32) = 743+primOpTag (VecBroadcastOp FloatVec 8 W64) = 744+primOpTag (VecPackOp IntVec 16 W8) = 745+primOpTag (VecPackOp IntVec 8 W16) = 746+primOpTag (VecPackOp IntVec 4 W32) = 747+primOpTag (VecPackOp IntVec 2 W64) = 748+primOpTag (VecPackOp IntVec 32 W8) = 749+primOpTag (VecPackOp IntVec 16 W16) = 750+primOpTag (VecPackOp IntVec 8 W32) = 751+primOpTag (VecPackOp IntVec 4 W64) = 752+primOpTag (VecPackOp IntVec 64 W8) = 753+primOpTag (VecPackOp IntVec 32 W16) = 754+primOpTag (VecPackOp IntVec 16 W32) = 755+primOpTag (VecPackOp IntVec 8 W64) = 756+primOpTag (VecPackOp WordVec 16 W8) = 757+primOpTag (VecPackOp WordVec 8 W16) = 758+primOpTag (VecPackOp WordVec 4 W32) = 759+primOpTag (VecPackOp WordVec 2 W64) = 760+primOpTag (VecPackOp WordVec 32 W8) = 761+primOpTag (VecPackOp WordVec 16 W16) = 762+primOpTag (VecPackOp WordVec 8 W32) = 763+primOpTag (VecPackOp WordVec 4 W64) = 764+primOpTag (VecPackOp WordVec 64 W8) = 765+primOpTag (VecPackOp WordVec 32 W16) = 766+primOpTag (VecPackOp WordVec 16 W32) = 767+primOpTag (VecPackOp WordVec 8 W64) = 768+primOpTag (VecPackOp FloatVec 4 W32) = 769+primOpTag (VecPackOp FloatVec 2 W64) = 770+primOpTag (VecPackOp FloatVec 8 W32) = 771+primOpTag (VecPackOp FloatVec 4 W64) = 772+primOpTag (VecPackOp FloatVec 16 W32) = 773+primOpTag (VecPackOp FloatVec 8 W64) = 774+primOpTag (VecUnpackOp IntVec 16 W8) = 775+primOpTag (VecUnpackOp IntVec 8 W16) = 776+primOpTag (VecUnpackOp IntVec 4 W32) = 777+primOpTag (VecUnpackOp IntVec 2 W64) = 778+primOpTag (VecUnpackOp IntVec 32 W8) = 779+primOpTag (VecUnpackOp IntVec 16 W16) = 780+primOpTag (VecUnpackOp IntVec 8 W32) = 781+primOpTag (VecUnpackOp IntVec 4 W64) = 782+primOpTag (VecUnpackOp IntVec 64 W8) = 783+primOpTag (VecUnpackOp IntVec 32 W16) = 784+primOpTag (VecUnpackOp IntVec 16 W32) = 785+primOpTag (VecUnpackOp IntVec 8 W64) = 786+primOpTag (VecUnpackOp WordVec 16 W8) = 787+primOpTag (VecUnpackOp WordVec 8 W16) = 788+primOpTag (VecUnpackOp WordVec 4 W32) = 789+primOpTag (VecUnpackOp WordVec 2 W64) = 790+primOpTag (VecUnpackOp WordVec 32 W8) = 791+primOpTag (VecUnpackOp WordVec 16 W16) = 792+primOpTag (VecUnpackOp WordVec 8 W32) = 793+primOpTag (VecUnpackOp WordVec 4 W64) = 794+primOpTag (VecUnpackOp WordVec 64 W8) = 795+primOpTag (VecUnpackOp WordVec 32 W16) = 796+primOpTag (VecUnpackOp WordVec 16 W32) = 797+primOpTag (VecUnpackOp WordVec 8 W64) = 798+primOpTag (VecUnpackOp FloatVec 4 W32) = 799+primOpTag (VecUnpackOp FloatVec 2 W64) = 800+primOpTag (VecUnpackOp FloatVec 8 W32) = 801+primOpTag (VecUnpackOp FloatVec 4 W64) = 802+primOpTag (VecUnpackOp FloatVec 16 W32) = 803+primOpTag (VecUnpackOp FloatVec 8 W64) = 804+primOpTag (VecInsertOp IntVec 16 W8) = 805+primOpTag (VecInsertOp IntVec 8 W16) = 806+primOpTag (VecInsertOp IntVec 4 W32) = 807+primOpTag (VecInsertOp IntVec 2 W64) = 808+primOpTag (VecInsertOp IntVec 32 W8) = 809+primOpTag (VecInsertOp IntVec 16 W16) = 810+primOpTag (VecInsertOp IntVec 8 W32) = 811+primOpTag (VecInsertOp IntVec 4 W64) = 812+primOpTag (VecInsertOp IntVec 64 W8) = 813+primOpTag (VecInsertOp IntVec 32 W16) = 814+primOpTag (VecInsertOp IntVec 16 W32) = 815+primOpTag (VecInsertOp IntVec 8 W64) = 816+primOpTag (VecInsertOp WordVec 16 W8) = 817+primOpTag (VecInsertOp WordVec 8 W16) = 818+primOpTag (VecInsertOp WordVec 4 W32) = 819+primOpTag (VecInsertOp WordVec 2 W64) = 820+primOpTag (VecInsertOp WordVec 32 W8) = 821+primOpTag (VecInsertOp WordVec 16 W16) = 822+primOpTag (VecInsertOp WordVec 8 W32) = 823+primOpTag (VecInsertOp WordVec 4 W64) = 824+primOpTag (VecInsertOp WordVec 64 W8) = 825+primOpTag (VecInsertOp WordVec 32 W16) = 826+primOpTag (VecInsertOp WordVec 16 W32) = 827+primOpTag (VecInsertOp WordVec 8 W64) = 828+primOpTag (VecInsertOp FloatVec 4 W32) = 829+primOpTag (VecInsertOp FloatVec 2 W64) = 830+primOpTag (VecInsertOp FloatVec 8 W32) = 831+primOpTag (VecInsertOp FloatVec 4 W64) = 832+primOpTag (VecInsertOp FloatVec 16 W32) = 833+primOpTag (VecInsertOp FloatVec 8 W64) = 834+primOpTag (VecAddOp IntVec 16 W8) = 835+primOpTag (VecAddOp IntVec 8 W16) = 836+primOpTag (VecAddOp IntVec 4 W32) = 837+primOpTag (VecAddOp IntVec 2 W64) = 838+primOpTag (VecAddOp IntVec 32 W8) = 839+primOpTag (VecAddOp IntVec 16 W16) = 840+primOpTag (VecAddOp IntVec 8 W32) = 841+primOpTag (VecAddOp IntVec 4 W64) = 842+primOpTag (VecAddOp IntVec 64 W8) = 843+primOpTag (VecAddOp IntVec 32 W16) = 844+primOpTag (VecAddOp IntVec 16 W32) = 845+primOpTag (VecAddOp IntVec 8 W64) = 846+primOpTag (VecAddOp WordVec 16 W8) = 847+primOpTag (VecAddOp WordVec 8 W16) = 848+primOpTag (VecAddOp WordVec 4 W32) = 849+primOpTag (VecAddOp WordVec 2 W64) = 850+primOpTag (VecAddOp WordVec 32 W8) = 851+primOpTag (VecAddOp WordVec 16 W16) = 852+primOpTag (VecAddOp WordVec 8 W32) = 853+primOpTag (VecAddOp WordVec 4 W64) = 854+primOpTag (VecAddOp WordVec 64 W8) = 855+primOpTag (VecAddOp WordVec 32 W16) = 856+primOpTag (VecAddOp WordVec 16 W32) = 857+primOpTag (VecAddOp WordVec 8 W64) = 858+primOpTag (VecAddOp FloatVec 4 W32) = 859+primOpTag (VecAddOp FloatVec 2 W64) = 860+primOpTag (VecAddOp FloatVec 8 W32) = 861+primOpTag (VecAddOp FloatVec 4 W64) = 862+primOpTag (VecAddOp FloatVec 16 W32) = 863+primOpTag (VecAddOp FloatVec 8 W64) = 864+primOpTag (VecSubOp IntVec 16 W8) = 865+primOpTag (VecSubOp IntVec 8 W16) = 866+primOpTag (VecSubOp IntVec 4 W32) = 867+primOpTag (VecSubOp IntVec 2 W64) = 868+primOpTag (VecSubOp IntVec 32 W8) = 869+primOpTag (VecSubOp IntVec 16 W16) = 870+primOpTag (VecSubOp IntVec 8 W32) = 871+primOpTag (VecSubOp IntVec 4 W64) = 872+primOpTag (VecSubOp IntVec 64 W8) = 873+primOpTag (VecSubOp IntVec 32 W16) = 874+primOpTag (VecSubOp IntVec 16 W32) = 875+primOpTag (VecSubOp IntVec 8 W64) = 876+primOpTag (VecSubOp WordVec 16 W8) = 877+primOpTag (VecSubOp WordVec 8 W16) = 878+primOpTag (VecSubOp WordVec 4 W32) = 879+primOpTag (VecSubOp WordVec 2 W64) = 880+primOpTag (VecSubOp WordVec 32 W8) = 881+primOpTag (VecSubOp WordVec 16 W16) = 882+primOpTag (VecSubOp WordVec 8 W32) = 883+primOpTag (VecSubOp WordVec 4 W64) = 884+primOpTag (VecSubOp WordVec 64 W8) = 885+primOpTag (VecSubOp WordVec 32 W16) = 886+primOpTag (VecSubOp WordVec 16 W32) = 887+primOpTag (VecSubOp WordVec 8 W64) = 888+primOpTag (VecSubOp FloatVec 4 W32) = 889+primOpTag (VecSubOp FloatVec 2 W64) = 890+primOpTag (VecSubOp FloatVec 8 W32) = 891+primOpTag (VecSubOp FloatVec 4 W64) = 892+primOpTag (VecSubOp FloatVec 16 W32) = 893+primOpTag (VecSubOp FloatVec 8 W64) = 894+primOpTag (VecMulOp IntVec 16 W8) = 895+primOpTag (VecMulOp IntVec 8 W16) = 896+primOpTag (VecMulOp IntVec 4 W32) = 897+primOpTag (VecMulOp IntVec 2 W64) = 898+primOpTag (VecMulOp IntVec 32 W8) = 899+primOpTag (VecMulOp IntVec 16 W16) = 900+primOpTag (VecMulOp IntVec 8 W32) = 901+primOpTag (VecMulOp IntVec 4 W64) = 902+primOpTag (VecMulOp IntVec 64 W8) = 903+primOpTag (VecMulOp IntVec 32 W16) = 904+primOpTag (VecMulOp IntVec 16 W32) = 905+primOpTag (VecMulOp IntVec 8 W64) = 906+primOpTag (VecMulOp WordVec 16 W8) = 907+primOpTag (VecMulOp WordVec 8 W16) = 908+primOpTag (VecMulOp WordVec 4 W32) = 909+primOpTag (VecMulOp WordVec 2 W64) = 910+primOpTag (VecMulOp WordVec 32 W8) = 911+primOpTag (VecMulOp WordVec 16 W16) = 912+primOpTag (VecMulOp WordVec 8 W32) = 913+primOpTag (VecMulOp WordVec 4 W64) = 914+primOpTag (VecMulOp WordVec 64 W8) = 915+primOpTag (VecMulOp WordVec 32 W16) = 916+primOpTag (VecMulOp WordVec 16 W32) = 917+primOpTag (VecMulOp WordVec 8 W64) = 918+primOpTag (VecMulOp FloatVec 4 W32) = 919+primOpTag (VecMulOp FloatVec 2 W64) = 920+primOpTag (VecMulOp FloatVec 8 W32) = 921+primOpTag (VecMulOp FloatVec 4 W64) = 922+primOpTag (VecMulOp FloatVec 16 W32) = 923+primOpTag (VecMulOp FloatVec 8 W64) = 924+primOpTag (VecDivOp FloatVec 4 W32) = 925+primOpTag (VecDivOp FloatVec 2 W64) = 926+primOpTag (VecDivOp FloatVec 8 W32) = 927+primOpTag (VecDivOp FloatVec 4 W64) = 928+primOpTag (VecDivOp FloatVec 16 W32) = 929+primOpTag (VecDivOp FloatVec 8 W64) = 930+primOpTag (VecQuotOp IntVec 16 W8) = 931+primOpTag (VecQuotOp IntVec 8 W16) = 932+primOpTag (VecQuotOp IntVec 4 W32) = 933+primOpTag (VecQuotOp IntVec 2 W64) = 934+primOpTag (VecQuotOp IntVec 32 W8) = 935+primOpTag (VecQuotOp IntVec 16 W16) = 936+primOpTag (VecQuotOp IntVec 8 W32) = 937+primOpTag (VecQuotOp IntVec 4 W64) = 938+primOpTag (VecQuotOp IntVec 64 W8) = 939+primOpTag (VecQuotOp IntVec 32 W16) = 940+primOpTag (VecQuotOp IntVec 16 W32) = 941+primOpTag (VecQuotOp IntVec 8 W64) = 942+primOpTag (VecQuotOp WordVec 16 W8) = 943+primOpTag (VecQuotOp WordVec 8 W16) = 944+primOpTag (VecQuotOp WordVec 4 W32) = 945+primOpTag (VecQuotOp WordVec 2 W64) = 946+primOpTag (VecQuotOp WordVec 32 W8) = 947+primOpTag (VecQuotOp WordVec 16 W16) = 948+primOpTag (VecQuotOp WordVec 8 W32) = 949+primOpTag (VecQuotOp WordVec 4 W64) = 950+primOpTag (VecQuotOp WordVec 64 W8) = 951+primOpTag (VecQuotOp WordVec 32 W16) = 952+primOpTag (VecQuotOp WordVec 16 W32) = 953+primOpTag (VecQuotOp WordVec 8 W64) = 954+primOpTag (VecRemOp IntVec 16 W8) = 955+primOpTag (VecRemOp IntVec 8 W16) = 956+primOpTag (VecRemOp IntVec 4 W32) = 957+primOpTag (VecRemOp IntVec 2 W64) = 958+primOpTag (VecRemOp IntVec 32 W8) = 959+primOpTag (VecRemOp IntVec 16 W16) = 960+primOpTag (VecRemOp IntVec 8 W32) = 961+primOpTag (VecRemOp IntVec 4 W64) = 962+primOpTag (VecRemOp IntVec 64 W8) = 963+primOpTag (VecRemOp IntVec 32 W16) = 964+primOpTag (VecRemOp IntVec 16 W32) = 965+primOpTag (VecRemOp IntVec 8 W64) = 966+primOpTag (VecRemOp WordVec 16 W8) = 967+primOpTag (VecRemOp WordVec 8 W16) = 968+primOpTag (VecRemOp WordVec 4 W32) = 969+primOpTag (VecRemOp WordVec 2 W64) = 970+primOpTag (VecRemOp WordVec 32 W8) = 971+primOpTag (VecRemOp WordVec 16 W16) = 972+primOpTag (VecRemOp WordVec 8 W32) = 973+primOpTag (VecRemOp WordVec 4 W64) = 974+primOpTag (VecRemOp WordVec 64 W8) = 975+primOpTag (VecRemOp WordVec 32 W16) = 976+primOpTag (VecRemOp WordVec 16 W32) = 977+primOpTag (VecRemOp WordVec 8 W64) = 978+primOpTag (VecNegOp IntVec 16 W8) = 979+primOpTag (VecNegOp IntVec 8 W16) = 980+primOpTag (VecNegOp IntVec 4 W32) = 981+primOpTag (VecNegOp IntVec 2 W64) = 982+primOpTag (VecNegOp IntVec 32 W8) = 983+primOpTag (VecNegOp IntVec 16 W16) = 984+primOpTag (VecNegOp IntVec 8 W32) = 985+primOpTag (VecNegOp IntVec 4 W64) = 986+primOpTag (VecNegOp IntVec 64 W8) = 987+primOpTag (VecNegOp IntVec 32 W16) = 988+primOpTag (VecNegOp IntVec 16 W32) = 989+primOpTag (VecNegOp IntVec 8 W64) = 990+primOpTag (VecNegOp FloatVec 4 W32) = 991+primOpTag (VecNegOp FloatVec 2 W64) = 992+primOpTag (VecNegOp FloatVec 8 W32) = 993+primOpTag (VecNegOp FloatVec 4 W64) = 994+primOpTag (VecNegOp FloatVec 16 W32) = 995+primOpTag (VecNegOp FloatVec 8 W64) = 996+primOpTag (VecIndexByteArrayOp IntVec 16 W8) = 997+primOpTag (VecIndexByteArrayOp IntVec 8 W16) = 998+primOpTag (VecIndexByteArrayOp IntVec 4 W32) = 999+primOpTag (VecIndexByteArrayOp IntVec 2 W64) = 1000+primOpTag (VecIndexByteArrayOp IntVec 32 W8) = 1001+primOpTag (VecIndexByteArrayOp IntVec 16 W16) = 1002+primOpTag (VecIndexByteArrayOp IntVec 8 W32) = 1003+primOpTag (VecIndexByteArrayOp IntVec 4 W64) = 1004+primOpTag (VecIndexByteArrayOp IntVec 64 W8) = 1005+primOpTag (VecIndexByteArrayOp IntVec 32 W16) = 1006+primOpTag (VecIndexByteArrayOp IntVec 16 W32) = 1007+primOpTag (VecIndexByteArrayOp IntVec 8 W64) = 1008+primOpTag (VecIndexByteArrayOp WordVec 16 W8) = 1009+primOpTag (VecIndexByteArrayOp WordVec 8 W16) = 1010+primOpTag (VecIndexByteArrayOp WordVec 4 W32) = 1011+primOpTag (VecIndexByteArrayOp WordVec 2 W64) = 1012+primOpTag (VecIndexByteArrayOp WordVec 32 W8) = 1013+primOpTag (VecIndexByteArrayOp WordVec 16 W16) = 1014+primOpTag (VecIndexByteArrayOp WordVec 8 W32) = 1015+primOpTag (VecIndexByteArrayOp WordVec 4 W64) = 1016+primOpTag (VecIndexByteArrayOp WordVec 64 W8) = 1017+primOpTag (VecIndexByteArrayOp WordVec 32 W16) = 1018+primOpTag (VecIndexByteArrayOp WordVec 16 W32) = 1019+primOpTag (VecIndexByteArrayOp WordVec 8 W64) = 1020+primOpTag (VecIndexByteArrayOp FloatVec 4 W32) = 1021+primOpTag (VecIndexByteArrayOp FloatVec 2 W64) = 1022+primOpTag (VecIndexByteArrayOp FloatVec 8 W32) = 1023+primOpTag (VecIndexByteArrayOp FloatVec 4 W64) = 1024+primOpTag (VecIndexByteArrayOp FloatVec 16 W32) = 1025+primOpTag (VecIndexByteArrayOp FloatVec 8 W64) = 1026+primOpTag (VecReadByteArrayOp IntVec 16 W8) = 1027+primOpTag (VecReadByteArrayOp IntVec 8 W16) = 1028+primOpTag (VecReadByteArrayOp IntVec 4 W32) = 1029+primOpTag (VecReadByteArrayOp IntVec 2 W64) = 1030+primOpTag (VecReadByteArrayOp IntVec 32 W8) = 1031+primOpTag (VecReadByteArrayOp IntVec 16 W16) = 1032+primOpTag (VecReadByteArrayOp IntVec 8 W32) = 1033+primOpTag (VecReadByteArrayOp IntVec 4 W64) = 1034+primOpTag (VecReadByteArrayOp IntVec 64 W8) = 1035+primOpTag (VecReadByteArrayOp IntVec 32 W16) = 1036+primOpTag (VecReadByteArrayOp IntVec 16 W32) = 1037+primOpTag (VecReadByteArrayOp IntVec 8 W64) = 1038+primOpTag (VecReadByteArrayOp WordVec 16 W8) = 1039+primOpTag (VecReadByteArrayOp WordVec 8 W16) = 1040+primOpTag (VecReadByteArrayOp WordVec 4 W32) = 1041+primOpTag (VecReadByteArrayOp WordVec 2 W64) = 1042+primOpTag (VecReadByteArrayOp WordVec 32 W8) = 1043+primOpTag (VecReadByteArrayOp WordVec 16 W16) = 1044+primOpTag (VecReadByteArrayOp WordVec 8 W32) = 1045+primOpTag (VecReadByteArrayOp WordVec 4 W64) = 1046+primOpTag (VecReadByteArrayOp WordVec 64 W8) = 1047+primOpTag (VecReadByteArrayOp WordVec 32 W16) = 1048+primOpTag (VecReadByteArrayOp WordVec 16 W32) = 1049+primOpTag (VecReadByteArrayOp WordVec 8 W64) = 1050+primOpTag (VecReadByteArrayOp FloatVec 4 W32) = 1051+primOpTag (VecReadByteArrayOp FloatVec 2 W64) = 1052+primOpTag (VecReadByteArrayOp FloatVec 8 W32) = 1053+primOpTag (VecReadByteArrayOp FloatVec 4 W64) = 1054+primOpTag (VecReadByteArrayOp FloatVec 16 W32) = 1055+primOpTag (VecReadByteArrayOp FloatVec 8 W64) = 1056+primOpTag (VecWriteByteArrayOp IntVec 16 W8) = 1057+primOpTag (VecWriteByteArrayOp IntVec 8 W16) = 1058+primOpTag (VecWriteByteArrayOp IntVec 4 W32) = 1059+primOpTag (VecWriteByteArrayOp IntVec 2 W64) = 1060+primOpTag (VecWriteByteArrayOp IntVec 32 W8) = 1061+primOpTag (VecWriteByteArrayOp IntVec 16 W16) = 1062+primOpTag (VecWriteByteArrayOp IntVec 8 W32) = 1063+primOpTag (VecWriteByteArrayOp IntVec 4 W64) = 1064+primOpTag (VecWriteByteArrayOp IntVec 64 W8) = 1065+primOpTag (VecWriteByteArrayOp IntVec 32 W16) = 1066+primOpTag (VecWriteByteArrayOp IntVec 16 W32) = 1067+primOpTag (VecWriteByteArrayOp IntVec 8 W64) = 1068+primOpTag (VecWriteByteArrayOp WordVec 16 W8) = 1069+primOpTag (VecWriteByteArrayOp WordVec 8 W16) = 1070+primOpTag (VecWriteByteArrayOp WordVec 4 W32) = 1071+primOpTag (VecWriteByteArrayOp WordVec 2 W64) = 1072+primOpTag (VecWriteByteArrayOp WordVec 32 W8) = 1073+primOpTag (VecWriteByteArrayOp WordVec 16 W16) = 1074+primOpTag (VecWriteByteArrayOp WordVec 8 W32) = 1075+primOpTag (VecWriteByteArrayOp WordVec 4 W64) = 1076+primOpTag (VecWriteByteArrayOp WordVec 64 W8) = 1077+primOpTag (VecWriteByteArrayOp WordVec 32 W16) = 1078+primOpTag (VecWriteByteArrayOp WordVec 16 W32) = 1079+primOpTag (VecWriteByteArrayOp WordVec 8 W64) = 1080+primOpTag (VecWriteByteArrayOp FloatVec 4 W32) = 1081+primOpTag (VecWriteByteArrayOp FloatVec 2 W64) = 1082+primOpTag (VecWriteByteArrayOp FloatVec 8 W32) = 1083+primOpTag (VecWriteByteArrayOp FloatVec 4 W64) = 1084+primOpTag (VecWriteByteArrayOp FloatVec 16 W32) = 1085+primOpTag (VecWriteByteArrayOp FloatVec 8 W64) = 1086+primOpTag (VecIndexOffAddrOp IntVec 16 W8) = 1087+primOpTag (VecIndexOffAddrOp IntVec 8 W16) = 1088+primOpTag (VecIndexOffAddrOp IntVec 4 W32) = 1089+primOpTag (VecIndexOffAddrOp IntVec 2 W64) = 1090+primOpTag (VecIndexOffAddrOp IntVec 32 W8) = 1091+primOpTag (VecIndexOffAddrOp IntVec 16 W16) = 1092+primOpTag (VecIndexOffAddrOp IntVec 8 W32) = 1093+primOpTag (VecIndexOffAddrOp IntVec 4 W64) = 1094+primOpTag (VecIndexOffAddrOp IntVec 64 W8) = 1095+primOpTag (VecIndexOffAddrOp IntVec 32 W16) = 1096+primOpTag (VecIndexOffAddrOp IntVec 16 W32) = 1097+primOpTag (VecIndexOffAddrOp IntVec 8 W64) = 1098+primOpTag (VecIndexOffAddrOp WordVec 16 W8) = 1099+primOpTag (VecIndexOffAddrOp WordVec 8 W16) = 1100+primOpTag (VecIndexOffAddrOp WordVec 4 W32) = 1101+primOpTag (VecIndexOffAddrOp WordVec 2 W64) = 1102+primOpTag (VecIndexOffAddrOp WordVec 32 W8) = 1103+primOpTag (VecIndexOffAddrOp WordVec 16 W16) = 1104+primOpTag (VecIndexOffAddrOp WordVec 8 W32) = 1105+primOpTag (VecIndexOffAddrOp WordVec 4 W64) = 1106+primOpTag (VecIndexOffAddrOp WordVec 64 W8) = 1107+primOpTag (VecIndexOffAddrOp WordVec 32 W16) = 1108+primOpTag (VecIndexOffAddrOp WordVec 16 W32) = 1109+primOpTag (VecIndexOffAddrOp WordVec 8 W64) = 1110+primOpTag (VecIndexOffAddrOp FloatVec 4 W32) = 1111+primOpTag (VecIndexOffAddrOp FloatVec 2 W64) = 1112+primOpTag (VecIndexOffAddrOp FloatVec 8 W32) = 1113+primOpTag (VecIndexOffAddrOp FloatVec 4 W64) = 1114+primOpTag (VecIndexOffAddrOp FloatVec 16 W32) = 1115+primOpTag (VecIndexOffAddrOp FloatVec 8 W64) = 1116+primOpTag (VecReadOffAddrOp IntVec 16 W8) = 1117+primOpTag (VecReadOffAddrOp IntVec 8 W16) = 1118+primOpTag (VecReadOffAddrOp IntVec 4 W32) = 1119+primOpTag (VecReadOffAddrOp IntVec 2 W64) = 1120+primOpTag (VecReadOffAddrOp IntVec 32 W8) = 1121+primOpTag (VecReadOffAddrOp IntVec 16 W16) = 1122+primOpTag (VecReadOffAddrOp IntVec 8 W32) = 1123+primOpTag (VecReadOffAddrOp IntVec 4 W64) = 1124+primOpTag (VecReadOffAddrOp IntVec 64 W8) = 1125+primOpTag (VecReadOffAddrOp IntVec 32 W16) = 1126+primOpTag (VecReadOffAddrOp IntVec 16 W32) = 1127+primOpTag (VecReadOffAddrOp IntVec 8 W64) = 1128+primOpTag (VecReadOffAddrOp WordVec 16 W8) = 1129+primOpTag (VecReadOffAddrOp WordVec 8 W16) = 1130+primOpTag (VecReadOffAddrOp WordVec 4 W32) = 1131+primOpTag (VecReadOffAddrOp WordVec 2 W64) = 1132+primOpTag (VecReadOffAddrOp WordVec 32 W8) = 1133+primOpTag (VecReadOffAddrOp WordVec 16 W16) = 1134+primOpTag (VecReadOffAddrOp WordVec 8 W32) = 1135+primOpTag (VecReadOffAddrOp WordVec 4 W64) = 1136+primOpTag (VecReadOffAddrOp WordVec 64 W8) = 1137+primOpTag (VecReadOffAddrOp WordVec 32 W16) = 1138+primOpTag (VecReadOffAddrOp WordVec 16 W32) = 1139+primOpTag (VecReadOffAddrOp WordVec 8 W64) = 1140+primOpTag (VecReadOffAddrOp FloatVec 4 W32) = 1141+primOpTag (VecReadOffAddrOp FloatVec 2 W64) = 1142+primOpTag (VecReadOffAddrOp FloatVec 8 W32) = 1143+primOpTag (VecReadOffAddrOp FloatVec 4 W64) = 1144+primOpTag (VecReadOffAddrOp FloatVec 16 W32) = 1145+primOpTag (VecReadOffAddrOp FloatVec 8 W64) = 1146+primOpTag (VecWriteOffAddrOp IntVec 16 W8) = 1147+primOpTag (VecWriteOffAddrOp IntVec 8 W16) = 1148+primOpTag (VecWriteOffAddrOp IntVec 4 W32) = 1149+primOpTag (VecWriteOffAddrOp IntVec 2 W64) = 1150+primOpTag (VecWriteOffAddrOp IntVec 32 W8) = 1151+primOpTag (VecWriteOffAddrOp IntVec 16 W16) = 1152+primOpTag (VecWriteOffAddrOp IntVec 8 W32) = 1153+primOpTag (VecWriteOffAddrOp IntVec 4 W64) = 1154+primOpTag (VecWriteOffAddrOp IntVec 64 W8) = 1155+primOpTag (VecWriteOffAddrOp IntVec 32 W16) = 1156+primOpTag (VecWriteOffAddrOp IntVec 16 W32) = 1157+primOpTag (VecWriteOffAddrOp IntVec 8 W64) = 1158+primOpTag (VecWriteOffAddrOp WordVec 16 W8) = 1159+primOpTag (VecWriteOffAddrOp WordVec 8 W16) = 1160+primOpTag (VecWriteOffAddrOp WordVec 4 W32) = 1161+primOpTag (VecWriteOffAddrOp WordVec 2 W64) = 1162+primOpTag (VecWriteOffAddrOp WordVec 32 W8) = 1163+primOpTag (VecWriteOffAddrOp WordVec 16 W16) = 1164+primOpTag (VecWriteOffAddrOp WordVec 8 W32) = 1165+primOpTag (VecWriteOffAddrOp WordVec 4 W64) = 1166+primOpTag (VecWriteOffAddrOp WordVec 64 W8) = 1167+primOpTag (VecWriteOffAddrOp WordVec 32 W16) = 1168+primOpTag (VecWriteOffAddrOp WordVec 16 W32) = 1169+primOpTag (VecWriteOffAddrOp WordVec 8 W64) = 1170+primOpTag (VecWriteOffAddrOp FloatVec 4 W32) = 1171+primOpTag (VecWriteOffAddrOp FloatVec 2 W64) = 1172+primOpTag (VecWriteOffAddrOp FloatVec 8 W32) = 1173+primOpTag (VecWriteOffAddrOp FloatVec 4 W64) = 1174+primOpTag (VecWriteOffAddrOp FloatVec 16 W32) = 1175+primOpTag (VecWriteOffAddrOp FloatVec 8 W64) = 1176+primOpTag (VecIndexScalarByteArrayOp IntVec 16 W8) = 1177+primOpTag (VecIndexScalarByteArrayOp IntVec 8 W16) = 1178+primOpTag (VecIndexScalarByteArrayOp IntVec 4 W32) = 1179+primOpTag (VecIndexScalarByteArrayOp IntVec 2 W64) = 1180+primOpTag (VecIndexScalarByteArrayOp IntVec 32 W8) = 1181+primOpTag (VecIndexScalarByteArrayOp IntVec 16 W16) = 1182+primOpTag (VecIndexScalarByteArrayOp IntVec 8 W32) = 1183+primOpTag (VecIndexScalarByteArrayOp IntVec 4 W64) = 1184+primOpTag (VecIndexScalarByteArrayOp IntVec 64 W8) = 1185+primOpTag (VecIndexScalarByteArrayOp IntVec 32 W16) = 1186+primOpTag (VecIndexScalarByteArrayOp IntVec 16 W32) = 1187+primOpTag (VecIndexScalarByteArrayOp IntVec 8 W64) = 1188+primOpTag (VecIndexScalarByteArrayOp WordVec 16 W8) = 1189+primOpTag (VecIndexScalarByteArrayOp WordVec 8 W16) = 1190+primOpTag (VecIndexScalarByteArrayOp WordVec 4 W32) = 1191+primOpTag (VecIndexScalarByteArrayOp WordVec 2 W64) = 1192+primOpTag (VecIndexScalarByteArrayOp WordVec 32 W8) = 1193+primOpTag (VecIndexScalarByteArrayOp WordVec 16 W16) = 1194+primOpTag (VecIndexScalarByteArrayOp WordVec 8 W32) = 1195+primOpTag (VecIndexScalarByteArrayOp WordVec 4 W64) = 1196+primOpTag (VecIndexScalarByteArrayOp WordVec 64 W8) = 1197+primOpTag (VecIndexScalarByteArrayOp WordVec 32 W16) = 1198+primOpTag (VecIndexScalarByteArrayOp WordVec 16 W32) = 1199+primOpTag (VecIndexScalarByteArrayOp WordVec 8 W64) = 1200+primOpTag (VecIndexScalarByteArrayOp FloatVec 4 W32) = 1201+primOpTag (VecIndexScalarByteArrayOp FloatVec 2 W64) = 1202+primOpTag (VecIndexScalarByteArrayOp FloatVec 8 W32) = 1203+primOpTag (VecIndexScalarByteArrayOp FloatVec 4 W64) = 1204+primOpTag (VecIndexScalarByteArrayOp FloatVec 16 W32) = 1205+primOpTag (VecIndexScalarByteArrayOp FloatVec 8 W64) = 1206+primOpTag (VecReadScalarByteArrayOp IntVec 16 W8) = 1207+primOpTag (VecReadScalarByteArrayOp IntVec 8 W16) = 1208+primOpTag (VecReadScalarByteArrayOp IntVec 4 W32) = 1209+primOpTag (VecReadScalarByteArrayOp IntVec 2 W64) = 1210+primOpTag (VecReadScalarByteArrayOp IntVec 32 W8) = 1211+primOpTag (VecReadScalarByteArrayOp IntVec 16 W16) = 1212+primOpTag (VecReadScalarByteArrayOp IntVec 8 W32) = 1213+primOpTag (VecReadScalarByteArrayOp IntVec 4 W64) = 1214+primOpTag (VecReadScalarByteArrayOp IntVec 64 W8) = 1215+primOpTag (VecReadScalarByteArrayOp IntVec 32 W16) = 1216+primOpTag (VecReadScalarByteArrayOp IntVec 16 W32) = 1217+primOpTag (VecReadScalarByteArrayOp IntVec 8 W64) = 1218+primOpTag (VecReadScalarByteArrayOp WordVec 16 W8) = 1219+primOpTag (VecReadScalarByteArrayOp WordVec 8 W16) = 1220+primOpTag (VecReadScalarByteArrayOp WordVec 4 W32) = 1221+primOpTag (VecReadScalarByteArrayOp WordVec 2 W64) = 1222+primOpTag (VecReadScalarByteArrayOp WordVec 32 W8) = 1223+primOpTag (VecReadScalarByteArrayOp WordVec 16 W16) = 1224+primOpTag (VecReadScalarByteArrayOp WordVec 8 W32) = 1225+primOpTag (VecReadScalarByteArrayOp WordVec 4 W64) = 1226+primOpTag (VecReadScalarByteArrayOp WordVec 64 W8) = 1227+primOpTag (VecReadScalarByteArrayOp WordVec 32 W16) = 1228+primOpTag (VecReadScalarByteArrayOp WordVec 16 W32) = 1229+primOpTag (VecReadScalarByteArrayOp WordVec 8 W64) = 1230+primOpTag (VecReadScalarByteArrayOp FloatVec 4 W32) = 1231+primOpTag (VecReadScalarByteArrayOp FloatVec 2 W64) = 1232+primOpTag (VecReadScalarByteArrayOp FloatVec 8 W32) = 1233+primOpTag (VecReadScalarByteArrayOp FloatVec 4 W64) = 1234+primOpTag (VecReadScalarByteArrayOp FloatVec 16 W32) = 1235+primOpTag (VecReadScalarByteArrayOp FloatVec 8 W64) = 1236+primOpTag (VecWriteScalarByteArrayOp IntVec 16 W8) = 1237+primOpTag (VecWriteScalarByteArrayOp IntVec 8 W16) = 1238+primOpTag (VecWriteScalarByteArrayOp IntVec 4 W32) = 1239+primOpTag (VecWriteScalarByteArrayOp IntVec 2 W64) = 1240+primOpTag (VecWriteScalarByteArrayOp IntVec 32 W8) = 1241+primOpTag (VecWriteScalarByteArrayOp IntVec 16 W16) = 1242+primOpTag (VecWriteScalarByteArrayOp IntVec 8 W32) = 1243+primOpTag (VecWriteScalarByteArrayOp IntVec 4 W64) = 1244+primOpTag (VecWriteScalarByteArrayOp IntVec 64 W8) = 1245+primOpTag (VecWriteScalarByteArrayOp IntVec 32 W16) = 1246+primOpTag (VecWriteScalarByteArrayOp IntVec 16 W32) = 1247+primOpTag (VecWriteScalarByteArrayOp IntVec 8 W64) = 1248+primOpTag (VecWriteScalarByteArrayOp WordVec 16 W8) = 1249+primOpTag (VecWriteScalarByteArrayOp WordVec 8 W16) = 1250+primOpTag (VecWriteScalarByteArrayOp WordVec 4 W32) = 1251+primOpTag (VecWriteScalarByteArrayOp WordVec 2 W64) = 1252+primOpTag (VecWriteScalarByteArrayOp WordVec 32 W8) = 1253+primOpTag (VecWriteScalarByteArrayOp WordVec 16 W16) = 1254+primOpTag (VecWriteScalarByteArrayOp WordVec 8 W32) = 1255+primOpTag (VecWriteScalarByteArrayOp WordVec 4 W64) = 1256+primOpTag (VecWriteScalarByteArrayOp WordVec 64 W8) = 1257+primOpTag (VecWriteScalarByteArrayOp WordVec 32 W16) = 1258+primOpTag (VecWriteScalarByteArrayOp WordVec 16 W32) = 1259+primOpTag (VecWriteScalarByteArrayOp WordVec 8 W64) = 1260+primOpTag (VecWriteScalarByteArrayOp FloatVec 4 W32) = 1261+primOpTag (VecWriteScalarByteArrayOp FloatVec 2 W64) = 1262+primOpTag (VecWriteScalarByteArrayOp FloatVec 8 W32) = 1263+primOpTag (VecWriteScalarByteArrayOp FloatVec 4 W64) = 1264+primOpTag (VecWriteScalarByteArrayOp FloatVec 16 W32) = 1265+primOpTag (VecWriteScalarByteArrayOp FloatVec 8 W64) = 1266+primOpTag (VecIndexScalarOffAddrOp IntVec 16 W8) = 1267+primOpTag (VecIndexScalarOffAddrOp IntVec 8 W16) = 1268+primOpTag (VecIndexScalarOffAddrOp IntVec 4 W32) = 1269+primOpTag (VecIndexScalarOffAddrOp IntVec 2 W64) = 1270+primOpTag (VecIndexScalarOffAddrOp IntVec 32 W8) = 1271+primOpTag (VecIndexScalarOffAddrOp IntVec 16 W16) = 1272+primOpTag (VecIndexScalarOffAddrOp IntVec 8 W32) = 1273+primOpTag (VecIndexScalarOffAddrOp IntVec 4 W64) = 1274+primOpTag (VecIndexScalarOffAddrOp IntVec 64 W8) = 1275+primOpTag (VecIndexScalarOffAddrOp IntVec 32 W16) = 1276+primOpTag (VecIndexScalarOffAddrOp IntVec 16 W32) = 1277+primOpTag (VecIndexScalarOffAddrOp IntVec 8 W64) = 1278+primOpTag (VecIndexScalarOffAddrOp WordVec 16 W8) = 1279+primOpTag (VecIndexScalarOffAddrOp WordVec 8 W16) = 1280+primOpTag (VecIndexScalarOffAddrOp WordVec 4 W32) = 1281+primOpTag (VecIndexScalarOffAddrOp WordVec 2 W64) = 1282+primOpTag (VecIndexScalarOffAddrOp WordVec 32 W8) = 1283+primOpTag (VecIndexScalarOffAddrOp WordVec 16 W16) = 1284+primOpTag (VecIndexScalarOffAddrOp WordVec 8 W32) = 1285+primOpTag (VecIndexScalarOffAddrOp WordVec 4 W64) = 1286+primOpTag (VecIndexScalarOffAddrOp WordVec 64 W8) = 1287+primOpTag (VecIndexScalarOffAddrOp WordVec 32 W16) = 1288+primOpTag (VecIndexScalarOffAddrOp WordVec 16 W32) = 1289+primOpTag (VecIndexScalarOffAddrOp WordVec 8 W64) = 1290+primOpTag (VecIndexScalarOffAddrOp FloatVec 4 W32) = 1291+primOpTag (VecIndexScalarOffAddrOp FloatVec 2 W64) = 1292+primOpTag (VecIndexScalarOffAddrOp FloatVec 8 W32) = 1293+primOpTag (VecIndexScalarOffAddrOp FloatVec 4 W64) = 1294+primOpTag (VecIndexScalarOffAddrOp FloatVec 16 W32) = 1295+primOpTag (VecIndexScalarOffAddrOp FloatVec 8 W64) = 1296+primOpTag (VecReadScalarOffAddrOp IntVec 16 W8) = 1297+primOpTag (VecReadScalarOffAddrOp IntVec 8 W16) = 1298+primOpTag (VecReadScalarOffAddrOp IntVec 4 W32) = 1299+primOpTag (VecReadScalarOffAddrOp IntVec 2 W64) = 1300+primOpTag (VecReadScalarOffAddrOp IntVec 32 W8) = 1301+primOpTag (VecReadScalarOffAddrOp IntVec 16 W16) = 1302+primOpTag (VecReadScalarOffAddrOp IntVec 8 W32) = 1303+primOpTag (VecReadScalarOffAddrOp IntVec 4 W64) = 1304+primOpTag (VecReadScalarOffAddrOp IntVec 64 W8) = 1305+primOpTag (VecReadScalarOffAddrOp IntVec 32 W16) = 1306+primOpTag (VecReadScalarOffAddrOp IntVec 16 W32) = 1307+primOpTag (VecReadScalarOffAddrOp IntVec 8 W64) = 1308+primOpTag (VecReadScalarOffAddrOp WordVec 16 W8) = 1309+primOpTag (VecReadScalarOffAddrOp WordVec 8 W16) = 1310+primOpTag (VecReadScalarOffAddrOp WordVec 4 W32) = 1311+primOpTag (VecReadScalarOffAddrOp WordVec 2 W64) = 1312+primOpTag (VecReadScalarOffAddrOp WordVec 32 W8) = 1313+primOpTag (VecReadScalarOffAddrOp WordVec 16 W16) = 1314+primOpTag (VecReadScalarOffAddrOp WordVec 8 W32) = 1315+primOpTag (VecReadScalarOffAddrOp WordVec 4 W64) = 1316+primOpTag (VecReadScalarOffAddrOp WordVec 64 W8) = 1317+primOpTag (VecReadScalarOffAddrOp WordVec 32 W16) = 1318+primOpTag (VecReadScalarOffAddrOp WordVec 16 W32) = 1319+primOpTag (VecReadScalarOffAddrOp WordVec 8 W64) = 1320+primOpTag (VecReadScalarOffAddrOp FloatVec 4 W32) = 1321+primOpTag (VecReadScalarOffAddrOp FloatVec 2 W64) = 1322+primOpTag (VecReadScalarOffAddrOp FloatVec 8 W32) = 1323+primOpTag (VecReadScalarOffAddrOp FloatVec 4 W64) = 1324+primOpTag (VecReadScalarOffAddrOp FloatVec 16 W32) = 1325+primOpTag (VecReadScalarOffAddrOp FloatVec 8 W64) = 1326+primOpTag (VecWriteScalarOffAddrOp IntVec 16 W8) = 1327+primOpTag (VecWriteScalarOffAddrOp IntVec 8 W16) = 1328+primOpTag (VecWriteScalarOffAddrOp IntVec 4 W32) = 1329+primOpTag (VecWriteScalarOffAddrOp IntVec 2 W64) = 1330+primOpTag (VecWriteScalarOffAddrOp IntVec 32 W8) = 1331+primOpTag (VecWriteScalarOffAddrOp IntVec 16 W16) = 1332+primOpTag (VecWriteScalarOffAddrOp IntVec 8 W32) = 1333+primOpTag (VecWriteScalarOffAddrOp IntVec 4 W64) = 1334+primOpTag (VecWriteScalarOffAddrOp IntVec 64 W8) = 1335+primOpTag (VecWriteScalarOffAddrOp IntVec 32 W16) = 1336+primOpTag (VecWriteScalarOffAddrOp IntVec 16 W32) = 1337+primOpTag (VecWriteScalarOffAddrOp IntVec 8 W64) = 1338+primOpTag (VecWriteScalarOffAddrOp WordVec 16 W8) = 1339+primOpTag (VecWriteScalarOffAddrOp WordVec 8 W16) = 1340+primOpTag (VecWriteScalarOffAddrOp WordVec 4 W32) = 1341+primOpTag (VecWriteScalarOffAddrOp WordVec 2 W64) = 1342+primOpTag (VecWriteScalarOffAddrOp WordVec 32 W8) = 1343+primOpTag (VecWriteScalarOffAddrOp WordVec 16 W16) = 1344+primOpTag (VecWriteScalarOffAddrOp WordVec 8 W32) = 1345+primOpTag (VecWriteScalarOffAddrOp WordVec 4 W64) = 1346+primOpTag (VecWriteScalarOffAddrOp WordVec 64 W8) = 1347+primOpTag (VecWriteScalarOffAddrOp WordVec 32 W16) = 1348+primOpTag (VecWriteScalarOffAddrOp WordVec 16 W32) = 1349+primOpTag (VecWriteScalarOffAddrOp WordVec 8 W64) = 1350+primOpTag (VecWriteScalarOffAddrOp FloatVec 4 W32) = 1351+primOpTag (VecWriteScalarOffAddrOp FloatVec 2 W64) = 1352+primOpTag (VecWriteScalarOffAddrOp FloatVec 8 W32) = 1353+primOpTag (VecWriteScalarOffAddrOp FloatVec 4 W64) = 1354+primOpTag (VecWriteScalarOffAddrOp FloatVec 16 W32) = 1355+primOpTag (VecWriteScalarOffAddrOp FloatVec 8 W64) = 1356+primOpTag PrefetchByteArrayOp3 = 1357+primOpTag PrefetchMutableByteArrayOp3 = 1358+primOpTag PrefetchAddrOp3 = 1359+primOpTag PrefetchValueOp3 = 1360+primOpTag PrefetchByteArrayOp2 = 1361+primOpTag PrefetchMutableByteArrayOp2 = 1362+primOpTag PrefetchAddrOp2 = 1363+primOpTag PrefetchValueOp2 = 1364+primOpTag PrefetchByteArrayOp1 = 1365+primOpTag PrefetchMutableByteArrayOp1 = 1366+primOpTag PrefetchAddrOp1 = 1367+primOpTag PrefetchValueOp1 = 1368+primOpTag PrefetchByteArrayOp0 = 1369+primOpTag PrefetchMutableByteArrayOp0 = 1370+primOpTag PrefetchAddrOp0 = 1371+primOpTag PrefetchValueOp0 = 1372
ghc-lib/stage0/lib/llvm-passes view
@@ -1,5 +1,5 @@ [-(0, "-enable-new-pm=0 -mem2reg -globalopt -lower-expect"),-(1, "-enable-new-pm=0 -O1 -globalopt"),-(2, "-enable-new-pm=0 -O2")+(0, "-passes=function(require<tbaa>),function(mem2reg),globalopt,function(lower-expect)"),+(1, "-passes=default<O1>"),+(2, "-passes=default<O2>") ]
ghc-lib/stage0/lib/settings view
@@ -1,20 +1,20 @@-[("C compiler command", "/usr/local/opt/ccache/libexec/gcc")-,("C compiler flags", "--target=x86_64-apple-darwin  -Qunused-arguments")-,("C++ compiler command", "/usr/local/opt/ccache/libexec/g++")-,("C++ compiler flags", "--target=x86_64-apple-darwin ")-,("C compiler link flags", "--target=x86_64-apple-darwin   -Wl,-no_fixup_chains -Wl,-no_warn_duplicate_libraries")+[("C compiler command", "/usr/bin/gcc")+,("C compiler flags", "--target=x86_64-apple-darwin -Qunused-arguments")+,("C++ compiler command", "/usr/bin/g++")+,("C++ compiler flags", "--target=x86_64-apple-darwin")+,("C compiler link flags", "--target=x86_64-apple-darwin -Wl,-no_fixup_chains -Wl,-no_warn_duplicate_libraries") ,("C compiler supports -no-pie", "NO")-,("Haskell CPP command", "/usr/local/opt/ccache/libexec/gcc")+,("CPP command", "/usr/bin/gcc")+,("CPP flags", "-E")+,("Haskell CPP command", "/usr/bin/gcc") ,("Haskell CPP flags", "-E -undef -traditional -Wno-invalid-pp-token -Wno-unicode -Wno-trigraphs")-,("ld command", "ld")-,("ld flags", "") ,("ld supports compact unwind", "YES") ,("ld supports filelist", "YES")-,("ld supports response files", "YES")-,("ld is GNU ld", "NO") ,("ld supports single module", "NO")-,("Merge objects command", "ld")+,("ld is GNU ld", "NO")+,("Merge objects command", "/usr/bin/ld") ,("Merge objects flags", "-r")+,("Merge objects supports response files", "YES") ,("ar command", "/usr/bin/ar") ,("ar flags", "qcls") ,("ar supports at file", "NO")@@ -22,10 +22,8 @@ ,("ranlib command", "/usr/bin/ranlib") ,("otool command", "otool") ,("install_name_tool command", "install_name_tool")-,("touch command", "touch")-,("dllwrap command", "/bin/false") ,("windres command", "/bin/false")-,("unlit command", "$topdir/bin/unlit")+,("unlit command", "$topdir/../bin/unlit") ,("cross compiling", "NO") ,("target platform string", "x86_64-apple-darwin") ,("target os", "OSDarwin")@@ -40,7 +38,7 @@ ,("LLVM target", "x86_64-apple-darwin") ,("LLVM llc command", "llc") ,("LLVM opt command", "opt")-,("LLVM clang command", "clang")+,("LLVM llvm-as command", "clang") ,("Use inplace MinGW toolchain", "NO") ,("Use interpreter", "YES") ,("Support SMP", "YES")
ghc-lib/stage0/rts/build/include/GhclibDerivedConstants.h view
@@ -7,7 +7,7 @@ // WORD_SIZE 8 // BITMAP_BITS_SHIFT 6 // TAG_BITS 3-#define HS_CONSTANTS "291,1,2,4096,252,9,0,8,16,24,32,40,48,56,64,72,80,84,88,92,96,100,104,112,120,128,136,144,152,168,184,200,216,232,248,280,312,344,376,408,440,504,568,632,696,760,824,832,840,848,856,864,872,888,904,-24,-16,-8,24,0,8,48,46,96,72,8,48,8,8,16,8,64,8,16,8,0,72,56,8,16,0,8,8,0,8,0,104,120,16,8,16,0,4,4,24,20,4,15,7,1,-16,255,0,255,7,10,6,6,1,6,6,6,6,6,0,16384,21,1024,8,4,8,8,6,3,30,1152921503533105152,0,1152921504606846976,1"+#define HS_CONSTANTS "291,1,2,4096,252,9,0,8,16,24,32,40,48,56,64,72,80,84,88,92,96,100,104,112,120,128,136,144,152,168,184,200,216,232,248,280,312,344,376,408,440,504,568,632,696,760,824,832,840,848,856,864,872,888,904,-24,-16,-8,24,0,8,48,46,96,72,8,48,8,8,16,8,64,8,16,8,0,72,56,8,8,16,0,8,8,0,8,0,112,128,16,8,16,0,0,4,4,24,20,4,15,7,1,-16,255,0,255,7,10,6,6,1,6,6,6,6,6,0,16384,21,1024,8,4,8,8,6,3,30,1152921503533105152,0,1152921504606846976,1" #define CONTROL_GROUP_CONST_291 291 #define STD_HDR_SIZE 1 #define PROF_HDR_SIZE 2@@ -100,6 +100,9 @@ #define OFFSET_Capability_weak_ptr_list_tl 1184 #define REP_Capability_weak_ptr_list_tl b64 #define Capability_weak_ptr_list_tl(__ptr__) REP_Capability_weak_ptr_list_tl[__ptr__+OFFSET_Capability_weak_ptr_list_tl]+#define OFFSET_Capability_n_run_queue 992+#define REP_Capability_n_run_queue b32+#define Capability_n_run_queue(__ptr__) REP_Capability_n_run_queue[__ptr__+OFFSET_Capability_n_run_queue] #define OFFSET_bdescr_start 0 #define REP_bdescr_start b64 #define bdescr_start(__ptr__) REP_bdescr_start[__ptr__+OFFSET_bdescr_start]@@ -173,6 +176,8 @@ #define StgEntCounter_entry_count(__ptr__) REP_StgEntCounter_entry_count[__ptr__+OFFSET_StgEntCounter_entry_count] #define SIZEOF_StgUpdateFrame_NoHdr 8 #define SIZEOF_StgUpdateFrame (SIZEOF_StgHeader+8)+#define SIZEOF_StgOrigThunkInfoFrame_NoHdr 8+#define SIZEOF_StgOrigThunkInfoFrame (SIZEOF_StgHeader+8) #define SIZEOF_StgCatchFrame_NoHdr 8 #define SIZEOF_StgCatchFrame (SIZEOF_StgHeader+8) #define SIZEOF_StgStopFrame_NoHdr 0@@ -211,43 +216,46 @@ #define OFFSET_StgTSO_what_next 24 #define REP_StgTSO_what_next b16 #define StgTSO_what_next(__ptr__) REP_StgTSO_what_next[__ptr__+SIZEOF_StgHeader+OFFSET_StgTSO_what_next]-#define OFFSET_StgTSO_why_blocked 26-#define REP_StgTSO_why_blocked b16+#define OFFSET_StgTSO_why_blocked 32+#define REP_StgTSO_why_blocked b32 #define StgTSO_why_blocked(__ptr__) REP_StgTSO_why_blocked[__ptr__+SIZEOF_StgHeader+OFFSET_StgTSO_why_blocked]-#define OFFSET_StgTSO_block_info 32+#define OFFSET_StgTSO_block_info 40 #define REP_StgTSO_block_info b64 #define StgTSO_block_info(__ptr__) REP_StgTSO_block_info[__ptr__+SIZEOF_StgHeader+OFFSET_StgTSO_block_info]-#define OFFSET_StgTSO_blocked_exceptions 88+#define OFFSET_StgTSO_blocked_exceptions 96 #define REP_StgTSO_blocked_exceptions b64 #define StgTSO_blocked_exceptions(__ptr__) REP_StgTSO_blocked_exceptions[__ptr__+SIZEOF_StgHeader+OFFSET_StgTSO_blocked_exceptions]-#define OFFSET_StgTSO_id 40+#define OFFSET_StgTSO_id 48 #define REP_StgTSO_id b64 #define StgTSO_id(__ptr__) REP_StgTSO_id[__ptr__+SIZEOF_StgHeader+OFFSET_StgTSO_id]-#define OFFSET_StgTSO_cap 64+#define OFFSET_StgTSO_cap 72 #define REP_StgTSO_cap b64 #define StgTSO_cap(__ptr__) REP_StgTSO_cap[__ptr__+SIZEOF_StgHeader+OFFSET_StgTSO_cap]-#define OFFSET_StgTSO_saved_errno 48+#define OFFSET_StgTSO_saved_errno 56 #define REP_StgTSO_saved_errno b32 #define StgTSO_saved_errno(__ptr__) REP_StgTSO_saved_errno[__ptr__+SIZEOF_StgHeader+OFFSET_StgTSO_saved_errno]-#define OFFSET_StgTSO_trec 72+#define OFFSET_StgTSO_trec 80 #define REP_StgTSO_trec b64 #define StgTSO_trec(__ptr__) REP_StgTSO_trec[__ptr__+SIZEOF_StgHeader+OFFSET_StgTSO_trec] #define OFFSET_StgTSO_flags 28 #define REP_StgTSO_flags b32 #define StgTSO_flags(__ptr__) REP_StgTSO_flags[__ptr__+SIZEOF_StgHeader+OFFSET_StgTSO_flags]-#define OFFSET_StgTSO_dirty 52+#define OFFSET_StgTSO_dirty 60 #define REP_StgTSO_dirty b32 #define StgTSO_dirty(__ptr__) REP_StgTSO_dirty[__ptr__+SIZEOF_StgHeader+OFFSET_StgTSO_dirty]-#define OFFSET_StgTSO_bq 96+#define OFFSET_StgTSO_bq 104 #define REP_StgTSO_bq b64 #define StgTSO_bq(__ptr__) REP_StgTSO_bq[__ptr__+SIZEOF_StgHeader+OFFSET_StgTSO_bq]-#define OFFSET_StgTSO_label 80+#define OFFSET_StgTSO_label 88 #define REP_StgTSO_label b64 #define StgTSO_label(__ptr__) REP_StgTSO_label[__ptr__+SIZEOF_StgHeader+OFFSET_StgTSO_label]-#define OFFSET_StgTSO_alloc_limit 104+#define OFFSET_StgTSO_bound 64+#define REP_StgTSO_bound b64+#define StgTSO_bound(__ptr__) REP_StgTSO_bound[__ptr__+SIZEOF_StgHeader+OFFSET_StgTSO_bound]+#define OFFSET_StgTSO_alloc_limit 112 #define REP_StgTSO_alloc_limit b64 #define StgTSO_alloc_limit(__ptr__) REP_StgTSO_alloc_limit[__ptr__+SIZEOF_StgHeader+OFFSET_StgTSO_alloc_limit]-#define OFFSET_StgTSO_cccs 120+#define OFFSET_StgTSO_cccs 128 #define REP_StgTSO_cccs b64 #define StgTSO_cccs(__ptr__) REP_StgTSO_cccs[__ptr__+SIZEOF_StgHeader+OFFSET_StgTSO_cccs] #define OFFSET_StgTSO_stackobj 16@@ -263,13 +271,23 @@ #define OFFSET_StgStack_dirty 4 #define REP_StgStack_dirty b8 #define StgStack_dirty(__ptr__) REP_StgStack_dirty[__ptr__+SIZEOF_StgHeader+OFFSET_StgStack_dirty]+#define OFFSET_StgStack_marking 5+#define REP_StgStack_marking b8+#define StgStack_marking(__ptr__) REP_StgStack_marking[__ptr__+SIZEOF_StgHeader+OFFSET_StgStack_marking] #define SIZEOF_StgTSOProfInfo 8 #define OFFSET_StgUpdateFrame_updatee 0 #define REP_StgUpdateFrame_updatee b64 #define StgUpdateFrame_updatee(__ptr__) REP_StgUpdateFrame_updatee[__ptr__+SIZEOF_StgHeader+OFFSET_StgUpdateFrame_updatee]+#define OFFSET_StgOrigThunkInfoFrame_info_ptr 0+#define REP_StgOrigThunkInfoFrame_info_ptr b64+#define StgOrigThunkInfoFrame_info_ptr(__ptr__) REP_StgOrigThunkInfoFrame_info_ptr[__ptr__+SIZEOF_StgHeader+OFFSET_StgOrigThunkInfoFrame_info_ptr] #define OFFSET_StgCatchFrame_handler 0 #define REP_StgCatchFrame_handler b64 #define StgCatchFrame_handler(__ptr__) REP_StgCatchFrame_handler[__ptr__+SIZEOF_StgHeader+OFFSET_StgCatchFrame_handler]+#define SIZEOF_StgRetFun 24+#define OFFSET_StgRetFun_size 8+#define OFFSET_StgRetFun_fun 16+#define OFFSET_StgRetFun_payload 24 #define SIZEOF_StgPAP_NoHdr 16 #define SIZEOF_StgPAP (SIZEOF_StgHeader+16) #define OFFSET_StgPAP_n_args 4@@ -517,25 +535,25 @@ #define OFFSET_StgCompactNFDataBlock_next 16 #define REP_StgCompactNFDataBlock_next b64 #define StgCompactNFDataBlock_next(__ptr__) REP_StgCompactNFDataBlock_next[__ptr__+OFFSET_StgCompactNFDataBlock_next]-#define OFFSET_RtsFlags_ProfFlags_doHeapProfile 280+#define OFFSET_RtsFlags_ProfFlags_doHeapProfile 288 #define REP_RtsFlags_ProfFlags_doHeapProfile b32 #define RtsFlags_ProfFlags_doHeapProfile(__ptr__) REP_RtsFlags_ProfFlags_doHeapProfile[__ptr__+OFFSET_RtsFlags_ProfFlags_doHeapProfile]-#define OFFSET_RtsFlags_ProfFlags_showCCSOnException 301+#define OFFSET_RtsFlags_ProfFlags_showCCSOnException 311 #define REP_RtsFlags_ProfFlags_showCCSOnException b8 #define RtsFlags_ProfFlags_showCCSOnException(__ptr__) REP_RtsFlags_ProfFlags_showCCSOnException[__ptr__+OFFSET_RtsFlags_ProfFlags_showCCSOnException]-#define OFFSET_RtsFlags_DebugFlags_apply 245+#define OFFSET_RtsFlags_DebugFlags_apply 253 #define REP_RtsFlags_DebugFlags_apply b8 #define RtsFlags_DebugFlags_apply(__ptr__) REP_RtsFlags_DebugFlags_apply[__ptr__+OFFSET_RtsFlags_DebugFlags_apply]-#define OFFSET_RtsFlags_DebugFlags_sanity 239+#define OFFSET_RtsFlags_DebugFlags_sanity 247 #define REP_RtsFlags_DebugFlags_sanity b8 #define RtsFlags_DebugFlags_sanity(__ptr__) REP_RtsFlags_DebugFlags_sanity[__ptr__+OFFSET_RtsFlags_DebugFlags_sanity]-#define OFFSET_RtsFlags_DebugFlags_weak 234+#define OFFSET_RtsFlags_DebugFlags_weak 242 #define REP_RtsFlags_DebugFlags_weak b8 #define RtsFlags_DebugFlags_weak(__ptr__) REP_RtsFlags_DebugFlags_weak[__ptr__+OFFSET_RtsFlags_DebugFlags_weak] #define OFFSET_RtsFlags_GcFlags_initialStkSize 16 #define REP_RtsFlags_GcFlags_initialStkSize b32 #define RtsFlags_GcFlags_initialStkSize(__ptr__) REP_RtsFlags_GcFlags_initialStkSize[__ptr__+OFFSET_RtsFlags_GcFlags_initialStkSize]-#define OFFSET_RtsFlags_MiscFlags_tickInterval 200+#define OFFSET_RtsFlags_MiscFlags_tickInterval 208 #define REP_RtsFlags_MiscFlags_tickInterval b64 #define RtsFlags_MiscFlags_tickInterval(__ptr__) REP_RtsFlags_MiscFlags_tickInterval[__ptr__+OFFSET_RtsFlags_MiscFlags_tickInterval] #define SIZEOF_StgFunInfoExtraFwd 32
ghc-lib/stage0/rts/build/include/ghcautoconf.h view
@@ -1,7 +1,7 @@ #if !defined(__GHCAUTOCONF_H__) #define __GHCAUTOCONF_H__-/* mk/config.h.  Generated from config.h.in by configure.  */-/* mk/config.h.in.  Generated from configure.ac by autoheader.  */+/* ghcautoconf.h.autoconf.  Generated from ghcautoconf.h.autoconf.in by configure.  */+/* ghcautoconf.h.autoconf.in.  Generated from configure.ac by autoheader.  */  /* Define if building universal (internal helper macro) */ /* #undef AC_APPLE_UNIVERSAL_BUILD */@@ -103,9 +103,6 @@ /* Define to 1 if you have the <bfd.h> header file. */ /* #undef HAVE_BFD_H */ -/* Does C compiler support __atomic primitives? */-#define HAVE_C11_ATOMICS 1- /* Define to 1 if you have the 'clock_gettime' function. */ #define HAVE_CLOCK_GETTIME 1 @@ -125,15 +122,15 @@  /* Define to 1 if you have the declaration of 'MADV_DONTNEED', and to 0 if you    don't. */-/* #undef HAVE_DECL_MADV_DONTNEED */+#define HAVE_DECL_MADV_DONTNEED 1  /* Define to 1 if you have the declaration of 'MADV_FREE', and to 0 if you    don't. */-/* #undef HAVE_DECL_MADV_FREE */+#define HAVE_DECL_MADV_FREE 1  /* Define to 1 if you have the declaration of 'MAP_NORESERVE', and to 0 if you    don't. */-/* #undef HAVE_DECL_MAP_NORESERVE */+#define HAVE_DECL_MAP_NORESERVE 1  /* Define to 1 if you have the declaration of 'program_invocation_short_name',    and to 0 if you don't. */@@ -148,9 +145,6 @@ /* Define to 1 if you have the 'dlinfo' function. */ /* #undef HAVE_DLINFO */ -/* Define to 1 if you have the <elfutils/libdw.h> header file. */-/* #undef HAVE_ELFUTILS_LIBDW_H */- /* Define to 1 if you have the <errno.h> header file. */ #define HAVE_ERRNO_H 1 @@ -160,9 +154,6 @@ /* Define to 1 if you have the <fcntl.h> header file. */ #define HAVE_FCNTL_H 1 -/* Define to 1 if you have the <ffi.h> header file. */-/* #undef HAVE_FFI_H */- /* Define to 1 if you have the 'fork' function. */ #define HAVE_FORK 1 @@ -202,18 +193,12 @@ /* Define to 1 if you need to link with libm */ #define HAVE_LIBM 1 -/* Define to 1 if you have the 'mingwex' library (-lmingwex). */-/* #undef HAVE_LIBMINGWEX */- /* Define to 1 if you have libnuma */ #define HAVE_LIBNUMA 0  /* Define to 1 if you have the 'pthread' library (-lpthread). */ #define HAVE_LIBPTHREAD 1 -/* Define to 1 if you have the 'rt' library (-lrt). */-/* #undef HAVE_LIBRT */- /* Define to 1 if you wish to compress IPE data in compiler results (requires    libzstd) */ #define HAVE_LIBZSTD 0@@ -311,9 +296,6 @@ /* Define to 1 if you have the 'sysconf' function. */ #define HAVE_SYSCONF 1 -/* Define to 1 if you have libffi. */-/* #undef HAVE_SYSTEM_LIBFFI */- /* Define to 1 if you have the <sys/cpuset.h> header file. */ /* #undef HAVE_SYS_CPUSET_H */ @@ -401,19 +383,13 @@ /* Define to 1 if 'vfork' works. */ #define HAVE_WORKING_VFORK 1 -/* Define to 1 if you have the <zstd.h> header file. */-/* #undef HAVE_ZSTD_H */- /* Define to 1 if C symbols have a leading underscore added by the compiler.    */ #define LEADING_UNDERSCORE 1 -/* Define to 1 if we need -latomic. */+/* Define to 1 if we need -latomic for sub-word atomic operations. */ #define NEED_ATOMIC_LIB 0 -/* Define 1 if we need to link code using pthreads with -lpthread */-#define NEED_PTHREAD_LIB 0- /* Define to the address where bug reports for this package should be sent. */ /* #undef PACKAGE_BUGREPORT */ @@ -658,41 +634,9 @@ /* Define as a signed integer type capable of holding a process identifier. */ /* #undef pid_t */ -/* The maximum supported LLVM version number */-#define sUPPORTED_LLVM_VERSION_MAX (16)--/* The minimum supported LLVM version number */-#define sUPPORTED_LLVM_VERSION_MIN (11)- /* Define as 'unsigned int' if <stddef.h> doesn't define. */ /* #undef size_t */  /* Define as 'fork' if 'vfork' does not work. */ /* #undef vfork */-/* ghcautoconf.h.autoconf.  Generated from ghcautoconf.h.autoconf.in by configure.  */-/* ghcautoconf.h.autoconf.in.  Generated from configure.ac by autoheader.  */--/* Define to the address where bug reports for this package should be sent. */-/* #undef PACKAGE_BUGREPORT */--/* Define to the full name of this package. */-/* #undef PACKAGE_NAME */--/* Define to the full name and version of this package. */-/* #undef PACKAGE_STRING */--/* Define to the one symbol short name of this package. */-/* #undef PACKAGE_TARNAME */--/* Define to the home page for this package. */-/* #undef PACKAGE_URL */--/* Define to the version of this package. */-/* #undef PACKAGE_VERSION */--/* ARM pre v6 */-/* #undef arm_HOST_ARCH_PRE_ARMv6 */--/* ARM pre v7 */-/* #undef arm_HOST_ARCH_PRE_ARMv7 */ #endif /* __GHCAUTOCONF_H__ */
ghc-lib/stage0/rts/build/include/ghcplatform.h view
@@ -4,23 +4,22 @@ #define BuildPlatform_TYPE  x86_64_apple_darwin #define HostPlatform_TYPE   x86_64_apple_darwin -#define x86_64_apple_darwin_BUILD 1-#define x86_64_apple_darwin_HOST 1--#define x86_64_BUILD_ARCH 1-#define x86_64_HOST_ARCH 1-#define BUILD_ARCH "x86_64"-#define HOST_ARCH "x86_64"+#define x86_64_apple_darwin_BUILD  1+#define x86_64_apple_darwin_HOST  1 -#define darwin_BUILD_OS 1-#define darwin_HOST_OS 1-#define BUILD_OS "darwin"-#define HOST_OS "darwin"+#define x86_64_BUILD_ARCH  1+#define x86_64_HOST_ARCH  1+#define BUILD_ARCH  "x86_64"+#define HOST_ARCH  "x86_64" -#define apple_BUILD_VENDOR 1-#define apple_HOST_VENDOR 1-#define BUILD_VENDOR "apple"-#define HOST_VENDOR "apple"+#define darwin_BUILD_OS  1+#define darwin_HOST_OS  1+#define BUILD_OS  "darwin"+#define HOST_OS  "darwin" +#define apple_BUILD_VENDOR  1+#define apple_HOST_VENDOR  1+#define BUILD_VENDOR  "apple"+#define HOST_VENDOR  "apple"  #endif /* __GHCPLATFORM_H__ */
− libraries/ghci/GHCi/BinaryArray.hs
@@ -1,78 +0,0 @@-{-# LANGUAGE BangPatterns, MagicHash, UnboxedTuples, FlexibleContexts #-}--- | Efficient serialisation for GHCi Instruction arrays------ Author: Ben Gamari----module GHCi.BinaryArray(putArray, getArray) where--import Prelude-import Foreign.Ptr-import Data.Binary-import Data.Binary.Put (putBuilder)-import qualified Data.Binary.Get.Internal as Binary-import qualified Data.ByteString.Builder as BB-import qualified Data.ByteString.Builder.Internal as BB-import qualified Data.Array.Base as A-import qualified Data.Array.IO.Internals as A-import qualified Data.Array.Unboxed as A-import GHC.Exts-import GHC.IO---- | An efficient serialiser of 'A.UArray'.-putArray :: Binary i => A.UArray i a -> Put-putArray (A.UArray l u _ arr#) = do-    put l-    put u-    putBuilder $ byteArrayBuilder arr#--byteArrayBuilder :: ByteArray# -> BB.Builder-byteArrayBuilder arr# = BB.builder $ go 0 (I# (sizeofByteArray# arr#))-  where-    go :: Int -> Int -> BB.BuildStep a -> BB.BuildStep a-    go !inStart !inEnd k (BB.BufferRange outStart outEnd)-      -- There is enough room in this output buffer to write all remaining array-      -- contents-      | inRemaining <= outRemaining = do-          copyByteArrayToAddr arr# inStart outStart inRemaining-          k (BB.BufferRange (outStart `plusPtr` inRemaining) outEnd)-      -- There is only enough space for a fraction of the remaining contents-      | otherwise = do-          copyByteArrayToAddr arr# inStart outStart outRemaining-          let !inStart' = inStart + outRemaining-          return $! BB.bufferFull 1 outEnd (go inStart' inEnd k)-      where-        inRemaining  = inEnd - inStart-        outRemaining = outEnd `minusPtr` outStart--    copyByteArrayToAddr :: ByteArray# -> Int -> Ptr a -> Int -> IO ()-    copyByteArrayToAddr src# (I# src_off#) (Ptr dst#) (I# len#) =-        IO $ \s -> case copyByteArrayToAddr# src# src_off# dst# len# s of-                     s' -> (# s', () #)---- | An efficient deserialiser of 'A.UArray'.-getArray :: (Binary i, A.Ix i, A.MArray A.IOUArray a IO) => Get (A.UArray i a)-getArray = do-    l <- get-    u <- get-    arr@(A.IOUArray (A.STUArray _ _ _ arr#)) <--        return $ unsafeDupablePerformIO $ A.newArray_ (l,u)-    let go 0 _ = return ()-        go !remaining !off = do-            Binary.readNWith n $ \ptr ->-              copyAddrToByteArray ptr arr# off n-            go (remaining - n) (off + n)-          where n = min chunkSize remaining-    go (I# (sizeofMutableByteArray# arr#)) 0-    return $! unsafeDupablePerformIO $ unsafeFreezeIOUArray arr-  where-    chunkSize = 10*1024--    copyAddrToByteArray :: Ptr a -> MutableByteArray# RealWorld-                        -> Int -> Int -> IO ()-    copyAddrToByteArray (Ptr src#) dst# (I# dst_off#) (I# len#) =-        IO $ \s -> case copyAddrToByteArray# src# dst# dst_off# len# s of-                     s' -> (# s', () #)---- this is inexplicably not exported in currently released array versions-unsafeFreezeIOUArray :: A.IOUArray ix e -> IO (A.UArray ix e)-unsafeFreezeIOUArray (A.IOUArray marr) = stToIO (A.unsafeFreezeSTUArray marr)
− libraries/ghci/GHCi/ResolvedBCO.hs
@@ -1,77 +0,0 @@-{-# LANGUAGE RecordWildCards, DeriveGeneric, GeneralizedNewtypeDeriving,-    BangPatterns, CPP #-}-module GHCi.ResolvedBCO-  ( ResolvedBCO(..)-  , ResolvedBCOPtr(..)-  , isLittleEndian-  ) where--import Prelude -- See note [Why do we import Prelude here?]-import GHC.Data.SizedSeq-import GHCi.RemoteTypes-import GHCi.BreakArray--import Data.Array.Unboxed-import Data.Binary-import GHC.Generics-import GHCi.BinaryArray---#include "MachDeps.h"--isLittleEndian :: Bool-#if defined(WORDS_BIGENDIAN)-isLittleEndian = False-#else-isLittleEndian = True-#endif---- -------------------------------------------------------------------------------- ResolvedBCO---- | A 'ResolvedBCO' is one in which all the 'Name' references have been--- resolved to actual addresses or 'RemoteHValues'.------ Note, all arrays are zero-indexed (we assume this when--- serializing/deserializing)-data ResolvedBCO-   = ResolvedBCO {-        resolvedBCOIsLE   :: Bool,-        resolvedBCOArity  :: {-# UNPACK #-} !Int,-        resolvedBCOInstrs :: UArray Int Word16,         -- insns-        resolvedBCOBitmap :: UArray Int Word64,         -- bitmap-        resolvedBCOLits   :: UArray Int Word64,         -- non-ptrs-        resolvedBCOPtrs   :: (SizedSeq ResolvedBCOPtr)  -- ptrs-   }-   deriving (Generic, Show)---- | The Binary instance for ResolvedBCOs.------ Note, that we do encode the endianness, however there is no support for mixed--- endianness setups.  This is primarily to ensure that ghc and iserv share the--- same endianness.-instance Binary ResolvedBCO where-  put ResolvedBCO{..} = do-    put resolvedBCOIsLE-    put resolvedBCOArity-    putArray resolvedBCOInstrs-    putArray resolvedBCOBitmap-    putArray resolvedBCOLits-    put resolvedBCOPtrs-  get = ResolvedBCO-        <$> get <*> get <*> getArray <*> getArray <*> getArray <*> get--data ResolvedBCOPtr-  = ResolvedBCORef {-# UNPACK #-} !Int-      -- ^ reference to the Nth BCO in the current set-  | ResolvedBCOPtr {-# UNPACK #-} !(RemoteRef HValue)-      -- ^ reference to a previously created BCO-  | ResolvedBCOStaticPtr {-# UNPACK #-} !(RemotePtr ())-      -- ^ reference to a static ptr-  | ResolvedBCOPtrBCO ResolvedBCO-      -- ^ a nested BCO-  | ResolvedBCOPtrBreakArray {-# UNPACK #-} !(RemoteRef BreakArray)-      -- ^ Resolves to the MutableArray# inside the BreakArray-  deriving (Generic, Show)--instance Binary ResolvedBCOPtr
+ rts/include/stg/MachRegs/arm32.h view
@@ -0,0 +1,60 @@+#pragma once++/* -----------------------------------------------------------------------------+   The ARM EABI register mapping++   Here we consider ARM mode (i.e. 32bit isns)+   and also CPU with full VFPv3 implementation++   ARM registers (see Chapter 5.1 in ARM IHI 0042D and+   Section 9.2.2 in ARM Software Development Toolkit Reference Guide)++   r15  PC         The Program Counter.+   r14  LR         The Link Register.+   r13  SP         The Stack Pointer.+   r12  IP         The Intra-Procedure-call scratch register.+   r11  v8/fp      Variable-register 8.+   r10  v7/sl      Variable-register 7.+   r9   v6/SB/TR   Platform register. The meaning of this register is+                   defined by the platform standard.+   r8   v5         Variable-register 5.+   r7   v4         Variable register 4.+   r6   v3         Variable register 3.+   r5   v2         Variable register 2.+   r4   v1         Variable register 1.+   r3   a4         Argument / scratch register 4.+   r2   a3         Argument / scratch register 3.+   r1   a2         Argument / result / scratch register 2.+   r0   a1         Argument / result / scratch register 1.++   VFPv2/VFPv3/NEON registers+   s0-s15/d0-d7/q0-q3    Argument / result/ scratch registers+   s16-s31/d8-d15/q4-q7  callee-saved registers (must be preserved across+                         subroutine calls)++   VFPv3/NEON registers (added to the VFPv2 registers set)+   d16-d31/q8-q15        Argument / result/ scratch registers+   ----------------------------------------------------------------------------- */++#define REG(x) __asm__(#x)++#define REG_Base        r4+#define REG_Sp          r5+#define REG_Hp          r6+#define REG_R1          r7+#define REG_R2          r8+#define REG_R3          r9+#define REG_R4          r10+#define REG_SpLim       r11++#if !defined(arm_HOST_ARCH_PRE_ARMv6)+/* d8 */+#define REG_F1    s16+#define REG_F2    s17+/* d9 */+#define REG_F3    s18+#define REG_F4    s19++#define REG_D1    d10+#define REG_D2    d11+#endif
+ rts/include/stg/MachRegs/arm64.h view
@@ -0,0 +1,64 @@+#pragma once+++/* -----------------------------------------------------------------------------+   The ARMv8/AArch64 ABI register mapping++   The AArch64 provides 31 64-bit general purpose registers+   and 32 128-bit SIMD/floating point registers.++   General purpose registers (see Chapter 5.1.1 in ARM IHI 0055B)++   Register | Special | Role in the procedure call standard+   ---------+---------+------------------------------------+     SP     |         | The Stack Pointer+     r30    |  LR     | The Link Register+     r29    |  FP     | The Frame Pointer+   r19-r28  |         | Callee-saved registers+     r18    |         | The Platform Register, if needed;+            |         | or temporary register+     r17    |  IP1    | The second intra-procedure-call temporary register+     r16    |  IP0    | The first intra-procedure-call scratch register+    r9-r15  |         | Temporary registers+     r8     |         | Indirect result location register+    r0-r7   |         | Parameter/result registers+++   FPU/SIMD registers++   s/d/q/v0-v7    Argument / result/ scratch registers+   s/d/q/v8-v15   callee-saved registers (must be preserved across subroutine calls,+                  but only bottom 64-bit value needs to be preserved)+   s/d/q/v16-v31  temporary registers++   ----------------------------------------------------------------------------- */++#define REG(x) __asm__(#x)++#define REG_Base        r19+#define REG_Sp          r20+#define REG_Hp          r21+#define REG_R1          r22+#define REG_R2          r23+#define REG_R3          r24+#define REG_R4          r25+#define REG_R5          r26+#define REG_R6          r27+#define REG_SpLim       r28++#define REG_F1          s8+#define REG_F2          s9+#define REG_F3          s10+#define REG_F4          s11++#define REG_D1          d12+#define REG_D2          d13+#define REG_D3          d14+#define REG_D4          d15++#define REG_XMM1        q4+#define REG_XMM2        q5++#define CALLER_SAVES_XMM1+#define CALLER_SAVES_XMM2+
+ rts/include/stg/MachRegs/loongarch64.h view
@@ -0,0 +1,51 @@+#pragma once++/* -----------------------------------------------------------------------------+   The loongarch64 register mapping++   Register    | Role(s)                                 | Call effect+   ------------+-----------------------------------------+-------------+   zero        | Hard-wired zero                         | -+   ra          | Return address                          | caller-saved+   tp          | Thread pointer                          | -+   sp          | Stack pointer                           | callee-saved+   a0,a1       | Arguments / return values               | caller-saved+   a2..a7      | Arguments                               | caller-saved+   t0..t8      | -                                       | caller-saved+   u0          | Reserve                                 | -+   fp          | Frame pointer                           | callee-saved+   s0..s8      | -                                       | callee-saved+   fa0,fa1     | Arguments / return values               | caller-saved+   fa2..fa7    | Arguments                               | caller-saved+   ft0..ft15   | -                                       | caller-saved+   fs0..fs7    | -                                       | callee-saved++   Each general purpose register as well as each floating-point+   register is 64 bits wide, also, the u0 register is called r21 in some cases.++   -------------------------------------------------------------------------- */++#define REG(x) __asm__("$" #x)++#define REG_Base        s0+#define REG_Sp          s1+#define REG_Hp          s2+#define REG_R1          s3+#define REG_R2          s4+#define REG_R3          s5+#define REG_R4          s6+#define REG_R5          s7+#define REG_SpLim       s8++#define REG_F1          fs0+#define REG_F2          fs1+#define REG_F3          fs2+#define REG_F4          fs3++#define REG_D1          fs4+#define REG_D2          fs5+#define REG_D3          fs6+#define REG_D4          fs7++#define MAX_REAL_FLOAT_REG   4+#define MAX_REAL_DOUBLE_REG  4
+ rts/include/stg/MachRegs/ppc.h view
@@ -0,0 +1,65 @@+#pragma once++/* -----------------------------------------------------------------------------+   The PowerPC register mapping++   0            system glue?    (caller-save, volatile)+   1            SP              (callee-save, non-volatile)+   2            AIX, powerpc64-linux:+                    RTOC        (a strange special case)+                powerpc32-linux:+                                reserved for use by system++   3-10         args/return     (caller-save, volatile)+   11,12        system glue?    (caller-save, volatile)+   13           on 64-bit:      reserved for thread state pointer+                on 32-bit:      (callee-save, non-volatile)+   14-31                        (callee-save, non-volatile)++   f0                           (caller-save, volatile)+   f1-f13       args/return     (caller-save, volatile)+   f14-f31                      (callee-save, non-volatile)++   \tr{14}--\tr{31} are wonderful callee-save registers on all ppc OSes.+   \tr{0}--\tr{12} are caller-save registers.++   \tr{%f14}--\tr{%f31} are callee-save floating-point registers.++   We can do the Whole Business with callee-save registers only!+   -------------------------------------------------------------------------- */+++#define REG(x) __asm__(#x)++#define REG_R1          r14+#define REG_R2          r15+#define REG_R3          r16+#define REG_R4          r17+#define REG_R5          r18+#define REG_R6          r19+#define REG_R7          r20+#define REG_R8          r21+#define REG_R9          r22+#define REG_R10         r23++#define REG_F1          fr14+#define REG_F2          fr15+#define REG_F3          fr16+#define REG_F4          fr17+#define REG_F5          fr18+#define REG_F6          fr19++#define REG_D1          fr20+#define REG_D2          fr21+#define REG_D3          fr22+#define REG_D4          fr23+#define REG_D5          fr24+#define REG_D6          fr25++#define REG_Sp          r24+#define REG_SpLim       r25+#define REG_Hp          r26+#define REG_Base        r27++#define MAX_REAL_FLOAT_REG   6+#define MAX_REAL_DOUBLE_REG  6
+ rts/include/stg/MachRegs/riscv64.h view
@@ -0,0 +1,61 @@+#pragma once++/* -----------------------------------------------------------------------------+   The riscv64 register mapping++   Register    | Role(s)                                 | Call effect+   ------------+-----------------------------------------+-------------+   zero        | Hard-wired zero                         | -+   ra          | Return address                          | caller-saved+   sp          | Stack pointer                           | callee-saved+   gp          | Global pointer                          | callee-saved+   tp          | Thread pointer                          | callee-saved+   t0,t1,t2    | -                                       | caller-saved+   s0          | Frame pointer                           | callee-saved+   s1          | -                                       | callee-saved+   a0,a1       | Arguments / return values               | caller-saved+   a2..a7      | Arguments                               | caller-saved+   s2..s11     | -                                       | callee-saved+   t3..t6      | -                                       | caller-saved+   ft0..ft7    | -                                       | caller-saved+   fs0,fs1     | -                                       | callee-saved+   fa0,fa1     | Arguments / return values               | caller-saved+   fa2..fa7    | Arguments                               | caller-saved+   fs2..fs11   | -                                       | callee-saved+   ft8..ft11   | -                                       | caller-saved++   Each general purpose register as well as each floating-point+   register is 64 bits wide.++   -------------------------------------------------------------------------- */++#define REG(x) __asm__(#x)++#define REG_Base        s1+#define REG_Sp          s2+#define REG_Hp          s3+#define REG_R1          s4+#define REG_R2          s5+#define REG_R3          s6+#define REG_R4          s7+#define REG_R5          s8+#define REG_R6          s9+#define REG_R7          s10+#define REG_SpLim       s11++#define REG_F1          fs0+#define REG_F2          fs1+#define REG_F3          fs2+#define REG_F4          fs3+#define REG_F5          fs4+#define REG_F6          fs5++#define REG_D1          fs6+#define REG_D2          fs7+#define REG_D3          fs8+#define REG_D4          fs9+#define REG_D5          fs10+#define REG_D6          fs11++#define MAX_REAL_FLOAT_REG   6+#define MAX_REAL_DOUBLE_REG  6
+ rts/include/stg/MachRegs/s390x.h view
@@ -0,0 +1,72 @@+#pragma once++/* -----------------------------------------------------------------------------+   The s390x register mapping++   Register    | Role(s)                                 | Call effect+   ------------+-------------------------------------+-----------------+   r0,r1       | -                                       | caller-saved+   r2          | Argument / return value                 | caller-saved+   r3,r4,r5    | Arguments                               | caller-saved+   r6          | Argument                                | callee-saved+   r7...r11    | -                                       | callee-saved+   r12         | (Commonly used as GOT pointer)          | callee-saved+   r13         | (Commonly used as literal pool pointer) | callee-saved+   r14         | Return address                          | caller-saved+   r15         | Stack pointer                           | callee-saved+   f0          | Argument / return value                 | caller-saved+   f2,f4,f6    | Arguments                               | caller-saved+   f1,f3,f5,f7 | -                                       | caller-saved+   f8...f15    | -                                       | callee-saved+   v0...v31    | -                                       | caller-saved++   Each general purpose register r0 through r15 as well as each floating-point+   register f0 through f15 is 64 bits wide. Each vector register v0 through v31+   is 128 bits wide.++   Note, the vector registers v0 through v15 overlap with the floating-point+   registers f0 through f15.++   -------------------------------------------------------------------------- */+++#define REG(x) __asm__("%" #x)++#define REG_Base        r7+#define REG_Sp          r8+#define REG_Hp          r10+#define REG_R1          r11+#define REG_R2          r12+#define REG_R3          r13+#define REG_R4          r6+#define REG_R5          r2+#define REG_R6          r3+#define REG_R7          r4+#define REG_R8          r5+#define REG_SpLim       r9+#define REG_MachSp      r15++#define REG_F1          f8+#define REG_F2          f9+#define REG_F3          f10+#define REG_F4          f11+#define REG_F5          f0+#define REG_F6          f1++#define REG_D1          f12+#define REG_D2          f13+#define REG_D3          f14+#define REG_D4          f15+#define REG_D5          f2+#define REG_D6          f3++#define CALLER_SAVES_R5+#define CALLER_SAVES_R6+#define CALLER_SAVES_R7+#define CALLER_SAVES_R8++#define CALLER_SAVES_F5+#define CALLER_SAVES_F6++#define CALLER_SAVES_D5+#define CALLER_SAVES_D6
+ rts/include/stg/MachRegs/wasm32.h view
@@ -0,0 +1,35 @@+#pragma once++#define REG_Base           0++#define REG_R1             1+#define REG_R2             2+#define REG_R3             3+#define REG_R4             4+#define REG_R5             5+#define REG_R6             6+#define REG_R7             7+#define REG_R8             8+#define REG_R9             9+#define REG_R10            10++#define REG_F1             11+#define REG_F2             12+#define REG_F3             13+#define REG_F4             14+#define REG_F5             15+#define REG_F6             16++#define REG_D1             17+#define REG_D2             18+#define REG_D3             19+#define REG_D4             20+#define REG_D5             21+#define REG_D6             22++#define REG_L1             23++#define REG_Sp             24+#define REG_SpLim          25+#define REG_Hp             26+#define REG_HpLim          27
+ rts/include/stg/MachRegs/x86.h view
@@ -0,0 +1,210 @@+/* -----------------------------------------------------------------------------+   The x86 register mapping++   Ok, we've only got 6 general purpose registers, a frame pointer and a+   stack pointer.  \tr{%eax} and \tr{%edx} are return values from C functions,+   hence they get trashed across ccalls and are caller saves. \tr{%ebx},+   \tr{%esi}, \tr{%edi}, \tr{%ebp} are all callee-saves.++   Reg     STG-Reg+   ---------------+   ebx     Base+   ebp     Sp+   esi     R1+   edi     Hp++   Leaving SpLim out of the picture.+   -------------------------------------------------------------------------- */++#if defined(MACHREGS_i386)++#define REG(x) __asm__("%" #x)++#if !defined(not_doing_dynamic_linking)+#define REG_Base    ebx+#endif+#define REG_Sp      ebp++#if !defined(STOLEN_X86_REGS)+#define STOLEN_X86_REGS 4+#endif++#if STOLEN_X86_REGS >= 3+# define REG_R1     esi+#endif++#if STOLEN_X86_REGS >= 4+# define REG_Hp     edi+#endif+#define REG_MachSp  esp++#define REG_XMM1    xmm0+#define REG_XMM2    xmm1+#define REG_XMM3    xmm2+#define REG_XMM4    xmm3++#define REG_YMM1    ymm0+#define REG_YMM2    ymm1+#define REG_YMM3    ymm2+#define REG_YMM4    ymm3++#define REG_ZMM1    zmm0+#define REG_ZMM2    zmm1+#define REG_ZMM3    zmm2+#define REG_ZMM4    zmm3++#define MAX_REAL_VANILLA_REG 1  /* always, since it defines the entry conv */+#define MAX_REAL_FLOAT_REG   0+#define MAX_REAL_DOUBLE_REG  0+#define MAX_REAL_LONG_REG    0+#define MAX_REAL_XMM_REG     4+#define MAX_REAL_YMM_REG     4+#define MAX_REAL_ZMM_REG     4++/* -----------------------------------------------------------------------------+  The x86-64 register mapping++  %rax          caller-saves, don't steal this one+  %rbx          YES+  %rcx          arg reg, caller-saves+  %rdx          arg reg, caller-saves+  %rsi          arg reg, caller-saves+  %rdi          arg reg, caller-saves+  %rbp          YES (our *prime* register)+  %rsp          (unavailable - stack pointer)+  %r8           arg reg, caller-saves+  %r9           arg reg, caller-saves+  %r10          caller-saves+  %r11          caller-saves+  %r12          YES+  %r13          YES+  %r14          YES+  %r15          YES++  %xmm0-7       arg regs, caller-saves+  %xmm8-15      caller-saves++  Use the caller-saves regs for Rn, because we don't always have to+  save those (as opposed to Sp/Hp/SpLim etc. which always have to be+  saved).++  --------------------------------------------------------------------------- */++#elif defined(MACHREGS_x86_64)++#define REG(x) __asm__("%" #x)++#define REG_Base  r13+#define REG_Sp    rbp+#define REG_Hp    r12+#define REG_R1    rbx+#define REG_R2    r14+#define REG_R3    rsi+#define REG_R4    rdi+#define REG_R5    r8+#define REG_R6    r9+#define REG_SpLim r15+#define REG_MachSp  rsp++/*+Map both Fn and Dn to register xmmn so that we can pass a function any+combination of up to six Float# or Double# arguments without touching+the stack. See Note [Overlapping global registers] for implications.+*/++#define REG_F1    xmm1+#define REG_F2    xmm2+#define REG_F3    xmm3+#define REG_F4    xmm4+#define REG_F5    xmm5+#define REG_F6    xmm6++#define REG_D1    xmm1+#define REG_D2    xmm2+#define REG_D3    xmm3+#define REG_D4    xmm4+#define REG_D5    xmm5+#define REG_D6    xmm6++#define REG_XMM1    xmm1+#define REG_XMM2    xmm2+#define REG_XMM3    xmm3+#define REG_XMM4    xmm4+#define REG_XMM5    xmm5+#define REG_XMM6    xmm6++#define REG_YMM1    ymm1+#define REG_YMM2    ymm2+#define REG_YMM3    ymm3+#define REG_YMM4    ymm4+#define REG_YMM5    ymm5+#define REG_YMM6    ymm6++#define REG_ZMM1    zmm1+#define REG_ZMM2    zmm2+#define REG_ZMM3    zmm3+#define REG_ZMM4    zmm4+#define REG_ZMM5    zmm5+#define REG_ZMM6    zmm6++#if !defined(mingw32_HOST_OS)+#define CALLER_SAVES_R3+#define CALLER_SAVES_R4+#endif+#define CALLER_SAVES_R5+#define CALLER_SAVES_R6++#define CALLER_SAVES_F1+#define CALLER_SAVES_F2+#define CALLER_SAVES_F3+#define CALLER_SAVES_F4+#define CALLER_SAVES_F5+#if !defined(mingw32_HOST_OS)+#define CALLER_SAVES_F6+#endif++#define CALLER_SAVES_D1+#define CALLER_SAVES_D2+#define CALLER_SAVES_D3+#define CALLER_SAVES_D4+#define CALLER_SAVES_D5+#if !defined(mingw32_HOST_OS)+#define CALLER_SAVES_D6+#endif++#define CALLER_SAVES_XMM1+#define CALLER_SAVES_XMM2+#define CALLER_SAVES_XMM3+#define CALLER_SAVES_XMM4+#define CALLER_SAVES_XMM5+#if !defined(mingw32_HOST_OS)+#define CALLER_SAVES_XMM6+#endif++#define CALLER_SAVES_YMM1+#define CALLER_SAVES_YMM2+#define CALLER_SAVES_YMM3+#define CALLER_SAVES_YMM4+#define CALLER_SAVES_YMM5+#if !defined(mingw32_HOST_OS)+#define CALLER_SAVES_YMM6+#endif++#define CALLER_SAVES_ZMM1+#define CALLER_SAVES_ZMM2+#define CALLER_SAVES_ZMM3+#define CALLER_SAVES_ZMM4+#define CALLER_SAVES_ZMM5+#if !defined(mingw32_HOST_OS)+#define CALLER_SAVES_ZMM6+#endif++#define MAX_REAL_VANILLA_REG 6+#define MAX_REAL_FLOAT_REG   6+#define MAX_REAL_DOUBLE_REG  6+#define MAX_REAL_LONG_REG    0+#define MAX_REAL_XMM_REG     6+#define MAX_REAL_YMM_REG     6+#define MAX_REAL_ZMM_REG     6++#endif  /* MACHREGS_i386 || MACHREGS_x86_64 */