packages feed

clash-lib 1.10.2 → 1.10.3

raw patch · 91 files changed

+4049/−1727 lines, 91 filesdep ~clash-preludedep ~ghcdep ~ghc-bignumPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependency ranges changed: clash-prelude, ghc, ghc-bignum, ghci, template-haskell

API changes (from Hackage documentation)

- Clash.Normalize.Strategy: applyMany :: [(String, Rewrite extra)] -> Rewrite extra
- Clash.Normalize.Strategy: innerMost :: Rewrite extra -> Rewrite extra
- Clash.Normalize.Strategy: topdownSucR :: Rewrite extra -> Rewrite extra
- Clash.Normalize.Transformations.Reduce: reduceNonRepPrim :: HasCallStack => NormRewrite
+ Clash.Core.Term: bindToList :: Bind a -> [(Id, a)]
+ Clash.Normalize.PrimitiveReductions: constantPropagation :: NormRewrite
+ Clash.Normalize.PrimitiveReductions: shareVec :: Bool -> InScopeSet -> Term -> NormalizeSession (InScopeSet, Term -> Term, Term)
+ Clash.Normalize.Strategy.Spec: constantPropagationSpec :: Strat
+ Clash.Normalize.Strategy.Spec: flattenSpec :: Strat
+ Clash.Normalize.Strategy.Spec: normalizationSpec :: Name -> Strat
+ Clash.Normalize.Transformations.ANF: nonRepANFWorker :: HasCallStack => TransformContext -> Term -> Term -> Term -> NormalizeSession Term
+ Clash.Normalize.Transformations.Case: caseCaseWorker :: HasCallStack => TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term
+ Clash.Normalize.Transformations.Case: caseConWorker :: HasCallStack => TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term
+ Clash.Normalize.Transformations.Case: caseEliminateNonReachableWorker :: HasCallStack => TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term
+ Clash.Normalize.Transformations.Case: caseFlatWorker :: HasCallStack => TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term
+ Clash.Normalize.Transformations.Case: caseLetWorker :: HasCallStack => TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term
+ Clash.Normalize.Transformations.Case: elimCaseBigNumInternalsWorker :: HasCallStack => TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term
+ Clash.Normalize.Transformations.Case: elimExistentialsWorker :: HasCallStack => TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term
+ Clash.Normalize.Transformations.Cast: argCastSpecWorker :: HasCallStack => TransformContext -> Term -> Term -> Term -> NormalizeSession Term
+ Clash.Normalize.Transformations.Cast: caseCastWorker :: HasCallStack => TransformContext -> Term -> Term -> Type -> Type -> NormalizeSession Term
+ Clash.Normalize.Transformations.Cast: elimCastCastWorker :: HasCallStack => TransformContext -> Term -> Term -> Type -> Type -> NormalizeSession Term
+ Clash.Normalize.Transformations.Cast: letCastWorker :: HasCallStack => TransformContext -> Term -> Term -> Type -> Type -> NormalizeSession Term
+ Clash.Normalize.Transformations.Cast: splitCastWorkWorker :: HasCallStack => TransformContext -> Term -> Bind Term -> Term -> NormalizeSession Term
+ Clash.Normalize.Transformations.DEC: disjointExpressionConsolidationWorker :: HasCallStack => TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term
+ Clash.Normalize.Transformations.EtaExpand: etaExpandSynWorker :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Inline: bindConstantVarWorker :: HasCallStack => TransformContext -> Term -> Bind Term -> Term -> NormalizeSession Term
+ Clash.Normalize.Transformations.Inline: collapseRHSNoopsWorker :: HasCallStack => TransformContext -> Term -> Bind Term -> Term -> NormalizeSession Term
+ Clash.Normalize.Transformations.Inline: inlineCastWorker :: HasCallStack => TransformContext -> Term -> Bind Term -> Term -> NormalizeSession Term
+ Clash.Normalize.Transformations.Inline: inlineCleanupWorker :: HasCallStack => TransformContext -> Term -> Bind Term -> Term -> NormalizeSession Term
+ Clash.Normalize.Transformations.Inline: inlineOrLiftNonRepWorker :: HasCallStack => TransformContext -> Term -> Bind Term -> Term -> NormalizeSession Term
+ Clash.Normalize.Transformations.Inline: inlineSimIOWorker :: HasCallStack => TransformContext -> Term -> Bind Term -> Term -> NormalizeSession Term
+ Clash.Normalize.Transformations.Inline: inlineSmallWorker :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Inline: inlineWorkFreeWorker :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Letrec: deadCodeWorker :: HasCallStack => TransformContext -> Term -> Bind Term -> Term -> NormalizeSession Term
+ Clash.Normalize.Transformations.Letrec: flattenLetWorker :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Letrec: removeUnusedExprCase :: TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term
+ Clash.Normalize.Transformations.Letrec: removeUnusedExprSpine :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Letrec: simpleCSEWorker :: HasCallStack => TransformContext -> Term -> Bind Term -> Term -> NormalizeSession Term
+ Clash.Normalize.Transformations.Letrec: topLetWorker :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.MultiPrim: setupMultiResultPrimWorker :: HasCallStack => TransformContext -> Term -> PrimInfo -> NormalizeSession Term
+ Clash.Normalize.Transformations.Reduce: reduceConstWorker :: HasCallStack => TransformContext -> Term -> Term -> Term -> NormalizeSession Term
+ Clash.Normalize.Transformations.Reduce: reducePrim :: Transformation
+ Clash.Normalize.Transformations.Reduce: reducePrimWorker :: HasCallStack => TransformContext -> Term -> Term -> Term -> NormalizeSession Term
+ Clash.Normalize.Transformations.SeparateArgs: separateArgumentsLambdaWorker :: HasCallStack => TransformContext -> Term -> Id -> Term -> NormalizeSession Term
+ Clash.Normalize.Transformations.SeparateArgs: separateArgumentsSpineWorker :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Specialize: appPropWorker :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Specialize: constantSpecWorker :: HasCallStack => TransformContext -> Term -> Term -> Term -> NormalizeSession Term
+ Clash.Normalize.Transformations.Specialize: nonRepSpecWorker :: HasCallStack => TransformContext -> Term -> Term -> Term -> NormalizeSession Term
+ Clash.Normalize.Transformations.Specialize: typeSpecWorker :: HasCallStack => TransformContext -> Term -> Term -> Type -> NormalizeSession Term
+ Clash.Normalize.Transformations.Specialize: zeroWidthSpecWorker :: HasCallStack => TransformContext -> Term -> Id -> Term -> NormalizeSession Term
+ Clash.Normalize.Transformations.XOptimize: xOptimizeWorker :: HasCallStack => TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term
+ Clash.Normalize.Types: [_constantPropagationStrategy] :: NormalizeState -> Rewrite NormalizeState
+ Clash.Normalize.Types: [_normalizationStrategy] :: NormalizeState -> Rewrite NormalizeState
+ Clash.Normalize.Types: [_workFreeAppCache] :: NormalizeState -> HashMap Term Term
+ Clash.Normalize.Types: constantPropagationStrategy :: Lens' NormalizeState (Rewrite NormalizeState)
+ Clash.Normalize.Types: normalizationStrategy :: Lens' NormalizeState (Rewrite NormalizeState)
+ Clash.Normalize.Types: workFreeAppCache :: Lens' NormalizeState (HashMap Term Term)
+ Clash.Normalize.Util: normalizeWorkFreeApp :: Id -> Binding Term -> [Either Term Type] -> NormalizeSession Term
+ Clash.Primitives.Types: UnresolvedPrimitiveEntry :: NonEmpty UnresolvedPrimitive -> UnresolvedPrimitiveEntry
+ Clash.Primitives.Types: [unUnresolvedPrimitiveEntry] :: UnresolvedPrimitiveEntry -> NonEmpty UnresolvedPrimitive
+ Clash.Primitives.Types: instance Data.Aeson.Types.FromJSON.FromJSON Clash.Primitives.Types.UnresolvedPrimitiveEntry
+ Clash.Primitives.Types: newtype UnresolvedPrimitiveEntry
+ Clash.Rewrite.Combinators: innerMost :: Rewrite extra -> Rewrite extra
+ Clash.Rewrite.Combinators: topdownSucR :: Rewrite extra -> Rewrite extra
+ Clash.Rewrite.StrategyDSL: (!->) :: Strategic a => a -> a -> a
+ Clash.Rewrite.StrategyDSL: (>-!) :: Strategic a => a -> a -> a
+ Clash.Rewrite.StrategyDSL: (>-!->) :: Strat -> Strat -> Strat
+ Clash.Rewrite.StrategyDSL: (>->) :: Strategic a => a -> a -> a
+ Clash.Rewrite.StrategyDSL: AnyWorker :: !Name -> TransformationWorker
+ Clash.Rewrite.StrategyDSL: BottomUp :: Step -> Strat
+ Clash.Rewrite.StrategyDSL: CApp :: Constructor
+ Clash.Rewrite.StrategyDSL: CCase :: Constructor
+ Clash.Rewrite.StrategyDSL: CCast :: Constructor
+ Clash.Rewrite.StrategyDSL: CData :: Constructor
+ Clash.Rewrite.StrategyDSL: CLam :: Constructor
+ Clash.Rewrite.StrategyDSL: CLet :: Constructor
+ Clash.Rewrite.StrategyDSL: CLiteral :: Constructor
+ Clash.Rewrite.StrategyDSL: CPrim :: Constructor
+ Clash.Rewrite.StrategyDSL: CTick :: Constructor
+ Clash.Rewrite.StrategyDSL: CTyApp :: Constructor
+ Clash.Rewrite.StrategyDSL: CTyLam :: Constructor
+ Clash.Rewrite.StrategyDSL: CVar :: Constructor
+ Clash.Rewrite.StrategyDSL: CallStrategy :: Name -> Strat
+ Clash.Rewrite.StrategyDSL: Chain :: [Transformation] -> Step
+ Clash.Rewrite.StrategyDSL: DeepSeqS :: Strat -> Strat -> Strat
+ Clash.Rewrite.StrategyDSL: EmbedS :: Strat -> Step
+ Clash.Rewrite.StrategyDSL: FieldWorker :: !Constructor -> !Name -> TransformationWorker
+ Clash.Rewrite.StrategyDSL: InnerMost :: Step -> Strat
+ Clash.Rewrite.StrategyDSL: OnChange :: Strat -> Strat -> Strat
+ Clash.Rewrite.StrategyDSL: OnChangeS :: Step -> Step -> Step
+ Clash.Rewrite.StrategyDSL: OnNoChange :: Strat -> Strat -> Strat
+ Clash.Rewrite.StrategyDSL: OnNoChangeS :: Step -> Step -> Step
+ Clash.Rewrite.StrategyDSL: Pass :: String -> Name -> Strat
+ Clash.Rewrite.StrategyDSL: Repeat :: Strat -> Strat
+ Clash.Rewrite.StrategyDSL: Seq :: Strat -> Strat -> Strat
+ Clash.Rewrite.StrategyDSL: SeqS :: Step -> Step -> Step
+ Clash.Rewrite.StrategyDSL: TopDown :: Step -> Strat
+ Clash.Rewrite.StrategyDSL: TopDownFix :: Step -> Strat
+ Clash.Rewrite.StrategyDSL: TopDownSuc :: Step -> Strat
+ Clash.Rewrite.StrategyDSL: Transformation :: !String -> ![TransformationWorker] -> Transformation
+ Clash.Rewrite.StrategyDSL: Worker :: !Constructor -> !Name -> TransformationWorker
+ Clash.Rewrite.StrategyDSL: [$sel:name:Transformation] :: Transformation -> !String
+ Clash.Rewrite.StrategyDSL: [$sel:workers:Transformation] :: Transformation -> ![TransformationWorker]
+ Clash.Rewrite.StrategyDSL: anyConstructor :: String -> Name -> Transformation
+ Clash.Rewrite.StrategyDSL: bottomup :: ToStep s => s -> Strat
+ Clash.Rewrite.StrategyDSL: callStrategy :: Name -> Strat
+ Clash.Rewrite.StrategyDSL: chain :: [Transformation] -> Step
+ Clash.Rewrite.StrategyDSL: class Strategic a
+ Clash.Rewrite.StrategyDSL: class ToStep s
+ Clash.Rewrite.StrategyDSL: data Constructor
+ Clash.Rewrite.StrategyDSL: data Step
+ Clash.Rewrite.StrategyDSL: data Strat
+ Clash.Rewrite.StrategyDSL: data Transformation
+ Clash.Rewrite.StrategyDSL: data TransformationWorker
+ Clash.Rewrite.StrategyDSL: infixr 5 >-!
+ Clash.Rewrite.StrategyDSL: infixr 6 >-!->
+ Clash.Rewrite.StrategyDSL: innerMost :: ToStep s => s -> Strat
+ Clash.Rewrite.StrategyDSL: instance Clash.Rewrite.StrategyDSL.Strategic Clash.Rewrite.StrategyDSL.Step
+ Clash.Rewrite.StrategyDSL: instance Clash.Rewrite.StrategyDSL.Strategic Clash.Rewrite.StrategyDSL.Strat
+ Clash.Rewrite.StrategyDSL: instance Clash.Rewrite.StrategyDSL.ToStep Clash.Rewrite.StrategyDSL.Step
+ Clash.Rewrite.StrategyDSL: instance Clash.Rewrite.StrategyDSL.ToStep Clash.Rewrite.StrategyDSL.Transformation
+ Clash.Rewrite.StrategyDSL: instance GHC.Classes.Eq Clash.Rewrite.StrategyDSL.Constructor
+ Clash.Rewrite.StrategyDSL: instance GHC.Classes.Eq Clash.Rewrite.StrategyDSL.Step
+ Clash.Rewrite.StrategyDSL: instance GHC.Classes.Eq Clash.Rewrite.StrategyDSL.Strat
+ Clash.Rewrite.StrategyDSL: instance GHC.Classes.Eq Clash.Rewrite.StrategyDSL.Transformation
+ Clash.Rewrite.StrategyDSL: instance GHC.Classes.Eq Clash.Rewrite.StrategyDSL.TransformationWorker
+ Clash.Rewrite.StrategyDSL: instance GHC.Classes.Ord Clash.Rewrite.StrategyDSL.Constructor
+ Clash.Rewrite.StrategyDSL: instance GHC.Enum.Bounded Clash.Rewrite.StrategyDSL.Constructor
+ Clash.Rewrite.StrategyDSL: instance GHC.Enum.Enum Clash.Rewrite.StrategyDSL.Constructor
+ Clash.Rewrite.StrategyDSL: instance GHC.Show.Show Clash.Rewrite.StrategyDSL.Constructor
+ Clash.Rewrite.StrategyDSL: instance GHC.Show.Show Clash.Rewrite.StrategyDSL.Step
+ Clash.Rewrite.StrategyDSL: instance GHC.Show.Show Clash.Rewrite.StrategyDSL.Strat
+ Clash.Rewrite.StrategyDSL: instance GHC.Show.Show Clash.Rewrite.StrategyDSL.Transformation
+ Clash.Rewrite.StrategyDSL: instance GHC.Show.Show Clash.Rewrite.StrategyDSL.TransformationWorker
+ Clash.Rewrite.StrategyDSL: named :: String -> Transformation -> Transformation
+ Clash.Rewrite.StrategyDSL: nested :: Strat -> Step
+ Clash.Rewrite.StrategyDSL: onApp :: Name -> [TransformationWorker]
+ Clash.Rewrite.StrategyDSL: onAppNode :: Name -> [TransformationWorker]
+ Clash.Rewrite.StrategyDSL: onCase :: Name -> [TransformationWorker]
+ Clash.Rewrite.StrategyDSL: onCast :: Name -> [TransformationWorker]
+ Clash.Rewrite.StrategyDSL: onData :: Name -> [TransformationWorker]
+ Clash.Rewrite.StrategyDSL: onLam :: Name -> [TransformationWorker]
+ Clash.Rewrite.StrategyDSL: onLet :: Name -> [TransformationWorker]
+ Clash.Rewrite.StrategyDSL: onLetNode :: Name -> [TransformationWorker]
+ Clash.Rewrite.StrategyDSL: onLiteral :: Name -> [TransformationWorker]
+ Clash.Rewrite.StrategyDSL: onPrim :: Name -> [TransformationWorker]
+ Clash.Rewrite.StrategyDSL: onPrimNode :: Name -> [TransformationWorker]
+ Clash.Rewrite.StrategyDSL: onTick :: Name -> [TransformationWorker]
+ Clash.Rewrite.StrategyDSL: onTickNode :: Name -> [TransformationWorker]
+ Clash.Rewrite.StrategyDSL: onTyApp :: Name -> [TransformationWorker]
+ Clash.Rewrite.StrategyDSL: onTyAppNode :: Name -> [TransformationWorker]
+ Clash.Rewrite.StrategyDSL: onTyLam :: Name -> [TransformationWorker]
+ Clash.Rewrite.StrategyDSL: onVar :: Name -> [TransformationWorker]
+ Clash.Rewrite.StrategyDSL: onVarNode :: Name -> [TransformationWorker]
+ Clash.Rewrite.StrategyDSL: one :: Transformation -> Step
+ Clash.Rewrite.StrategyDSL: pass :: String -> Name -> Strat
+ Clash.Rewrite.StrategyDSL: repeatR :: Strat -> Strat
+ Clash.Rewrite.StrategyDSL: toStep :: ToStep s => s -> Step
+ Clash.Rewrite.StrategyDSL: toTransformation :: String -> [TransformationWorker] -> Transformation
+ Clash.Rewrite.StrategyDSL: topdown :: ToStep s => s -> Strat
+ Clash.Rewrite.StrategyDSL: topdownFix :: ToStep s => s -> Strat
+ Clash.Rewrite.StrategyDSL: topdownSuc :: ToStep s => s -> Strat
+ Clash.Rewrite.StrategyDSL.TH: asRewriteQ :: Transformation -> Q Exp
+ Clash.Rewrite.StrategyDSL.TH: compileStrategy :: Strat -> Q Exp
+ Clash.Rewrite.StrategyDSL.TH: compileStrategyReference :: Strat -> Q Exp
+ Clash.Rewrite.StrategyDSL.TH: dispatchQ :: Step -> Q Exp
+ Clash.Rewrite.Util: applyWith :: String -> TransformContext -> Term -> RewriteMonad extra Term -> RewriteMonad extra (Term, Bool)
- Clash.Normalize.PrimitiveReductions: reduceFoldr :: PrimInfo -> Integer -> Type -> Term -> Term -> Term -> TransformContext -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceFoldr :: PrimInfo -> Integer -> Type -> Bool -> Term -> Term -> Term -> TransformContext -> NormalizeSession Term
- Clash.Normalize.PrimitiveReductions: reduceInit :: PrimInfo -> Integer -> Type -> Term -> TransformContext -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceInit :: PrimInfo -> Integer -> Type -> Bool -> Term -> TransformContext -> NormalizeSession Term
- Clash.Normalize.PrimitiveReductions: reduceMap :: PrimInfo -> Integer -> Type -> Type -> Term -> Term -> TransformContext -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceMap :: PrimInfo -> Integer -> Type -> Type -> Bool -> Term -> Term -> TransformContext -> NormalizeSession Term
- Clash.Normalize.PrimitiveReductions: reduceZipWith :: PrimInfo -> Integer -> Type -> Type -> Type -> Term -> Term -> Term -> TransformContext -> NormalizeSession Term
+ Clash.Normalize.PrimitiveReductions: reduceZipWith :: PrimInfo -> Integer -> Type -> Type -> Type -> Bool -> Bool -> Term -> Term -> Term -> TransformContext -> NormalizeSession Term
- Clash.Normalize.Transformations.ANF: nonRepANF :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.ANF: nonRepANF :: Transformation
- Clash.Normalize.Transformations.Case: caseCase :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Case: caseCase :: Transformation
- Clash.Normalize.Transformations.Case: caseCon :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Case: caseCon :: Transformation
- Clash.Normalize.Transformations.Case: caseEliminateNonReachable :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Case: caseEliminateNonReachable :: Transformation
- Clash.Normalize.Transformations.Case: caseFlat :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Case: caseFlat :: Transformation
- Clash.Normalize.Transformations.Case: caseLet :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Case: caseLet :: Transformation
- Clash.Normalize.Transformations.Case: elimCaseBigNumInternals :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Case: elimCaseBigNumInternals :: Transformation
- Clash.Normalize.Transformations.Case: elimExistentials :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Case: elimExistentials :: Transformation
- Clash.Normalize.Transformations.Cast: argCastSpec :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Cast: argCastSpec :: Transformation
- Clash.Normalize.Transformations.Cast: caseCast :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Cast: caseCast :: Transformation
- Clash.Normalize.Transformations.Cast: elimCastCast :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Cast: elimCastCast :: Transformation
- Clash.Normalize.Transformations.Cast: letCast :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Cast: letCast :: Transformation
- Clash.Normalize.Transformations.Cast: splitCastWork :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Cast: splitCastWork :: Transformation
- Clash.Normalize.Transformations.DEC: disjointExpressionConsolidation :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.DEC: disjointExpressionConsolidation :: Transformation
- Clash.Normalize.Transformations.EtaExpand: etaExpandSyn :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.EtaExpand: etaExpandSyn :: Transformation
- Clash.Normalize.Transformations.Inline: bindConstantVar :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Inline: bindConstantVar :: Transformation
- Clash.Normalize.Transformations.Inline: collapseRHSNoops :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Inline: collapseRHSNoops :: Transformation
- Clash.Normalize.Transformations.Inline: inlineCast :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Inline: inlineCast :: Transformation
- Clash.Normalize.Transformations.Inline: inlineCleanup :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Inline: inlineCleanup :: Transformation
- Clash.Normalize.Transformations.Inline: inlineOrLiftNonRep :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Inline: inlineOrLiftNonRep :: Transformation
- Clash.Normalize.Transformations.Inline: inlineSimIO :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Inline: inlineSimIO :: Transformation
- Clash.Normalize.Transformations.Inline: inlineSmall :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Inline: inlineSmall :: Transformation
- Clash.Normalize.Transformations.Inline: inlineWorkFree :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Inline: inlineWorkFree :: Transformation
- Clash.Normalize.Transformations.Letrec: deadCode :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Letrec: deadCode :: Transformation
- Clash.Normalize.Transformations.Letrec: flattenLet :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Letrec: flattenLet :: Transformation
- Clash.Normalize.Transformations.Letrec: removeUnusedExpr :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Letrec: removeUnusedExpr :: Transformation
- Clash.Normalize.Transformations.Letrec: simpleCSE :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Letrec: simpleCSE :: Transformation
- Clash.Normalize.Transformations.Letrec: topLet :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Letrec: topLet :: Transformation
- Clash.Normalize.Transformations.MultiPrim: setupMultiResultPrim :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.MultiPrim: setupMultiResultPrim :: Transformation
- Clash.Normalize.Transformations.Reduce: reduceConst :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Reduce: reduceConst :: Transformation
- Clash.Normalize.Transformations.SeparateArgs: separateArguments :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.SeparateArgs: separateArguments :: Transformation
- Clash.Normalize.Transformations.Specialize: appProp :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Specialize: appProp :: Transformation
- Clash.Normalize.Transformations.Specialize: constantSpec :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Specialize: constantSpec :: Transformation
- Clash.Normalize.Transformations.Specialize: nonRepSpec :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Specialize: nonRepSpec :: Transformation
- Clash.Normalize.Transformations.Specialize: typeSpec :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Specialize: typeSpec :: Transformation
- Clash.Normalize.Transformations.Specialize: zeroWidthSpec :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.Specialize: zeroWidthSpec :: Transformation
- Clash.Normalize.Transformations.XOptimize: xOptimize :: HasCallStack => NormRewrite
+ Clash.Normalize.Transformations.XOptimize: xOptimize :: Transformation
- Clash.Normalize.Types: NormalizeState :: BindingMap -> Map (Id, Int, Either Term Type) Id -> VarEnv Int -> VarEnv (VarEnv Int) -> Map Text (Set Int) -> VarEnv Bool -> NormalizeState
+ Clash.Normalize.Types: NormalizeState :: BindingMap -> Map (Id, Int, Either Term Type) Id -> VarEnv Int -> VarEnv (VarEnv Int) -> Map Text (Set Int) -> VarEnv Bool -> Rewrite NormalizeState -> Rewrite NormalizeState -> HashMap Term Term -> NormalizeState
- Clash.Primitives.GHC.Literal: literalTF :: Text -> (Bool -> [Either Term Type] -> Int -> (BlackBoxMeta, BlackBox)) -> BlackBoxFunction
+ Clash.Primitives.GHC.Literal: literalTF :: NonEmpty Text -> (Bool -> [Either Term Type] -> Int -> (BlackBoxMeta, BlackBox)) -> BlackBoxFunction
- Clash.Rewrite.Types: bindings :: forall extra_a4WL8. Lens' (RewriteState extra_a4WL8) BindingMap
+ Clash.Rewrite.Types: bindings :: forall extra_a52V5. Lens' (RewriteState extra_a52V5) BindingMap
- Clash.Rewrite.Types: curFun :: forall extra_a4WL8. Lens' (RewriteState extra_a4WL8) (Id, SrcSpan)
+ Clash.Rewrite.Types: curFun :: forall extra_a52V5. Lens' (RewriteState extra_a52V5) (Id, SrcSpan)
- Clash.Rewrite.Types: extra :: forall extra_a4WL8 extra_a4WWF. Lens (RewriteState extra_a4WL8) (RewriteState extra_a4WWF) extra_a4WL8 extra_a4WWF
+ Clash.Rewrite.Types: extra :: forall extra_a52V5 extra_a536C. Lens (RewriteState extra_a52V5) (RewriteState extra_a536C) extra_a52V5 extra_a536C
- Clash.Rewrite.Types: globalHeap :: forall extra_a4WL8. Lens' (RewriteState extra_a4WL8) PrimHeap
+ Clash.Rewrite.Types: globalHeap :: forall extra_a52V5. Lens' (RewriteState extra_a52V5) PrimHeap
- Clash.Rewrite.Types: hwTypeCache :: forall extra_a4WL8. Lens' (RewriteState extra_a4WL8) HWMap
+ Clash.Rewrite.Types: hwTypeCache :: forall extra_a52V5. Lens' (RewriteState extra_a52V5) HWMap
- Clash.Rewrite.Types: nameCounter :: forall extra_a4WL8. Lens' (RewriteState extra_a4WL8) Int
+ Clash.Rewrite.Types: nameCounter :: forall extra_a52V5. Lens' (RewriteState extra_a52V5) Int
- Clash.Rewrite.Types: transformAppliedCounters :: forall extra_a4WL8. Lens' (RewriteState extra_a4WL8) (HashMap Text Word)
+ Clash.Rewrite.Types: transformAppliedCounters :: forall extra_a52V5. Lens' (RewriteState extra_a52V5) (HashMap Text Word)
- Clash.Rewrite.Types: transformCounter :: forall extra_a4WL8. Lens' (RewriteState extra_a4WL8) Word
+ Clash.Rewrite.Types: transformCounter :: forall extra_a52V5. Lens' (RewriteState extra_a52V5) Word
- Clash.Rewrite.Types: transformTriedCounters :: forall extra_a4WL8. Lens' (RewriteState extra_a4WL8) (HashMap Text Word)
+ Clash.Rewrite.Types: transformTriedCounters :: forall extra_a52V5. Lens' (RewriteState extra_a52V5) (HashMap Text Word)
- Clash.Rewrite.Types: uniqSupply :: forall extra_a4WL8. Lens' (RewriteState extra_a4WL8) Supply
+ Clash.Rewrite.Types: uniqSupply :: forall extra_a52V5. Lens' (RewriteState extra_a52V5) Supply
- Clash.Rewrite.Types: workFreeBinders :: forall extra_a4WL8. Lens' (RewriteState extra_a4WL8) (VarEnv Bool)
+ Clash.Rewrite.Types: workFreeBinders :: forall extra_a52V5. Lens' (RewriteState extra_a52V5) (VarEnv Bool)
- Clash.Rewrite.Util: inlineBinders :: (Term -> LetBinding -> RewriteMonad extra Bool) -> Rewrite extra
+ Clash.Rewrite.Util: inlineBinders :: (Term -> LetBinding -> RewriteMonad extra Bool) -> TransformContext -> Term -> Bind Term -> Term -> RewriteMonad extra Term
- Clash.Rewrite.Util: inlineOrLiftBinders :: (LetBinding -> RewriteMonad extra Bool) -> (Term -> LetBinding -> Bool) -> Rewrite extra
+ Clash.Rewrite.Util: inlineOrLiftBinders :: (LetBinding -> RewriteMonad extra Bool) -> (Term -> LetBinding -> Bool) -> TransformContext -> Term -> Bind Term -> Term -> RewriteMonad extra Term

Files

CHANGELOG.md view
@@ -1,5 +1,48 @@ # Changelog for the Clash project +## 1.10.3 - *14 Oct, 2026*++### Added:+- Added support for GHC 9.14.+  [#3182](https://github.com/clash-lang/clash-compiler/pull/3182)+- Add `NumConvert` support for converting from `SNat`+  [#3455](https://github.com/clash-lang/clash-compiler/pull/3455)++### Changed:+- Normalization now knows which `Term` constructors each transformation can fire on, and only offers a node to the transformations that can match it. Measured ~25% faster HDL generation end-to-end on a large industrial design, with identical HDL. Transformations that cannot match a node no longer show up in `-fclash-debug-transformations` and `-fclash-debug-count-transformations` output.+  [#3328](https://github.com/clash-lang/clash-compiler/pull/3328)+- `Clash.Signal.Internal.resetGenN` now reports `clash-non-synthesizable` on every backend, instead of only on SystemVerilog.+  [#3410](https://github.com/clash-lang/clash-compiler/pull/3410)+- In `clash-lib`, the `reduceNonRepPrim` transformation is renamed to `reducePrim`, because it replaces primitives for more reasons than non-representable arguments or results. To debug it with `-fclash-debug-transformations`, use the new name.+  [#3462](https://github.com/clash-lang/clash-compiler/pull/3462)+- In `clash-lib`, the `inlineWorkFree` transformation now normalizes an application of a function to constant arguments only once, and reuses the result at every place the same application occurs. Before, every occurrence was normalized separately. This speeds up normalization of designs that compute a lot with type-level naturals at compile time, for example through `KnownNat` constraints.+  [#3472](https://github.com/clash-lang/clash-compiler/pull/3472)++### Fixed:+- Clash no longer errors when unused arguments of local functions are non-representable in very specific circumstances+  [#3407](https://github.com/clash-lang/clash-compiler/issues/3407)+- `ensureSpine` on a `Signal` no longer crashes Clash with an internal error. It now applies the sample's `ensureSpine` instance in HDL, preserving fixed bits in custom representations. Undefined stream recovery in simulation uses the same instance instead of `deepErrorX`, fixing mismatches for function-valued samples.+  [#3432](https://github.com/clash-lang/clash-compiler/issues/3432)+- Functions testing for `XException` (`isX`, `hasX`, `maybeIsX`, and `maybeHasX`) are now marked non-translatable. This makes the Clash compiler throw a proper error, instead of an internal one when it encounters their use.+  [#3434](https://github.com/clash-lang/clash-compiler/pull/3434)+- Clash no longer crashes when generating HDL for `toEnum` on an enumeration with a single constructor.+  [#3439](https://github.com/clash-lang/clash-compiler/issues/3439)+- Clash now reports an error when using GHC 9.12.1 through 9.12.3, which contain bugs affecting Clash. The GHC compatibility matrix now lists 9.12.4 as the minimum supported GHC 9.12 release.+  [#3415](https://github.com/clash-lang/clash-compiler/issues/3415)+- Extending arithmetic (`add`, `sub`, and `mul`) on `Index` now handles zero-width+  arguments correctly. VHDL subtraction from zero-width `BitVector`, `Signed`, and+  `Unsigned` values now negates the widened operand correctly, including boundary+  values.+  [#3310](https://github.com/clash-lang/clash-compiler/issues/3310)+- Clash now checks all input targets before loading modules or generating HDL. Invalid arguments, including Clash flags passed without their leading dash, are reported immediately, instead of after compiling earlier inputs.+  [#3314](https://github.com/clash-lang/clash-compiler/issues/3314)+- Projecting a zero-width field, such as a `CallStack`, no longer renders a reference to an undeclared `c$sel` in the HDL in very specific circumstances.+  [#3460](https://github.com/clash-lang/clash-compiler/issues/3460)+- Clash no longer takes minutes to compile designs that unroll `map`, `zipWith`, `foldr`, or `init` over vectors bound to top-level definitions. This most often happened with modules compiled with `-ffull-laziness`, which is enabled by `-O`, for example by Cabal.+  [#3461](https://github.com/clash-lang/clash-compiler/issues/3461)+- Fixed accidental free variable capture in `appProp`, which could produce subtly incorrect HDL.+  [#3478](https://github.com/clash-lang/clash-compiler/issues/3478)+ ## 1.10.2 *Sep 4th, 2026*  Highlights:@@ -60,6 +103,7 @@ * In `clash-ghc`, Clash no longer enables `-dynamic-too` when the build is already dynamic, which made GHC emit an `-Winconsistent-flags` warning. See [#3354](https://github.com/clash-lang/clash-compiler/issues/3354), fixed in [#3358](https://github.com/clash-lang/clash-compiler/pull/3358). * In `clash-lib`, the SystemVerilog backend no longer emits out-of-bounds array indices when a nested modifier selects a half of an `RTree`. The size of a tree half was computed as `(d-1)^2` instead of `2^(d-1)`, so for an `RTree 3` the right half was emitted as `[4:8]` on an array whose valid indices are `0..7`. See [#3359](https://github.com/clash-lang/clash-compiler/issues/3359), fixed in [#3360](https://github.com/clash-lang/clash-compiler/pull/3360). * In `clash-lib` and `clash-ghc`, structural equality and ordering now account for the names and types of variables, including in `eqTerm` and `eqType`, instead of relying only on variable uniques. See [#3361](https://github.com/clash-lang/clash-compiler/issues/3361), fixed in [#3362](https://github.com/clash-lang/clash-compiler/pull/3362).+* `popCount`, `countLeadingZeros` and `countTrailingZeros` on `BitVector` (and hence on `Unsigned`, `Signed` and `Index`, which delegate to it) went through `Integer`, which made Clash emit a `Dubious primitive instantiation` warning for `GHC.Num.Integer.integerToInt#` and put an `Integer` in the generated HDL. They now use `Clash.Sized.Internal.Index.fromEnum#`, which has a black box of its own. See [#3409](https://github.com/clash-lang/clash-compiler/pull/3409).  ## 1.10.1 *Aug 27th, 2026* 
clash-lib.cabal view
@@ -1,6 +1,6 @@ Cabal-version:        2.2 Name:                 clash-lib-Version:              1.10.2+Version:              1.10.3 Synopsis:             Clash: a functional hardware description language - As a library Description:   Clash is a functional hardware description language that borrows both its@@ -57,7 +57,8 @@ tested-with:          GHC == 9.6.7,                       GHC == 9.8.4,                       GHC == 9.10.3,-                      GHC == 9.12.4+                      GHC == 9.12.4,+                      GHC == 9.14.1  Extra-source-files:   README.md,@@ -155,7 +156,7 @@                       base16-bytestring       >= 0.1.1    && < 1.1,                       binary                  >= 0.8.5    && < 0.11,                       bytestring              >= 0.10.0.2 && < 0.13,-                      clash-prelude           == 1.10.2,+                      clash-prelude           == 1.10.3,                       containers              >= 0.6.7    && < 0.9,                       cryptohash-sha256       >= 0.11     && < 0.12,                       data-default            >= 0.7      && < 0.9,@@ -165,12 +166,12 @@                       exceptions              >= 0.8.3    && < 0.11.0,                       extra                   >= 1.6.17   && < 1.9,                       filepath                >= 1.3.0.1  && < 1.6,-                      ghc                     >= 9.6.0    && < 9.13,+                      ghc                     >= 9.6.0    && < 9.15,                       ghc-boot,                       ghc-boot-th,                       ghc-prim,-                      ghc-bignum              >=1.0       && <1.4,-                      ghci                    >= 9.6.0    && < 9.13,+                      ghc-bignum              >=1.0       && <1.5,+                      ghci                    >= 9.6.0    && < 9.15,                       hashable                >= 1.4.1.0  && < 1.6,                       haskell-src-meta        >= 0.8      && < 0.9,                       hint                    >= 0.7      && < 0.10,@@ -183,7 +184,7 @@                       pretty-show             >= 1.9      && < 2.0,                       primitive               >= 0.5.0.1  && < 1.0,                       string-interpolate      >= 0.3      && < 1.1,-                      template-haskell        >= 2.20.0.0  && < 2.24,+                      template-haskell        >= 2.20.0.0  && < 2.25,                       temporary               >= 1.2.1    && < 1.4,                       terminal-size           >= 0.3      && < 0.4,                       text                    >= 1.2.2    && < 2.2,@@ -263,6 +264,7 @@                       Clash.Normalize.PrimitiveReductions                       Clash.Normalize.Primitives                       Clash.Normalize.Strategy+                      Clash.Normalize.Strategy.Spec                       Clash.Normalize.Transformations                       Clash.Normalize.Transformations.ANF                       Clash.Normalize.Transformations.Case@@ -296,6 +298,8 @@                       Clash.Primitives.Xilinx.ClockGen                        Clash.Rewrite.Combinators+                      Clash.Rewrite.StrategyDSL+                      Clash.Rewrite.StrategyDSL.TH                       Clash.Rewrite.Types                       Clash.Rewrite.Util                       Clash.Rewrite.WorkFree@@ -437,5 +441,7 @@                  Clash.Tests.Netlist.Id                  Clash.Tests.Util.Interpolate                  Clash.Tests.Normalize.Transformations+                 Clash.Tests.Rewrite.StrategyDSL+                 Clash.Tests.Rewrite.StrategyDSL.Stubs                   Test.Clash.Rewrite
prims/common/Control_Exception_Base.primitives.yaml view
@@ -1,61 +1,61 @@ - BlackBox:-    name: Control.Exception.Base.recSelError+    name: ["Control.Exception.Base.recSelError", "GHC.Internal.Control.Exception.Base.recSelError"]     kind: Expression     type: 'recSelError ::       Addr# -> a'     template: ~ERRORO     workInfo: Constant - BlackBox:-    name: Control.Exception.Base.recConError+    name: ["Control.Exception.Base.recConError", "GHC.Internal.Control.Exception.Base.recConError"]     kind: Expression     type: 'recConError ::       Addr# -> a'     template: ~ERRORO     workInfo: Constant - BlackBox:-    name: Control.Exception.Base.irrefutPatError+    name: ["Control.Exception.Base.irrefutPatError", "GHC.Internal.Control.Exception.Base.irrefutPatError"]     kind: Expression     type: 'irrefutPatError       :: Addr# -> a'     template: ~ERRORO     workInfo: Constant - BlackBox:-    name: Control.Exception.Base.runtimeError+    name: ["Control.Exception.Base.runtimeError", "GHC.Internal.Control.Exception.Base.runtimeError"]     kind: Expression     type: 'runtimeError ::       Addr# -> a'     template: ~ERRORO     workInfo: Constant - BlackBox:-    name: Control.Exception.Base.nonExhaustiveGuardsError+    name: ["Control.Exception.Base.nonExhaustiveGuardsError", "GHC.Internal.Control.Exception.Base.nonExhaustiveGuardsError"]     kind: Expression     type: 'nonExhaustiveGuardsError       :: Addr# -> a'     template: ~ERRORO     workInfo: Constant - BlackBox:-    name: Control.Exception.Base.patError+    name: ["Control.Exception.Base.patError", "GHC.Internal.Control.Exception.Base.patError"]     kind: Expression     type: 'patError :: Addr#       -> a'     template: ~ERRORO     workInfo: Constant - BlackBox:-    name: Control.Exception.Base.noMethodBindingError+    name: ["Control.Exception.Base.noMethodBindingError", "GHC.Internal.Control.Exception.Base.noMethodBindingError"]     kind: Expression     type: 'noMethodBindingError       :: Addr# -> a'     template: ~ERRORO     workInfo: Constant - BlackBox:-    name: Control.Exception.Base.absentError+    name: ["Control.Exception.Base.absentError", "GHC.Internal.Control.Exception.Base.absentError"]     kind: Expression     type: 'absentError ::       Addr# -> a'     template: ~ERRORO     workInfo: Constant - BlackBox:-    name: Control.Exception.Base.typeError+    name: ["Control.Exception.Base.typeError", "GHC.Internal.Control.Exception.Base.typeError"]     kind: Expression     type: 'typeError :: Addr#       -> a'
prims/common/Debug_Trace.primitives.yaml view
@@ -1,5 +1,5 @@ - BlackBox:-    name: Debug.Trace.trace+    name: ["Debug.Trace.trace", "GHC.Internal.Debug.Trace.trace"]     kind: Expression     type: 'trace :: String       -> a -> a'
prims/common/GHC_CString.primitives.yaml view
@@ -1,14 +1,14 @@ - BlackBox:-    name: GHC.CString.unpackCString#+    name: ["GHC.CString.unpackCString#", "GHC.Internal.CString.unpackCString#"]     kind: Expression     template: ~LIT[0]     workInfo: Never - BlackBox:-    name: GHC.CString.unpackFoldrCString#+    name: ["GHC.CString.unpackFoldrCString#", "GHC.Internal.CString.unpackFoldrCString#"]     kind: Expression     template: ~LIT[0]     workInfo: Never - Primitive:-    name: GHC.CString.unpackCStringUtf8#+    name: ["GHC.CString.unpackCStringUtf8#", "GHC.Internal.CString.unpackCStringUtf8#"]     primType: Function     workInfo: Never
prims/common/GHC_Classes.primitives.yaml view
@@ -1,23 +1,23 @@ - BlackBox:-    name: GHC.Classes.gtInt+    name: ["GHC.Classes.gtInt", "GHC.Internal.Classes.gtInt"]     kind: Expression     type: 'gtInt :: Int ->       Int -> Bool'     template: ~ARG[0] > ~ARG[1] - BlackBox:-    name: GHC.Classes.geInt+    name: ["GHC.Classes.geInt", "GHC.Internal.Classes.geInt"]     kind: Expression     type: 'geInt :: Int ->       Int -> Bool'     template: ~ARG[0] >= ~ARG[1] - BlackBox:-    name: GHC.Classes.ltInt+    name: ["GHC.Classes.ltInt", "GHC.Internal.Classes.ltInt"]     kind: Expression     type: 'ltInt :: Int ->       Int -> Bool'     template: ~ARG[0] < ~ARG[1] - BlackBox:-    name: GHC.Classes.leInt+    name: ["GHC.Classes.leInt", "GHC.Internal.Classes.leInt"]     kind: Expression     type: 'leInt :: Int ->       Int -> Bool'
prims/common/GHC_Err.primitives.yaml view
@@ -1,17 +1,17 @@ - BlackBox:-    name: GHC.Err.error+    name: ["GHC.Err.error", "GHC.Internal.Err.error"]     kind: Expression     type: 'error :: forall r a . HasCallStack => [Char] -> a'     template: ~ERRORO     workInfo: Constant - BlackBox:-    name: GHC.Err.errorWithoutStackTrace+    name: ["GHC.Err.errorWithoutStackTrace", "GHC.Internal.Err.errorWithoutStackTrace"]     kind: Expression     type: 'errorWithoutStackTrace :: forall r a . [Char] -> a'     template: ~ERRORO     workInfo: Constant - BlackBox:-    name: GHC.Err.undefined+    name: ["GHC.Err.undefined", "GHC.Internal.Err.undefined"]     kind: Expression     type: 'undefined :: forall r a . HasCallStack => a'     template: ~ERRORO
− prims/common/GHC_Internal_Control_Exception_Base.primitives.yaml
@@ -1,63 +0,0 @@-- BlackBox:-    name: GHC.Internal.Control.Exception.Base.recSelError-    kind: Expression-    type: 'recSelError ::-      Addr# -> a'-    template: ~ERRORO-    workInfo: Constant-- BlackBox:-    name: GHC.Internal.Control.Exception.Base.recConError-    kind: Expression-    type: 'recConError ::-      Addr# -> a'-    template: ~ERRORO-    workInfo: Constant-- BlackBox:-    name: GHC.Internal.Control.Exception.Base.irrefutPatError-    kind: Expression-    type: 'irrefutPatError-      :: Addr# -> a'-    template: ~ERRORO-    workInfo: Constant-- BlackBox:-    name: GHC.Internal.Control.Exception.Base.runtimeError-    kind: Expression-    type: 'runtimeError ::-      Addr# -> a'-    template: ~ERRORO-    workInfo: Constant-- BlackBox:-    name: GHC.Internal.Control.Exception.Base.nonExhaustiveGuardsError-    kind: Expression-    type: 'nonExhaustiveGuardsError-      :: Addr# -> a'-    template: ~ERRORO-    workInfo: Constant-- BlackBox:-    name: GHC.Internal.Control.Exception.Base.patError-    kind: Expression-    type: 'patError :: Addr#-      -> a'-    template: ~ERRORO-    workInfo: Constant-- BlackBox:-    name: GHC.Internal.Control.Exception.Base.noMethodBindingError-    kind: Expression-    type: 'noMethodBindingError-      :: Addr# -> a'-    template: ~ERRORO-    workInfo: Constant-- BlackBox:-    name: GHC.Internal.Control.Exception.Base.absentError-    kind: Expression-    type: 'absentError ::-      Addr# -> a'-    template: ~ERRORO-    workInfo: Constant-- BlackBox:-    name: GHC.Internal.Control.Exception.Base.typeError-    kind: Expression-    type: 'typeError :: Addr#-      -> a'-    template: ~ERRORO-    workInfo: Constant
− prims/common/GHC_Internal_Debug_Trace.primitives.yaml
@@ -1,7 +0,0 @@-- BlackBox:-    name: GHC.Internal.Debug.Trace.trace-    kind: Expression-    type: 'trace :: String-      -> a -> a'-    template: ~ARG[1]-    workInfo: Never
− prims/common/GHC_Internal_Err.primitives.yaml
@@ -1,18 +0,0 @@-- BlackBox:-    name: GHC.Internal.Err.error-    kind: Expression-    type: 'error :: forall r a . HasCallStack => [Char] -> a'-    template: ~ERRORO-    workInfo: Constant-- BlackBox:-    name: GHC.Internal.Err.errorWithoutStackTrace-    kind: Expression-    type: 'errorWithoutStackTrace :: forall r a . [Char] -> a'-    template: ~ERRORO-    workInfo: Constant-- BlackBox:-    name: GHC.Internal.Err.undefined-    kind: Expression-    type: 'undefined :: forall r a . HasCallStack => a'-    template: ~ERRORO-    workInfo: Constant
− prims/common/GHC_Internal_TypeNats.primitives.yaml
@@ -1,17 +0,0 @@-- BlackBox:-    name: GHC.Internal.TypeNats.natVal-    kind: Expression-    type: 'natVal :: forall-      n proxy. KnownNat n => proxy n -> Natural'-    template: ~ARG[0]-    workInfo: Never-- Primitive:-    name: GHC.Internal.TypeNats.someNatVal-    primType: Function-    type: 'someNatVal :: Natural -> SomeNat'-    workInfo: Never-- Primitive:-    name: GHC.Internal.TypeNats.withSomeSNat-    primType: Function-    type: 'withSomeSNat :: forall rep (r :: TYPE rep). Natural -> (forall n. SNat n -> r) -> r'-    workInfo: Never
prims/common/GHC_Magic.primitives.yaml view
@@ -1,18 +1,18 @@ - Primitive:-    name: GHC.Magic.lazy+    name: ["GHC.Magic.lazy", "GHC.Internal.Magic.lazy"]     primType: Function     workInfo: Never - Primitive:-    name: GHC.Magic.noinline+    name: ["GHC.Magic.noinline", "GHC.Internal.Magic.noinline"]     primType: Function     type: forall a. a -> a     workInfo: Never - Primitive:-    name: GHC.Magic.nospec+    name: ["GHC.Magic.nospec", "GHC.Internal.Magic.nospec"]     primType: Function     type: forall a. a -> a     workInfo: Never - Primitive:-    name: GHC.Magic.runRW#+    name: ["GHC.Magic.runRW#", "GHC.Internal.Magic.runRW#"]     primType: Function     workInfo: Never
prims/common/GHC_Num_Integer.primitives.yaml view
@@ -1,32 +1,32 @@ - Primitive:-    name: GHC.Num.Integer.IS+    name: ["GHC.Num.Integer.IS", "GHC.Internal.Bignum.Integer.IS"]     comment: Needed to make the evaluator handle this constructor strictly     primType: Constructor     warning: 'GHC.Num.Integer.IS: Integers are dynamically sized in simulation, but       fixed-length after synthesis. Use carefully.'     workInfo: Never - Primitive:-    name: GHC.Num.Integer.IP+    name: ["GHC.Num.Integer.IP", "GHC.Internal.Bignum.Integer.IP"]     comment: Needed to make the evaluator handle this constructor strictly     primType: Constructor     warning: 'GHC.Num.Integer.IP: Integers are dynamically sized in simulation, but       fixed-length after synthesis. Use carefully.'     workInfo: Never - Primitive:-    name: GHC.Num.Integer.IN+    name: ["GHC.Num.Integer.IN", "GHC.Internal.Bignum.Integer.IN"]     comment: Needed to make the evaluator handle this constructor strictly     primType: Constructor     warning: 'GHC.Num.Integer.IN: Integers are dynamically sized in simulation, but       fixed-length after synthesis. Use carefully.'     workInfo: Never - Primitive:-    name: GHC.Num.Integer.integerFromNatural+    name: ["GHC.Num.Integer.integerFromNatural", "GHC.Internal.Bignum.Integer.integerFromNatural"]     primType: Function     warning: 'GHC.Num.Integer.integerFromNatural: No blackbox available without size       inference for Natural and Integer'     workInfo: Never - BlackBox:-    name: GHC.Num.Integer.integerAdd+    name: ["GHC.Num.Integer.integerAdd", "GHC.Internal.Bignum.Integer.integerAdd"]     kind: Expression     type: 'integerAdd :: Integer       -> Integer -> Integer'@@ -34,7 +34,7 @@     warning: 'GHC.Num.Integer.integerAdd: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerSub+    name: ["GHC.Num.Integer.integerSub", "GHC.Internal.Bignum.Integer.integerSub"]     kind: Expression     type: 'integerSub :: Integer       -> Integer -> Integer'@@ -42,7 +42,7 @@     warning: 'GHC.Num.Integer.integerSub: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerLe+    name: ["GHC.Num.Integer.integerLe", "GHC.Internal.Bignum.Integer.integerLe"]     kind: Expression     type: 'integerLe :: Integer       -> Integer -> Bool'@@ -50,7 +50,7 @@     warning: 'GHC.Num.Integer.integerLe: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerGt+    name: ["GHC.Num.Integer.integerGt", "GHC.Internal.Bignum.Integer.integerGt"]     kind: Expression     type: 'integerGt :: Integer       -> Integer -> Bool'@@ -58,7 +58,7 @@     warning: 'GHC.Num.Integer.integerGt: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerLt+    name: ["GHC.Num.Integer.integerLt", "GHC.Internal.Bignum.Integer.integerLt"]     kind: Expression     type: 'integerLt :: Integer       -> Integer -> Bool'@@ -66,7 +66,7 @@     warning: 'GHC.Num.Integer.integerLt: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerGe+    name: ["GHC.Num.Integer.integerGe", "GHC.Internal.Bignum.Integer.integerGe"]     kind: Expression     type: 'integerGe :: Integer       -> Integer -> Bool'
prims/common/GHC_Num_Natural.primitives.yaml view
@@ -1,19 +1,19 @@ - Primitive:-    name: GHC.Num.Natural.NS+    name: ["GHC.Num.Natural.NS", "GHC.Internal.Bignum.Natural.NS"]     comment: Needed to make the evaluator handle this constructor strictly     primType: Constructor     warning: 'GHC.Num.Natural.NS: Naturals are dynamically sized in simulation, but       fixed-length after synthesis. Use carefully.'     workInfo: Never - Primitive:-    name: GHC.Num.Natural.NB+    name: ["GHC.Num.Natural.NB", "GHC.Internal.Bignum.Natural.NB"]     comment: Needed to make the evaluator handle this constructor strictly     primType: Constructor     warning: 'GHC.Num.Natural.NB: Naturals are dynamically sized in simulation, but       fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Natural.naturalAdd+    name: ["GHC.Num.Natural.naturalAdd", "GHC.Internal.Bignum.Natural.naturalAdd"]     kind: Expression     type: 'naturalSub :: Natural       -> Natural -> Natural'@@ -21,13 +21,13 @@     warning: 'GHC.Num.Natural.naturalAdd: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - Primitive:-    name: GHC.Num.Natural.naturalSub+    name: ["GHC.Num.Natural.naturalSub", "GHC.Internal.Bignum.Natural.naturalSub"]     primType: Function     warning: 'GHC.Num.Natural.naturalSub: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Natural.naturalSubUnsafe+    name: ["GHC.Num.Natural.naturalSubUnsafe", "GHC.Internal.Bignum.Natural.naturalSubUnsafe"]     kind: Expression     type: 'naturalSubUnsafe       :: Natural -> Natural -> Natural'@@ -35,7 +35,7 @@     warning: 'GHC.Num.Natural.naturalSubUnsafe: Naturals are dynamically sized in       simulation, but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalSubThrow+    name: ["GHC.Num.Natural.naturalSubThrow", "GHC.Internal.Bignum.Natural.naturalSubThrow"]     kind: Expression     type: 'naturalSubThrow       :: Natural -> Natural -> Natural'@@ -43,7 +43,7 @@     warning: 'GHC.Num.Natural.naturalSubThrow: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalMul+    name: ["GHC.Num.Natural.naturalMul", "GHC.Internal.Bignum.Natural.naturalMul"]     kind: Expression     type: 'naturalMul :: Natural       -> Natural -> Natural'@@ -51,13 +51,13 @@     warning: 'GHC.Num.Natural.naturalMul: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - Primitive:-    name: GHC.Num.Natural.naturalGcd+    name: ["GHC.Num.Natural.naturalGcd", "GHC.Internal.Bignum.Natural.naturalGcd"]     primType: Function     warning: 'GHC.Num.Natural.naturalGcd: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.'     workInfo: Never - Primitive:-    name: GHC.Num.Natural.naturalLcm+    name: ["GHC.Num.Natural.naturalLcm", "GHC.Internal.Bignum.Natural.naturalLcm"]     primType: Function     warning: 'GHC.Num.Natural.naturalLcm: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.'
prims/common/GHC_Prim.primitives.yaml view
@@ -1,107 +1,107 @@ - Primitive:-    name: GHC.Prim.dataToTag#+    name: ["GHC.Prim.dataToTag#", "GHC.Internal.Prim.dataToTag#"]     primType: Function - Primitive:-    name: GHC.Prim.dataToTagSmall#+    name: ["GHC.Prim.dataToTagSmall#", "GHC.Internal.Prim.dataToTagSmall#"]     primType: Function - Primitive:-    name: GHC.Prim.dataToTagLarge#+    name: ["GHC.Prim.dataToTagLarge#", "GHC.Internal.Prim.dataToTagLarge#"]     primType: Function - Primitive:-    name: GHC.Prim.tagToEnum#+    name: ["GHC.Prim.tagToEnum#", "GHC.Internal.Prim.tagToEnum#"]     primType: Function - BlackBox:-    name: GHC.Prim.unsafeCoerce#+    name: ["GHC.Prim.unsafeCoerce#", "GHC.Internal.Prim.unsafeCoerce#"]     kind: Expression     type: 'unsafeCoerce# ::       a -> b'     template: ~ARG[0]     workInfo: Never - BlackBox:-    name: GHC.Prim.+#+    name: ["GHC.Prim.+#", "GHC.Internal.Prim.+#"]     kind: Expression     type: '(+#) :: Int# ->       Int# -> Int#'     template: ~ARG[0] + ~ARG[1] - BlackBox:-    name: GHC.Prim.plusInt8#+    name: ["GHC.Prim.plusInt8#", "GHC.Internal.Prim.plusInt8#"]     kind: Expression     template: ~ARG[0] + ~ARG[1] - BlackBox:-    name: GHC.Prim.plusInt16#+    name: ["GHC.Prim.plusInt16#", "GHC.Internal.Prim.plusInt16#"]     kind: Expression     template: ~ARG[0] + ~ARG[1] - BlackBox:-    name: GHC.Prim.plusInt32#+    name: ["GHC.Prim.plusInt32#", "GHC.Internal.Prim.plusInt32#"]     kind: Expression     template: ~ARG[0] + ~ARG[1] - BlackBox:-    name: GHC.Prim.plusInt64#+    name: ["GHC.Prim.plusInt64#", "GHC.Internal.Prim.plusInt64#"]     kind: Expression     template: ~ARG[0] + ~ARG[1] - BlackBox:-    name: GHC.Prim.-#+    name: ["GHC.Prim.-#", "GHC.Internal.Prim.-#"]     kind: Expression     type: '(-#) :: Int# ->       Int# -> Int#'     template: ~ARG[0] - ~ARG[1] - BlackBox:-    name: GHC.Prim.subInt8#+    name: ["GHC.Prim.subInt8#", "GHC.Internal.Prim.subInt8#"]     kind: Expression     template: ~ARG[0] - ~ARG[1] - BlackBox:-    name: GHC.Prim.subInt16#+    name: ["GHC.Prim.subInt16#", "GHC.Internal.Prim.subInt16#"]     kind: Expression     template: ~ARG[0] - ~ARG[1] - BlackBox:-    name: GHC.Prim.subInt32#+    name: ["GHC.Prim.subInt32#", "GHC.Internal.Prim.subInt32#"]     kind: Expression     template: ~ARG[0] - ~ARG[1] - BlackBox:-    name: GHC.Prim.subInt64#+    name: ["GHC.Prim.subInt64#", "GHC.Internal.Prim.subInt64#"]     kind: Expression     template: ~ARG[0] - ~ARG[1] - BlackBox:-    name: GHC.Prim.plusWord#+    name: ["GHC.Prim.plusWord#", "GHC.Internal.Prim.plusWord#"]     kind: Expression     type: 'plusWord# :: Word#       -> Word# -> Word#'     template: ~ARG[0] + ~ARG[1] - BlackBox:-    name: GHC.Prim.plusWord8#+    name: ["GHC.Prim.plusWord8#", "GHC.Internal.Prim.plusWord8#"]     kind: Expression     template: ~ARG[0] + ~ARG[1] - BlackBox:-    name: GHC.Prim.plusWord16#+    name: ["GHC.Prim.plusWord16#", "GHC.Internal.Prim.plusWord16#"]     kind: Expression     template: ~ARG[0] + ~ARG[1] - BlackBox:-    name: GHC.Prim.plusWord32#+    name: ["GHC.Prim.plusWord32#", "GHC.Internal.Prim.plusWord32#"]     kind: Expression     template: ~ARG[0] + ~ARG[1] - BlackBox:-    name: GHC.Prim.plusWord64#+    name: ["GHC.Prim.plusWord64#", "GHC.Internal.Prim.plusWord64#"]     kind: Expression     template: ~ARG[0] + ~ARG[1] - BlackBox:-    name: GHC.Prim.minusWord#+    name: ["GHC.Prim.minusWord#", "GHC.Internal.Prim.minusWord#"]     kind: Expression     type: 'minusWord# :: Word#       -> Word# -> Word#'     template: ~ARG[0] - ~ARG[1] - BlackBox:-    name: GHC.Prim.subWord8#+    name: ["GHC.Prim.subWord8#", "GHC.Internal.Prim.subWord8#"]     kind: Expression     template: ~ARG[0] - ~ARG[1] - BlackBox:-    name: GHC.Prim.subWord16#+    name: ["GHC.Prim.subWord16#", "GHC.Internal.Prim.subWord16#"]     kind: Expression     template: ~ARG[0] - ~ARG[1] - BlackBox:-    name: GHC.Prim.subWord32#+    name: ["GHC.Prim.subWord32#", "GHC.Internal.Prim.subWord32#"]     kind: Expression     template: ~ARG[0] - ~ARG[1] - BlackBox:-    name: GHC.Prim.subWord64#+    name: ["GHC.Prim.subWord64#", "GHC.Internal.Prim.subWord64#"]     kind: Expression     template: ~ARG[0] - ~ARG[1]
prims/common/GHC_Prim_Panic.primitives.yaml view
@@ -1,5 +1,5 @@ - BlackBox:-    name: GHC.Prim.Panic.absentError+    name: ["GHC.Prim.Panic.absentError", "GHC.Internal.Prim.Panic.absentError"]     kind: Expression     type: 'absentError ::       Addr# -> a'
prims/common/GHC_TypeNats.primitives.yaml view
@@ -1,17 +1,17 @@ - BlackBox:-    name: GHC.TypeNats.natVal+    name: ["GHC.TypeNats.natVal", "GHC.Internal.TypeNats.natVal"]     kind: Expression     type: 'natVal :: forall       n proxy. KnownNat n => proxy n -> Natural'     template: ~ARG[0]     workInfo: Never - Primitive:-    name: GHC.TypeNats.someNatVal+    name: ["GHC.TypeNats.someNatVal", "GHC.Internal.TypeNats.someNatVal"]     primType: Function     type: 'someNatVal :: Natural -> SomeNat'     workInfo: Never - Primitive:-    name: GHC.TypeNats.withSomeSNat+    name: ["GHC.TypeNats.withSomeSNat", "GHC.Internal.TypeNats.withSomeSNat"]     primType: Function     type: 'withSomeSNat :: forall rep (r :: TYPE rep). Natural -> (forall n. SNat n -> r) -> r'     workInfo: Never
prims/common/GHC_Types.primitives.yaml view
@@ -1,16 +1,16 @@ - Primitive:-    name: GHC.Types.MkCoercible+    name: ["GHC.Types.MkCoercible", "GHC.Internal.Types.MkCoercible"]     primType: Constructor     workInfo: Never - BlackBox:-    name: GHC.Types.I#+    name: ["GHC.Types.I#", "GHC.Internal.Types.I#"]     kind: Expression     comment: Needed to make the evaluator handle this constructor strictly     type: 'I# :: Int# -> Int'     template: ~ARG[0]     workInfo: Never - BlackBox:-    name: GHC.Types.W#+    name: ["GHC.Types.W#", "GHC.Internal.Types.W#"]     kind: Expression     comment: Needed to make the evaluator handle this constructor strictly     type: 'W# :: Word# -> Word'
prims/commonverilog/Clash_Sized_Internal_Index.primitives.yaml view
@@ -102,19 +102,19 @@     kind: Declaration     type: Index m -> Index       n -> Index (m + n - 1)-    template: assign ~RESULT = ~ARG[0] + ~ARG[1];+    template: assign ~RESULT = ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THEN~ARG[0] + ~ARG[1]~ELSE~IF~SIZE[~TYP[0]]~THEN~ARG[0]~ELSE~ARG[1]~FI~FI; - BlackBox:     name: Clash.Sized.Internal.Index.minus#     kind: Declaration     type: Index m -> Index       n -> Index (m + n - 1)-    template: assign ~RESULT = ~ARG[0] - ~ARG[1];+    template: assign ~RESULT = ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THEN~ARG[0] - ~ARG[1]~ELSE~IF~SIZE[~TYP[0]]~THEN~ARG[0]~ELSE-~ARG[1]~FI~FI; - BlackBox:     name: Clash.Sized.Internal.Index.times#     kind: Declaration     type: Index m -> Index       n -> Index (((m-1) * (n-1)) + 1)-    template: assign ~RESULT = ~ARG[0] * ~ARG[1];+    template: assign ~RESULT = ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THEN~ARG[0] * ~ARG[1]~ELSE~SIZE[~TYPO]'d0~FI; - BlackBox:     name: Clash.Sized.Internal.Index.rem#     kind: Expression
prims/commonverilog/GHC_Classes.primitives.yaml view
@@ -1,29 +1,29 @@ - BlackBox:-    name: GHC.Classes.eqInt+    name: ["GHC.Classes.eqInt", "GHC.Internal.Classes.eqInt"]     kind: Expression     type: 'eqInt :: Int ->       Int -> Bool'     template: ~ARG[0] == ~ARG[1] - BlackBox:-    name: GHC.Classes.neInt+    name: ["GHC.Classes.neInt", "GHC.Internal.Classes.neInt"]     kind: Expression     type: 'neInt :: Int ->       Int -> Bool'     template: ~ARG[0] != ~ARG[1] - BlackBox:-    name: GHC.Classes.&&+    name: ["GHC.Classes.&&", "GHC.Internal.Classes.&&"]     kind: Expression     type: '(&&) :: Bool ->       Bool -> Bool'     template: ~ARG[0] & ~ARG[1] - BlackBox:-    name: GHC.Classes.||+    name: ["GHC.Classes.||", "GHC.Internal.Classes.||"]     kind: Expression     type: '(||) :: Bool ->       Bool -> Bool'     template: ~ARG[0] | ~ARG[1] - BlackBox:-    name: GHC.Classes.not+    name: ["GHC.Classes.not", "GHC.Internal.Classes.not"]     kind: Expression     type: 'not :: Bool ->       Bool'
prims/commonverilog/GHC_Num_Integer.primitives.yaml view
@@ -1,5 +1,5 @@ - BlackBox:-    name: GHC.Num.Integer.integerToNatural+    name: ["GHC.Num.Integer.integerToNatural", "GHC.Internal.Bignum.Integer.integerToNatural"]     kind: Expression     type: 'integerToNatural       :: Integer -> Natural'@@ -8,7 +8,7 @@       simulation, but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Integer.integerToNaturalThrow+    name: ["GHC.Num.Integer.integerToNaturalThrow", "GHC.Internal.Bignum.Integer.integerToNaturalThrow"]     kind: Expression     type: 'integerToNaturalThrow       :: Integer -> Natural'@@ -17,7 +17,7 @@       in simulation, but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Integer.integerToNaturalClamp+    name: ["GHC.Num.Integer.integerToNaturalClamp", "GHC.Internal.Bignum.Integer.integerToNaturalClamp"]     kind: Expression     type: 'integerToNatural       :: Integer -> Natural'@@ -26,7 +26,7 @@       in simulation, but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Integer.integerToInt#+    name: ["GHC.Num.Integer.integerToInt#", "GHC.Internal.Bignum.Integer.integerToInt#"]     kind: Declaration     type: 'integerToInt ::       Integer -> Int#'@@ -35,7 +35,7 @@       but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Integer.integerMul+    name: ["GHC.Num.Integer.integerMul", "GHC.Internal.Bignum.Integer.integerMul"]     kind: Expression     type: 'integerMul :: Integer       -> Integer -> Integer'@@ -43,7 +43,7 @@     warning: 'GHC.Num.Integer.integerMul: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerNegate+    name: ["GHC.Num.Integer.integerNegate", "GHC.Internal.Bignum.Integer.integerNegate"]     kind: Expression     type: 'integerNegate ::       Integer -> Integer'@@ -51,7 +51,7 @@     warning: 'GHC.Num.Integer.integerNegate: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerAbs+    name: ["GHC.Num.Integer.integerAbs", "GHC.Internal.Bignum.Integer.integerAbs"]     kind: Expression     type: 'integerAbs :: Integer       -> Integer'@@ -59,7 +59,7 @@     warning: 'GHC.Num.Integer.integerAbs: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerRem+    name: ["GHC.Num.Integer.integerRem", "GHC.Internal.Bignum.Integer.integerRem"]     kind: Expression     type: 'integerRem :: Integer       -> Integer -> Integer'@@ -67,7 +67,7 @@     warning: 'GHC.Num.Integer.integerRem: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerEq+    name: ["GHC.Num.Integer.integerEq", "GHC.Internal.Bignum.Integer.integerEq"]     kind: Expression     type: 'integerEq :: Integer       -> Integer -> Bool'@@ -75,7 +75,7 @@     warning: 'GHC.Num.Integer.integerEq: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerNe+    name: ["GHC.Num.Integer.integerNe", "GHC.Internal.Bignum.Integer.integerNe"]     kind: Expression     type: 'integerNe :: Integer       -> Integer -> Bool'@@ -83,7 +83,7 @@     warning: 'GHC.Num.Integer.integerNe: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerEq#+    name: ["GHC.Num.Integer.integerEq#", "GHC.Internal.Bignum.Integer.integerEq#"]     kind: Expression     type: 'integerEq :: Integer       -> Integer -> Int#'@@ -91,7 +91,7 @@     warning: 'GHC.Num.Integer.integerEq#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerNe#+    name: ["GHC.Num.Integer.integerNe#", "GHC.Internal.Bignum.Integer.integerNe#"]     kind: Expression     type: 'integerNe# :: Integer       -> Integer -> Int#'@@ -99,7 +99,7 @@     warning: 'GHC.Num.Integer.integerNe#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerLe#+    name: ["GHC.Num.Integer.integerLe#", "GHC.Internal.Bignum.Integer.integerLe#"]     kind: Expression     type: 'integerLe :: Integer       -> Integer -> Int#'@@ -107,7 +107,7 @@     warning: 'GHC.Num.Integer.integerLe#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerGt#+    name: ["GHC.Num.Integer.integerGt#", "GHC.Internal.Bignum.Integer.integerGt#"]     kind: Expression     type: 'integerGt# :: Integer       -> Integer -> Int#'@@ -115,7 +115,7 @@     warning: 'GHC.Num.Integer.integerGt#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerLt#+    name: ["GHC.Num.Integer.integerLt#", "GHC.Internal.Bignum.Integer.integerLt#"]     kind: Expression     type: 'integerLt# :: Integer       -> Integer -> Int#'@@ -123,7 +123,7 @@     warning: 'GHC.Num.Integer.integerLt#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerGe#+    name: ["GHC.Num.Integer.integerGe#", "GHC.Internal.Bignum.Integer.integerGe#"]     kind: Expression     type: 'integerGe# :: Integer       -> Integer -> Int#'@@ -131,7 +131,7 @@     warning: 'GHC.Num.Integer.integerGe#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerShiftR#+    name: ["GHC.Num.Integer.integerShiftR#", "GHC.Internal.Bignum.Integer.integerShiftR#"]     kind: Expression     type: 'integerShiftR ::       Integer -> Word# -> Integer'@@ -139,7 +139,7 @@     warning: 'GHC.Num.Integer.integerShiftR#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerShiftL#+    name: ["GHC.Num.Integer.integerShiftL#", "GHC.Internal.Bignum.Integer.integerShiftL#"]     kind: Expression     type: 'integerShiftL ::       Integer -> Word# -> Integer'@@ -147,7 +147,7 @@     warning: 'GHC.Num.Integer.integerShiftL#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerTestBit#+    name: ["GHC.Num.Integer.integerTestBit#", "GHC.Internal.Bignum.Integer.integerTestBit#"]     kind: Expression     type: 'integerTestBit       :: Integer -> Word# -> Int#'@@ -155,7 +155,7 @@     warning: 'GHC.Num.Integer.integerTestBit#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerFromWord#+    name: ["GHC.Num.Integer.integerFromWord#", "GHC.Internal.Bignum.Integer.integerFromWord#"]     kind: Declaration     type: 'integerFromWord#       :: Word# -> Integer'@@ -164,7 +164,7 @@       simulation, but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Integer.integerToWord#+    name: ["GHC.Num.Integer.integerToWord#", "GHC.Internal.Bignum.Integer.integerToWord#"]     kind: Declaration     type: 'integerToWord#       :: Integer -> Word#'@@ -173,7 +173,7 @@       but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Integer.integerToInt64#+    name: ["GHC.Num.Integer.integerToInt64#", "GHC.Internal.Bignum.Integer.integerToInt64#"]     kind: Expression     type: 'integerToInt64#:: Integer -> Int64#'     template: ~ARG[0]@@ -181,7 +181,7 @@       simulation, but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Integer.integerToWord64#+    name: ["GHC.Num.Integer.integerToWord64#", "GHC.Internal.Bignum.Integer.integerToWord64#"]     comment: only used by 32 bit GHC     kind: Declaration     type: 'integerToWord64#@@ -191,7 +191,7 @@       simulation, but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Integer.integerFromWord64#+    name: ["GHC.Num.Integer.integerFromWord64#", "GHC.Internal.Bignum.Integer.integerFromWord64#"]     kind: Declaration     type: 'integerFromWord64# :: Word64# -> Integer'     template: assign ~RESULT = $signed(~ARG[0]);@@ -199,7 +199,7 @@       simulation, but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Integer.integerBit#+    name: ["GHC.Num.Integer.integerBit#", "GHC.Internal.Bignum.Integer.integerBit#"]     kind: Expression     type: 'integerBit# ::       Word# -> Integer'@@ -207,7 +207,7 @@     warning: 'GHC.Num.Integer.integerBit#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerComplement+    name: ["GHC.Num.Integer.integerComplement", "GHC.Internal.Bignum.Integer.integerComplement"]     kind: Expression     type: 'integerComplement       :: Integer -> Integer'@@ -215,7 +215,7 @@     warning: 'GHC.Num.Integer.integerComplement: Integers are dynamically sized in       simulation, but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerXor+    name: ["GHC.Num.Integer.integerXor", "GHC.Internal.Bignum.Integer.integerXor"]     kind: Expression     type: 'integerXor :: Integer       -> Integer -> Integer'@@ -223,7 +223,7 @@     warning: 'GHC.Num.Integer.integerXor: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerOr+    name: ["GHC.Num.Integer.integerOr", "GHC.Internal.Bignum.Integer.integerOr"]     kind: Expression     type: 'integerOr :: Integer       -> Integer -> Integer'@@ -231,7 +231,7 @@     warning: 'GHC.Num.Integer.integerOr: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerAnd+    name: ["GHC.Num.Integer.integerAnd", "GHC.Internal.Bignum.Integer.integerAnd"]     kind: Expression     type: 'andInteger :: Integer       -> Integer -> Integer'@@ -239,7 +239,7 @@     warning: 'GHC.Num.Integer.integerAnd: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerSignum+    name: ["GHC.Num.Integer.integerSignum", "GHC.Internal.Bignum.Integer.integerSignum"]     kind: Expression     type: 'integerSignum ::       Integer -> Integer'@@ -248,7 +248,7 @@     warning: 'GHC.Num.Integer.integerSignum: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.$wintegerSignum+    name: ["GHC.Num.Integer.$wintegerSignum", "GHC.Internal.Bignum.Integer.$wintegerSignum"]     kind: Expression     type: 'integerSignum ::       Integer -> Int#'@@ -257,7 +257,7 @@     warning: 'GHC.Num.Integer.$wintegerSignum: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerLogBase#+    name: ["GHC.Num.Integer.integerLogBase#", "GHC.Internal.Bignum.Integer.integerLogBase#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -279,7 +279,7 @@     warning: 'GHC.Num.Integer.integerLogBase#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerCompare+    name: ["GHC.Num.Integer.integerCompare", "GHC.Internal.Bignum.Integer.integerCompare"]     kind: Expression     type: 'integerCompare       :: Integer -> Integer -> Ordering'@@ -288,7 +288,7 @@     warning: 'GHC.Num.Integer.integerCompare: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerQuot+    name: ["GHC.Num.Integer.integerQuot", "GHC.Internal.Bignum.Integer.integerQuot"]     kind: Expression     type: 'integerQuot ::       Integer -> Integer -> Integer'@@ -296,7 +296,7 @@     warning: 'GHC.Num.Integer.integerQuot: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.$wintegerFromInt64#+    name: ["GHC.Num.Integer.$wintegerFromInt64#", "GHC.Internal.Bignum.Integer.$wintegerFromInt64#"]     kind: Declaration     type: '$wintegerFromInt64# :: Int64# -> Int#'     template: |-
prims/commonverilog/GHC_Num_Natural.primitives.yaml view
@@ -1,5 +1,5 @@ - BlackBox:-    name: GHC.Num.Natural.naturalMul+    name: ["GHC.Num.Natural.naturalMul", "GHC.Internal.Bignum.Natural.naturalMul"]     kind: Expression     type: 'naturalMul :: Natural       -> Natural -> Natural'@@ -7,7 +7,7 @@     warning: 'GHC.Num.Natural.naturalMul: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalFromWord#+    name: ["GHC.Num.Natural.naturalFromWord#", "GHC.Internal.Bignum.Natural.naturalFromWord#"]     kind: Declaration     type: 'naturalFromWord#       :: Word# -> Natural'@@ -16,7 +16,7 @@       simulation, but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Natural.naturalRem+    name: ["GHC.Num.Natural.naturalRem", "GHC.Internal.Bignum.Natural.naturalRem"]     kind: Expression     type: 'naturalRem :: Natural       -> Natural -> Natural'@@ -24,7 +24,7 @@     warning: 'GHC.Num.Natural.naturalRem: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalLogBase#+    name: ["GHC.Num.Natural.naturalLogBase#", "GHC.Internal.Bignum.Natural.naturalLogBase#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -46,7 +46,7 @@     warning: 'GHC.Num.Natural.naturalLogBase#: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalEq#+    name: ["GHC.Num.Natural.naturalEq#", "GHC.Internal.Bignum.Natural.naturalEq#"]     kind: Expression     type: 'naturalEq :: Natural       -> Natural -> Int#'@@ -54,7 +54,7 @@     warning: 'GHC.Num.Natural.naturalEq#: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalNe#+    name: ["GHC.Num.Natural.naturalNe#", "GHC.Internal.Bignum.Natural.naturalNe#"]     kind: Expression     type: 'naturalNe# :: Natural       -> Natural -> Int#'@@ -62,7 +62,7 @@     warning: 'GHC.Num.Natural.naturalNe#: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalLe#+    name: ["GHC.Num.Natural.naturalLe#", "GHC.Internal.Bignum.Natural.naturalLe#"]     kind: Expression     type: 'naturalLe :: Natural       -> Natural -> Int#'@@ -70,7 +70,7 @@     warning: 'GHC.Num.Natural.naturalLe#: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalGt#+    name: ["GHC.Num.Natural.naturalGt#", "GHC.Internal.Bignum.Natural.naturalGt#"]     kind: Expression     type: 'naturalGt# :: Natural       -> Natural -> Int#'@@ -78,7 +78,7 @@     warning: 'GHC.Num.Natural.naturalGt#: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalLt#+    name: ["GHC.Num.Natural.naturalLt#", "GHC.Internal.Bignum.Natural.naturalLt#"]     kind: Expression     type: 'naturalLt# :: Natural       -> Natural -> Int#'@@ -86,7 +86,7 @@     warning: 'GHC.Num.Natural.naturalLt#: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalGe#+    name: ["GHC.Num.Natural.naturalGe#", "GHC.Internal.Bignum.Natural.naturalGe#"]     kind: Expression     type: 'naturalGe# :: Natural       -> Natural -> Int#'@@ -94,7 +94,7 @@     warning: 'GHC.Num.Natural.naturalGe#: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalShiftL#+    name: ["GHC.Num.Natural.naturalShiftL#", "GHC.Internal.Bignum.Natural.naturalShiftL#"]     kind: Expression     type: 'naturalShiftL#       :: Natural -> Word# -> Natural'@@ -102,7 +102,7 @@     warning: 'GHC.Num.Natural.naturalShiftL#: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalShiftR#+    name: ["GHC.Num.Natural.naturalShiftR#", "GHC.Internal.Bignum.Natural.naturalShiftR#"]     kind: Expression     type: 'naturalShiftR#       :: Natuarl -> Word# -> Natural'@@ -110,7 +110,7 @@     warning: 'GHC.Num.Natural.naturalShiftR#: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.NaturalCompare+    name: ["GHC.Num.Natural.NaturalCompare", "GHC.Internal.Bignum.Natural.NaturalCompare"]     kind: Expression     type: 'naturalCompare       :: Natural -> Natural -> Ordering'@@ -119,7 +119,7 @@     warning: 'GHC.Num.Natural.naturalCompare: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalQuot+    name: ["GHC.Num.Natural.naturalQuot", "GHC.Internal.Bignum.Natural.naturalQuot"]     kind: Expression     type: 'naturalQuot ::       Natural -> Natural -> Natural'
prims/commonverilog/GHC_Prim.primitives.yaml view
@@ -1,247 +1,247 @@ - BlackBox:-    name: GHC.Prim.gtChar#+    name: ["GHC.Prim.gtChar#", "GHC.Internal.Prim.gtChar#"]     kind: Expression     type: 'gtChar# :: Char#       -> Char# -> Int#'     template: '(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0' - BlackBox:-    name: GHC.Prim.geChar#+    name: ["GHC.Prim.geChar#", "GHC.Internal.Prim.geChar#"]     kind: Expression     type: 'geChar# :: Char#       -> Char# -> Int#'     template: '(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0' - BlackBox:-    name: GHC.Prim.eqChar#+    name: ["GHC.Prim.eqChar#", "GHC.Internal.Prim.eqChar#"]     kind: Expression     type: 'eqChar# :: Char#       -> Char# -> Int#'     template: '(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0' - BlackBox:-    name: GHC.Prim.neChar#+    name: ["GHC.Prim.neChar#", "GHC.Internal.Prim.neChar#"]     kind: Expression     type: 'neChar# :: Char#       -> Char# -> Int#'     template: '(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0' - BlackBox:-    name: GHC.Prim.ltChar#+    name: ["GHC.Prim.ltChar#", "GHC.Internal.Prim.ltChar#"]     kind: Expression     type: 'ltChar# :: Char#       -> Char# -> Int#'     template: '(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0' - BlackBox:-    name: GHC.Prim.leChar#+    name: ["GHC.Prim.leChar#", "GHC.Internal.Prim.leChar#"]     kind: Expression     type: 'leChar# :: Char#       -> Char# -> Int#'     template: '(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0' - BlackBox:-    name: GHC.Prim.ord#+    name: ["GHC.Prim.ord#", "GHC.Internal.Prim.ord#"]     kind: Expression     type: 'ord :: Char# ->       Int#'     template: $signed({{(~SIZE[~TYPO]-~SIZE[~TYP[0]]) {1'b0}},~VAR[c][0]}) - BlackBox:-    name: GHC.Prim.*#+    name: ["GHC.Prim.*#", "GHC.Internal.Prim.*#"]     kind: Expression     type: '(*#) :: Int# ->       Int# -> Int#'     template: ~ARG[0] * ~ARG[1] - BlackBox:-    name: GHC.Prim.remInt#+    name: ["GHC.Prim.remInt#", "GHC.Internal.Prim.remInt#"]     kind: Expression     type: 'remInt# :: Int#       -> Int# -> Int#'     template: ~ARG[0] % ~ARG[1] - BlackBox:-    name: GHC.Prim.andI#+    name: ["GHC.Prim.andI#", "GHC.Internal.Prim.andI#"]     kind: Expression     type: 'andI# :: Int# ->       Int# -> Int#'     template: ~ARG[0] & ~ARG[1] - BlackBox:-    name: GHC.Prim.orI#+    name: ["GHC.Prim.orI#", "GHC.Internal.Prim.orI#"]     kind: Expression     type: 'orI# :: Int# ->       Int# -> Int#'     template: ~ARG[0] | ~ARG[1] - BlackBox:-    name: GHC.Prim.xorI#+    name: ["GHC.Prim.xorI#", "GHC.Internal.Prim.xorI#"]     kind: Expression     type: 'xorI# :: Int# ->       Int# -> Int#'     template: ~ARG[0] ^ ~ARG[1] - BlackBox:-    name: GHC.Prim.notI#+    name: ["GHC.Prim.notI#", "GHC.Internal.Prim.notI#"]     kind: Expression     type: 'notI# :: Int# ->       Int#'     template: ~ ~ARG[0] - BlackBox:-    name: GHC.Prim.negateInt#+    name: ["GHC.Prim.negateInt#", "GHC.Internal.Prim.negateInt#"]     kind: Expression     type: 'negateInt# :: Int#       -> Int#'     template: -(~ARG[0]) - BlackBox:-    name: GHC.Prim.>#+    name: ["GHC.Prim.>#", "GHC.Internal.Prim.>#"]     kind: Expression     type: '(>#) :: Int# ->       Int# -> Int#'     template: '(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0' - BlackBox:-    name: GHC.Prim.>=#+    name: ["GHC.Prim.>=#", "GHC.Internal.Prim.>=#"]     kind: Expression     type: '(>=#) :: Int# ->       Int# -> Int#'     template: '(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0' - BlackBox:-    name: GHC.Prim.==#+    name: ["GHC.Prim.==#", "GHC.Internal.Prim.==#"]     kind: Expression     type: '(==) :: Int# ->       Int# -> Int#'     template: '(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0' - BlackBox:-    name: GHC.Prim./=#+    name: ["GHC.Prim./=#", "GHC.Internal.Prim./=#"]     kind: Expression     type: '(/=#) :: Int# ->       Int# -> Int#'     template: '(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0' - BlackBox:-    name: GHC.Prim.<#+    name: ["GHC.Prim.<#", "GHC.Internal.Prim.<#"]     kind: Expression     type: '(<#) :: Int# ->       Int# -> Int#'     template: '(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0' - BlackBox:-    name: GHC.Prim.<=#+    name: ["GHC.Prim.<=#", "GHC.Internal.Prim.<=#"]     kind: Expression     type: '(<=#) :: Int# ->       Int# -> Int#'     template: '(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0' - BlackBox:-    name: GHC.Prim.chr#+    name: ["GHC.Prim.chr#", "GHC.Internal.Prim.chr#"]     kind: Expression     type: 'ord :: Int# ->       Char#'     template: $unsigned(~VAR[i][0][0+:~SIZE[~TYPO]]) - BlackBox:-    name: GHC.Prim.int2Word#+    name: ["GHC.Prim.int2Word#", "GHC.Internal.Prim.int2Word#"]     kind: Expression     type: 'int2Word# :: Int#       -> Word#'     template: $unsigned(~ARG[0])     workInfo: Never - BlackBox:-    name: GHC.Prim.uncheckedIShiftL#+    name: ["GHC.Prim.uncheckedIShiftL#", "GHC.Internal.Prim.uncheckedIShiftL#"]     kind: Expression     type: 'uncheckedIShiftL#       :: Int# -> Int# -> Int#'     template: ~ARG[0] <<< ~ARG[1] - BlackBox:-    name: GHC.Prim.uncheckedIShiftRA#+    name: ["GHC.Prim.uncheckedIShiftRA#", "GHC.Internal.Prim.uncheckedIShiftRA#"]     kind: Expression     type: 'uncheckedIShiftRA#       :: Int# -> Int# -> Int#'     template: ~ARG[0] >>> ~ARG[1] - BlackBox:-    name: GHC.Prim.uncheckedIShiftRL#+    name: ["GHC.Prim.uncheckedIShiftRL#", "GHC.Internal.Prim.uncheckedIShiftRL#"]     kind: Expression     type: 'uncheckedIShiftRL#       :: Int# -> Int# -> Int#'     template: ~ARG[0] >> ~ARG[1] - BlackBox:-    name: GHC.Prim.timesWord#+    name: ["GHC.Prim.timesWord#", "GHC.Internal.Prim.timesWord#"]     kind: Expression     type: 'timesWord# :: Word#       -> Word# -> Word#'     template: ~ARG[0] * ~ARG[1] - BlackBox:-    name: GHC.Prim.remWord#+    name: ["GHC.Prim.remWord#", "GHC.Internal.Prim.remWord#"]     kind: Expression     type: 'remWord# :: Word#       -> Word# -> Word#'     template: ~ARG[0] % ~ARG[1] - BlackBox:-    name: GHC.Prim.and#+    name: ["GHC.Prim.and#", "GHC.Internal.Prim.and#"]     kind: Expression     type: 'and# :: Word# ->       Word# -> Word#'     template: ~ARG[0] & ~ARG[1] - BlackBox:-    name: GHC.Prim.or#+    name: ["GHC.Prim.or#", "GHC.Internal.Prim.or#"]     kind: Expression     type: 'or# :: Word# ->       Word# -> Word#'     template: ~ARG[0] | ~ARG[1] - BlackBox:-    name: GHC.Prim.xor#+    name: ["GHC.Prim.xor#", "GHC.Internal.Prim.xor#"]     kind: Expression     type: 'xor# :: Word# ->       Word# -> Word#'     template: ~ARG[0] ^ ~ARG[1] - BlackBox:-    name: GHC.Prim.not#+    name: ["GHC.Prim.not#", "GHC.Internal.Prim.not#"]     kind: Expression     type: 'not# :: Word# ->       Word#'     template: ~ ~ARG[0] - BlackBox:-    name: GHC.Prim.uncheckedShiftL#+    name: ["GHC.Prim.uncheckedShiftL#", "GHC.Internal.Prim.uncheckedShiftL#"]     kind: Expression     type: 'uncheckedShiftL#       :: Word# -> Int# -> Word#'     template: ~ARG[0] << ~ARG[1] - BlackBox:-    name: GHC.Prim.uncheckedShiftRL#+    name: ["GHC.Prim.uncheckedShiftRL#", "GHC.Internal.Prim.uncheckedShiftRL#"]     kind: Expression     type: 'uncheckedShiftRL#       :: Word# -> Int# -> Word#'     template: ~ARG[0] >> ~ARG[1] - BlackBox:-    name: GHC.Prim.word2Int#+    name: ["GHC.Prim.word2Int#", "GHC.Internal.Prim.word2Int#"]     kind: Expression     type: 'int2Word# :: Word#       -> Int#'     template: $signed(~ARG[0])     workInfo: Never - BlackBox:-    name: GHC.Prim.gtWord#+    name: ["GHC.Prim.gtWord#", "GHC.Internal.Prim.gtWord#"]     kind: Expression     type: 'gtWord# :: Word#       -> Word# -> Int#'     template: '(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0' - BlackBox:-    name: GHC.Prim.geWord#+    name: ["GHC.Prim.geWord#", "GHC.Internal.Prim.geWord#"]     kind: Expression     type: 'geWord# :: Word#       -> Word# -> Int#'     template: '(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0' - BlackBox:-    name: GHC.Prim.eqWord#+    name: ["GHC.Prim.eqWord#", "GHC.Internal.Prim.eqWord#"]     kind: Expression     type: 'eqWord# :: Word#       -> Word# -> Int#'     template: '(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0' - BlackBox:-    name: GHC.Prim.neWord#+    name: ["GHC.Prim.neWord#", "GHC.Internal.Prim.neWord#"]     kind: Expression     type: 'neWord# :: Word#       -> Word# -> Int#'     template: '(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0' - BlackBox:-    name: GHC.Prim.ltWord#+    name: ["GHC.Prim.ltWord#", "GHC.Internal.Prim.ltWord#"]     kind: Expression     type: 'ltWord# :: Word#       -> Word# -> Int#'     template: '(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0' - BlackBox:-    name: GHC.Prim.leWord#+    name: ["GHC.Prim.leWord#", "GHC.Internal.Prim.leWord#"]     kind: Expression     type: 'leWord# :: Word#       -> Word# -> Int#'     template: '(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]''sd1 : ~SIZE[~TYPO]''sd0' - BlackBox:-    name: GHC.Prim.byteSwap16#+    name: ["GHC.Prim.byteSwap16#", "GHC.Internal.Prim.byteSwap16#"]     kind: Declaration     type: 'byteSwap16# ::       Word# -> Word#'@@ -252,7 +252,7 @@       // byteSwap16 end     workInfo: Never - BlackBox:-    name: GHC.Prim.byteSwap32#+    name: ["GHC.Prim.byteSwap32#", "GHC.Internal.Prim.byteSwap32#"]     kind: Declaration     type: 'byteSwap32# ::       Word# -> Word#'@@ -263,7 +263,7 @@       // byteSwap32 end     workInfo: Never - BlackBox:-    name: GHC.Prim.byteSwap64#+    name: ["GHC.Prim.byteSwap64#", "GHC.Internal.Prim.byteSwap64#"]     kind: Declaration     type: 'byteSwap64# ::       Word# -> Word#'@@ -274,7 +274,7 @@       // byteSwap64 end     workInfo: Never - BlackBox:-    name: GHC.Prim.byteSwap#+    name: ["GHC.Prim.byteSwap#", "GHC.Internal.Prim.byteSwap#"]     kind: Declaration     type: 'byteSwap# :: Word#       -> Word#'@@ -286,7 +286,7 @@       // byteSwap end     workInfo: Never - BlackBox:-    name: GHC.Prim.narrow8Int#+    name: ["GHC.Prim.narrow8Int#", "GHC.Internal.Prim.narrow8Int#"]     kind: Declaration     type: 'narrow8Int# ::       Int# -> Int#'@@ -296,7 +296,7 @@       // narrow8Int end     workInfo: Never - BlackBox:-    name: GHC.Prim.narrow16Int#+    name: ["GHC.Prim.narrow16Int#", "GHC.Internal.Prim.narrow16Int#"]     kind: Declaration     type: 'narrow16Int# ::       Int# -> Int#'@@ -306,7 +306,7 @@       // narrow16Int end     workInfo: Never - BlackBox:-    name: GHC.Prim.narrow32Int#+    name: ["GHC.Prim.narrow32Int#", "GHC.Internal.Prim.narrow32Int#"]     kind: Declaration     type: 'narrow32Int# ::       Int# -> Int#'@@ -316,7 +316,7 @@       // narrow32Int end     workInfo: Never - BlackBox:-    name: GHC.Prim.narrow8Word#+    name: ["GHC.Prim.narrow8Word#", "GHC.Internal.Prim.narrow8Word#"]     kind: Declaration     type: 'narrow8Int# ::       Word# -> Word#'@@ -326,7 +326,7 @@       // narrow8Word end     workInfo: Never - BlackBox:-    name: GHC.Prim.narrow16Word#+    name: ["GHC.Prim.narrow16Word#", "GHC.Internal.Prim.narrow16Word#"]     kind: Declaration     type: 'narrow16Word# ::       Word# -> Word#'@@ -336,7 +336,7 @@       // narrow16Word end     workInfo: Never - BlackBox:-    name: GHC.Prim.narrow32Word#+    name: ["GHC.Prim.narrow32Word#", "GHC.Internal.Prim.narrow32Word#"]     kind: Declaration     type: 'narrow32Int# ::       Word# -> Word#'@@ -346,7 +346,7 @@       // narrow32Word end     workInfo: Never - BlackBox:-    name: GHC.Prim.bitReverse#+    name: ["GHC.Prim.bitReverse#", "GHC.Internal.Prim.bitReverse#"]     kind: Declaration     type: 'bitReverse# ::       Word# -> Word#'@@ -361,7 +361,7 @@       // bitReverse end     workInfo: Never - BlackBox:-    name: GHC.Prim.bitReverse8#+    name: ["GHC.Prim.bitReverse8#", "GHC.Internal.Prim.bitReverse8#"]     kind: Declaration     type: 'bitReverse8# ::       Word# -> Word#'@@ -376,7 +376,7 @@       // bitReverse8 end     workInfo: Never - BlackBox:-    name: GHC.Prim.bitReverse16#+    name: ["GHC.Prim.bitReverse16#", "GHC.Internal.Prim.bitReverse16#"]     kind: Declaration     type: 'bitReverse16# ::       Word# -> Word#'@@ -391,7 +391,7 @@       // bitReverse16 end     workInfo: Never - BlackBox:-    name: GHC.Prim.bitReverse32#+    name: ["GHC.Prim.bitReverse32#", "GHC.Internal.Prim.bitReverse32#"]     kind: Declaration     type: 'bitReverse32# ::       Word# -> Word#'@@ -406,7 +406,7 @@       // bitReverse32 end     workInfo: Never - BlackBox:-    name: GHC.Prim.bitReverse64#+    name: ["GHC.Prim.bitReverse64#", "GHC.Internal.Prim.bitReverse64#"]     kind: Declaration     type: 'bitReverse64# ::       Word# -> Word#'@@ -421,19 +421,19 @@       // bitReverse64 end     workInfo: Never - BlackBox:-    name: GHC.Prim.quotInt#+    name: ["GHC.Prim.quotInt#", "GHC.Internal.Prim.quotInt#"]     kind: Expression     type: 'quotInt# :: Int#       -> Int# -> Int#'     template: ~ARG[0] / ~ARG[1] - BlackBox:-    name: GHC.Prim.quotWord#+    name: ["GHC.Prim.quotWord#", "GHC.Internal.Prim.quotWord#"]     kind: Expression     type: 'quotWord# :: Word#       -> Word# -> Word#'     template: ~ARG[0] / ~ARG[1] - BlackBox:-    name: GHC.Prim.int8ToInt#+    name: ["GHC.Prim.int8ToInt#", "GHC.Internal.Prim.int8ToInt#"]     kind: Declaration     template: |-       // int8ToInt begin@@ -441,7 +441,7 @@       // int8ToInt end     workInfo: Never - BlackBox:-    name: GHC.Prim.intToInt8#+    name: ["GHC.Prim.intToInt8#", "GHC.Internal.Prim.intToInt8#"]     kind: Declaration     template: |-       // intToInt8 begin@@ -449,64 +449,64 @@       // intToInt8 end     workInfo: Never - BlackBox:-    name: GHC.Prim.negateInt8#+    name: ["GHC.Prim.negateInt8#", "GHC.Internal.Prim.negateInt8#"]     kind: Expression     template: -(~ARG[0]) - BlackBox:-    name: GHC.Prim.timesInt8#+    name: ["GHC.Prim.timesInt8#", "GHC.Internal.Prim.timesInt8#"]     kind: Expression     template: ~ARG[0] * ~ARG[1] - BlackBox:-    name: GHC.Prim.quotInt8#+    name: ["GHC.Prim.quotInt8#", "GHC.Internal.Prim.quotInt8#"]     kind: Expression     template: ~ARG[0] / ~ARG[1] - BlackBox:-    name: GHC.Prim.remInt8#+    name: ["GHC.Prim.remInt8#", "GHC.Internal.Prim.remInt8#"]     kind: Expression     template: ~ARG[0] % ~ARG[1] - BlackBox:-    name: GHC.Prim.uncheckedShiftLInt8#+    name: ["GHC.Prim.uncheckedShiftLInt8#", "GHC.Internal.Prim.uncheckedShiftLInt8#"]     kind: Expression     template: ~ARG[0] <<< ~ARG[1] - BlackBox:-    name: GHC.Prim.uncheckedShiftRAInt8#+    name: ["GHC.Prim.uncheckedShiftRAInt8#", "GHC.Internal.Prim.uncheckedShiftRAInt8#"]     kind: Expression     template: ~ARG[0] >>> ~ARG[1] - BlackBox:-    name: GHC.Prim.uncheckedShiftRLInt8#+    name: ["GHC.Prim.uncheckedShiftRLInt8#", "GHC.Internal.Prim.uncheckedShiftRLInt8#"]     kind: Expression     template: ~ARG[0] >> ~ARG[1] - BlackBox:-    name: GHC.Prim.int8ToWord8#+    name: ["GHC.Prim.int8ToWord8#", "GHC.Internal.Prim.int8ToWord8#"]     kind: Expression     template: $unsigned(~ARG[0])     workInfo: Never - BlackBox:-    name: GHC.Prim.eqInt8#+    name: ["GHC.Prim.eqInt8#", "GHC.Internal.Prim.eqInt8#"]     kind: Expression     template: "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.geInt8#+    name: ["GHC.Prim.geInt8#", "GHC.Internal.Prim.geInt8#"]     kind: Expression     template: "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.gtInt8#+    name: ["GHC.Prim.gtInt8#", "GHC.Internal.Prim.gtInt8#"]     kind: Expression     template: "(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.leInt8#+    name: ["GHC.Prim.leInt8#", "GHC.Internal.Prim.leInt8#"]     kind: Expression     template: "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.ltInt8#+    name: ["GHC.Prim.ltInt8#", "GHC.Internal.Prim.ltInt8#"]     kind: Expression     template: "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.neInt8#+    name: ["GHC.Prim.neInt8#", "GHC.Internal.Prim.neInt8#"]     kind: Expression     template: "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.word8ToWord#+    name: ["GHC.Prim.word8ToWord#", "GHC.Internal.Prim.word8ToWord#"]     kind: Declaration     template: |-       // word8ToWord begin@@ -514,7 +514,7 @@       // word8ToWord end     workInfo: Never - BlackBox:-    name: GHC.Prim.wordToWord8#+    name: ["GHC.Prim.wordToWord8#", "GHC.Internal.Prim.wordToWord8#"]     kind: Declaration     template: |-       // wordToWord8 begin@@ -522,72 +522,72 @@       // wordToWord8 end     workInfo: Never - BlackBox:-    name: GHC.Prim.timesWord8#+    name: ["GHC.Prim.timesWord8#", "GHC.Internal.Prim.timesWord8#"]     kind: Expression     template: ~ARG[0] * ~ARG[1] - BlackBox:-    name: GHC.Prim.quotWord8#+    name: ["GHC.Prim.quotWord8#", "GHC.Internal.Prim.quotWord8#"]     kind: Expression     template: ~ARG[0] / ~ARG[1] - BlackBox:-    name: GHC.Prim.remWord8#+    name: ["GHC.Prim.remWord8#", "GHC.Internal.Prim.remWord8#"]     kind: Expression     template: ~ARG[0] % ~ARG[1] - BlackBox:-    name: GHC.Prim.andWord8#+    name: ["GHC.Prim.andWord8#", "GHC.Internal.Prim.andWord8#"]     kind: Expression     template: ~ARG[0] & ~ARG[1] - BlackBox:-    name: GHC.Prim.orWord8#+    name: ["GHC.Prim.orWord8#", "GHC.Internal.Prim.orWord8#"]     kind: Expression     template: ~ARG[0] | ~ARG[1] - BlackBox:-    name: GHC.Prim.xorWord8#+    name: ["GHC.Prim.xorWord8#", "GHC.Internal.Prim.xorWord8#"]     kind: Expression     template: ~ARG[0] ^ ~ARG[1] - BlackBox:-    name: GHC.Prim.notWord8#+    name: ["GHC.Prim.notWord8#", "GHC.Internal.Prim.notWord8#"]     kind: Expression     template: ~ ~ARG[0] - BlackBox:-    name: GHC.Prim.uncheckedShiftLWord8#+    name: ["GHC.Prim.uncheckedShiftLWord8#", "GHC.Internal.Prim.uncheckedShiftLWord8#"]     kind: Expression     template: ~ARG[0] << ~ARG[1] - BlackBox:-    name: GHC.Prim.uncheckedShiftRLWord8#+    name: ["GHC.Prim.uncheckedShiftRLWord8#", "GHC.Internal.Prim.uncheckedShiftRLWord8#"]     kind: Expression     template: ~ARG[0] >> ~ARG[1] - BlackBox:-    name: GHC.Prim.word8ToInt8#+    name: ["GHC.Prim.word8ToInt8#", "GHC.Internal.Prim.word8ToInt8#"]     kind: Expression     template: $signed(~ARG[0])     workInfo: Never - BlackBox:-    name: GHC.Prim.eqWord8#+    name: ["GHC.Prim.eqWord8#", "GHC.Internal.Prim.eqWord8#"]     kind: Expression     template: "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.geWord8#+    name: ["GHC.Prim.geWord8#", "GHC.Internal.Prim.geWord8#"]     kind: Expression     template: "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.gtWord8#+    name: ["GHC.Prim.gtWord8#", "GHC.Internal.Prim.gtWord8#"]     kind: Expression     template: "(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.leWord8#+    name: ["GHC.Prim.leWord8#", "GHC.Internal.Prim.leWord8#"]     kind: Expression     template: "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.ltWord8#+    name: ["GHC.Prim.ltWord8#", "GHC.Internal.Prim.ltWord8#"]     kind: Expression     template: "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.neWord8#+    name: ["GHC.Prim.neWord8#", "GHC.Internal.Prim.neWord8#"]     kind: Expression     template: "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.int16ToInt#+    name: ["GHC.Prim.int16ToInt#", "GHC.Internal.Prim.int16ToInt#"]     kind: Declaration     template: |-       // int16ToInt begin@@ -595,7 +595,7 @@       // int16ToInt end     workInfo: Never - BlackBox:-    name: GHC.Prim.intToInt16#+    name: ["GHC.Prim.intToInt16#", "GHC.Internal.Prim.intToInt16#"]     kind: Declaration     template: |-       // intToInt16 begin@@ -603,64 +603,64 @@       // intToInt16 end     workInfo: Never - BlackBox:-    name: GHC.Prim.negateInt16#+    name: ["GHC.Prim.negateInt16#", "GHC.Internal.Prim.negateInt16#"]     kind: Expression     template: -(~ARG[0]) - BlackBox:-    name: GHC.Prim.timesInt16#+    name: ["GHC.Prim.timesInt16#", "GHC.Internal.Prim.timesInt16#"]     kind: Expression     template: ~ARG[0] * ~ARG[1] - BlackBox:-    name: GHC.Prim.quotInt16#+    name: ["GHC.Prim.quotInt16#", "GHC.Internal.Prim.quotInt16#"]     kind: Expression     template: ~ARG[0] / ~ARG[1] - BlackBox:-    name: GHC.Prim.remInt16#+    name: ["GHC.Prim.remInt16#", "GHC.Internal.Prim.remInt16#"]     kind: Expression     template: ~ARG[0] % ~ARG[1] - BlackBox:-    name: GHC.Prim.uncheckedShiftLInt16#+    name: ["GHC.Prim.uncheckedShiftLInt16#", "GHC.Internal.Prim.uncheckedShiftLInt16#"]     kind: Expression     template: ~ARG[0] <<< ~ARG[1] - BlackBox:-    name: GHC.Prim.uncheckedShiftRAInt16#+    name: ["GHC.Prim.uncheckedShiftRAInt16#", "GHC.Internal.Prim.uncheckedShiftRAInt16#"]     kind: Expression     template: ~ARG[0] >>> ~ARG[1] - BlackBox:-    name: GHC.Prim.uncheckedShiftRLInt16#+    name: ["GHC.Prim.uncheckedShiftRLInt16#", "GHC.Internal.Prim.uncheckedShiftRLInt16#"]     kind: Expression     template: ~ARG[0] >> ~ARG[1] - BlackBox:-    name: GHC.Prim.int16ToWord16#+    name: ["GHC.Prim.int16ToWord16#", "GHC.Internal.Prim.int16ToWord16#"]     kind: Expression     template: $unsigned(~ARG[0])     workInfo: Never - BlackBox:-    name: GHC.Prim.eqInt16#+    name: ["GHC.Prim.eqInt16#", "GHC.Internal.Prim.eqInt16#"]     kind: Expression     template: "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.geInt16#+    name: ["GHC.Prim.geInt16#", "GHC.Internal.Prim.geInt16#"]     kind: Expression     template: "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.gtInt16#+    name: ["GHC.Prim.gtInt16#", "GHC.Internal.Prim.gtInt16#"]     kind: Expression     template: "(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.leInt16#+    name: ["GHC.Prim.leInt16#", "GHC.Internal.Prim.leInt16#"]     kind: Expression     template: "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.ltInt16#+    name: ["GHC.Prim.ltInt16#", "GHC.Internal.Prim.ltInt16#"]     kind: Expression     template: "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.neInt16#+    name: ["GHC.Prim.neInt16#", "GHC.Internal.Prim.neInt16#"]     kind: Expression     template: "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.word16ToWord#+    name: ["GHC.Prim.word16ToWord#", "GHC.Internal.Prim.word16ToWord#"]     kind: Declaration     template: |-       // word16ToWord begin@@ -668,7 +668,7 @@       // word16ToWord end     workInfo: Never - BlackBox:-    name: GHC.Prim.wordToWord16#+    name: ["GHC.Prim.wordToWord16#", "GHC.Internal.Prim.wordToWord16#"]     kind: Declaration     template: |-       // wordToWord16 begin@@ -676,72 +676,72 @@       // wordToWord16 end     workInfo: Never - BlackBox:-    name: GHC.Prim.timesWord16#+    name: ["GHC.Prim.timesWord16#", "GHC.Internal.Prim.timesWord16#"]     kind: Expression     template: ~ARG[0] * ~ARG[1] - BlackBox:-    name: GHC.Prim.quotWord16#+    name: ["GHC.Prim.quotWord16#", "GHC.Internal.Prim.quotWord16#"]     kind: Expression     template: ~ARG[0] / ~ARG[1] - BlackBox:-    name: GHC.Prim.remWord16#+    name: ["GHC.Prim.remWord16#", "GHC.Internal.Prim.remWord16#"]     kind: Expression     template: ~ARG[0] % ~ARG[1] - BlackBox:-    name: GHC.Prim.andWord16#+    name: ["GHC.Prim.andWord16#", "GHC.Internal.Prim.andWord16#"]     kind: Expression     template: ~ARG[0] & ~ARG[1] - BlackBox:-    name: GHC.Prim.orWord16#+    name: ["GHC.Prim.orWord16#", "GHC.Internal.Prim.orWord16#"]     kind: Expression     template: ~ARG[0] | ~ARG[1] - BlackBox:-    name: GHC.Prim.xorWord16#+    name: ["GHC.Prim.xorWord16#", "GHC.Internal.Prim.xorWord16#"]     kind: Expression     template: ~ARG[0] ^ ~ARG[1] - BlackBox:-    name: GHC.Prim.notWord16#+    name: ["GHC.Prim.notWord16#", "GHC.Internal.Prim.notWord16#"]     kind: Expression     template: ~ ~ARG[0] - BlackBox:-    name: GHC.Prim.uncheckedShiftLWord16#+    name: ["GHC.Prim.uncheckedShiftLWord16#", "GHC.Internal.Prim.uncheckedShiftLWord16#"]     kind: Expression     template: ~ARG[0] << ~ARG[1] - BlackBox:-    name: GHC.Prim.uncheckedShiftRLWord16#+    name: ["GHC.Prim.uncheckedShiftRLWord16#", "GHC.Internal.Prim.uncheckedShiftRLWord16#"]     kind: Expression     template: ~ARG[0] >> ~ARG[1] - BlackBox:-    name: GHC.Prim.word16ToInt16#+    name: ["GHC.Prim.word16ToInt16#", "GHC.Internal.Prim.word16ToInt16#"]     kind: Expression     template: $signed(~ARG[0])     workInfo: Never - BlackBox:-    name: GHC.Prim.eqWord16#+    name: ["GHC.Prim.eqWord16#", "GHC.Internal.Prim.eqWord16#"]     kind: Expression     template: "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.geWord16#+    name: ["GHC.Prim.geWord16#", "GHC.Internal.Prim.geWord16#"]     kind: Expression     template: "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.gtWord16#+    name: ["GHC.Prim.gtWord16#", "GHC.Internal.Prim.gtWord16#"]     kind: Expression     template: "(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.leWord16#+    name: ["GHC.Prim.leWord16#", "GHC.Internal.Prim.leWord16#"]     kind: Expression     template: "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.ltWord16#+    name: ["GHC.Prim.ltWord16#", "GHC.Internal.Prim.ltWord16#"]     kind: Expression     template: "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.neWord16#+    name: ["GHC.Prim.neWord16#", "GHC.Internal.Prim.neWord16#"]     kind: Expression     template: "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.int32ToInt#+    name: ["GHC.Prim.int32ToInt#", "GHC.Internal.Prim.int32ToInt#"]     kind: Declaration     template: |-       // int32ToInt begin@@ -749,7 +749,7 @@       // int32ToInt end     workInfo: Never - BlackBox:-    name: GHC.Prim.intToInt32#+    name: ["GHC.Prim.intToInt32#", "GHC.Internal.Prim.intToInt32#"]     kind: Declaration     template: |-       // intToInt32 begin@@ -757,64 +757,64 @@       // intToInt32 end     workInfo: Never - BlackBox:-    name: GHC.Prim.negateInt32#+    name: ["GHC.Prim.negateInt32#", "GHC.Internal.Prim.negateInt32#"]     kind: Expression     template: -(~ARG[0]) - BlackBox:-    name: GHC.Prim.timesInt32#+    name: ["GHC.Prim.timesInt32#", "GHC.Internal.Prim.timesInt32#"]     kind: Expression     template: ~ARG[0] * ~ARG[1] - BlackBox:-    name: GHC.Prim.quotInt32#+    name: ["GHC.Prim.quotInt32#", "GHC.Internal.Prim.quotInt32#"]     kind: Expression     template: ~ARG[0] / ~ARG[1] - BlackBox:-    name: GHC.Prim.remInt32#+    name: ["GHC.Prim.remInt32#", "GHC.Internal.Prim.remInt32#"]     kind: Expression     template: ~ARG[0] % ~ARG[1] - BlackBox:-    name: GHC.Prim.uncheckedShiftLInt32#+    name: ["GHC.Prim.uncheckedShiftLInt32#", "GHC.Internal.Prim.uncheckedShiftLInt32#"]     kind: Expression     template: ~ARG[0] <<< ~ARG[1] - BlackBox:-    name: GHC.Prim.uncheckedShiftRAInt32#+    name: ["GHC.Prim.uncheckedShiftRAInt32#", "GHC.Internal.Prim.uncheckedShiftRAInt32#"]     kind: Expression     template: ~ARG[0] >>> ~ARG[1] - BlackBox:-    name: GHC.Prim.uncheckedShiftRLInt32#+    name: ["GHC.Prim.uncheckedShiftRLInt32#", "GHC.Internal.Prim.uncheckedShiftRLInt32#"]     kind: Expression     template: ~ARG[0] >> ~ARG[1] - BlackBox:-    name: GHC.Prim.int32ToWord32#+    name: ["GHC.Prim.int32ToWord32#", "GHC.Internal.Prim.int32ToWord32#"]     kind: Expression     template: $unsigned(~ARG[0])     workInfo: Never - BlackBox:-    name: GHC.Prim.eqInt32#+    name: ["GHC.Prim.eqInt32#", "GHC.Internal.Prim.eqInt32#"]     kind: Expression     template: "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.geInt32#+    name: ["GHC.Prim.geInt32#", "GHC.Internal.Prim.geInt32#"]     kind: Expression     template: "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.gtInt32#+    name: ["GHC.Prim.gtInt32#", "GHC.Internal.Prim.gtInt32#"]     kind: Expression     template: "(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.leInt32#+    name: ["GHC.Prim.leInt32#", "GHC.Internal.Prim.leInt32#"]     kind: Expression     template: "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.ltInt32#+    name: ["GHC.Prim.ltInt32#", "GHC.Internal.Prim.ltInt32#"]     kind: Expression     template: "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.neInt32#+    name: ["GHC.Prim.neInt32#", "GHC.Internal.Prim.neInt32#"]     kind: Expression     template: "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.word32ToWord#+    name: ["GHC.Prim.word32ToWord#", "GHC.Internal.Prim.word32ToWord#"]     kind: Declaration     template: |-       // word32ToWord begin@@ -822,7 +822,7 @@       // word32ToWord end     workInfo: Never - BlackBox:-    name: GHC.Prim.wordToWord32#+    name: ["GHC.Prim.wordToWord32#", "GHC.Internal.Prim.wordToWord32#"]     kind: Declaration     template: |-       // wordToWord32 begin@@ -830,72 +830,72 @@       // wordToWord32 end     workInfo: Never - BlackBox:-    name: GHC.Prim.timesWord32#+    name: ["GHC.Prim.timesWord32#", "GHC.Internal.Prim.timesWord32#"]     kind: Expression     template: ~ARG[0] * ~ARG[1] - BlackBox:-    name: GHC.Prim.quotWord32#+    name: ["GHC.Prim.quotWord32#", "GHC.Internal.Prim.quotWord32#"]     kind: Expression     template: ~ARG[0] / ~ARG[1] - BlackBox:-    name: GHC.Prim.remWord32#+    name: ["GHC.Prim.remWord32#", "GHC.Internal.Prim.remWord32#"]     kind: Expression     template: ~ARG[0] % ~ARG[1] - BlackBox:-    name: GHC.Prim.andWord32#+    name: ["GHC.Prim.andWord32#", "GHC.Internal.Prim.andWord32#"]     kind: Expression     template: ~ARG[0] & ~ARG[1] - BlackBox:-    name: GHC.Prim.orWord32#+    name: ["GHC.Prim.orWord32#", "GHC.Internal.Prim.orWord32#"]     kind: Expression     template: ~ARG[0] | ~ARG[1] - BlackBox:-    name: GHC.Prim.xorWord32#+    name: ["GHC.Prim.xorWord32#", "GHC.Internal.Prim.xorWord32#"]     kind: Expression     template: ~ARG[0] ^ ~ARG[1] - BlackBox:-    name: GHC.Prim.notWord32#+    name: ["GHC.Prim.notWord32#", "GHC.Internal.Prim.notWord32#"]     kind: Expression     template: ~ ~ARG[0] - BlackBox:-    name: GHC.Prim.uncheckedShiftLWord32#+    name: ["GHC.Prim.uncheckedShiftLWord32#", "GHC.Internal.Prim.uncheckedShiftLWord32#"]     kind: Expression     template: ~ARG[0] << ~ARG[1] - BlackBox:-    name: GHC.Prim.uncheckedShiftRLWord32#+    name: ["GHC.Prim.uncheckedShiftRLWord32#", "GHC.Internal.Prim.uncheckedShiftRLWord32#"]     kind: Expression     template: ~ARG[0] >> ~ARG[1] - BlackBox:-    name: GHC.Prim.word32ToInt32#+    name: ["GHC.Prim.word32ToInt32#", "GHC.Internal.Prim.word32ToInt32#"]     kind: Expression     template: $signed(~ARG[0])     workInfo: Never - BlackBox:-    name: GHC.Prim.eqWord32#+    name: ["GHC.Prim.eqWord32#", "GHC.Internal.Prim.eqWord32#"]     kind: Expression     template: "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.geWord32#+    name: ["GHC.Prim.geWord32#", "GHC.Internal.Prim.geWord32#"]     kind: Expression     template: "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.gtWord32#+    name: ["GHC.Prim.gtWord32#", "GHC.Internal.Prim.gtWord32#"]     kind: Expression     template: "(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.leWord32#+    name: ["GHC.Prim.leWord32#", "GHC.Internal.Prim.leWord32#"]     kind: Expression     template: "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.ltWord32#+    name: ["GHC.Prim.ltWord32#", "GHC.Internal.Prim.ltWord32#"]     kind: Expression     template: "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.neWord32#+    name: ["GHC.Prim.neWord32#", "GHC.Internal.Prim.neWord32#"]     kind: Expression     template: "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.int64ToInt#+    name: ["GHC.Prim.int64ToInt#", "GHC.Internal.Prim.int64ToInt#"]     kind: Declaration     template: |-       // int64ToInt begin@@ -903,7 +903,7 @@       // int64ToInt end     workInfo: Never - BlackBox:-    name: GHC.Prim.intToInt64#+    name: ["GHC.Prim.intToInt64#", "GHC.Internal.Prim.intToInt64#"]     kind: Declaration     template: |-       // intToInt64 begin@@ -911,64 +911,64 @@       // intToInt64 end     workInfo: Never - BlackBox:-    name: GHC.Prim.negateInt64#+    name: ["GHC.Prim.negateInt64#", "GHC.Internal.Prim.negateInt64#"]     kind: Expression     template: -(~ARG[0]) - BlackBox:-    name: GHC.Prim.timesInt64#+    name: ["GHC.Prim.timesInt64#", "GHC.Internal.Prim.timesInt64#"]     kind: Expression     template: ~ARG[0] * ~ARG[1] - BlackBox:-    name: GHC.Prim.quotInt64#+    name: ["GHC.Prim.quotInt64#", "GHC.Internal.Prim.quotInt64#"]     kind: Expression     template: ~ARG[0] / ~ARG[1] - BlackBox:-    name: GHC.Prim.remInt64#+    name: ["GHC.Prim.remInt64#", "GHC.Internal.Prim.remInt64#"]     kind: Expression     template: ~ARG[0] % ~ARG[1] - BlackBox:-    name: GHC.Prim.uncheckedIShiftL64#+    name: ["GHC.Prim.uncheckedIShiftL64#", "GHC.Internal.Prim.uncheckedIShiftL64#"]     kind: Expression     template: ~ARG[0] <<< ~ARG[1] - BlackBox:-    name: GHC.Prim.uncheckedIShiftRA64#+    name: ["GHC.Prim.uncheckedIShiftRA64#", "GHC.Internal.Prim.uncheckedIShiftRA64#"]     kind: Expression     template: ~ARG[0] >>> ~ARG[1] - BlackBox:-    name: GHC.Prim.uncheckedIShiftRL64#+    name: ["GHC.Prim.uncheckedIShiftRL64#", "GHC.Internal.Prim.uncheckedIShiftRL64#"]     kind: Expression     template: ~ARG[0] >> ~ARG[1] - BlackBox:-    name: GHC.Prim.int64ToWord64#+    name: ["GHC.Prim.int64ToWord64#", "GHC.Internal.Prim.int64ToWord64#"]     kind: Expression     template: $unsigned(~ARG[0])     workInfo: Never - BlackBox:-    name: GHC.Prim.eqInt64#+    name: ["GHC.Prim.eqInt64#", "GHC.Internal.Prim.eqInt64#"]     kind: Expression     template: "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.geInt64#+    name: ["GHC.Prim.geInt64#", "GHC.Internal.Prim.geInt64#"]     kind: Expression     template: "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.gtInt64#+    name: ["GHC.Prim.gtInt64#", "GHC.Internal.Prim.gtInt64#"]     kind: Expression     template: "(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.leInt64#+    name: ["GHC.Prim.leInt64#", "GHC.Internal.Prim.leInt64#"]     kind: Expression     template: "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.ltInt64#+    name: ["GHC.Prim.ltInt64#", "GHC.Internal.Prim.ltInt64#"]     kind: Expression     template: "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.neInt64#+    name: ["GHC.Prim.neInt64#", "GHC.Internal.Prim.neInt64#"]     kind: Expression     template: "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.word64ToWord#+    name: ["GHC.Prim.word64ToWord#", "GHC.Internal.Prim.word64ToWord#"]     kind: Declaration     template: |-       // word64ToWord begin@@ -976,7 +976,7 @@       // word64ToWord end     workInfo: Never - BlackBox:-    name: GHC.Prim.wordToWord64#+    name: ["GHC.Prim.wordToWord64#", "GHC.Internal.Prim.wordToWord64#"]     kind: Declaration     template: |-       // wordToWord64 begin@@ -984,67 +984,67 @@       // wordToWord64 end     workInfo: Never - BlackBox:-    name: GHC.Prim.timesWord64#+    name: ["GHC.Prim.timesWord64#", "GHC.Internal.Prim.timesWord64#"]     kind: Expression     template: ~ARG[0] * ~ARG[1] - BlackBox:-    name: GHC.Prim.quotWord64#+    name: ["GHC.Prim.quotWord64#", "GHC.Internal.Prim.quotWord64#"]     kind: Expression     template: ~ARG[0] / ~ARG[1] - BlackBox:-    name: GHC.Prim.remWord64#+    name: ["GHC.Prim.remWord64#", "GHC.Internal.Prim.remWord64#"]     kind: Expression     template: ~ARG[0] % ~ARG[1] - BlackBox:-    name: GHC.Prim.and64#+    name: ["GHC.Prim.and64#", "GHC.Internal.Prim.and64#"]     kind: Expression     template: ~ARG[0] & ~ARG[1] - BlackBox:-    name: GHC.Prim.or64#+    name: ["GHC.Prim.or64#", "GHC.Internal.Prim.or64#"]     kind: Expression     template: ~ARG[0] | ~ARG[1] - BlackBox:-    name: GHC.Prim.xor64#+    name: ["GHC.Prim.xor64#", "GHC.Internal.Prim.xor64#"]     kind: Expression     template: ~ARG[0] ^ ~ARG[1] - BlackBox:-    name: GHC.Prim.not64#+    name: ["GHC.Prim.not64#", "GHC.Internal.Prim.not64#"]     kind: Expression     template: ~ ~ARG[0] - BlackBox:-    name: GHC.Prim.uncheckedShiftL64#+    name: ["GHC.Prim.uncheckedShiftL64#", "GHC.Internal.Prim.uncheckedShiftL64#"]     kind: Expression     template: ~ARG[0] << ~ARG[1] - BlackBox:-    name: GHC.Prim.uncheckedShiftRL64#+    name: ["GHC.Prim.uncheckedShiftRL64#", "GHC.Internal.Prim.uncheckedShiftRL64#"]     kind: Expression     template: ~ARG[0] >> ~ARG[1] - BlackBox:-    name: GHC.Prim.word64ToInt64#+    name: ["GHC.Prim.word64ToInt64#", "GHC.Internal.Prim.word64ToInt64#"]     kind: Expression     template: $signed(~ARG[0])     workInfo: Never - BlackBox:-    name: GHC.Prim.eqWord64#+    name: ["GHC.Prim.eqWord64#", "GHC.Internal.Prim.eqWord64#"]     kind: Expression     template: "(~ARG[0] == ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.geWord64#+    name: ["GHC.Prim.geWord64#", "GHC.Internal.Prim.geWord64#"]     kind: Expression     template: "(~ARG[0] >= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.gtWord64#+    name: ["GHC.Prim.gtWord64#", "GHC.Internal.Prim.gtWord64#"]     kind: Expression     template: "(~ARG[0] > ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.leWord64#+    name: ["GHC.Prim.leWord64#", "GHC.Internal.Prim.leWord64#"]     kind: Expression     template: "(~ARG[0] <= ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.ltWord64#+    name: ["GHC.Prim.ltWord64#", "GHC.Internal.Prim.ltWord64#"]     kind: Expression     template: "(~ARG[0] < ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0" - BlackBox:-    name: GHC.Prim.neWord64#+    name: ["GHC.Prim.neWord64#", "GHC.Internal.Prim.neWord64#"]     kind: Expression     template: "(~ARG[0] != ~ARG[1]) ? ~SIZE[~TYPO]'sd1 : ~SIZE[~TYPO]'sd0"
prims/systemverilog/Clash_Signal_Internal.primitives.yaml view
@@ -174,5 +174,5 @@       end       // pragma translate_on       // resetGen end-    warning: Clash.Signal.Internal.resetGenN can not be synthesized to hardware!+    warning: Clash.Signal.Internal.resetGenN cannot be synthesized to hardware!     workInfo: Always
prims/systemverilog/GHC_Classes.primitives.yaml view
@@ -1,5 +1,5 @@ - BlackBox:-    name: GHC.Classes.divInt#+    name: ["GHC.Classes.divInt#", "GHC.Internal.Classes.divInt#"]     kind: Declaration     type: 'divInt# :: Int#       -> Int# -> Int#'@@ -25,7 +25,7 @@       assign ~RESULT = $signed(~SYM[6][~SIZE[~TYPO]-1:0]);       // divInt# end - BlackBox:-    name: GHC.Classes.modInt#+    name: ["GHC.Classes.modInt#", "GHC.Internal.Classes.modInt#"]     kind: Declaration     type: 'modInt# :: Int#       -> Int# -> Int#'
prims/systemverilog/GHC_Num_Integer.primitives.yaml view
@@ -1,5 +1,5 @@ - BlackBox:-    name: GHC.Num.Integer.integerDiv+    name: ["GHC.Num.Integer.integerDiv", "GHC.Internal.Bignum.Integer.integerDiv"]     kind: Declaration     type: 'integerDiv :: Integer       -> Integer -> Integer'@@ -27,7 +27,7 @@     warning: 'GHC.Num.Integer.integerDiv: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerMod+    name: ["GHC.Num.Integer.integerMod", "GHC.Internal.Bignum.Integer.integerMod"]     kind: Declaration     type: 'integerMod :: Integer       -> Integer -> Integer'@@ -45,7 +45,7 @@     warning: 'GHC.Num.Integer.integerMod: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerDivMod#+    name: ["GHC.Num.Integer.integerDivMod#", "GHC.Internal.Bignum.Integer.integerDivMod#"]     kind: Declaration     type: 'integerDivMod ::       Integer -> Integer -> (# Integer, Integer #)'@@ -83,7 +83,7 @@     warning: 'GHC.Num.Integer.integerDivMod#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerQuotRem#+    name: ["GHC.Num.Integer.integerQuotRem#", "GHC.Internal.Bignum.Integer.integerQuotRem#"]     kind: Declaration     type: 'integerQuotRem       :: Integer -> Integer -> (# Integer, Integer #)'
prims/systemverilog/GHC_Prim.primitives.yaml view
@@ -1,5 +1,5 @@ - BlackBox:-    name: GHC.Prim.quotRemInt#+    name: ["GHC.Prim.quotRemInt#", "GHC.Internal.Prim.quotRemInt#"]     kind: Declaration     type: 'quotRemInt# ::       Int# -> Int# -> (#Int#, Int##)'@@ -13,7 +13,7 @@       assign ~RESULT = {~SYM[0],~SYM[1]};       // quotRemInt end - BlackBox:-    name: GHC.Prim.quotRemWord#+    name: ["GHC.Prim.quotRemWord#", "GHC.Internal.Prim.quotRemWord#"]     kind: Declaration     type: 'quotRemWord# ::       Word# -> Word# -> (#Word#, Word##)'@@ -27,7 +27,7 @@       assign ~RESULT = {~SYM[0],~SYM[1]};       // quotRemWord end - BlackBox:-    name: GHC.Prim.popCnt8#+    name: ["GHC.Prim.popCnt8#", "GHC.Internal.Prim.popCnt8#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -81,7 +81,7 @@       assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);       // popCnt8 end - BlackBox:-    name: GHC.Prim.popCnt16#+    name: ["GHC.Prim.popCnt16#", "GHC.Internal.Prim.popCnt16#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -135,7 +135,7 @@       assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);       // popCnt16 end - BlackBox:-    name: GHC.Prim.popCnt32#+    name: ["GHC.Prim.popCnt32#", "GHC.Internal.Prim.popCnt32#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -189,7 +189,7 @@       assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);       // popCnt32 end - BlackBox:-    name: GHC.Prim.popCnt64#+    name: ["GHC.Prim.popCnt64#", "GHC.Internal.Prim.popCnt64#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -243,7 +243,7 @@       assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);       // popCnt64 end - BlackBox:-    name: GHC.Prim.popCnt#+    name: ["GHC.Prim.popCnt#", "GHC.Internal.Prim.popCnt#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -297,7 +297,7 @@       assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);       // popCnt end - BlackBox:-    name: GHC.Prim.clz8#+    name: ["GHC.Prim.clz8#", "GHC.Internal.Prim.clz8#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -363,7 +363,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // clz8 end - BlackBox:-    name: GHC.Prim.clz16#+    name: ["GHC.Prim.clz16#", "GHC.Internal.Prim.clz16#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -445,7 +445,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // clz16 end - BlackBox:-    name: GHC.Prim.clz32#+    name: ["GHC.Prim.clz32#", "GHC.Internal.Prim.clz32#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -543,7 +543,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // clz32 end - BlackBox:-    name: GHC.Prim.clz64#+    name: ["GHC.Prim.clz64#", "GHC.Internal.Prim.clz64#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -657,7 +657,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // clz64 end - BlackBox:-    name: GHC.Prim.clz#+    name: ["GHC.Prim.clz#", "GHC.Internal.Prim.clz#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -846,7 +846,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // clz end - BlackBox:-    name: GHC.Prim.ctz8#+    name: ["GHC.Prim.ctz8#", "GHC.Internal.Prim.ctz8#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -917,7 +917,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // ctz8 end - BlackBox:-    name: GHC.Prim.ctz16#+    name: ["GHC.Prim.ctz16#", "GHC.Internal.Prim.ctz16#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -1004,7 +1004,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // ctz16 end - BlackBox:-    name: GHC.Prim.ctz32#+    name: ["GHC.Prim.ctz32#", "GHC.Internal.Prim.ctz32#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -1107,7 +1107,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // ctz32 end - BlackBox:-    name: GHC.Prim.ctz64#+    name: ["GHC.Prim.ctz64#", "GHC.Internal.Prim.ctz64#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -1226,7 +1226,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // ctz64 end - BlackBox:-    name: GHC.Prim.ctz#+    name: ["GHC.Prim.ctz#", "GHC.Internal.Prim.ctz#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -1425,7 +1425,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // ctz end - BlackBox:-    name: GHC.Prim.quotRemInt8#+    name: ["GHC.Prim.quotRemInt8#", "GHC.Internal.Prim.quotRemInt8#"]     kind: Declaration     type: 'quotRemInt8# ::       Int8# -> Int8# -> (#Int8#, Int8##)'@@ -1439,7 +1439,7 @@       assign ~RESULT = {~SYM[0],~SYM[1]};       // quotRemInt8 end - BlackBox:-    name: GHC.Prim.quotRemWord8#+    name: ["GHC.Prim.quotRemWord8#", "GHC.Internal.Prim.quotRemWord8#"]     kind: Declaration     type: 'quotRemWord8# ::       Word8# -> Word8# -> (#Word8#, Word8##)'@@ -1453,7 +1453,7 @@       assign ~RESULT = {~SYM[0],~SYM[1]};       // quotRemWord8 end - BlackBox:-    name: GHC.Prim.quotRemInt16#+    name: ["GHC.Prim.quotRemInt16#", "GHC.Internal.Prim.quotRemInt16#"]     kind: Declaration     type: 'quotRemInt16# ::       Int16# -> Int16# -> (#Int16#, Int16##)'@@ -1467,7 +1467,7 @@       assign ~RESULT = {~SYM[0],~SYM[1]};       // quotRemInt16 end - BlackBox:-    name: GHC.Prim.quotRemWord16#+    name: ["GHC.Prim.quotRemWord16#", "GHC.Internal.Prim.quotRemWord16#"]     kind: Declaration     type: 'quotRemWord16# ::       Word16# -> Word16# -> (#Word16#, Word16##)'@@ -1481,7 +1481,7 @@       assign ~RESULT = {~SYM[0],~SYM[1]};       // quotRemWord16 end - BlackBox:-    name: GHC.Prim.quotRemInt32#+    name: ["GHC.Prim.quotRemInt32#", "GHC.Internal.Prim.quotRemInt32#"]     kind: Declaration     type: 'quotRemInt32# ::       Int32# -> Int32# -> (#Int32#, Int32##)'@@ -1495,7 +1495,7 @@       assign ~RESULT = {~SYM[0],~SYM[1]};       // quotRemInt32 end - BlackBox:-    name: GHC.Prim.quotRemWord32#+    name: ["GHC.Prim.quotRemWord32#", "GHC.Internal.Prim.quotRemWord32#"]     kind: Declaration     type: 'quotRemWord32# ::       Word32# -> Word32# -> (#Word32#, Word32##)'
prims/verilog/Clash_Signal_Internal.primitives.yaml view
@@ -180,4 +180,5 @@       assign ~RESULT = ~SYM[0];       // pragma translate_on       // resetGen end+    warning: Clash.Signal.Internal.resetGenN cannot be synthesized to hardware!     workInfo: Always
prims/verilog/GHC_Classes.primitives.yaml view
@@ -1,5 +1,5 @@ - BlackBox:-    name: GHC.Classes.divInt#+    name: ["GHC.Classes.divInt#", "GHC.Internal.Classes.divInt#"]     kind: Declaration     type: 'divInt# :: Int#       -> Int# -> Int#'@@ -25,7 +25,7 @@       assign ~RESULT = $signed(~SYM[6][~SIZE[~TYPO]-1:0]);       // divInt# end - BlackBox:-    name: GHC.Classes.modInt#+    name: ["GHC.Classes.modInt#", "GHC.Internal.Classes.modInt#"]     kind: Declaration     type: 'modInt# :: Int#       -> Int# -> Int#'
prims/verilog/GHC_Num_Integer.primitives.yaml view
@@ -1,5 +1,5 @@ - BlackBox:-    name: GHC.Num.Integer.integerDiv+    name: ["GHC.Num.Integer.integerDiv", "GHC.Internal.Bignum.Integer.integerDiv"]     kind: Declaration     type: 'integerDiv :: Integer       -> Integer -> Integer'@@ -27,7 +27,7 @@     warning: 'GHC.Num.Integer.integerDiv: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerMod+    name: ["GHC.Num.Integer.integerMod", "GHC.Internal.Bignum.Integer.integerMod"]     kind: Declaration     type: 'integerMod :: Integer       -> Integer -> Integer'@@ -45,7 +45,7 @@     warning: 'GHC.Num.Integer.integerMod: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerDivMod#+    name: ["GHC.Num.Integer.integerDivMod#", "GHC.Internal.Bignum.Integer.integerDivMod#"]     kind: Declaration     type: 'integerDivMod ::       Integer -> Integer -> (# Integer, Integer #)'@@ -85,7 +85,7 @@     warning: 'GHC.Num.Integer.integerDivMod#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerQuotRem#+    name: ["GHC.Num.Integer.integerQuotRem#", "GHC.Internal.Bignum.Integer.integerQuotRem#"]     kind: Declaration     type: 'integerQuotRem       :: Integer -> Integer -> (# Integer, Integer #)'
prims/verilog/GHC_Prim.primitives.yaml view
@@ -1,5 +1,5 @@ - BlackBox:-    name: GHC.Prim.quotRemInt#+    name: ["GHC.Prim.quotRemInt#", "GHC.Internal.Prim.quotRemInt#"]     kind: Declaration     type: 'quotRemInt# ::       Int# -> Int# -> (#Int#, Int##)'@@ -13,7 +13,7 @@       assign ~RESULT = {~SYM[0],~SYM[1]};       // quotRemInt end - BlackBox:-    name: GHC.Prim.quotRemWord#+    name: ["GHC.Prim.quotRemWord#", "GHC.Internal.Prim.quotRemWord#"]     kind: Declaration     type: 'quotRemWord# ::       Word# -> Word# -> (#Word#, Word##)'@@ -27,7 +27,7 @@       assign ~RESULT = {~SYM[0],~SYM[1]};       // quotRemWord end - BlackBox:-    name: GHC.Prim.popCnt8#+    name: ["GHC.Prim.popCnt8#", "GHC.Internal.Prim.popCnt8#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -91,7 +91,7 @@       assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);       // popCnt8 end - BlackBox:-    name: GHC.Prim.popCnt16#+    name: ["GHC.Prim.popCnt16#", "GHC.Internal.Prim.popCnt16#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -155,7 +155,7 @@       assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);       // popCnt16 end - BlackBox:-    name: GHC.Prim.popCnt32#+    name: ["GHC.Prim.popCnt32#", "GHC.Internal.Prim.popCnt32#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -219,7 +219,7 @@       assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);       // popCnt32 end - BlackBox:-    name: GHC.Prim.popCnt64#+    name: ["GHC.Prim.popCnt64#", "GHC.Internal.Prim.popCnt64#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -283,7 +283,7 @@       assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);       // popCnt64 end - BlackBox:-    name: GHC.Prim.popCnt#+    name: ["GHC.Prim.popCnt#", "GHC.Internal.Prim.popCnt#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -347,7 +347,7 @@       assign ~RESULT = $unsigned(~SYM[3][(2*~SYM[0])-2]);       // popCnt end - BlackBox:-    name: GHC.Prim.clz8#+    name: ["GHC.Prim.clz8#", "GHC.Internal.Prim.clz8#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -413,7 +413,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // clz8 end - BlackBox:-    name: GHC.Prim.clz16#+    name: ["GHC.Prim.clz16#", "GHC.Internal.Prim.clz16#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -495,7 +495,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // clz16 end - BlackBox:-    name: GHC.Prim.clz32#+    name: ["GHC.Prim.clz32#", "GHC.Internal.Prim.clz32#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -593,7 +593,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // clz32 end - BlackBox:-    name: GHC.Prim.clz64#+    name: ["GHC.Prim.clz64#", "GHC.Internal.Prim.clz64#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -707,7 +707,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // clz64 end - BlackBox:-    name: GHC.Prim.clz#+    name: ["GHC.Prim.clz#", "GHC.Internal.Prim.clz#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -895,7 +895,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // clz end - BlackBox:-    name: GHC.Prim.ctz8#+    name: ["GHC.Prim.ctz8#", "GHC.Internal.Prim.ctz8#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -966,7 +966,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // ctz8 end - BlackBox:-    name: GHC.Prim.ctz16#+    name: ["GHC.Prim.ctz16#", "GHC.Internal.Prim.ctz16#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -1053,7 +1053,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // ctz16 end - BlackBox:-    name: GHC.Prim.ctz32#+    name: ["GHC.Prim.ctz32#", "GHC.Internal.Prim.ctz32#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -1156,7 +1156,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // ctz32 end - BlackBox:-    name: GHC.Prim.ctz64#+    name: ["GHC.Prim.ctz64#", "GHC.Internal.Prim.ctz64#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -1275,7 +1275,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // ctz64 end - BlackBox:-    name: GHC.Prim.ctz#+    name: ["GHC.Prim.ctz#", "GHC.Internal.Prim.ctz#"]     imports:     - ~INCLUDENAME[0].inc     includes:@@ -1473,7 +1473,7 @@       assign ~RESULT = $unsigned(~SYM[7]);       // ctz end - BlackBox:-    name: GHC.Prim.quotRemInt8#+    name: ["GHC.Prim.quotRemInt8#", "GHC.Internal.Prim.quotRemInt8#"]     kind: Declaration     type: 'quotRemInt8# ::       Int8# -> Int8# -> (#Int8#, Int8##)'@@ -1487,7 +1487,7 @@       assign ~RESULT = {~SYM[0],~SYM[1]};       // quotRemInt8 end - BlackBox:-    name: GHC.Prim.quotRemWord8#+    name: ["GHC.Prim.quotRemWord8#", "GHC.Internal.Prim.quotRemWord8#"]     kind: Declaration     type: 'quotRemWord8# ::       Word8# -> Word8# -> (#Word8#, Word8##)'@@ -1501,7 +1501,7 @@       assign ~RESULT = {~SYM[0],~SYM[1]};       // quotRemWord8 end - BlackBox:-    name: GHC.Prim.quotRemInt16#+    name: ["GHC.Prim.quotRemInt16#", "GHC.Internal.Prim.quotRemInt16#"]     kind: Declaration     type: 'quotRemInt16# ::       Int16# -> Int16# -> (#Int16#, Int16##)'@@ -1515,7 +1515,7 @@       assign ~RESULT = {~SYM[0],~SYM[1]};       // quotRemInt16 end - BlackBox:-    name: GHC.Prim.quotRemWord16#+    name: ["GHC.Prim.quotRemWord16#", "GHC.Internal.Prim.quotRemWord16#"]     kind: Declaration     type: 'quotRemWord16# ::       Word16# -> Word16# -> (#Word16#, Word16##)'@@ -1529,7 +1529,7 @@       assign ~RESULT = {~SYM[0],~SYM[1]};       // quotRemWord16 end - BlackBox:-    name: GHC.Prim.quotRemInt32#+    name: ["GHC.Prim.quotRemInt32#", "GHC.Internal.Prim.quotRemInt32#"]     kind: Declaration     type: 'quotRemInt32# ::       Int32# -> Int32# -> (#Int32#, Int32##)'@@ -1543,7 +1543,7 @@       assign ~RESULT = {~SYM[0],~SYM[1]};       // quotRemInt32 end - BlackBox:-    name: GHC.Prim.quotRemWord32#+    name: ["GHC.Prim.quotRemWord32#", "GHC.Internal.Prim.quotRemWord32#"]     kind: Declaration     type: 'quotRemWord32# ::       Word32# -> Word32# -> (#Word32#, Word32##)'
prims/vhdl/Clash_Signal_Internal.primitives.yaml view
@@ -218,6 +218,7 @@       -- pragma translate_on       end block;       -- resetGen end+    warning: Clash.Signal.Internal.resetGenN cannot be synthesized to hardware!     workInfo: Always - BlackBox:     name: Clash.Signal.Internal.unsafeFromReset
prims/vhdl/Clash_Sized_Internal_BitVector.primitives.yaml view
@@ -449,7 +449,8 @@     type: 'minus# :: (KnownNat       m, KnownNat n) => BitVector m -> BitVector n -> BitVector (Max m n + 1)'     template: ~IF~AND[~SIZE[~TYP[2]],~SIZE[~TYP[3]]]~THENstd_logic_vector(resize(unsigned(~ARG[2]),~SIZE[~TYPO])-      - resize(unsigned(~ARG[3]),~SIZE[~TYPO]))~ELSE~IF~SIZE[~TYP[2]]~THENstd_logic_vector(resize(unsigned(~ARG[2]),~SIZE[~TYPO]))~ELSEstd_logic_vector(-resize(signed(~ARG[3]),~SIZE[~TYPO]))~FI~FI+      - resize(unsigned(~ARG[3]),~SIZE[~TYPO]))~ELSE~IF~SIZE[~TYP[2]]~THENstd_logic_vector(resize(unsigned(~ARG[2]),~SIZE[~TYPO]))~ELSEstd_logic_vector(to_unsigned(0,~SIZE[~TYPO])+      - resize(unsigned(~ARG[3]),~SIZE[~TYPO]))~FI~FI - BlackBox:     name: Clash.Sized.Internal.BitVector.times#     kind: Expression
prims/vhdl/Clash_Sized_Internal_Index.primitives.yaml view
@@ -99,19 +99,22 @@     kind: Expression     type: Index m -> Index       n -> Index (m + n - 1)-    template: resize(~ARG[0],~SIZE[~TYPO]) + resize(~ARG[1],~SIZE[~TYPO])+    template: ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THENresize(~ARG[0],~SIZE[~TYPO])+      + resize(~ARG[1],~SIZE[~TYPO])~ELSE~IF~SIZE[~TYP[0]]~THENresize(~ARG[0],~SIZE[~TYPO])~ELSEresize(~ARG[1],~SIZE[~TYPO])~FI~FI - BlackBox:     name: Clash.Sized.Internal.Index.minus#     kind: Expression     type: Index m -> Index       n -> Index (m + n - 1)-    template: resize(~ARG[0],~SIZE[~TYPO]) - resize(~ARG[1],~SIZE[~TYPO])+    template: ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THENresize(~ARG[0],~SIZE[~TYPO])+      - resize(~ARG[1],~SIZE[~TYPO])~ELSE~IF~SIZE[~TYP[0]]~THENresize(~ARG[0],~SIZE[~TYPO])~ELSEto_unsigned(0,~SIZE[~TYPO])+      - resize(~ARG[1],~SIZE[~TYPO])~FI~FI - BlackBox:     name: Clash.Sized.Internal.Index.times#     kind: Expression     type: Index m -> Index       n -> Index (((m-1) * (n-1)) + 1)-    template: resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])+    template: ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THENresize(~ARG[0] * ~ARG[1],~SIZE[~TYPO])~ELSEto_unsigned(0,~SIZE[~TYPO])~FI - BlackBox:     name: Clash.Sized.Internal.Index.rem#     kind: Declaration
prims/vhdl/Clash_Sized_Internal_Signed.primitives.yaml view
@@ -132,8 +132,7 @@     type: 'minus# :: Signed       m -> Signed n -> Signed (1 + Max m n)'     template: ~IF~AND[~SIZE[~TYP[0]],~SIZE[~TYP[1]]]~THENresize(~ARG[0],~SIZE[~TYPO])-      - resize(~ARG[1],~SIZE[~TYPO])~ELSE~IF~SIZE[~TYP[0]]~THENresize(~ARG[0],~SIZE[~TYPO])~ELSEresize(--      ~ARG[1],~SIZE[~TYPO])~FI~FI+      - resize(~ARG[1],~SIZE[~TYPO])~ELSE~IF~SIZE[~TYP[0]]~THENresize(~ARG[0],~SIZE[~TYPO])~ELSE-resize(~ARG[1],~SIZE[~TYPO])~FI~FI - BlackBox:     name: Clash.Sized.Internal.Signed.times#     kind: Expression
prims/vhdl/Clash_Sized_Internal_Unsigned.primitives.yaml view
@@ -117,7 +117,8 @@     type: 'minus# :: (KnownNat       m,KnownNat n) => Unsigned m -> Unsigned n -> Unsigned (1 + Max m n)'     template: ~IF~AND[~SIZE[~TYP[2]],~SIZE[~TYP[3]]]~THENresize(~ARG[2],~SIZE[~TYPO])-      - resize(~ARG[3],~SIZE[~TYPO])~ELSE~IF~SIZE[~TYP[2]]~THENresize(~ARG[2],~SIZE[~TYPO])~ELSEresize(~ARG[3],~SIZE[~TYPO])~FI~FI+      - resize(~ARG[3],~SIZE[~TYPO])~ELSE~IF~SIZE[~TYP[2]]~THENresize(~ARG[2],~SIZE[~TYPO])~ELSEto_unsigned(0,~SIZE[~TYPO])+      - resize(~ARG[3],~SIZE[~TYPO])~FI~FI - BlackBox:     name: Clash.Sized.Internal.Unsigned.times#     kind: Expression
prims/vhdl/GHC_Classes.primitives.yaml view
@@ -1,35 +1,35 @@ - BlackBox:-    name: GHC.Classes.eqInt+    name: ["GHC.Classes.eqInt", "GHC.Internal.Classes.eqInt"]     kind: Expression     type: 'eqInt :: Int ->       Int -> Bool'     template: ~ARG[0] = ~ARG[1] - BlackBox:-    name: GHC.Classes.neInt+    name: ["GHC.Classes.neInt", "GHC.Internal.Classes.neInt"]     kind: Expression     type: 'neInt :: Int ->       Int -> Bool'     template: ~ARG[0] /= ~ARG[1] - BlackBox:-    name: GHC.Classes.&&+    name: ["GHC.Classes.&&", "GHC.Internal.Classes.&&"]     kind: Expression     type: '(&&) :: Bool ->       Bool -> Bool'     template: ~ARG[0] and ~ARG[1] - BlackBox:-    name: GHC.Classes.||+    name: ["GHC.Classes.||", "GHC.Internal.Classes.||"]     kind: Expression     type: '(::) :: Bool ->       Bool -> Bool'     template: ~ARG[0] or ~ARG[1] - BlackBox:-    name: GHC.Classes.not+    name: ["GHC.Classes.not", "GHC.Internal.Classes.not"]     kind: Expression     type: 'not :: Bool ->       Bool'     template: not ~ARG[0] - BlackBox:-    name: GHC.Classes.divInt#+    name: ["GHC.Classes.divInt#", "GHC.Internal.Classes.divInt#"]     kind: Declaration     type: 'divInt# :: Int#       -> Int# -> Int#'@@ -55,7 +55,7 @@       end block;       -- divInt# end - BlackBox:-    name: GHC.Classes.modInt#+    name: ["GHC.Classes.modInt#", "GHC.Internal.Classes.modInt#"]     kind: Expression     type: 'modInt# :: Int#       -> Int# -> Int#'
prims/vhdl/GHC_Num_Integer.primitives.yaml view
@@ -1,5 +1,5 @@ - BlackBox:-    name: GHC.Num.Integer.integerToNatural+    name: ["GHC.Num.Integer.integerToNatural", "GHC.Internal.Bignum.Integer.integerToNatural"]     kind: Expression     type: 'integerToNatural       :: Integer -> Natural'@@ -8,7 +8,7 @@       simulation, but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Integer.integerToNaturalThrow+    name: ["GHC.Num.Integer.integerToNaturalThrow", "GHC.Internal.Bignum.Integer.integerToNaturalThrow"]     kind: Declaration     type: 'integerToNaturalThrow       :: Integer -> Natural'@@ -21,7 +21,7 @@       in simulation, but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Integer.integerToNaturalClamp+    name: ["GHC.Num.Integer.integerToNaturalClamp", "GHC.Internal.Bignum.Integer.integerToNaturalClamp"]     kind: Declaration     type: 'integerToNatural       :: Integer -> Natural'@@ -34,7 +34,7 @@       in simulation, but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Integer.integerToInt#+    name: ["GHC.Num.Integer.integerToInt#", "GHC.Internal.Bignum.Integer.integerToInt#"]     kind: Expression     type: 'integerToInt ::       Integer -> Int#'@@ -43,7 +43,7 @@       but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Integer.integerMul+    name: ["GHC.Num.Integer.integerMul", "GHC.Internal.Bignum.Integer.integerMul"]     kind: Declaration     type: 'integerMul :: Integer       -> Integer -> Integer'@@ -57,7 +57,7 @@     warning: 'GHC.Num.Integer.integerMul: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerNegate+    name: ["GHC.Num.Integer.integerNegate", "GHC.Internal.Bignum.Integer.integerNegate"]     kind: Expression     type: 'integerNegate ::       Integer -> Integer'@@ -65,7 +65,7 @@     warning: 'GHC.Num.Integer.integerNegate: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerAbs+    name: ["GHC.Num.Integer.integerAbs", "GHC.Internal.Bignum.Integer.integerAbs"]     kind: Expression     type: 'integerAbs :: Integer       -> Integer'@@ -73,7 +73,7 @@     warning: 'GHC.Num.Integer.integerAbs: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerDiv+    name: ["GHC.Num.Integer.integerDiv", "GHC.Internal.Bignum.Integer.integerDiv"]     kind: Declaration     type: 'integerDiv :: Integer       -> Integer -> Integer'@@ -101,7 +101,7 @@     warning: 'GHC.Num.Integer.integerDiv: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerMod+    name: ["GHC.Num.Integer.integerMod", "GHC.Internal.Bignum.Integer.integerMod"]     kind: Expression     type: 'integerMod :: Integer       -> Integer -> Integer'@@ -109,7 +109,7 @@     warning: 'GHC.Num.Integer.integerMod: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerDivMod#+    name: ["GHC.Num.Integer.integerDivMod#", "GHC.Internal.Bignum.Integer.integerDivMod#"]     kind: Declaration     type: 'integerDivMod ::       Integer -> Integer -> (# Integer, Integer #)'@@ -145,7 +145,7 @@     warning: 'GHC.Num.Integer.integerDivMod#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerQuotRem#+    name: ["GHC.Num.Integer.integerQuotRem#", "GHC.Internal.Bignum.Integer.integerQuotRem#"]     kind: Declaration     type: 'integerQuotRem       :: Integer -> Integer -> (# Integer, Integer #)'@@ -158,7 +158,7 @@     warning: 'GHC.Num.Integer.integerQuotRem#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerRem+    name: ["GHC.Num.Integer.integerRem", "GHC.Internal.Bignum.Integer.integerRem"]     kind: Declaration     type: 'integerRem :: Integer       -> Integer -> Integer'@@ -171,7 +171,7 @@     warning: 'GHC.Num.Integer.integerRem: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerEq+    name: ["GHC.Num.Integer.integerEq", "GHC.Internal.Bignum.Integer.integerEq"]     kind: Expression     type: 'integerEq :: Integer       -> Integer -> Bool'@@ -179,7 +179,7 @@     warning: 'GHC.Num.Integer.integerEq: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerNe+    name: ["GHC.Num.Integer.integerNe", "GHC.Internal.Bignum.Integer.integerNe"]     kind: Expression     type: 'integerNe :: Integer       -> Integer -> Bool'@@ -187,7 +187,7 @@     warning: 'GHC.Num.Integer.integerNe: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerEq#+    name: ["GHC.Num.Integer.integerEq#", "GHC.Internal.Bignum.Integer.integerEq#"]     kind: Declaration     type: 'integerEq# :: Integer       -> Integer -> Int#'@@ -195,7 +195,7 @@     warning: 'GHC.Num.Integer.integerEq#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerNe#+    name: ["GHC.Num.Integer.integerNe#", "GHC.Internal.Bignum.Integer.integerNe#"]     kind: Declaration     type: 'integerNe# :: Integer       -> Integer -> Int#'@@ -203,7 +203,7 @@     warning: 'GHC.Num.Integer.integerNe#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerLe#+    name: ["GHC.Num.Integer.integerLe#", "GHC.Internal.Bignum.Integer.integerLe#"]     kind: Declaration     type: 'integerLe# :: Integer       -> Integer -> Int#'@@ -211,7 +211,7 @@     warning: 'GHC.Num.Integer.integerLe#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerGt#+    name: ["GHC.Num.Integer.integerGt#", "GHC.Internal.Bignum.Integer.integerGt#"]     kind: Declaration     type: 'integerGt# :: Integer       -> Integer -> Int#'@@ -219,7 +219,7 @@     warning: 'GHC.Num.Integer.integerGt#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerLt#+    name: ["GHC.Num.Integer.integerLt#", "GHC.Internal.Bignum.Integer.integerLt#"]     kind: Declaration     type: 'integerLt# :: Integer       -> Integer -> Int#'@@ -227,7 +227,7 @@     warning: 'GHC.Num.Integer.integerLt#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerGe#+    name: ["GHC.Num.Integer.integerGe#", "GHC.Internal.Bignum.Integer.integerGe#"]     kind: Declaration     type: 'integerGe# :: Integer       -> Integer -> Int#'@@ -235,7 +235,7 @@     warning: 'GHC.Num.Integer.integerGe#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerShiftR#+    name: ["GHC.Num.Integer.integerShiftR#", "GHC.Internal.Bignum.Integer.integerShiftR#"]     kind: Declaration     type: 'integerShiftR#       :: Integer -> Word# -> Integer'@@ -253,7 +253,7 @@     warning: 'GHC.Num.Integer.integerShiftR#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerShiftL#+    name: ["GHC.Num.Integer.integerShiftL#", "GHC.Internal.Bignum.Integer.integerShiftL#"]     kind: Declaration     type: 'integerShiftL#       :: Integer -> Word# -> Integer'@@ -271,7 +271,7 @@     warning: 'GHC.Num.Integer.integerShiftL#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerTestBit#+    name: ["GHC.Num.Integer.integerTestBit#", "GHC.Internal.Bignum.Integer.integerTestBit#"]     kind: Declaration     type: 'integerTestBit       :: Integer -> Word# -> Int#'@@ -279,7 +279,7 @@     warning: 'GHC.Num.Integer.integerTestBit#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerFromWord#+    name: ["GHC.Num.Integer.integerFromWord#", "GHC.Internal.Bignum.Integer.integerFromWord#"]     kind: Expression     type: 'integerFromWord       :: Word# -> Integer'@@ -288,7 +288,7 @@       simulation, but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Integer.integerToWord#+    name: ["GHC.Num.Integer.integerToWord#", "GHC.Internal.Bignum.Integer.integerToWord#"]     kind: Expression     type: 'integerToWord ::       Integer -> Word#'@@ -297,7 +297,7 @@       but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Integer.integerToInt64#+    name: ["GHC.Num.Integer.integerToInt64#", "GHC.Internal.Bignum.Integer.integerToInt64#"]     kind: Expression     type: 'integerToInt64# :: Integer -> Int64#'     template: ~ARG[0]@@ -305,7 +305,7 @@       simulation, but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Integer.integerToWord64#+    name: ["GHC.Num.Integer.integerToWord64#", "GHC.Internal.Bignum.Integer.integerToWord64#"]     comment: only used by 32 bit GHC     kind: Expression     type: 'integerToWord ::@@ -315,7 +315,7 @@       simulation, but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Integer.integerFromWord64#+    name: ["GHC.Num.Integer.integerFromWord64#", "GHC.Internal.Bignum.Integer.integerFromWord64#"]     kind: Expression     type: 'integerFromWord64# :: Word64# -> Integer'     template: signed(std_logic_vector(~ARG[0]))@@ -323,7 +323,7 @@       simulation, but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Integer.integerBit#+    name: ["GHC.Num.Integer.integerBit#", "GHC.Internal.Bignum.Integer.integerBit#"]     kind: Expression     type: 'integerBit :: Word#       -> Integer'@@ -331,7 +331,7 @@     warning: 'GHC.Num.Integer.integerBit#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerComplement+    name: ["GHC.Num.Integer.integerComplement", "GHC.Internal.Bignum.Integer.integerComplement"]     kind: Expression     type: 'integerComplement       :: Integer -> Integer'@@ -339,7 +339,7 @@     warning: 'GHC.Num.Integer.integerComplement: Integers are dynamically sized in       simulation, but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerXor+    name: ["GHC.Num.Integer.integerXor", "GHC.Internal.Bignum.Integer.integerXor"]     kind: Expression     type: 'integerXor :: Integer       -> Integer -> Integer'@@ -347,7 +347,7 @@     warning: 'GHC.Num.Integer.integerXor: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerOr+    name: ["GHC.Num.Integer.integerOr", "GHC.Internal.Bignum.Integer.integerOr"]     kind: Expression     type: 'integerOr :: Integer       -> Integer -> Integer'@@ -355,7 +355,7 @@     warning: 'GHC.Num.Integer.integerOr: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerAnd+    name: ["GHC.Num.Integer.integerAnd", "GHC.Internal.Bignum.Integer.integerAnd"]     kind: Expression     type: 'integerAnd :: Integer       -> Integer -> Integer'@@ -363,7 +363,7 @@     warning: 'GHC.Num.Integer.integerAnd: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerSignum+    name: ["GHC.Num.Integer.integerSignum", "GHC.Internal.Bignum.Integer.integerSignum"]     kind: Declaration     type: 'integerSignum ::       Integer -> Integer'@@ -377,7 +377,7 @@     warning: 'GHC.Num.Integer.integerSignum: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.$wintegerSignum+    name: ["GHC.Num.Integer.$wintegerSignum", "GHC.Internal.Bignum.Integer.$wintegerSignum"]     kind: Declaration     type: '$wsignumInteger       :: Integer -> Int#'@@ -391,7 +391,7 @@     warning: 'GHC.Num.Integer.$wintegerSignum: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerLogBase#+    name: ["GHC.Num.Integer.integerLogBase#", "GHC.Internal.Bignum.Integer.integerLogBase#"]     kind: Expression     type: 'integerLogBase#       :: Integer -> Integer -> Int#'@@ -399,7 +399,7 @@     warning: 'GHC.Num.Integer.integerLogBase#: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerCompare+    name: ["GHC.Num.Integer.integerCompare", "GHC.Internal.Bignum.Integer.integerCompare"]     kind: Declaration     type: 'integerCompare       :: Integer -> Integer -> Ordering'@@ -413,7 +413,7 @@     warning: 'GHC.Num.Integer.integerCompare: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.integerQuot+    name: ["GHC.Num.Integer.integerQuot", "GHC.Internal.Bignum.Integer.integerQuot"]     kind: Declaration     type: 'integerQuot ::       Integer -> Integer -> Integer'@@ -426,7 +426,7 @@     warning: 'GHC.Num.Integer.integerQuot: Integers are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Integer.$wintegerFromInt64#+    name: ["GHC.Num.Integer.$wintegerFromInt64#", "GHC.Internal.Bignum.Integer.$wintegerFromInt64#"]     kind: Expression     type: '$wintegerFromInt64# :: Int64# -> Int#'     template: resize(~ARG[0],~SIZE[~TYPO])
prims/vhdl/GHC_Num_Natural.primitives.yaml view
@@ -1,5 +1,5 @@ - BlackBox:-    name: GHC.Num.Natural.naturalMul+    name: ["GHC.Num.Natural.naturalMul", "GHC.Internal.Bignum.Natural.naturalMul"]     kind: Expression     type: 'timesNatural ::       Natural -> Natural -> Natural'@@ -7,7 +7,7 @@     warning: 'GHC.Num.Natural.timesNatural: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalFromWord#+    name: ["GHC.Num.Natural.naturalFromWord#", "GHC.Internal.Bignum.Natural.naturalFromWord#"]     kind: Expression     type: 'naturalFromWord#       :: Word# -> Natural'@@ -16,7 +16,7 @@       simulation, but fixed-length after synthesis. Use carefully.'     workInfo: Never - BlackBox:-    name: GHC.Num.Natural.naturalRem+    name: ["GHC.Num.Natural.naturalRem", "GHC.Internal.Bignum.Natural.naturalRem"]     kind: Declaration     type: 'naturalRem :: Natural       -> Natural -> Natural'@@ -29,7 +29,7 @@     warning: 'GHC.Num.Natural.naturalRem: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalLogBase#+    name: ["GHC.Num.Natural.naturalLogBase#", "GHC.Internal.Bignum.Natural.naturalLogBase#"]     kind: Expression     type: 'naturalLogBase#       :: Natural -> Natural -> Word#'@@ -37,7 +37,7 @@     warning: 'GHC.Num.Natural.naturalLogBase#: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalEq#+    name: ["GHC.Num.Natural.naturalEq#", "GHC.Internal.Bignum.Natural.naturalEq#"]     kind: Declaration     type: 'naturalEq# :: Natural       -> Natural -> Int#'@@ -45,7 +45,7 @@     warning: 'GHC.Num.Natural.naturalEq#: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalNe#+    name: ["GHC.Num.Natural.naturalNe#", "GHC.Internal.Bignum.Natural.naturalNe#"]     kind: Declaration     type: 'naturalNe# :: Natural       -> Natural -> Int#'@@ -54,7 +54,7 @@     warning: 'GHC.Num.Natural.naturalNe#: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalLe#+    name: ["GHC.Num.Natural.naturalLe#", "GHC.Internal.Bignum.Natural.naturalLe#"]     kind: Declaration     type: 'naturalLe# :: Natural       -> Natural -> Int#'@@ -63,7 +63,7 @@     warning: 'GHC.Num.Natural.naturalLe#: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalGt#+    name: ["GHC.Num.Natural.naturalGt#", "GHC.Internal.Bignum.Natural.naturalGt#"]     kind: Declaration     type: 'naturalGt# :: Natural       -> Natural -> Int#'@@ -71,7 +71,7 @@     warning: 'GHC.Num.Natural.naturalGt#: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalLt#+    name: ["GHC.Num.Natural.naturalLt#", "GHC.Internal.Bignum.Natural.naturalLt#"]     kind: Declaration     type: 'naturalLt# :: Natural       -> Natural -> Int#'@@ -79,7 +79,7 @@     warning: 'GHC.Num.Natural.naturalLt#: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalGe#+    name: ["GHC.Num.Natural.naturalGe#", "GHC.Internal.Bignum.Natural.naturalGe#"]     kind: Declaration     type: 'naturalGe# :: Natural       -> Natural -> Int#'@@ -88,7 +88,7 @@     warning: 'GHC.Num.Natural.naturalGe#: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalShiftL#+    name: ["GHC.Num.Natural.naturalShiftL#", "GHC.Internal.Bignum.Natural.naturalShiftL#"]     kind: Declaration     type: 'naturalShiftL#       :: Natural -> Word# -> Natural'@@ -106,7 +106,7 @@     warning: 'GHC.Num.Natural.naturalShiftL#: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalShiftR#+    name: ["GHC.Num.Natural.naturalShiftR#", "GHC.Internal.Bignum.Natural.naturalShiftR#"]     kind: Declaration     type: 'naturalShiftR#       :: Natural -> Word# -> Natural'@@ -124,7 +124,7 @@     warning: 'GHC.Num.Natural.naturalShiftR#: Naturals are dynamically sized in simulation,       but fixed-length after synthesis. Use carefully.' - BlackBox:-    name: GHC.Num.Natural.naturalCompare+    name: ["GHC.Num.Natural.naturalCompare", "GHC.Internal.Bignum.Natural.naturalCompare"]     kind: Declaration     type: 'naturalCompare       :: Natural -> Natural -> Ordering'@@ -135,7 +135,7 @@                "10";       -- end naturalCompare - BlackBox:-    name: GHC.Num.Natural.naturalQuot+    name: ["GHC.Num.Natural.naturalQuot", "GHC.Internal.Bignum.Natural.naturalQuot"]     kind: Declaration     type: 'naturalQuot ::       Natural -> Natural -> Natural'
prims/vhdl/GHC_Prim.primitives.yaml view
@@ -1,47 +1,47 @@ - BlackBox:-    name: GHC.Prim.gtChar#+    name: ["GHC.Prim.gtChar#", "GHC.Internal.Prim.gtChar#"]     kind: Declaration     type: 'gtChar# :: Char#       -> Char# -> Int#'     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.geChar#+    name: ["GHC.Prim.geChar#", "GHC.Internal.Prim.geChar#"]     kind: Declaration     type: 'geChar# :: Char#       -> Char# -> Int#'     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.eqChar#+    name: ["GHC.Prim.eqChar#", "GHC.Internal.Prim.eqChar#"]     kind: Declaration     type: 'eqChar# :: Char#       -> Char# -> Int#'     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.neChar#+    name: ["GHC.Prim.neChar#", "GHC.Internal.Prim.neChar#"]     kind: Declaration     type: 'neChar# :: Char#       -> Char# -> Int#'     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.ltChar#+    name: ["GHC.Prim.ltChar#", "GHC.Internal.Prim.ltChar#"]     kind: Declaration     type: 'ltChar# :: Char#       -> Char# -> Int#'     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.leChar#+    name: ["GHC.Prim.leChar#", "GHC.Internal.Prim.leChar#"]     kind: Declaration     type: 'leChar# :: Char#       -> Char# -> Int#'     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.ord#+    name: ["GHC.Prim.ord#", "GHC.Internal.Prim.ord#"]     kind: Expression     type: 'ord# :: Char# ->       Int#'     template: signed(std_logic_vector(resize(~ARG[0],~SIZE[~TYPO]))) - BlackBox:-    name: GHC.Prim.*#+    name: ["GHC.Prim.*#", "GHC.Internal.Prim.*#"]     kind: Declaration     type: '(*#) :: Int# ->       Int# -> Int#'@@ -53,7 +53,7 @@         ~RESULT <= ~SYM[1](~SIZE[~TYPO]-1 downto 0);       end block; - BlackBox:-    name: GHC.Prim.remInt#+    name: ["GHC.Prim.remInt#", "GHC.Internal.Prim.remInt#"]     kind: Declaration     type: 'remInt# :: Int#       -> Int# -> Int#'@@ -64,7 +64,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.quotRemInt#+    name: ["GHC.Prim.quotRemInt#", "GHC.Internal.Prim.quotRemInt#"]     kind: Declaration     type: 'quotRemInt# ::       Int# -> Int# -> (#Int#, Int##)'@@ -76,87 +76,87 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.andI#+    name: ["GHC.Prim.andI#", "GHC.Internal.Prim.andI#"]     kind: Expression     type: 'and# :: Int# ->       Int# -> Int#'     template: ~ARG[0] and ~ARG[1] - BlackBox:-    name: GHC.Prim.orI#+    name: ["GHC.Prim.orI#", "GHC.Internal.Prim.orI#"]     kind: Expression     type: 'or# :: Int# ->       Int# -> Int#'     template: ~ARG[0] or ~ARG[1] - BlackBox:-    name: GHC.Prim.xorI#+    name: ["GHC.Prim.xorI#", "GHC.Internal.Prim.xorI#"]     kind: Expression     type: 'xor# :: Int# ->       Int# -> Int#'     template: ~ARG[0] xor ~ARG[1] - BlackBox:-    name: GHC.Prim.notI#+    name: ["GHC.Prim.notI#", "GHC.Internal.Prim.notI#"]     kind: Expression     type: 'not# :: Int# ->       Int#'     template: not ~ARG[0] - BlackBox:-    name: GHC.Prim.negateInt#+    name: ["GHC.Prim.negateInt#", "GHC.Internal.Prim.negateInt#"]     kind: Expression     type: 'negateInt# :: Int#       -> Int#'     template: -~ARG[0] - BlackBox:-    name: GHC.Prim.>#+    name: ["GHC.Prim.>#", "GHC.Internal.Prim.>#"]     kind: Declaration     type: '(>#) :: Int# ->       Int# -> Int#'     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.>=#+    name: ["GHC.Prim.>=#", "GHC.Internal.Prim.>=#"]     kind: Declaration     type: '(>=#) :: Int# ->       Int# -> Int#'     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.==#+    name: ["GHC.Prim.==#", "GHC.Internal.Prim.==#"]     kind: Declaration     type: '(==) :: Int# ->       Int# -> Int#'     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim./=#+    name: ["GHC.Prim./=#", "GHC.Internal.Prim./=#"]     kind: Declaration     type: '(/=#) :: Int# ->       Int# -> Int#'     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.<#+    name: ["GHC.Prim.<#", "GHC.Internal.Prim.<#"]     kind: Declaration     type: '(<#) :: Int# ->       Int# -> Int#'     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.<=#+    name: ["GHC.Prim.<=#", "GHC.Internal.Prim.<=#"]     kind: Declaration     type: '(<=#) :: Int# ->       Int# -> Int#'     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.chr#+    name: ["GHC.Prim.chr#", "GHC.Internal.Prim.chr#"]     kind: Expression     type: 'ord# :: Int# ->       Chr#'     template: resize(unsigned(std_logic_vector(~ARG[0])),21)     workInfo: Never - BlackBox:-    name: GHC.Prim.int2Word#+    name: ["GHC.Prim.int2Word#", "GHC.Internal.Prim.int2Word#"]     kind: Expression     type: 'word2Int# :: Int#       -> Word#'     template: unsigned(std_logic_vector(~ARG[0]))     workInfo: Never - BlackBox:-    name: GHC.Prim.uncheckedIShiftL#+    name: ["GHC.Prim.uncheckedIShiftL#", "GHC.Internal.Prim.uncheckedIShiftL#"]     kind: Declaration     type: 'uncheckedIShiftL#       :: Int# -> Int# -> Int#'@@ -176,7 +176,7 @@             ;       end block; - BlackBox:-    name: GHC.Prim.uncheckedIShiftRA#+    name: ["GHC.Prim.uncheckedIShiftRA#", "GHC.Internal.Prim.uncheckedIShiftRA#"]     kind: Declaration     type: 'uncheckedIShiftRA#       :: Int# -> Int# -> Int#'@@ -196,7 +196,7 @@             ;       end block; - BlackBox:-    name: GHC.Prim.uncheckedIShiftRL#+    name: ["GHC.Prim.uncheckedIShiftRL#", "GHC.Internal.Prim.uncheckedIShiftRL#"]     kind: Declaration     type: 'uncheckedIShiftRL#       :: Int# -> Int# -> Int#'@@ -216,13 +216,13 @@             ;       end block; - BlackBox:-    name: GHC.Prim.timesWord#+    name: ["GHC.Prim.timesWord#", "GHC.Internal.Prim.timesWord#"]     kind: Expression     type: 'timesWord# :: Word#       -> Word# -> Word#'     template: resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO]) - BlackBox:-    name: GHC.Prim.remWord#+    name: ["GHC.Prim.remWord#", "GHC.Internal.Prim.remWord#"]     kind: Declaration     type: 'remWord# :: Word#       -> Word# -> Word#'@@ -233,7 +233,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.quotRemWord#+    name: ["GHC.Prim.quotRemWord#", "GHC.Internal.Prim.quotRemWord#"]     kind: Declaration     type: 'quotRemWord# ::       Word# -> Word# -> (#Word#, Word##)'@@ -245,31 +245,31 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.and#+    name: ["GHC.Prim.and#", "GHC.Internal.Prim.and#"]     kind: Expression     type: 'and# :: Word# ->       Word# -> Word#'     template: ~ARG[0] and ~ARG[1] - BlackBox:-    name: GHC.Prim.or#+    name: ["GHC.Prim.or#", "GHC.Internal.Prim.or#"]     kind: Expression     type: 'or# :: Word# ->       Word# -> Word#'     template: ~ARG[0] or ~ARG[1] - BlackBox:-    name: GHC.Prim.xor#+    name: ["GHC.Prim.xor#", "GHC.Internal.Prim.xor#"]     kind: Expression     type: 'xor# :: Word# ->       Word# -> Word#'     template: ~ARG[0] xor ~ARG[1] - BlackBox:-    name: GHC.Prim.not#+    name: ["GHC.Prim.not#", "GHC.Internal.Prim.not#"]     kind: Expression     type: 'not# :: Word# ->       Word#'     template: not ~ARG[0] - BlackBox:-    name: GHC.Prim.uncheckedShiftL#+    name: ["GHC.Prim.uncheckedShiftL#", "GHC.Internal.Prim.uncheckedShiftL#"]     kind: Declaration     type: 'uncheckedShiftL#       :: Word# -> Int# -> Word#'@@ -289,7 +289,7 @@             ;       end block; - BlackBox:-    name: GHC.Prim.uncheckedShiftRL#+    name: ["GHC.Prim.uncheckedShiftRL#", "GHC.Internal.Prim.uncheckedShiftRL#"]     kind: Declaration     type: 'uncheckedShiftR#       :: Word# -> Int# -> Word#'@@ -309,50 +309,50 @@             ;       end block; - BlackBox:-    name: GHC.Prim.word2Int#+    name: ["GHC.Prim.word2Int#", "GHC.Internal.Prim.word2Int#"]     kind: Expression     type: 'word2Int# :: word#       -> Int#'     template: signed(std_logic_vector(~ARG[0]))     workInfo: Never - BlackBox:-    name: GHC.Prim.gtWord#+    name: ["GHC.Prim.gtWord#", "GHC.Internal.Prim.gtWord#"]     kind: Declaration     type: 'gtWord# :: Word#       -> Word# -> Int#'     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.geWord#+    name: ["GHC.Prim.geWord#", "GHC.Internal.Prim.geWord#"]     kind: Declaration     type: 'geWord# :: Word#       -> Word# -> Int#'     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.eqWord#+    name: ["GHC.Prim.eqWord#", "GHC.Internal.Prim.eqWord#"]     kind: Declaration     type: 'eqWord# :: Word#       -> Word# -> Int#'     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.neWord#+    name: ["GHC.Prim.neWord#", "GHC.Internal.Prim.neWord#"]     kind: Declaration     type: 'neWord# :: Word#       -> Word# -> Int#'     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.ltWord#+    name: ["GHC.Prim.ltWord#", "GHC.Internal.Prim.ltWord#"]     kind: Declaration     type: 'ltWord# :: Word#       -> Word# -> Int#'     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.leWord#+    name: ["GHC.Prim.leWord#", "GHC.Internal.Prim.leWord#"]     kind: Declaration     type: 'leWord# :: Word#       -> Word# -> Int#'     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.popCnt8#+    name: ["GHC.Prim.popCnt8#", "GHC.Internal.Prim.popCnt8#"]     kind: Declaration     type: 'popCnt8 :: Word#       -> Word#'@@ -392,7 +392,7 @@       end block;       -- popCnt8 end - BlackBox:-    name: GHC.Prim.popCnt16#+    name: ["GHC.Prim.popCnt16#", "GHC.Internal.Prim.popCnt16#"]     kind: Declaration     type: 'popCnt16 :: Word#       -> Word#'@@ -432,7 +432,7 @@       end block;       -- popCnt16 end - BlackBox:-    name: GHC.Prim.popCnt32#+    name: ["GHC.Prim.popCnt32#", "GHC.Internal.Prim.popCnt32#"]     kind: Declaration     type: 'popCnt32 :: Word#       -> Word#'@@ -472,7 +472,7 @@       end block;       -- popCnt32 end - BlackBox:-    name: GHC.Prim.popCnt64#+    name: ["GHC.Prim.popCnt64#", "GHC.Internal.Prim.popCnt64#"]     kind: Declaration     type: 'popCnt64 :: Word#       -> Word#'@@ -512,7 +512,7 @@       end block;       -- popCnt64 end - BlackBox:-    name: GHC.Prim.popCnt#+    name: ["GHC.Prim.popCnt#", "GHC.Internal.Prim.popCnt#"]     kind: Declaration     type: 'popCnt :: Word#       -> Word#'@@ -552,7 +552,7 @@       end block;       -- popCnt end - BlackBox:-    name: GHC.Prim.clz8#+    name: ["GHC.Prim.clz8#", "GHC.Internal.Prim.clz8#"]     kind: Expression     type: 'clz8 :: Word# -> Word#'     imports:@@ -603,7 +603,7 @@         end;     template: resize(~INCLUDENAME[0].clz8(~VAR[][0](7 downto 0)),~SIZE[~TYPO]) - BlackBox:-    name: GHC.Prim.clz16#+    name: ["GHC.Prim.clz16#", "GHC.Internal.Prim.clz16#"]     kind: Expression     type: 'clz16 :: Word# -> Word#'     imports:@@ -656,7 +656,7 @@         end;     template: resize(~INCLUDENAME[0].clz16(~VAR[][0](15 downto 0)),~SIZE[~TYPO]) - BlackBox:-    name: GHC.Prim.clz32#+    name: ["GHC.Prim.clz32#", "GHC.Internal.Prim.clz32#"]     kind: Expression     type: 'clz32 :: Word# -> Word#'     imports:@@ -712,7 +712,7 @@     template: resize(~INCLUDENAME[0].clz32(~VAR[][0](31 downto 0)),~SIZE[~TYPO])  - BlackBox:-    name: GHC.Prim.clz64#+    name: ["GHC.Prim.clz64#", "GHC.Internal.Prim.clz64#"]     kind: Expression     type: 'clz64 :: Word# -> Word#'     imports:@@ -769,7 +769,7 @@         end;     template: resize(~INCLUDENAME[0].clz64(~ARG[0]),~SIZE[~TYPO]) - BlackBox:-    name: GHC.Prim.clz#+    name: ["GHC.Prim.clz#", "GHC.Internal.Prim.clz#"]     kind: Expression     type: 'clz :: Word# -> Word#'     imports:@@ -844,7 +844,7 @@         end;     template: resize(~INCLUDENAME[0].clz(~ARG[0]),~SIZE[~TYPO]) - BlackBox:-    name: GHC.Prim.ctz8#+    name: ["GHC.Prim.ctz8#", "GHC.Internal.Prim.ctz8#"]     kind: Declaration     type: 'ctz8 :: Word# -> Word#'     imports:@@ -910,7 +910,7 @@       end block;       -- ctz8 end - BlackBox:-    name: GHC.Prim.ctz16#+    name: ["GHC.Prim.ctz16#", "GHC.Internal.Prim.ctz16#"]     kind: Declaration     type: 'ctz16 :: Word# -> Word#'     imports:@@ -978,7 +978,7 @@       end block;       -- ctz16 end - BlackBox:-    name: GHC.Prim.ctz32#+    name: ["GHC.Prim.ctz32#", "GHC.Internal.Prim.ctz32#"]     kind: Declaration     type: 'ctz32 :: Word# -> Word#'     imports:@@ -1048,7 +1048,7 @@       end block;       -- ctz32 end - BlackBox:-    name: GHC.Prim.ctz64#+    name: ["GHC.Prim.ctz64#", "GHC.Internal.Prim.ctz64#"]     kind: Declaration     type: 'ctz64 :: Word# -> Word#'     imports:@@ -1117,7 +1117,7 @@       end block;       -- ctz64 end - BlackBox:-    name: GHC.Prim.ctz#+    name: ["GHC.Prim.ctz#", "GHC.Internal.Prim.ctz#"]     kind: Declaration     type: 'ctz :: Word# -> Word#'     imports:@@ -1203,7 +1203,7 @@       end block;       -- ctz end - BlackBox:-    name: GHC.Prim.byteSwap16#+    name: ["GHC.Prim.byteSwap16#", "GHC.Internal.Prim.byteSwap16#"]     kind: Declaration     type: 'byteSwap16# ::       Word# -> Word#'@@ -1214,7 +1214,7 @@       -- byteSwap16 end     workInfo: Never - BlackBox:-    name: GHC.Prim.byteSwap32#+    name: ["GHC.Prim.byteSwap32#", "GHC.Internal.Prim.byteSwap32#"]     kind: Declaration     type: 'byteSwap32# ::       Word# -> Word#'@@ -1227,7 +1227,7 @@       -- byteSwap32 end     workInfo: Never - BlackBox:-    name: GHC.Prim.byteSwap64#+    name: ["GHC.Prim.byteSwap64#", "GHC.Internal.Prim.byteSwap64#"]     kind: Declaration     type: 'byteSwap64# ::       Word# -> Word#'@@ -1240,7 +1240,7 @@       -- byteSwap64 end     workInfo: Never - BlackBox:-    name: GHC.Prim.byteSwap#+    name: ["GHC.Prim.byteSwap#", "GHC.Internal.Prim.byteSwap#"]     kind: Declaration     type: 'byteSwap# :: Word#       -> Word#'@@ -1255,49 +1255,49 @@       -- byteSwap end     workInfo: Never - BlackBox:-    name: GHC.Prim.narrow8Int#+    name: ["GHC.Prim.narrow8Int#", "GHC.Internal.Prim.narrow8Int#"]     kind: Expression     type: 'narrow8Int# ::       Int# -> Int#'     template: resize(~VAR[i][0](7 downto 0),~SIZE[~TYPO])     workInfo: Never - BlackBox:-    name: GHC.Prim.narrow16Int#+    name: ["GHC.Prim.narrow16Int#", "GHC.Internal.Prim.narrow16Int#"]     kind: Expression     type: 'narrow16Int# ::       Int# -> Int#'     template: resize(~VAR[i][0](15 downto 0),~SIZE[~TYPO])     workInfo: Never - BlackBox:-    name: GHC.Prim.narrow32Int#+    name: ["GHC.Prim.narrow32Int#", "GHC.Internal.Prim.narrow32Int#"]     kind: Expression     type: 'narrow32Int# ::       Int# -> Int#'     template: resize(~VAR[i][0](31 downto 0),~SIZE[~TYPO])     workInfo: Never - BlackBox:-    name: GHC.Prim.narrow8Word#+    name: ["GHC.Prim.narrow8Word#", "GHC.Internal.Prim.narrow8Word#"]     kind: Expression     type: 'narrow8Word# ::       Word# -> Word#'     template: resize(~VAR[w][0](7 downto 0),~SIZE[~TYPO])     workInfo: Never - BlackBox:-    name: GHC.Prim.narrow16Word#+    name: ["GHC.Prim.narrow16Word#", "GHC.Internal.Prim.narrow16Word#"]     kind: Expression     type: 'narrow16Word# ::       Word# -> Word#'     template: resize(~VAR[w][0](15 downto 0),~SIZE[~TYPO])     workInfo: Never - BlackBox:-    name: GHC.Prim.narrow32Word#+    name: ["GHC.Prim.narrow32Word#", "GHC.Internal.Prim.narrow32Word#"]     kind: Expression     type: 'narrow32Word# ::       Word# -> Word#'     template: resize(~VAR[w][0](31 downto 0),~SIZE[~TYPO])     workInfo: Never - BlackBox:-    name: GHC.Prim.bitReverse#+    name: ["GHC.Prim.bitReverse#", "GHC.Internal.Prim.bitReverse#"]     kind: Declaration     type: 'bitReverse# ::       Word# -> Word#'@@ -1310,7 +1310,7 @@       -- bitReverse end     workInfo: Never - BlackBox:-    name: GHC.Prim.bitReverse8#+    name: ["GHC.Prim.bitReverse8#", "GHC.Internal.Prim.bitReverse8#"]     kind: Declaration     type: 'bitReverse8# ::       Word# -> Word#'@@ -1323,7 +1323,7 @@       -- bitReverse8 end     workInfo: Never - BlackBox:-    name: GHC.Prim.bitReverse16#+    name: ["GHC.Prim.bitReverse16#", "GHC.Internal.Prim.bitReverse16#"]     kind: Declaration     type: 'bitReverse16# ::       Word# -> Word#'@@ -1336,7 +1336,7 @@       -- bitReverse16 end     workInfo: Never - BlackBox:-    name: GHC.Prim.bitReverse32#+    name: ["GHC.Prim.bitReverse32#", "GHC.Internal.Prim.bitReverse32#"]     kind: Declaration     type: 'bitReverse32# ::       Word# -> Word#'@@ -1349,7 +1349,7 @@       -- bitReverse32 end     workInfo: Never - BlackBox:-    name: GHC.Prim.bitReverse64#+    name: ["GHC.Prim.bitReverse64#", "GHC.Internal.Prim.bitReverse64#"]     kind: Declaration     type: 'bitReverse64# ::       Word# -> Word#'@@ -1362,7 +1362,7 @@       -- bitReverse64 end     workInfo: Never - BlackBox:-    name: GHC.Prim.quotInt#+    name: ["GHC.Prim.quotInt#", "GHC.Internal.Prim.quotInt#"]     kind: Declaration     type: 'quotInt# :: Int#       -> Int# -> Int#'@@ -1373,7 +1373,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.quotWord#+    name: ["GHC.Prim.quotWord#", "GHC.Internal.Prim.quotWord#"]     kind: Declaration     type: 'quotWord# :: Word#       -> Word# -> Word#'@@ -1384,21 +1384,21 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.int8ToInt#+    name: ["GHC.Prim.int8ToInt#", "GHC.Internal.Prim.int8ToInt#"]     kind: Expression     template: resize(~ARG[0],~SIZE[~TYPO])     workInfo: Never - BlackBox:-    name: GHC.Prim.intToInt8#+    name: ["GHC.Prim.intToInt8#", "GHC.Internal.Prim.intToInt8#"]     kind: Expression     template: ~VAR[i][0](7 downto 0)     workInfo: Never - BlackBox:-    name: GHC.Prim.negateInt8#+    name: ["GHC.Prim.negateInt8#", "GHC.Internal.Prim.negateInt8#"]     kind: Expression     template: -~ARG[0] - BlackBox:-    name: GHC.Prim.timesInt8#+    name: ["GHC.Prim.timesInt8#", "GHC.Internal.Prim.timesInt8#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_mult][0] : block@@ -1408,7 +1408,7 @@         ~RESULT <= ~SYM[1](~SIZE[~TYPO]-1 downto 0);       end block; - BlackBox:-    name: GHC.Prim.quotInt8#+    name: ["GHC.Prim.quotInt8#", "GHC.Internal.Prim.quotInt8#"]     kind: Declaration     template: |-       ~RESULT <= ~ARG[0] / ~ARG[1]@@ -1417,7 +1417,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.remInt8#+    name: ["GHC.Prim.remInt8#", "GHC.Internal.Prim.remInt8#"]     kind: Declaration     template: |-       ~RESULT <= ~ARG[0] rem ~ARG[1]@@ -1426,7 +1426,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.quotRemInt8#+    name: ["GHC.Prim.quotRemInt8#", "GHC.Internal.Prim.quotRemInt8#"]     kind: Declaration     template: |-       ~RESULT <= (~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])@@ -1435,7 +1435,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.uncheckedShiftLInt8#+    name: ["GHC.Prim.uncheckedShiftLInt8#", "GHC.Internal.Prim.uncheckedShiftLInt8#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftL][0] : block@@ -1453,7 +1453,7 @@             ;       end block; - BlackBox:-    name: GHC.Prim.uncheckedShiftRAInt8#+    name: ["GHC.Prim.uncheckedShiftRAInt8#", "GHC.Internal.Prim.uncheckedShiftRAInt8#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftR][0] : block@@ -1471,7 +1471,7 @@             ;       end block; - BlackBox:-    name: GHC.Prim.uncheckedShiftRLInt8#+    name: ["GHC.Prim.uncheckedShiftRLInt8#", "GHC.Internal.Prim.uncheckedShiftRLInt8#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftRL][0] : block@@ -1489,50 +1489,50 @@             ;       end block; - BlackBox:-    name: GHC.Prim.int8ToWord8#+    name: ["GHC.Prim.int8ToWord8#", "GHC.Internal.Prim.int8ToWord8#"]     kind: Expression     template: unsigned(std_logic_vector(~ARG[0]))     workInfo: Never - BlackBox:-    name: GHC.Prim.eqInt8#+    name: ["GHC.Prim.eqInt8#", "GHC.Internal.Prim.eqInt8#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.geInt8#+    name: ["GHC.Prim.geInt8#", "GHC.Internal.Prim.geInt8#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.gtInt8#+    name: ["GHC.Prim.gtInt8#", "GHC.Internal.Prim.gtInt8#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.leInt8#+    name: ["GHC.Prim.leInt8#", "GHC.Internal.Prim.leInt8#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.ltInt8#+    name: ["GHC.Prim.ltInt8#", "GHC.Internal.Prim.ltInt8#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.neInt8#+    name: ["GHC.Prim.neInt8#", "GHC.Internal.Prim.neInt8#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.word8ToWord#+    name: ["GHC.Prim.word8ToWord#", "GHC.Internal.Prim.word8ToWord#"]     kind: Expression     template: resize(~ARG[0],~SIZE[~TYPO])     workInfo: Never - BlackBox:-    name: GHC.Prim.wordToWord8#+    name: ["GHC.Prim.wordToWord8#", "GHC.Internal.Prim.wordToWord8#"]     kind: Expression     template: resize(~ARG[0],~SIZE[~TYPO])     workInfo: Never - BlackBox:-    name: GHC.Prim.timesWord8#+    name: ["GHC.Prim.timesWord8#", "GHC.Internal.Prim.timesWord8#"]     kind: Expression     template: resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO]) - BlackBox:-    name: GHC.Prim.quotWord8#+    name: ["GHC.Prim.quotWord8#", "GHC.Internal.Prim.quotWord8#"]     kind: Declaration     template: |-       ~RESULT <= ~ARG[0] / ~ARG[1]@@ -1541,7 +1541,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.remWord8#+    name: ["GHC.Prim.remWord8#", "GHC.Internal.Prim.remWord8#"]     kind: Declaration     template: |-       ~RESULT <= ~ARG[0] rem ~ARG[1]@@ -1550,7 +1550,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.quotRemWord8#+    name: ["GHC.Prim.quotRemWord8#", "GHC.Internal.Prim.quotRemWord8#"]     kind: Declaration     template: |-       ~RESULT <= (~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])@@ -1559,23 +1559,23 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.andWord8#+    name: ["GHC.Prim.andWord8#", "GHC.Internal.Prim.andWord8#"]     kind: Expression     template: ~ARG[0] and ~ARG[1] - BlackBox:-    name: GHC.Prim.orWord8#+    name: ["GHC.Prim.orWord8#", "GHC.Internal.Prim.orWord8#"]     kind: Expression     template: ~ARG[0] or ~ARG[1] - BlackBox:-    name: GHC.Prim.xorWord8#+    name: ["GHC.Prim.xorWord8#", "GHC.Internal.Prim.xorWord8#"]     kind: Expression     template: ~ARG[0] xor ~ARG[1] - BlackBox:-    name: GHC.Prim.notWord8#+    name: ["GHC.Prim.notWord8#", "GHC.Internal.Prim.notWord8#"]     kind: Expression     template: not ~ARG[0] - BlackBox:-    name: GHC.Prim.uncheckedShiftLWord8#+    name: ["GHC.Prim.uncheckedShiftLWord8#", "GHC.Internal.Prim.uncheckedShiftLWord8#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftL][0] : block@@ -1593,7 +1593,7 @@             ;       end block; - BlackBox:-    name: GHC.Prim.uncheckedShiftRLWord8#+    name: ["GHC.Prim.uncheckedShiftRLWord8#", "GHC.Internal.Prim.uncheckedShiftRLWord8#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftRL][0] : block@@ -1611,50 +1611,50 @@             ;       end block; - BlackBox:-    name: GHC.Prim.word8ToInt8#+    name: ["GHC.Prim.word8ToInt8#", "GHC.Internal.Prim.word8ToInt8#"]     kind: Expression     template: signed(std_logic_vector(~ARG[0]))     workInfo: Never - BlackBox:-    name: GHC.Prim.eqWord8#+    name: ["GHC.Prim.eqWord8#", "GHC.Internal.Prim.eqWord8#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.geWord8#+    name: ["GHC.Prim.geWord8#", "GHC.Internal.Prim.geWord8#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.gtWord8#+    name: ["GHC.Prim.gtWord8#", "GHC.Internal.Prim.gtWord8#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.leWord8#+    name: ["GHC.Prim.leWord8#", "GHC.Internal.Prim.leWord8#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.ltWord8#+    name: ["GHC.Prim.ltWord8#", "GHC.Internal.Prim.ltWord8#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.neWord8#+    name: ["GHC.Prim.neWord8#", "GHC.Internal.Prim.neWord8#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.int16ToInt#+    name: ["GHC.Prim.int16ToInt#", "GHC.Internal.Prim.int16ToInt#"]     kind: Expression     template: resize(~ARG[0],~SIZE[~TYPO])     workInfo: Never - BlackBox:-    name: GHC.Prim.intToInt16#+    name: ["GHC.Prim.intToInt16#", "GHC.Internal.Prim.intToInt16#"]     kind: Expression     template: ~VAR[i][0](15 downto 0)     workInfo: Never - BlackBox:-    name: GHC.Prim.negateInt16#+    name: ["GHC.Prim.negateInt16#", "GHC.Internal.Prim.negateInt16#"]     kind: Expression     template: -~ARG[0] - BlackBox:-    name: GHC.Prim.timesInt16#+    name: ["GHC.Prim.timesInt16#", "GHC.Internal.Prim.timesInt16#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_mult][0] : block@@ -1664,7 +1664,7 @@         ~RESULT <= ~SYM[1](~SIZE[~TYPO]-1 downto 0);       end block; - BlackBox:-    name: GHC.Prim.quotInt16#+    name: ["GHC.Prim.quotInt16#", "GHC.Internal.Prim.quotInt16#"]     kind: Declaration     template: |-       ~RESULT <= ~ARG[0] / ~ARG[1]@@ -1673,7 +1673,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.remInt16#+    name: ["GHC.Prim.remInt16#", "GHC.Internal.Prim.remInt16#"]     kind: Declaration     template: |-       ~RESULT <= ~ARG[0] rem ~ARG[1]@@ -1682,7 +1682,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.quotRemInt16#+    name: ["GHC.Prim.quotRemInt16#", "GHC.Internal.Prim.quotRemInt16#"]     kind: Declaration     template: |-       ~RESULT <= (~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])@@ -1691,7 +1691,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.uncheckedShiftLInt16#+    name: ["GHC.Prim.uncheckedShiftLInt16#", "GHC.Internal.Prim.uncheckedShiftLInt16#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftL][0] : block@@ -1709,7 +1709,7 @@             ;       end block; - BlackBox:-    name: GHC.Prim.uncheckedShiftRAInt16#+    name: ["GHC.Prim.uncheckedShiftRAInt16#", "GHC.Internal.Prim.uncheckedShiftRAInt16#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftR][0] : block@@ -1727,7 +1727,7 @@             ;       end block; - BlackBox:-    name: GHC.Prim.uncheckedShiftRLInt16#+    name: ["GHC.Prim.uncheckedShiftRLInt16#", "GHC.Internal.Prim.uncheckedShiftRLInt16#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftRL][0] : block@@ -1745,50 +1745,50 @@             ;       end block; - BlackBox:-    name: GHC.Prim.int16ToWord16#+    name: ["GHC.Prim.int16ToWord16#", "GHC.Internal.Prim.int16ToWord16#"]     kind: Expression     template: unsigned(std_logic_vector(~ARG[0]))     workInfo: Never - BlackBox:-    name: GHC.Prim.eqInt16#+    name: ["GHC.Prim.eqInt16#", "GHC.Internal.Prim.eqInt16#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.geInt16#+    name: ["GHC.Prim.geInt16#", "GHC.Internal.Prim.geInt16#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.gtInt16#+    name: ["GHC.Prim.gtInt16#", "GHC.Internal.Prim.gtInt16#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.leInt16#+    name: ["GHC.Prim.leInt16#", "GHC.Internal.Prim.leInt16#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.ltInt16#+    name: ["GHC.Prim.ltInt16#", "GHC.Internal.Prim.ltInt16#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.neInt16#+    name: ["GHC.Prim.neInt16#", "GHC.Internal.Prim.neInt16#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.word16ToWord#+    name: ["GHC.Prim.word16ToWord#", "GHC.Internal.Prim.word16ToWord#"]     kind: Expression     template: resize(~ARG[0],~SIZE[~TYPO])     workInfo: Never - BlackBox:-    name: GHC.Prim.wordToWord16#+    name: ["GHC.Prim.wordToWord16#", "GHC.Internal.Prim.wordToWord16#"]     kind: Expression     template: resize(~ARG[0],~SIZE[~TYPO])     workInfo: Never - BlackBox:-    name: GHC.Prim.timesWord16#+    name: ["GHC.Prim.timesWord16#", "GHC.Internal.Prim.timesWord16#"]     kind: Expression     template: resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO]) - BlackBox:-    name: GHC.Prim.quotWord16#+    name: ["GHC.Prim.quotWord16#", "GHC.Internal.Prim.quotWord16#"]     kind: Declaration     template: |-       ~RESULT <= ~ARG[0] / ~ARG[1]@@ -1797,7 +1797,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.remWord16#+    name: ["GHC.Prim.remWord16#", "GHC.Internal.Prim.remWord16#"]     kind: Declaration     template: |-       ~RESULT <= ~ARG[0] rem ~ARG[1]@@ -1806,7 +1806,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.quotRemWord16#+    name: ["GHC.Prim.quotRemWord16#", "GHC.Internal.Prim.quotRemWord16#"]     kind: Declaration     template: |-       ~RESULT <= (~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])@@ -1815,23 +1815,23 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.andWord16#+    name: ["GHC.Prim.andWord16#", "GHC.Internal.Prim.andWord16#"]     kind: Expression     template: ~ARG[0] and ~ARG[1] - BlackBox:-    name: GHC.Prim.orWord16#+    name: ["GHC.Prim.orWord16#", "GHC.Internal.Prim.orWord16#"]     kind: Expression     template: ~ARG[0] or ~ARG[1] - BlackBox:-    name: GHC.Prim.xorWord16#+    name: ["GHC.Prim.xorWord16#", "GHC.Internal.Prim.xorWord16#"]     kind: Expression     template: ~ARG[0] xor ~ARG[1] - BlackBox:-    name: GHC.Prim.notWord16#+    name: ["GHC.Prim.notWord16#", "GHC.Internal.Prim.notWord16#"]     kind: Expression     template: not ~ARG[0] - BlackBox:-    name: GHC.Prim.uncheckedShiftLWord16#+    name: ["GHC.Prim.uncheckedShiftLWord16#", "GHC.Internal.Prim.uncheckedShiftLWord16#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftL][0] : block@@ -1849,7 +1849,7 @@             ;       end block; - BlackBox:-    name: GHC.Prim.uncheckedShiftRLWord16#+    name: ["GHC.Prim.uncheckedShiftRLWord16#", "GHC.Internal.Prim.uncheckedShiftRLWord16#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftRL][0] : block@@ -1867,50 +1867,50 @@             ;       end block; - BlackBox:-    name: GHC.Prim.word16ToInt16#+    name: ["GHC.Prim.word16ToInt16#", "GHC.Internal.Prim.word16ToInt16#"]     kind: Expression     template: signed(std_logic_vector(~ARG[0]))     workInfo: Never - BlackBox:-    name: GHC.Prim.eqWord16#+    name: ["GHC.Prim.eqWord16#", "GHC.Internal.Prim.eqWord16#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.geWord16#+    name: ["GHC.Prim.geWord16#", "GHC.Internal.Prim.geWord16#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.gtWord16#+    name: ["GHC.Prim.gtWord16#", "GHC.Internal.Prim.gtWord16#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.leWord16#+    name: ["GHC.Prim.leWord16#", "GHC.Internal.Prim.leWord16#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.ltWord16#+    name: ["GHC.Prim.ltWord16#", "GHC.Internal.Prim.ltWord16#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.neWord16#+    name: ["GHC.Prim.neWord16#", "GHC.Internal.Prim.neWord16#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.int32ToInt#+    name: ["GHC.Prim.int32ToInt#", "GHC.Internal.Prim.int32ToInt#"]     kind: Expression     template: resize(~ARG[0],~SIZE[~TYPO])     workInfo: Never - BlackBox:-    name: GHC.Prim.intToInt32#+    name: ["GHC.Prim.intToInt32#", "GHC.Internal.Prim.intToInt32#"]     kind: Expression     template: ~VAR[i][0](31 downto 0)     workInfo: Never - BlackBox:-    name: GHC.Prim.negateInt32#+    name: ["GHC.Prim.negateInt32#", "GHC.Internal.Prim.negateInt32#"]     kind: Expression     template: -~ARG[0] - BlackBox:-    name: GHC.Prim.timesInt32#+    name: ["GHC.Prim.timesInt32#", "GHC.Internal.Prim.timesInt32#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_mult][0] : block@@ -1920,7 +1920,7 @@         ~RESULT <= ~SYM[1](~SIZE[~TYPO]-1 downto 0);       end block; - BlackBox:-    name: GHC.Prim.quotInt32#+    name: ["GHC.Prim.quotInt32#", "GHC.Internal.Prim.quotInt32#"]     kind: Declaration     template: |-       ~RESULT <= ~ARG[0] / ~ARG[1]@@ -1929,7 +1929,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.remInt32#+    name: ["GHC.Prim.remInt32#", "GHC.Internal.Prim.remInt32#"]     kind: Declaration     template: |-       ~RESULT <= ~ARG[0] rem ~ARG[1]@@ -1938,7 +1938,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.quotRemInt32#+    name: ["GHC.Prim.quotRemInt32#", "GHC.Internal.Prim.quotRemInt32#"]     kind: Declaration     template: |-       ~RESULT <= (~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])@@ -1947,7 +1947,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.uncheckedShiftLInt32#+    name: ["GHC.Prim.uncheckedShiftLInt32#", "GHC.Internal.Prim.uncheckedShiftLInt32#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftL][0] : block@@ -1965,7 +1965,7 @@             ;       end block; - BlackBox:-    name: GHC.Prim.uncheckedShiftRAInt32#+    name: ["GHC.Prim.uncheckedShiftRAInt32#", "GHC.Internal.Prim.uncheckedShiftRAInt32#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftR][0] : block@@ -1983,7 +1983,7 @@             ;       end block; - BlackBox:-    name: GHC.Prim.uncheckedShiftRLInt32#+    name: ["GHC.Prim.uncheckedShiftRLInt32#", "GHC.Internal.Prim.uncheckedShiftRLInt32#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftRL][0] : block@@ -2001,50 +2001,50 @@             ;       end block; - BlackBox:-    name: GHC.Prim.int32ToWord32#+    name: ["GHC.Prim.int32ToWord32#", "GHC.Internal.Prim.int32ToWord32#"]     kind: Expression     template: unsigned(std_logic_vector(~ARG[0]))     workInfo: Never - BlackBox:-    name: GHC.Prim.eqInt32#+    name: ["GHC.Prim.eqInt32#", "GHC.Internal.Prim.eqInt32#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.geInt32#+    name: ["GHC.Prim.geInt32#", "GHC.Internal.Prim.geInt32#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.gtInt32#+    name: ["GHC.Prim.gtInt32#", "GHC.Internal.Prim.gtInt32#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.leInt32#+    name: ["GHC.Prim.leInt32#", "GHC.Internal.Prim.leInt32#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.ltInt32#+    name: ["GHC.Prim.ltInt32#", "GHC.Internal.Prim.ltInt32#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.neInt32#+    name: ["GHC.Prim.neInt32#", "GHC.Internal.Prim.neInt32#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.word32ToWord#+    name: ["GHC.Prim.word32ToWord#", "GHC.Internal.Prim.word32ToWord#"]     kind: Expression     template: resize(~ARG[0],~SIZE[~TYPO])     workInfo: Never - BlackBox:-    name: GHC.Prim.wordToWord32#+    name: ["GHC.Prim.wordToWord32#", "GHC.Internal.Prim.wordToWord32#"]     kind: Expression     template: resize(~ARG[0],~SIZE[~TYPO])     workInfo: Never - BlackBox:-    name: GHC.Prim.timesWord32#+    name: ["GHC.Prim.timesWord32#", "GHC.Internal.Prim.timesWord32#"]     kind: Expression     template: resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO]) - BlackBox:-    name: GHC.Prim.quotWord32#+    name: ["GHC.Prim.quotWord32#", "GHC.Internal.Prim.quotWord32#"]     kind: Declaration     template: |-       ~RESULT <= ~ARG[0] / ~ARG[1]@@ -2053,7 +2053,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.remWord32#+    name: ["GHC.Prim.remWord32#", "GHC.Internal.Prim.remWord32#"]     kind: Declaration     template: |-       ~RESULT <= ~ARG[0] rem ~ARG[1]@@ -2062,7 +2062,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.quotRemWord32#+    name: ["GHC.Prim.quotRemWord32#", "GHC.Internal.Prim.quotRemWord32#"]     kind: Declaration     template: |-       ~RESULT <= (~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])@@ -2071,23 +2071,23 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.andWord32#+    name: ["GHC.Prim.andWord32#", "GHC.Internal.Prim.andWord32#"]     kind: Expression     template: ~ARG[0] and ~ARG[1] - BlackBox:-    name: GHC.Prim.orWord32#+    name: ["GHC.Prim.orWord32#", "GHC.Internal.Prim.orWord32#"]     kind: Expression     template: ~ARG[0] or ~ARG[1] - BlackBox:-    name: GHC.Prim.xorWord32#+    name: ["GHC.Prim.xorWord32#", "GHC.Internal.Prim.xorWord32#"]     kind: Expression     template: ~ARG[0] xor ~ARG[1] - BlackBox:-    name: GHC.Prim.notWord32#+    name: ["GHC.Prim.notWord32#", "GHC.Internal.Prim.notWord32#"]     kind: Expression     template: not ~ARG[0] - BlackBox:-    name: GHC.Prim.uncheckedShiftLWord32#+    name: ["GHC.Prim.uncheckedShiftLWord32#", "GHC.Internal.Prim.uncheckedShiftLWord32#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftL][0] : block@@ -2105,7 +2105,7 @@             ;       end block; - BlackBox:-    name: GHC.Prim.uncheckedShiftRLWord32#+    name: ["GHC.Prim.uncheckedShiftRLWord32#", "GHC.Internal.Prim.uncheckedShiftRLWord32#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftRL][0] : block@@ -2123,50 +2123,50 @@             ;       end block; - BlackBox:-    name: GHC.Prim.word32ToInt32#+    name: ["GHC.Prim.word32ToInt32#", "GHC.Internal.Prim.word32ToInt32#"]     kind: Expression     template: signed(std_logic_vector(~ARG[0]))     workInfo: Never - BlackBox:-    name: GHC.Prim.eqWord32#+    name: ["GHC.Prim.eqWord32#", "GHC.Internal.Prim.eqWord32#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.geWord32#+    name: ["GHC.Prim.geWord32#", "GHC.Internal.Prim.geWord32#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.gtWord32#+    name: ["GHC.Prim.gtWord32#", "GHC.Internal.Prim.gtWord32#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.leWord32#+    name: ["GHC.Prim.leWord32#", "GHC.Internal.Prim.leWord32#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.ltWord32#+    name: ["GHC.Prim.ltWord32#", "GHC.Internal.Prim.ltWord32#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.neWord32#+    name: ["GHC.Prim.neWord32#", "GHC.Internal.Prim.neWord32#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.int64ToInt#+    name: ["GHC.Prim.int64ToInt#", "GHC.Internal.Prim.int64ToInt#"]     kind: Expression     template: resize(~ARG[0],~SIZE[~TYPO])     workInfo: Never - BlackBox:-    name: GHC.Prim.intToInt64#+    name: ["GHC.Prim.intToInt64#", "GHC.Internal.Prim.intToInt64#"]     kind: Expression     template: resize(~ARG[0],~SIZE[~TYPO])     workInfo: Never - BlackBox:-    name: GHC.Prim.negateInt64#+    name: ["GHC.Prim.negateInt64#", "GHC.Internal.Prim.negateInt64#"]     kind: Expression     template: -~ARG[0] - BlackBox:-    name: GHC.Prim.timesInt64#+    name: ["GHC.Prim.timesInt64#", "GHC.Internal.Prim.timesInt64#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_mult][0] : block@@ -2176,7 +2176,7 @@         ~RESULT <= ~SYM[1](~SIZE[~TYPO]-1 downto 0);       end block; - BlackBox:-    name: GHC.Prim.quotInt64#+    name: ["GHC.Prim.quotInt64#", "GHC.Internal.Prim.quotInt64#"]     kind: Declaration     template: |-       ~RESULT <= ~ARG[0] / ~ARG[1]@@ -2185,7 +2185,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.remInt64#+    name: ["GHC.Prim.remInt64#", "GHC.Internal.Prim.remInt64#"]     kind: Declaration     template: |-       ~RESULT <= ~ARG[0] rem ~ARG[1]@@ -2194,7 +2194,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.quotRemInt64#+    name: ["GHC.Prim.quotRemInt64#", "GHC.Internal.Prim.quotRemInt64#"]     kind: Declaration     template: |-       ~RESULT <= (~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])@@ -2203,7 +2203,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.uncheckedIShiftL64#+    name: ["GHC.Prim.uncheckedIShiftL64#", "GHC.Internal.Prim.uncheckedIShiftL64#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftL][0] : block@@ -2221,7 +2221,7 @@             ;       end block; - BlackBox:-    name: GHC.Prim.uncheckedIShiftRA64#+    name: ["GHC.Prim.uncheckedIShiftRA64#", "GHC.Internal.Prim.uncheckedIShiftRA64#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftR][0] : block@@ -2239,7 +2239,7 @@             ;       end block; - BlackBox:-    name: GHC.Prim.uncheckedIShiftRL64#+    name: ["GHC.Prim.uncheckedIShiftRL64#", "GHC.Internal.Prim.uncheckedIShiftRL64#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftRL][0] : block@@ -2257,50 +2257,50 @@             ;       end block; - BlackBox:-    name: GHC.Prim.int64ToWord64#+    name: ["GHC.Prim.int64ToWord64#", "GHC.Internal.Prim.int64ToWord64#"]     kind: Expression     template: unsigned(std_logic_vector(~ARG[0]))     workInfo: Never - BlackBox:-    name: GHC.Prim.eqInt64#+    name: ["GHC.Prim.eqInt64#", "GHC.Internal.Prim.eqInt64#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.geInt64#+    name: ["GHC.Prim.geInt64#", "GHC.Internal.Prim.geInt64#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.gtInt64#+    name: ["GHC.Prim.gtInt64#", "GHC.Internal.Prim.gtInt64#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.leInt64#+    name: ["GHC.Prim.leInt64#", "GHC.Internal.Prim.leInt64#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.ltInt64#+    name: ["GHC.Prim.ltInt64#", "GHC.Internal.Prim.ltInt64#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.neInt64#+    name: ["GHC.Prim.neInt64#", "GHC.Internal.Prim.neInt64#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.word64ToWord#+    name: ["GHC.Prim.word64ToWord#", "GHC.Internal.Prim.word64ToWord#"]     kind: Expression     template: resize(~ARG[0],~SIZE[~TYPO])     workInfo: Never - BlackBox:-    name: GHC.Prim.wordToWord64#+    name: ["GHC.Prim.wordToWord64#", "GHC.Internal.Prim.wordToWord64#"]     kind: Expression     template: resize(~ARG[0],~SIZE[~TYPO])     workInfo: Never - BlackBox:-    name: GHC.Prim.timesWord64#+    name: ["GHC.Prim.timesWord64#", "GHC.Internal.Prim.timesWord64#"]     kind: Expression     template: resize(~ARG[0] * ~ARG[1],~SIZE[~TYPO]) - BlackBox:-    name: GHC.Prim.quotWord64#+    name: ["GHC.Prim.quotWord64#", "GHC.Internal.Prim.quotWord64#"]     kind: Declaration     template: |-       ~RESULT <= ~ARG[0] / ~ARG[1]@@ -2309,7 +2309,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.remWord64#+    name: ["GHC.Prim.remWord64#", "GHC.Internal.Prim.remWord64#"]     kind: Declaration     template: |-       ~RESULT <= ~ARG[0] rem ~ARG[1]@@ -2318,7 +2318,7 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.quotRemWord64#+    name: ["GHC.Prim.quotRemWord64#", "GHC.Internal.Prim.quotRemWord64#"]     kind: Declaration     template: |-       ~RESULT <= (~ARG[0] / ~ARG[1], ~ARG[0] rem ~ARG[1])@@ -2327,23 +2327,23 @@           -- pragma translate_on           ; - BlackBox:-    name: GHC.Prim.and64#+    name: ["GHC.Prim.and64#", "GHC.Internal.Prim.and64#"]     kind: Expression     template: ~ARG[0] and ~ARG[1] - BlackBox:-    name: GHC.Prim.or64#+    name: ["GHC.Prim.or64#", "GHC.Internal.Prim.or64#"]     kind: Expression     template: ~ARG[0] or ~ARG[1] - BlackBox:-    name: GHC.Prim.xor64#+    name: ["GHC.Prim.xor64#", "GHC.Internal.Prim.xor64#"]     kind: Expression     template: ~ARG[0] xor ~ARG[1] - BlackBox:-    name: GHC.Prim.not64#+    name: ["GHC.Prim.not64#", "GHC.Internal.Prim.not64#"]     kind: Expression     template: not ~ARG[0] - BlackBox:-    name: GHC.Prim.uncheckedShiftL64#+    name: ["GHC.Prim.uncheckedShiftL64#", "GHC.Internal.Prim.uncheckedShiftL64#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftL][0] : block@@ -2361,7 +2361,7 @@             ;       end block; - BlackBox:-    name: GHC.Prim.uncheckedShiftRL64#+    name: ["GHC.Prim.uncheckedShiftRL64#", "GHC.Internal.Prim.uncheckedShiftRL64#"]     kind: Declaration     template: |-       ~GENSYM[~RESULT_shiftRL][0] : block@@ -2379,31 +2379,31 @@             ;       end block; - BlackBox:-    name: GHC.Prim.word64ToInt64#+    name: ["GHC.Prim.word64ToInt64#", "GHC.Internal.Prim.word64ToInt64#"]     kind: Expression     template: signed(std_logic_vector(~ARG[0]))     workInfo: Never - BlackBox:-    name: GHC.Prim.eqWord64#+    name: ["GHC.Prim.eqWord64#", "GHC.Internal.Prim.eqWord64#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] = ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.geWord64#+    name: ["GHC.Prim.geWord64#", "GHC.Internal.Prim.geWord64#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] >= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.gtWord64#+    name: ["GHC.Prim.gtWord64#", "GHC.Internal.Prim.gtWord64#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] > ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.leWord64#+    name: ["GHC.Prim.leWord64#", "GHC.Internal.Prim.leWord64#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] <= ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.ltWord64#+    name: ["GHC.Prim.ltWord64#", "GHC.Internal.Prim.ltWord64#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] < ~ARG[1] else to_signed(0,~SIZE[~TYPO]); - BlackBox:-    name: GHC.Prim.neWord64#+    name: ["GHC.Prim.neWord64#", "GHC.Internal.Prim.neWord64#"]     kind: Declaration     template: ~RESULT <= to_signed(1,~SIZE[~TYPO]) when ~ARG[0] /= ~ARG[1] else to_signed(0,~SIZE[~TYPO]);
src/Clash/Core/Term.hs view
@@ -29,6 +29,7 @@   , TmName   , varToId   , Bind(..)+  , bindToList   , LetBinding   , Pat (..)   , patIds
src/Clash/Core/TyCon.hs view
@@ -129,6 +129,9 @@       any (`T.isPrefixOf` (nameOcc nm)) $ map T.pack         [ "GHC.Tuple.Prim.Tuple"         , "GHC.Tuple.Tuple"+        -- GHC >= 9.14 hosts the Tuple type constructors here, with+        -- 'base'\''s 'GHC.Tuple' re-exporting them.+        , "GHC.Internal.Tuple.Tuple"         ]  -- | Get the DataCons belonging to a TyCon
src/Clash/Core/Type.hs view
@@ -518,11 +518,11 @@       [i1, i2] ->         Just $ ConstTy $ TyCon $           case compare i1 i2 of-            LT -> Name User "GHC.Types.LT"+            LT -> Name User (showt 'LT)                     (fromGhcUnique ordLTDataConKey) wiredInSrcSpan-            EQ -> Name User "GHC.Types.EQ"+            EQ -> Name User (showt 'EQ)                     (fromGhcUnique ordEQDataConKey) wiredInSrcSpan-            GT -> Name User "GHC.Types.GT"+            GT -> Name User (showt 'GT)                     (fromGhcUnique ordGTDataConKey) wiredInSrcSpan       _ -> Nothing @@ -531,11 +531,11 @@       [s1, s2] ->         Just $ ConstTy $ TyCon $           case compare s1 s2 of-            LT -> Name User "GHC.Types.LT"+            LT -> Name User (showt 'LT)                     (fromGhcUnique ordLTDataConKey) wiredInSrcSpan-            EQ -> Name User "GHC.Types.EQ"+            EQ -> Name User (showt 'EQ)                     (fromGhcUnique ordEQDataConKey) wiredInSrcSpan-            GT -> Name User "GHC.Types.GT"+            GT -> Name User (showt 'GT)                     (fromGhcUnique ordGTDataConKey) wiredInSrcSpan       _ -> Nothing 
src/Clash/Core/Util.hs view
@@ -629,7 +629,11 @@   --   isHidden :: Name a -> [Type] -> Bool   isHidden nm [a1, a2] | TyConApp a2Nm _ <- tyView a2 =-       nameOcc nm `elem` ["GHC.Classes.(%,%)", "GHC.Classes.CTuple2"]+       -- Constraint-tuple type constructors moved from 'GHC.Classes' (<= 9.12)+       -- to 'GHC.Internal.Classes' (>= 9.14); both forms appear here.+       nameOcc nm `elem` [ "GHC.Classes.(%,%)", "GHC.Internal.Classes.(%,%)"+                         , "GHC.Classes.CTuple2", "GHC.Internal.Classes.CTuple2"+                         ]     && splitTy (tyView (stripIP a1))     && nameOcc a2Nm == "Clash.Signal.Internal.KnownDomain"   isHidden _ _ = False@@ -643,7 +647,10 @@                            -- in a bitvector, so we need to make sure Clash                            -- splits them off                            , "Clash.Explicit.SimIO.File"+                           -- Handle moved to 'GHC.Internal.IO.Handle.Types' on+                           -- GHC >= 9.14.                            , "GHC.IO.Handle.Types.Handle"+                           , "GHC.Internal.IO.Handle.Types.Handle"                            ]   splitTy _ = False 
src/Clash/Driver.hs view
@@ -275,6 +275,8 @@   -> Maybe TopEntity   -> String   -> (String, Maybe String)+prefixModuleName _hdl _compPrefix (Just (tb@(TestBench _))) _modName =+  error $ "Internal error: prefixModuleName: unexpected TestBench: " <> show tb prefixModuleName hdl compPrefix annM modName =   case compPrefix of     Just (Data.Text.unpack -> p)
src/Clash/Driver/BrokenGhcs.hs view
@@ -1,5 +1,6 @@ {-|-Copyright   :  (C) 2024, Martijn Bastiaan+Copyright   :  (C) 2024, Martijn Bastiaan,+                   2026, QBayLogic B.V. License     :  BSD2 (see the file LICENSE) Maintainer  :  QBayLogic B.V. <devops@qbaylogic.com> @@ -114,7 +115,7 @@  -- | Which GHCs are broken and why brokenGhcs :: [Why]-brokenGhcs = [brokenClashCores, brokenTypeErrors, slowStarts]+brokenGhcs = [brokenClashCores, brokenTypeErrors, slowStarts, brokenGhc912]  where   brokenClashCores = Why     { what = "GHC is known to fail compilation of libraries used by the Clash compiler test suite"@@ -135,6 +136,16 @@     , solution = "Upgrade to GHC 9.6.3 or newer, or downgrade to GHC 9.4.7"     , issue = "https://github.com/clash-lang/clash-compiler/issues/2710"     , brokenOn = [(All, GhcRange{from=Ghc 9 4 8, to=Ghc 9 6 3})]+    }++  -- GHC 9.12.4 fixes the bugs affecting Clash reported in:+  -- https://gitlab.haskell.org/ghc/ghc/-/work_items/26185+  -- https://gitlab.haskell.org/ghc/ghc/-/work_items/26711+  brokenGhc912 = Why+    { what = "GHC 9.12.1 through 9.12.3 contain bugs affecting Clash"+    , solution = "Upgrade to GHC 9.12.4 or newer"+    , issue = "https://github.com/clash-lang/clash-compiler/issues/3415"+    , brokenOn = [(All, GhcRange{from=Ghc 9 12 1, to=Ghc 9 12 4})]     }  -- | Given a 'BrokenOn', determine whether current OS matches
src/Clash/Netlist.hs view
@@ -26,6 +26,9 @@ import           Control.Lens                     ((.=), (<~)) import qualified Control.Lens                     as Lens import           Control.Monad                    (zipWithM)+import           Data.Text.Extra                  (showt)+import           GHC.Num.Integer                  (Integer(..))+import           GHC.Num.Natural                  (Natural(..)) import           Control.Monad.Extra              (concatMapM, mapMaybeM) import           Control.Monad.Reader             (runReaderT) import           Control.Monad.State.Strict       (State, runStateT, runState)@@ -945,6 +948,10 @@    case scrutRendered of     Left newDecls -> pure (Noop, newDecls)+    -- The projected field is zero-width / void, so it is filtered out of the+    -- subject's fields below and there is nothing to select. Rendering it+    -- anyway would reference the pattern's binder, which is never declared.+    Right (_, _, decls) | isVoid vHwTy -> pure (Noop, decls)     Right (selId, modM, decls) -> do       let altVarId = Id.unsafeFromCoreId varTm       modifier <- case pat of@@ -1098,22 +1105,22 @@         in  return dc'       Void {} -> return Noop       Signed _-        | dcNm == "GHC.Num.Integer.IS"+        | dcNm == showt 'IS         , (a:_) <- argExprsFiltered         -> pure a         -- ByteArray# are non-translatable / void, except when they're literals-        | dcNm == "GHC.Num.Integer.IP"+        | dcNm == showt 'IP         , (a@(HW.Literal Nothing (NumLit _)):_) <- argExprs         -> pure a-        | dcNm == "GHC.Num.Integer.IN"+        | dcNm == showt 'IN         -- ByteArray# are non-translatable / void, except when they're literals         , (HW.Literal Nothing (NumLit i):_) <- argExprs         -> pure (HW.Literal Nothing (NumLit (negate i)))       Unsigned _-        | dcNm == "GHC.Num.Natural.NS"+        | dcNm == showt 'NS         , (a:_) <- argExprsFiltered         -> pure a-        | dcNm == "GHC.Num.Natural.NB"+        | dcNm == showt 'NB         -- ByteArray# are non-translatable / void, except when they're literals         , (a@(HW.Literal Nothing (NumLit _)):_) <- argExprs         -> pure a
src/Clash/Netlist/BlackBox.hs view
@@ -3,7 +3,7 @@   Copyright  :  (C) 2012-2016, University of Twente,                     2016-2017, Myrtle Software Ltd,                     2017     , Google Inc.,-                    2021-2024, QBayLogic B.V.+                    2021-2026, QBayLogic B.V.                     2022     , Google Inc.   License    :  BSD2 (see the file LICENSE)   Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>@@ -20,6 +20,11 @@ {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TemplateHaskell #-} +-- 'dataToTagSmall#' and 'dataToTagLarge#' (used below in TH name quotes so that+-- Clash can match the primops by their canonical names across GHC versions) are+-- deprecated as of GHC 9.14 in favor of @dataToTag#@ from @GHC.Magic@.+{-# OPTIONS_GHC -Wno-deprecations #-}+ module Clash.Netlist.BlackBox     ( mkBlackBoxContext     , extractPrimWarnOrFail@@ -50,6 +55,9 @@ import           Data.Text                     (unpack) import qualified Data.Text                     as TextS import           Data.Text.Extra+import           GHC.Num.Integer               (Integer(..))+import           GHC.Num.Natural               (Natural(..))+import qualified GHC.Prim import           GHC.Stack   (HasCallStack, callStack, prettyCallStack) import qualified System.Console.ANSI           as ANSI@@ -527,7 +535,7 @@                     -- Otherwise don't render them                     Nothing -> return (Identifier (Id.unsafeMake "__VOID__") Nothing,[])         P.Primitive pNm _ _-          | pNm == "GHC.Prim.tagToEnum#" -> do+          | pNm == showt 'GHC.Prim.tagToEnum# -> do               hwTy <- N.unsafeCoreTypeToHWTypeM' $(curLoc) ty               case args of                 [Right (ConstTy (TyCon tcN)), Left (C.Literal (IntLiteral i))] -> do@@ -542,6 +550,9 @@                   (scrutExpr,scrutDecls) <-                     mkExpr False declType (NetlistId (Id.unsafeMake "c$tte_rhs") scrutTy) scrut                   case scrutExpr of+                    -- Singleton enumerations have no hardware representation,+                    -- just like their constructor applications.+                    _ | isVoid hwTy -> return (Noop,scrutDecls)                     Identifier id_ Nothing -> return (DataTag hwTy (Left id_),scrutDecls)                     _ -> do                       scrutHTy <- unsafeCoreTypeToHWTypeM' $(curLoc) scrutTy@@ -549,6 +560,9 @@                       netDecl <- N.mkInit declType assignTy tmpRhs scrutHTy scrutExpr                       return (DataTag hwTy (Left tmpRhs), netDecl ++ scrutDecls)                 _ -> error $ $(curLoc) ++ "tagToEnum: " ++ show (map (either showPpr showPpr) args)+          -- 'dataToTag#' was removed from GHC.Prim in favor of+          -- 'dataToTagSmall#' / 'dataToTagLarge#'. Kept as a literal for+          -- compatibility with older GHCs where it may still appear.           | pNm == "GHC.Prim.dataToTag#" -> case args of               [Right _,Left (Data dc)] -> do                 iw <- Lens.view intWidth@@ -556,13 +570,18 @@               [Right _,Left scrut] -> mkDataToTag declType assignTy scrut               _ -> error $ $(curLoc) ++ "dataToTag: " ++ show (map (either showPpr showPpr) args) +#if MIN_VERSION_ghc(9,10,0)+          -- 'dataToTagSmall#' / 'dataToTagLarge#' only exist on GHC >= 9.10;+          -- TH-quoting them requires the symbols to be in scope at compile+          -- time, so this clause is CPP-gated.           | pNm `elem`-            ["GHC.Prim.dataToTagSmall#", "GHC.Prim.dataToTagLarge#"] -> case args of+            [showt 'GHC.Prim.dataToTagSmall#, showt 'GHC.Prim.dataToTagLarge#] -> case args of               [Right _, Right _,Left (Data dc)] -> do                 iw <- Lens.view intWidth                 return (N.Literal (Just (Signed iw,iw)) (NumLit $ toInteger $ dcTag dc - 1),[])               [Right _, Right _,Left scrut] -> mkDataToTag declType assignTy scrut               _ -> error $ $(curLoc) ++ "dataToTag: " ++ show (map (either showPpr showPpr) args)+#endif            | pNm == "Clash.Explicit.SimIO.mealyIO" -> do               resM <- resBndr1 True dst@@ -647,14 +666,14 @@                 _ ->                   return (Noop,decls) -          | pNm == "GHC.Num.Integer.IS" -> do+          | pNm == showt 'IS -> do               (expr,decls) <- case lefts args of                 (arg:_) -> mkExpr False declType dst arg                 _ -> error "internal error: insufficient arguments"               iw <- Lens.view intWidth               return (N.DataCon (Signed iw) (DC (Void Nothing,-1)) [expr],decls) -          | pNm == "GHC.Num.Integer.IP" -> do+          | pNm == showt 'IP -> do               (expr,decls) <- case lefts args of                 (arg:_) -> mkExpr False declType dst arg                 _ -> error "internal error: insufficient arguments"@@ -662,7 +681,7 @@                 N.Literal Nothing (NumLit _) -> return (expr,decls)                 _ -> error "non-constant ByteArray# not supported" -          | pNm == "GHC.Num.Integer.IN" -> do+          | pNm == showt 'IN -> do               (expr,decls) <- case lefts args of                 (arg:_) -> mkExpr False declType dst arg                 _ -> error "internal error: insufficient arguments"@@ -671,14 +690,14 @@                   return (N.Literal Nothing (NumLit (negate i)),decls)                 _ -> error "non-constant ByteArray# not supported" -          | pNm == "GHC.Num.Natural.NS" -> do+          | pNm == showt 'NS -> do               (expr,decls) <- case lefts args of                 (arg:_) -> mkExpr False declType dst arg                 _ -> error "internal error: insufficient arguments"               iw <- Lens.view intWidth               return (N.DataCon (Unsigned iw) (DC (Void Nothing,-1)) [expr],decls) -          | pNm == "GHC.Num.Integer.NB" -> do+          | pNm == showt 'NB -> do               (expr,decls) <- case lefts args of                 (arg:_) -> mkExpr False declType dst arg                 _ -> error "internal error: insufficient arguments"
src/Clash/Netlist/BlackBox/Util.hs view
@@ -14,6 +14,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE LambdaCase #-}+{-# LANGUAGE MagicHash #-} {-# LANGUAGE NumericUnderscores #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-}@@ -62,8 +63,13 @@ import qualified Data.Set                        as Set import           Data.Set                        (Set) import qualified Data.Text+import           Data.Text.Extra                 (showt) import           Data.Text.Lazy                  (Text) import qualified Data.Text.Lazy                  as Text+import qualified GHC.CString+import           GHC.Exts                        (Int(..), Word(..))+import           GHC.Int                         (Int8(..), Int16(..), Int32(..), Int64(..))+import           GHC.Word                        (Word8(..), Word16(..), Word32(..), Word64(..)) import           System.Directory                (doesFileExist, canonicalizePath) import           System.IO.Unsafe                (unsafePerformIO) @@ -657,9 +663,9 @@           | DataCon (Unsigned _) _ [Literal _ (NumLit i)] <- l             -> fromInteger i           | BlackBoxE pNm _lib _use _incl _templ bbCtx _paren <- l-          , pNm `elem` ["GHC.Int.I8#", "GHC.Int.I16#", "GHC.Int.I32#", "GHC.Int.I64#"-                       ,"GHC.Word.W8#","GHC.Word.W16#","GHC.Word.W32#","GHC.Word.W64#"-                       ,"GHC.Types.I#","GHC.Types.W#"+          , pNm `elem` [ showt 'I8#, showt 'I16#, showt 'I32#, showt 'I64#+                       , showt 'W8#, showt 'W16#, showt 'W32#, showt 'W64#+                       , showt 'I#, showt 'W#                        ]           , [Literal _ (NumLit j)] <- extractLiterals bbCtx           -> fromInteger j@@ -877,9 +883,9 @@   mkLit (DataCon _ (DC (Void {}, _)) [Literal (Just (Signed _,_)) i])   = Literal Nothing i  -- Int   mkLit (DataCon _ (DC (Void {}, _)) [Literal (Just (Unsigned _,_)) i]) = Literal Nothing i  -- SNat, Word -  mkLit (BlackBoxE pNm _ _ _ _ bbCtx _) | pNm `elem` ["GHC.Int.I8#", "GHC.Int.I16#", "GHC.Int.I32#", "GHC.Int.I64#"-                                                     ,"GHC.Word.W8#","GHC.Word.W16#","GHC.Word.W32#","GHC.Word.W64#"-                                                     ,"GHC.Types.I#","GHC.Types.W#"+  mkLit (BlackBoxE pNm _ _ _ _ bbCtx _) | pNm `elem` [ showt 'I8#, showt 'I16#, showt 'I32#, showt 'I64#+                                                     , showt 'W8#, showt 'W16#, showt 'W32#, showt 'W64#+                                                     , showt 'I#, showt 'W#                                                      ]                                         , [Literal _ i] <- extractLiterals bbCtx                                         = Literal Nothing i@@ -1094,10 +1100,10 @@   case bbInputs ctx of     (e0,_,_):_ -> exprToString e0     _ -> error "internal error: insufficient bbInputs"-exprToString (BlackBoxE "GHC.CString.unpackCString#" _ _ _ _ ctx _) =-  case bbInputs ctx of-    (e0,_,_):_ -> exprToString e0-    _ -> error "internal error: insufficient bbInputs"+exprToString (BlackBoxE nm _ _ _ _ ctx _)+  | nm == showt 'GHC.CString.unpackCString#,+    (e0,_,_):_ <- bbInputs ctx+  = exprToString e0 exprToString _ = Nothing  prettyBlackBox :: Monad m
src/Clash/Netlist/Id/Internal.hs view
@@ -47,6 +47,8 @@ -- is "foo_12_13" this function would return "Just 25". In this case, "foo_12_26" -- is guaranteed to be a fresh identifier. lookupFreshCache# :: FreshCache -> Identifier -> Maybe Word+lookupFreshCache# _fresh0 rawId@RawIdentifier {} =+  error $ "Internal error: unexpected raw identifier: " <> show rawId lookupFreshCache# fresh0 id0 = do   fresh1 <- HashMap.lookup (i_baseNameCaseFold id0) fresh0   IntMap.lookup (length (i_extensionsRev id0)) fresh1@@ -75,7 +77,7 @@   -> (IdentifierSet, Identifier) mkUnique# _is0 (RawIdentifier {}) =   error "Internal error: mkUnique# cannot be used on RawIdentifiers"-mkUnique# is0 id_@(i_extensionsRev -> []) = deepen# is0 id_+mkUnique# is0 id_@UniqueIdentifier{i_extensionsRev=[]} = deepen# is0 id_ mkUnique# is id0 = (is{is_freshCache=freshCache, is_store=isStore}, id2)  where   freshCache = updateFreshCache# (is_freshCache is) id2@@ -147,7 +149,7 @@ next# :: HasCallStack => IdentifierSet -> Identifier ->  (IdentifierSet, Identifier) next# is0 (RawIdentifier t Nothing _) = uncurry next# (make# is0 t) next# is0 (RawIdentifier _ (Just id_) _) = next# is0 id_-next# is0 id_@(i_extensionsRev -> []) = deepen# is0 id_+next# is0 id_@UniqueIdentifier{i_extensionsRev=[]} = deepen# is0 id_ next# is0 id_ = mkUnique# is0 id_  -- | Non-monadic, internal version of 'nextN'
src/Clash/Netlist/Util.hs view
@@ -1467,6 +1467,8 @@   -- ^ Top entity annotation   -> m Identifier   -- ^ New identifier+genTopName _prefixM tb@(TestBench {}) =+  error $ "Internal error: genTopName: unexpected TestBench: " <> show tb genTopName prefixM ann =   case prefixM of     Just prefix | not (Text.null prefix) ->
src/Clash/Normalize.hs view
@@ -14,6 +14,8 @@ {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-} +--{-# OPTIONS_GHC -ddump-splices #-}+ module Clash.Normalize where  import           Control.Exception                (throw)@@ -29,6 +31,7 @@ import qualified Clash.Data.UniqMap               as UniqMap import           Data.List   (intersect, mapAccumL)+import qualified Data.HashMap.Strict              as HashMap import qualified Data.Map                         as Map import qualified Data.Maybe                       as Maybe import qualified Data.Set                         as Set@@ -70,17 +73,16 @@   (HWMap, FilteredHWType(..)) import           Clash.Netlist.Util   (splitNormalized)-import           Clash.Normalize.Strategy-import           Clash.Normalize.Transformations+import           Clash.Normalize.Strategy         (constantPropagation, normalization)+import           Clash.Normalize.Strategy.Spec    (flattenSpec) import           Clash.Normalize.Types import           Clash.Normalize.Util-import           Clash.Rewrite.Combinators-  ((>->), (!->), bottomupR, repeatR, topdownFixR)+import           Clash.Rewrite.StrategyDSL.TH     (compileStrategy) import           Clash.Rewrite.Types   (RewriteEnv (..), RewriteState (..), bindings, debugOpts, extra,    tcCache, topEntities, newInlineStrategy) import           Clash.Rewrite.Util-  (apply, isUntranslatableType, runRewriteSession)+  (isUntranslatableType, runRewriteSession) import           Clash.Util import           Clash.Util.Interpolate           (i) import           Clash.Util.Supply                (Supply)@@ -144,6 +146,9 @@                   emptyVarEnv                   Map.empty                   rcsMap+                  normalization+                  constantPropagation+                  HashMap.empty -- workFreeAppCache  normalize   :: [Id]@@ -348,37 +353,6 @@            then return (Right ((nm,e),us))            else return (Left b) -{--Note [flatten pass structure]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Through experimentation we've learned the following:--1. The evaluator-backed rewrites ('reduceConst', 'reduceNonRepPrim') must not-   sit inside the top-down propagation bundle. 'topdownFixR' settles that bundle-   at each node with 'repeatR', so a bundled 'reduceConst' is re-attempted --   evaluator call and all - for every 'appProp' or 'caseCon' that fires there.-   On large designs we've measured that dominates; hoisting them out was worth-   ~30%. See #3338.--2. There should be exactly two traversals per round, and the bottom-up one has-   to come first.--   'allR' rebuilds every node it walks, so each extra traversal costs a full-   term rebuild per round even when nothing fires. Running 'flattenLet' and the-   evaluator-backed rewrites as one fused bottom-up pass instead of two-   consecutive ones is therefore free of charge (it does not change which-   rewrites fire, or in which order they fire relative to each other).--   Running that bottom-up pass _before_ the top-down one lets the constants it-   folds be consumed by 'caseCon' in the same round. With the passes the other-   way round the folded constants sit unused until the next round, so-   constant-heavy designs pay for an extra iteration of the whole loop:-   @tests/shouldwork/Basic/AES.hs@ did ~36k extra node visits per transformation-   that way.--If you touch code related to this, please make sure to run benchmarks.--}- -- | Flatten a 'CallTree', memoizing results by binder Id within one cleanup -- pass. Without the cache, every binder reachable from the root is flattened -- as many times as it appears in the (un-deduplicated) call tree.@@ -438,26 +412,8 @@          return (CBranch (nm,(Binding nm' sp inl pr newExpr' r)) (concat allUsed'))       else return (CBranch (nm,(Binding nm' sp inl pr newExpr r)) allUsed) -  flatten =-    -- See Note [flatten pass structure].-    repeatR (bottomupR (apply "flattenLet" flattenLet >->-                        (apply "reduceConst" reduceConst !->-                           apply "deadcode" deadCode) >->-                        apply "reduceNonRepPrim" reduceNonRepPrim >->-                        apply "removeUnusedExpr" removeUnusedExpr) >->-             topdownFixR (apply "appProp" appProp >->-               apply "bindConstantVar" bindConstantVar >->-               apply "caseCon" caseCon)) !->-    topdownSucR (apply "topLet" topLet) >->-    -- See [Note] relation `collapseRHSNoops` and `inlineCleanup`-    -- Note that we do this as the very last step, after all constant propagation-    -- has been done to avoid #3036.-    topdownSucR (apply "collapseRHSNoops" collapseRHSNoops) >->-    topdownSucR (apply "inlineCleanup" inlineCleanup) >->-    bottomupR (apply "caseCon" caseCon) >-> -- https://github.com/clash-lang/clash-compiler/issues/3159 / #3204-    bottomupR (apply "flattenLet" flattenLet) >-> -- https://github.com/clash-lang/clash-compiler/issues/3185-    bottomupR (apply "bindConstantVar" bindConstantVar) >-> -- https://github.com/clash-lang/clash-compiler/issues/3041-    topdownSucR (apply "topLet" topLet)+  -- The flattening strategy is described in Clash.Normalize.Strategy.Spec.+  flatten = $(compileStrategy flattenSpec)    goCheap c@(CLeaf   (nm2,(Binding _ _ inl2 _ e _)))     | isNoInline inl2  = (Nothing     ,[c])
src/Clash/Normalize/PrimitiveReductions.hs view
@@ -54,6 +54,7 @@ import qualified Data.Maybe                       as Maybe import           Data.Semigroup                   (sconcat) import           Data.Text.Extra                  (showt)+import qualified GHC.Classes import           GHC.Stack                        (HasCallStack)  import           GHC.Builtin.Names@@ -71,8 +72,8 @@ import           Clash.Core.Pretty                (showPpr) import           Clash.Core.Subst                 (extendTvSubst, mkSubst, substTy) import           Clash.Core.Term-  (IsMultiPrim (..), CoreContext (..), PrimInfo (..), Term (..), WorkInfo (..), Pat (..),-   collectTermIds, mkApps, PrimUnfolding(..))+  (Bind (..), IsMultiPrim (..), CoreContext (..), PrimInfo (..), Term (..), WorkInfo (..),+   Pat (..), collectTermIds, mkApps, PrimUnfolding(..), stripTicks) import           Clash.Core.Type                  (LitTy (..), Type (..),                                                    TypeView (..), coreView1,                                                    mkFunTy, mkTyConApp,@@ -84,14 +85,14 @@   (integerPrimTy, typeNatKind, liftedTypeKind) import           Clash.Core.Util   (appendToVec, extractElems, extractTElems, mkRTree,-   mkUniqInternalId, mkUniqSystemTyVar, mkVec, dataConInstArgTys, primCo)-import           Clash.Core.Var                   (mkTyVar, mkLocalId)-import           Clash.Core.VarEnv                (extendInScopeSetList)+   mkInternalVar, mkUniqInternalId, mkUniqSystemTyVar, mkVec, dataConInstArgTys, primCo)+import           Clash.Core.Var                   (isLocalId, mkTyVar, mkLocalId)+import           Clash.Core.VarEnv+  (InScopeSet, extendInScopeSet, extendInScopeSetList) import qualified Clash.Data.UniqMap as UniqMap import qualified Clash.Normalize.Primitives as NP (undefined) import           Clash.Sized.RTree                (RTree) import           Clash.Sized.Vector               (Vec)-import {-# SOURCE #-} Clash.Normalize.Strategy import           Clash.Normalize.Types import           Clash.Rewrite.Types import           Clash.Rewrite.Util@@ -111,6 +112,14 @@ typeNatSub =   Name User "GHC.TypeNats.-" (fromGhcUnique typeNatSubTyFamNameKey) wiredInSrcSpan +-- | The compiled 'Clash.Normalize.Strategy.constantPropagation' strategy,+-- taken from the normalization state. See the documentation of+-- '_constantPropagationStrategy' for why it is not simply imported.+constantPropagation :: NormRewrite+constantPropagation ctx tm = do+  strategy <- Lens.use (extra . constantPropagationStrategy)+  strategy ctx tm+ vecHeadPrim   :: TyConName   -- ^ Vec TyCon name@@ -175,8 +184,40 @@   nTV = mkTyVar typeNatKind (mkUnsafeSystemName "n" 0)   aTV = mkTyVar liftedTypeKind (mkUnsafeSystemName "a" 1) +-- | Let-bind a vector, unless it already is a local variable. This makes sure+-- the head and tail projections of 'extractHeadTail' share the vector instead+-- of each getting their own copy. Because single-step reductions feed the tail+-- projection back into the primitive, such copies pile up: unrolling a vector+-- of length @n@ would otherwise result in @n@ copies of the vector. That is+-- harmless for local variables, but a global binder gets inlined (and+-- normalized) at every occurrence. See:+--+--   https://github.com/clash-lang/clash-compiler/issues/3461+--+-- Non-representable vectors are never let-bound:+-- 'Clash.Normalize.Transformations.Inline.inlineOrLiftNonRep' would inline or+-- lift such a let-binding, undoing the sharing.+shareVec+  :: Bool+  -- ^ Whether the vector is representable+  -> InScopeSet+  -> Term+  -- ^ Vector to share+  -> NormalizeSession (InScopeSet, Term -> Term, Term)+  -- ^ (Updated in scope set, function binding the vector, the shared vector)+shareVec isRepresentable is0 vec+  | not isRepresentable = noShare+  | Var v <- stripTicks vec, isLocalId v = noShare+  | otherwise = do+      tcm <- Lens.view tcCache+      v <- mkInternalVar is0 "vec" (inferCoreTypeOf tcm vec)+      pure (extendInScopeSet is0 v, Let (NonRec v vec), Var v)+ where+  noShare = pure (is0, id, vec)+ -- | Makes two case statements: the first one extract the _head_ from the given--- vector, the latter the tail.+-- vector, the latter the tail. Use 'shareVec' on the vector first to prevent+-- it from being duplicated. extractHeadTail   :: DataCon   -- ^ The Cons (:>) constructor@@ -287,17 +328,21 @@   -> Type -- ^ Element type of the lhs of the function   -> Type -- ^ Element type of the rhs of the function   -> Type -- ^ Element type of the result of the function+  -> Bool -- ^ Whether the 1st vector argument is representable, see 'shareVec'+  -> Bool -- ^ Whether the 2nd vector argument is representable, see 'shareVec'   -> Term -- ^ The zipWith'd functions   -> Term -- ^ The 1st vector argument   -> Term -- ^ The 2nd vector argument   -> TransformContext   -> NormalizeSession Term-reduceZipWith zipWithPrimInfo n lhsElTy rhsElTy resElTy fun lhsArg rhsArg _ctx = do+reduceZipWith zipWithPrimInfo n lhsElTy rhsElTy resElTy lhsRep rhsRep fun lhsArg0 rhsArg0 (TransformContext is0 _) = do   tcm <- Lens.view tcCache-  changed (go tcm (inferCoreTypeOf tcm lhsArg))+  (is1, bindLhs, lhsArg1) <- shareVec lhsRep is0 lhsArg0+  (_, bindRhs, rhsArg1) <- shareVec rhsRep is1 rhsArg0+  changed (bindLhs (bindRhs (go tcm lhsArg1 rhsArg1 (inferCoreTypeOf tcm lhsArg0))))  where-  go tcm (coreView1 tcm -> Just ty) = go tcm ty-  go tcm (tyView -> TyConApp vecTcNm _)+  go tcm lhsArg rhsArg (coreView1 tcm -> Just ty) = go tcm lhsArg rhsArg ty+  go tcm lhsArg rhsArg (tyView -> TyConApp vecTcNm _)     | (Just vecTc) <- UniqMap.lookup vecTcNm tcm     , nameOcc vecTcNm == showt ''Vec     , [nilCon, consCon] <- tyConDataCons vecTc@@ -317,7 +362,7 @@                                              , Left bs ]         in           mkVecCons consCon resElTy n c cs-  go _ ty =+  go _ _ _ ty =     error $ $(curLoc) ++ [I.i|       reduceZipWith: argument does not have a vector type: @@ -332,17 +377,19 @@   -> Integer  -- ^ Length of the vector   -> Type -- ^ Argument type of the function   -> Type -- ^ Result type of the function+  -> Bool -- ^ Whether the map'd over vector is representable, see 'shareVec'   -> Term -- ^ The map'd function   -> Term -- ^ The map'd over vector   -> TransformContext   -> NormalizeSession Term-reduceMap mapPrimInfo n argElTy resElTy fun arg _ctx = do+reduceMap mapPrimInfo n argElTy resElTy argRep fun arg0 (TransformContext is0 _) = do     tcm <- Lens.view tcCache-    let ty = inferCoreTypeOf tcm arg-    changed (go tcm ty)+    let ty = inferCoreTypeOf tcm arg0+    (_, bindArg, arg1) <- shareVec argRep is0 arg0+    changed (bindArg (go tcm arg1 ty))   where-    go tcm (coreView1 tcm -> Just ty') = go tcm ty'-    go tcm (tyView -> TyConApp vecTcNm _)+    go tcm arg (coreView1 tcm -> Just ty') = go tcm arg ty'+    go tcm arg (tyView -> TyConApp vecTcNm _)       | (Just vecTc)     <- UniqMap.lookup vecTcNm tcm       , nameOcc vecTcNm == showt ''Vec       , [nilCon,consCon] <- tyConDataCons vecTc@@ -360,7 +407,7 @@                                            , Left as ]           in             mkVecCons consCon resElTy n b bs-    go _ ty =+    go _ _ ty =       error $ $(curLoc) ++ [I.i|         reduceMap: argument does not have a vector type: @@ -620,6 +667,8 @@   -- ^ Length of the vector   -> Type   -- ^ Element type of the argument vector+  -> Bool+  -- ^ Whether the argument vector is representable, see 'shareVec'   -> Term   -- ^ The function to fold with   -> Term@@ -628,14 +677,15 @@   -- ^ The argument vector   -> TransformContext   -> NormalizeSession Term-reduceFoldr _ 0 _ _ start _ _ = changed start-reduceFoldr foldrPrimInfo n aTy fun start arg _ctx = do+reduceFoldr _ 0 _ _ _ start _ _ = changed start+reduceFoldr foldrPrimInfo n aTy argRep fun start arg0 (TransformContext is0 _) = do     tcm <- Lens.view tcCache-    let ty = inferCoreTypeOf tcm arg-    changed (go tcm ty)+    let ty = inferCoreTypeOf tcm arg0+    (_, bindArg, arg1) <- shareVec argRep is0 arg0+    changed (bindArg (go tcm arg1 ty))   where-    go tcm (coreView1 tcm -> Just ty') = go tcm ty'-    go tcm (tyView -> TyConApp vecTcNm _)+    go tcm arg (coreView1 tcm -> Just ty') = go tcm arg ty'+    go tcm arg (tyView -> TyConApp vecTcNm _)       | nameOcc vecTcNm == showt ''Vec       , Just vecTc <- UniqMap.lookup vecTcNm tcm       , [_nilCon, consCon] <- tyConDataCons vecTc@@ -650,7 +700,7 @@         in           mkApps fun [Left a, Left b] -    go _ ty =+    go _ _ ty =       error $ $(curLoc) ++ [I.i|         reduceFoldr: argument does not have a vector type: @@ -862,16 +912,18 @@   :: PrimInfo -- ^ Primitive info for 'init'   -> Integer  -- ^ Length of the vector   -> Type -- ^ Element type of the vector+  -> Bool -- ^ Whether the argument vector is representable, see 'shareVec'   -> Term -- ^ The argument vector   -> TransformContext   -> NormalizeSession Term-reduceInit initPrimInfo n aTy vArg _ctx = do+reduceInit initPrimInfo n aTy vArgRep vArg0 (TransformContext is0 _) = do   tcm <- Lens.view tcCache-  let ty = inferCoreTypeOf tcm vArg-  changed (go tcm ty)+  let ty = inferCoreTypeOf tcm vArg0+  (_, bindArg, vArg1) <- shareVec vArgRep is0 vArg0+  changed (bindArg (go tcm vArg1 ty))  where-  go tcm (coreView1 tcm -> Just ty') = go tcm ty'-  go tcm (tyView -> TyConApp vecTcNm _)+  go tcm vArg (coreView1 tcm -> Just ty') = go tcm vArg ty'+  go tcm vArg (tyView -> TyConApp vecTcNm _)     | (Just vecTc) <- UniqMap.lookup vecTcNm tcm     , nameOcc vecTcNm == showt ''Vec     , [nilCon, consCon]  <- tyConDataCons vecTc@@ -885,7 +937,7 @@         in           mkVecCons consCon aTy n a as1 -  go _ ty =+  go _ _ ty =     error $ $(curLoc) ++ [I.i|       reduceInit: argument does not have a vector type: @@ -1110,7 +1162,7 @@     -> Term   eqIntPrim intTy boolTy =     Prim (PrimInfo-           "GHC.Classes.eqInt"+           (showt 'GHC.Classes.eqInt)            (mkFunTy intTy (mkFunTy intTy boolTy))            WorkVariable            SingleResult@@ -1219,7 +1271,7 @@     -> Term   eqIntPrim intTy boolTy =     Prim ( PrimInfo-            "GHC.Classes.eqInt"+            (showt 'GHC.Classes.eqInt)             (mkFunTy intTy (mkFunTy intTy boolTy))             WorkVariable             SingleResult
src/Clash/Normalize/Strategy.hs view
@@ -4,340 +4,29 @@   License    :  BSD2 (see the file LICENSE)   Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> -  Transformation process for normalization+  Transformation process for normalization. The strategies themselves are+  described in "Clash.Normalize.Strategy.Spec". -} -{-# LANGUAGE CPP #-}--module Clash.Normalize.Strategy where--import Clash.Normalize.Transformations-import Clash.Normalize.Types-import Clash.Rewrite.Combinators-import Clash.Rewrite.Types-import Clash.Rewrite.Util+{-# LANGUAGE TemplateHaskell #-} --- [Note: bottomup traversal reduceConst]------ 2-May-2019: There is a bug in the evaluator where all data constructors are--- considered lazy, even though their declaration says they have strict fields.--- This causes some reductions to fail because the term under the constructor is--- not in WHNF, which is what some of the evaluation rules for certain primitive--- operations expect. Using a bottom-up traversal works around this bug by--- ensuring that the values under the constructor are in WHNF.------ Using a bottomup traversal ensures that constants are reduced to NF, even if--- constructors are lazy, thus ensuring more sensible/smaller generated HDL.+--{-# OPTIONS_GHC -ddump-splices #-} --- | Normalisation transformation-normalization :: NormRewrite-normalization =-  rmDeadcode >-> multPrim >-> constantPropagation >-> rmUnusedExpr >-!-> anf >-!-> rmDeadcode >->-  bindConst >-> letTL-  >-> evalConst-  >-!-> cse >-!-> cleanup >->-  elimCaseBigNum >->  -- see [Note] late elimCaseBigNum-  xOptim >-> rmDeadcode >->-  cleanup >-> bindSimIO >-> recLetRec >-> splitArgs-  where-    multPrim   = topdownR (apply "setupMultiResultPrim" setupMultiResultPrim)-    anf        = topdownR (apply "nonRepANF" nonRepANF) >-> apply "ANF" makeANF >-> topdownR (apply "caseCon" caseCon)-    letTL      = topdownSucR (apply "topLet" topLet)-    recLetRec  = apply "recToLetRec" recToLetRec-    rmUnusedExpr = bottomupR (apply "removeUnusedExpr" removeUnusedExpr)-    rmDeadcode = bottomupR (apply "deadcode" deadCode)-    bindConst  = topdownR (apply "bindConstantVar" bindConstantVar)-    -- See [Note] bottomup traversal reduceConst:-    evalConst  = bottomupR (apply "reduceConst" reduceConst)-    cse        = topdownR (apply "CSE" simpleCSE)-    elimCaseBigNum = topdownR (apply "elimCaseBigNum" elimCaseBigNumInternals)-    xOptim     = bottomupR (apply "xOptimize" xOptimize)-    cleanup    = topdownR (apply "etaExpandSyn" etaExpandSyn) >->-                 topdownSucR (apply "inlineCleanup" inlineCleanup) !->-                 innerMost (applyMany [("caseCon"        , caseCon)-                                      ,("bindConstantVar", bindConstantVar)-                                      ,("letFlat"        , flattenLet)])-                 >-> rmDeadcode >-> letTL-    splitArgs  = topdownR (apply "separateArguments" separateArguments) !->-                 bottomupR (apply "caseCon" caseCon)-    bindSimIO  = topdownR (apply "bindSimIO" inlineSimIO)+module Clash.Normalize.Strategy+  ( normalization+  , constantPropagation+  ) where +import Clash.Normalize.Strategy.Spec+import Clash.Normalize.Types (NormRewrite)+import Clash.Rewrite.StrategyDSL.TH (compileStrategy)  constantPropagation :: NormRewrite-constantPropagation =-  inlineAndPropagate >->-  caseFlattening >->-  etaTL >->-  dec >->-  spec >->-  dec >->-  conSpec-  where-    etaTL              = apply "etaTL" etaExpansionTL !-> topdownR (apply "applicationPropagation" appProp)-    -- The outer repeatR is still needed: inlineNR is a full traversal whose-    -- results can only be processed by re-running the top-down bundle from the-    -- new root.-    ---    -- NB: 'topdownFixR' is deliberately _not_ used here, see-    -- Note [topdownFixR is not for inlining bundles].-    inlineAndPropagate = repeatR (topdownR (applyMany transPropagateAndInline) >-> inlineNR)-    spec               = bottomupR (applyMany specTransformations)-    caseFlattening     = topdownFixR (apply "caseFlat" caseFlat)-    dec                = topdownFixR (apply "DEC" disjointExpressionConsolidation)-    conSpec            = bottomupR  ((apply "appPropCS" appProp !->-                                     bottomupR (apply "constantSpec" constantSpec)) >-!-                                     apply "constantSpec" constantSpec)--    transPropagateAndInline :: [(String,NormRewrite)]-    transPropagateAndInline =-      [ ("applicationPropagation", appProp              )-      , ("bindConstantVar"       , bindConstantVar      )-      , ("caseLet"               , caseLet              )-      , ("caseCase"              , caseCase             )-      , ("caseCon"               , caseCon              )-      , ("elimExistentials"      , elimExistentials     )-      , ("caseEliminateNonReachable"  , caseEliminateNonReachable )-      , ("removeUnusedExpr"      , removeUnusedExpr     )-      -- These transformations can safely be applied in a top-down traversal as-      -- they themselves check whether the to-be-inlined binder is recursive or not.-      , ("inlineWorkFree"  , inlineWorkFree)-      , ("inlineSmall"     , inlineSmall)-      , ("bindOrLiftNonRep", inlineOrLiftNonRep) -- See: [Note] bindNonRep before liftNonRep-                                                 -- See: [Note] bottom-up traversal for liftNonRep-      , ("reduceNonRepPrim", reduceNonRepPrim)---      , ("caseCast"        , caseCast)-      , ("letCast"         , letCast)-      , ("splitCastWork"   , splitCastWork)-      , ("argCastSpec"     , argCastSpec)-      , ("inlineCast"      , inlineCast)-      , ("elimCastCast"    , elimCastCast)-      ]--    -- InlineNonRep cannot be applied in a top-down traversal, as the non-representable-    -- binder might be recursive. The idea is, is that if the recursive-    -- non-representable binder is inlined once, we can get rid of the recursive-    -- aspect using the case-of-known-constructor-    ---    -- Note that we first do a dead code removal pass, which makes sure that-    -- unused let-bindings get cleaned up. Only if no dead code is removed-    -- 'inlineNonRep' is executed. We do this for two reasons:-    ---    --   1. 'deadCode' is an expensive operation and is therefore left out of-    --      the hot loop 'transPropagateAndInline'.-    ---    --   2. In various situations 'transPropagateAndInline' can do more work-    --      after 'deadCode' was successful. This work in turn might remove a-    --      a construct 'inlineNonRep' would fire on - saving the compiler work.-    ---    inlineNR :: NormRewrite-    inlineNR =-          bottomupR (apply "deadCode" deadCode)-      >-! apply "inlineNonRep" inlineNonRep--    specTransformations :: [(String,NormRewrite)]-    specTransformations =-      [ ("typeSpec"    , typeSpec)-      , ("nonRepSpec"  , nonRepSpec)-      , ("zeroWidthSpec", zeroWidthSpec)-        -- See Note [zeroWidthSpec enabling transformations]-      ]--{--[Note] late elimCaseBigNum--elimCaseBigNum is placed fairly late in the pipeline, after any constant folding and after caseCon.-Because Naturals also hide inside SNat/Nat/KnownNats, and those can be bigger then 64bits.-But they're ultimately monomorphic and thus static and will be evaluated.-We just have to make sure that evaluation happens before we do elimCaseBigNum.--For an example of where this can happen see foldableSNat in tests/shouldwork/Issues/T3157_IntegerNaturalInternals.hs--}--{--Note [zeroWidthSpec enabling transformations]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-When zeroWidthSpec fires, it can lead to better results in normalization, but-this is somewhat incidental. The extra transformations which fire are typically-from--  * calls to transformations like caseCon which occur after constantPropagation-    (e.g. caseCon run after ANF conversion).--  * flattening / inlining which happens late in normalization (after regular-    normalization has occurred)--  * normalizing another function due to being marked NOINLINE--If we consider the following:--    data AB = A | B--    ab :: KnownNat n => Index n -> AB -> AB-    ab n A = if n >  0 then A else B-    ab n B = if n == 0 then B else A-    {-# NOINLINE ab #-}--    topEntity = ab @1-    {-# NOINLINE topEntity #-}--The zeroWidthSpec transformation fires on the topEntity, giving a-post-normalization topEntity of--    \(x :: Index 1) ->-      \(y :: AB) ->-        letrec result :: AB = ab' y in result--where--    ab' = ab (fromInteger# 0)--The extra transformations which fire happen later when ab' is normalized.-Removing the NOINLINE from ab gives the same result, but the extra-transformations fire in flattening instead.--}--{- [Note] bottom-up traversal for liftNonRep-We used to say:--"The liftNonRep transformation must be applied in a topDown traversal because-of what Clash considers tail calls in its join-point analysis."--Consider:--> let fail = \x -> ...-> in  case ... of->       A -> let fail1 = \y -> case ... of->                                 X -> fail ...->                                 Y -> ...->            in case ... of->                 P -> fail1 ...->                 Q -> ...->       B -> fail ...--under "normal" tail call rules, the local 'fail' functions is not a join-point-because it is used in a let-binding. However, we apply "special" tail call rules-in Clash. Because 'fail' is used in a TC position within 'fail1', and 'fail1' is-only used in a TC position, in Clash, we consider 'tail' also only to be used-in a TC position.--Now image we apply 'liftNonRep' in a bottom up traversal, we will end up with:--> fail1 = \fail y -> case ... of->   X -> fail ...->   Y -> ...--> let fail = \x -> ...-> in  case ... of->       A -> case ... of->                 P -> fail1 fail ...->                 Q -> ...->       B -> fail ...--Suddenly, 'fail' ends up in an argument position, because it occurred as a-_locally_ bound variable within 'fail1'. And because of that 'fail' stops being-a join-point.--However, when we apply 'liftNonRep' in a top down traversal we end up with:--> fail = \x -> ...->-> fail1 = \y -> case ... of->   X -> fail ...->   Y -> ...->-> let ...-> in  case ... of->       A -> let->            in case ... of->                 P -> fail1 ...->                 Q -> ...->       B -> fail ...--and all is well with the world.--UPDATE:-We can now just perform liftNonRep in a bottom-up traversal again, because-liftNonRep no longer checks that if the binding that is lifted is a join-point.-However, for this to work, bindNonRep must always have been exhaustively applied-before liftNonRep. See also: [Note] bindNonRep before liftNonRep.--}--{- [Note] bindNonRep before liftNonRep-The combination of liftNonRep and nonRepSpec can lead to non-termination in an-unchecked rewrite system (without termination measures in place) on the-following:--> main = f not-> f    = \a x -> (a x) && (f a x)--nonRepSpec will lead to:--> main = f'-> f    = \a x -> (a x) && (f a x)-> f'   = (\a x -> (a x) && (f a x)) not--then lamApp leads to:--> main = f'-> f    = \a x -> (a x) && (f a x)-> f'   = let a = not in (\x -> (a x) && (f a x))--then liftNonRep leads to:--> main = f'-> f    = \a x -> (a x) && (f a x)-> f'   = \x -> (g x) && (f g x)-> g    = not--and nonRepSepc leads to:--> main = f'-> f    = \a x -> (a x) && (f a x)-> f'   = \x -> (g x) && (f'' g x)-> g    = not-> f''  = (\a x -> (a x) && (f a x)) g--This cycle continues indefinitely, as liftNonRep creates a new global variable,-which is never alpha-equivalent to the previous global variable introduced by-liftNonRep.--That is why bindNonRep must always be applied before liftNonRep. When we end up-in the situation after lamApp:--> main = f'-> f    = \a x -> (a x) && (f a x)-> f'   = let a = not in (\x -> (a x) && (f a x))--bindNonRep will now lead to:--> main = f'-> f    = \a x -> (a x) && (f a x)-> f'   = \x -> (not x) && (f not x)--Because `f` has already been specialized on the alpha-equivalent-to-itself `not`-function, liftNonRep leads to:--> main = f'-> f    = \a x -> (a x) && (f a x)-> f'   = \x -> (not x) && (f' x)--And there is no non-terminating rewriting cycle.--That is why bindNonRep must always be exhaustively applied before we apply-liftNonRep.--}---- | Topdown traversal, stops upon first success-topdownSucR :: Rewrite extra -> Rewrite extra-topdownSucR r = r >-! (allR (topdownSucR r))-{-# INLINE topdownSucR #-}+constantPropagation = $(compileStrategy constantPropagationSpec) -innerMost :: Rewrite extra -> Rewrite extra-innerMost = let go r = bottomupR (r !-> innerMost r) in go-{-# INLINE innerMost #-}+-- constantPropagation is defined first: the splice below quotes its name,+-- and a top-level splice can only see the declarations above it. -applyMany :: [(String,Rewrite extra)] -> Rewrite extra-applyMany = foldr1 (>->) . map (uncurry apply)-{-# INLINE applyMany #-}+-- | Normalisation transformation+normalization :: NormRewrite+normalization = $(compileStrategy (normalizationSpec 'constantPropagation))
− src/Clash/Normalize/Strategy.hs-boot
@@ -1,6 +0,0 @@-module Clash.Normalize.Strategy (constantPropagation, normalization) where--import Clash.Normalize.Types (NormRewrite)--normalization :: NormRewrite-constantPropagation :: NormRewrite
+ src/Clash/Normalize/Strategy/Spec.hs view
@@ -0,0 +1,402 @@+{-|+  Copyright  :  (C) 2012-2016, University of Twente,+                (C) 2021-2026, QBayLogic B.V.+  License    :  BSD2 (see the file LICENSE)+  Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>++  The normalization strategies, as pure "Clash.Rewrite.StrategyDSL" values.+  "Clash.Normalize.Strategy" compiles 'normalizationSpec' and+  'constantPropagationSpec' into the executable 'Clash.Normalize.Strategy.normalization'+  and 'Clash.Normalize.Strategy.constantPropagation'; "Clash.Normalize"+  compiles 'flattenSpec' into the flattening strategy of @flattenCallTree@.+-}++{-# LANGUAGE DisambiguateRecordFields #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NoFieldSelectors #-}+{-# LANGUAGE OverloadedRecordDot #-}+{-# LANGUAGE TemplateHaskellQuotes #-}++module Clash.Normalize.Strategy.Spec+  ( normalizationSpec+  , constantPropagationSpec+  , flattenSpec+  ) where++import Language.Haskell.TH.Syntax (Name)++import Clash.Normalize.Transformations+import Clash.Rewrite.StrategyDSL++-- [Note: bottomup traversal reduceConst]+--+-- 2-May-2019: There is a bug in the evaluator where all data constructors are+-- considered lazy, even though their declaration says they have strict fields.+-- This causes some reductions to fail because the term under the constructor is+-- not in WHNF, which is what some of the evaluation rules for certain primitive+-- operations expect. Using a bottom-up traversal works around this bug by+-- ensuring that the values under the constructor are in WHNF.+--+-- Using a bottomup traversal ensures that constants are reduced to NF, even if+-- constructors are lazy, thus ensuring more sensible/smaller generated HDL.++-- | Normalisation transformation. The argument is the name of the compiled+-- 'Clash.Normalize.Strategy.constantPropagation' binding.+normalizationSpec :: Name -> Strat+normalizationSpec constantPropagationName =+  rmDeadcode >-> multPrim >-> callStrategy constantPropagationName >->+  rmUnusedExpr >-!-> anf >-!-> rmDeadcode >->+  bindConst >-> letTL+  >-> evalConst+  >-!-> cse >-!-> cleanup >->+  elimCaseBigNum >->  -- see [Note] late elimCaseBigNum+  xOptim >-> rmDeadcode >->+  cleanup >-> bindSimIO >-> recLetRec >-> splitArgs+  where+    multPrim   = topdown setupMultiResultPrim+    anf        = topdown nonRepANF >-> pass "ANF" 'makeANF >-> topdown caseCon+    letTL      = topdownSuc topLet+    recLetRec  = pass "recToLetRec" 'recToLetRec+    rmUnusedExpr = bottomup removeUnusedExpr+    rmDeadcode = bottomup (named "deadcode" deadCode)+    bindConst  = topdown bindConstantVar+    -- See [Note] bottomup traversal reduceConst:+    evalConst  = bottomup reduceConst+    cse        = topdown simpleCSE+    elimCaseBigNum = topdown elimCaseBigNumInternals+    xOptim     = bottomup xOptimize+    cleanup    = topdown etaExpandSyn >->+                 topdownSuc inlineCleanup !->+                 innerMost (chain [ caseCon+                                  , bindConstantVar+                                  , named "letFlat" flattenLet+                                  ])+                 >-> rmDeadcode >-> letTL+    splitArgs  = topdown separateArguments !->+                 bottomup caseCon+    bindSimIO  = topdown inlineSimIO+++constantPropagationSpec :: Strat+constantPropagationSpec =+  inlineAndPropagate >->+  caseFlattening >->+  etaTL >->+  dec >->+  spec >->+  dec >->+  conSpec+  where+    etaTL              = pass "etaTL" 'etaExpansionTL !-> topdown appProp+    -- The outer repeatR is still needed: inlineNR is a full traversal whose+    -- results can only be processed by re-running the top-down chain from the+    -- new root.+    --+    -- NB: 'topdownFix' is deliberately _not_ used here, see+    -- Note [topdownFixR is not for inlining bundles].+    inlineAndPropagate = repeatR (topdown transPropagateAndInline >-> inlineNR)+    spec               = bottomup specTransformations+    caseFlattening     = topdownFix caseFlat+    dec                = topdownFix disjointExpressionConsolidation+    conSpec            = bottomup ((one (named "appPropCS" appProp) !->+                                    nested (bottomup constantSpec)) >-!+                                   one constantSpec)++    transPropagateAndInline :: Step+    transPropagateAndInline = chain+      [ appProp+      , bindConstantVar+      , caseLet+      , caseCase+      , caseCon+      , elimExistentials+      , caseEliminateNonReachable+      , removeUnusedExpr+      -- These transformations can safely be applied in a top-down traversal as+      -- they themselves check whether the to-be-inlined binder is recursive or not.+      , inlineWorkFree+      , inlineSmall+      , inlineOrLiftNonRep -- See: [Note] bindNonRep before liftNonRep+                           -- See: [Note] bottom-up traversal for liftNonRep+      , reducePrim++      , caseCast+      , letCast+      , splitCastWork+      , argCastSpec+      , inlineCast+      , elimCastCast+      ]++    -- InlineNonRep cannot be applied in a top-down traversal, as the non-representable+    -- binder might be recursive. The idea is, is that if the recursive+    -- non-representable binder is inlined once, we can get rid of the recursive+    -- aspect using the case-of-known-constructor+    --+    -- Note that we first do a dead code removal pass, which makes sure that+    -- unused let-bindings get cleaned up. Only if no dead code is removed+    -- 'inlineNonRep' is executed. We do this for two reasons:+    --+    --   1. 'deadCode' is an expensive operation and is therefore left out of+    --      the hot loop 'transPropagateAndInline'.+    --+    --   2. In various situations 'transPropagateAndInline' can do more work+    --      after 'deadCode' was successful. This work in turn might remove a+    --      a construct 'inlineNonRep' would fire on - saving the compiler work.+    --+    inlineNR :: Strat+    inlineNR =+          bottomup deadCode+      >-! pass "inlineNonRep" 'inlineNonRep++    specTransformations :: Step+    specTransformations = chain+      [ typeSpec+      , nonRepSpec+      , zeroWidthSpec+        -- See Note [zeroWidthSpec enabling transformations]+      ]++{-+Note [flatten pass structure]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Through experimentation we've learned the following:++1. The evaluator-backed rewrites ('reduceConst', 'reducePrim') must not+   sit inside the top-down propagation chain. 'topdownFix' settles that chain+   at each node until a fixpoint, so a chained 'reduceConst' is re-attempted -+   evaluator call and all - for every 'appProp' or 'caseCon' that fires there.+   On large designs we've measured that dominates; hoisting them out was worth+   ~30%. See #3338.++2. There should be exactly two traversals per round, and the bottom-up one has+   to come first.++   A traversal rebuilds every node it walks, so each extra traversal costs a+   full term rebuild per round even when nothing fires. Running 'flattenLet'+   and the evaluator-backed rewrites as one fused bottom-up pass instead of two+   consecutive ones is therefore free of charge (it does not change which+   rewrites fire, or in which order they fire relative to each other).++   Running that bottom-up pass _before_ the top-down one lets the constants it+   folds be consumed by 'caseCon' in the same round. With the passes the other+   way round the folded constants sit unused until the next round, so+   constant-heavy designs pay for an extra iteration of the whole loop:+   @tests/shouldwork/Basic/AES.hs@ did ~36k extra node visits per transformation+   that way.++If you touch code related to this, please make sure to run benchmarks.+-}++-- | The flattening strategy of 'Clash.Normalize.flattenCallTree'.+flattenSpec :: Strat+flattenSpec =+  -- See Note [flatten pass structure].+  repeatR (bottomup (one flattenLet >->+                     (one reduceConst !-> one deadCode) >->+                     chain [ reducePrim+                           , removeUnusedExpr+                           ]) >->+           topdownFix (chain [ named "appProp" appProp+                             , bindConstantVar+                             , caseCon+                             ])) !->+  bottomup deadCode >-> -- See #3407+  letTL >->+  -- See [Note] relation `collapseRHSNoops` and `inlineCleanup`+  -- Note that we do this as the very last step, after all constant propagation+  -- has been done to avoid #3036.+  topdownSuc collapseRHSNoops >->+  topdownSuc inlineCleanup >->+  bottomup caseCon >-> -- https://github.com/clash-lang/clash-compiler/issues/3159 / #3204+  bottomup flattenLet >-> -- https://github.com/clash-lang/clash-compiler/issues/3185+  bottomup bindConstantVar >-> -- https://github.com/clash-lang/clash-compiler/issues/3041+  letTL+  where+    letTL = topdownSuc topLet++{-+[Note] late elimCaseBigNum++elimCaseBigNum is placed fairly late in the pipeline, after any constant folding and after caseCon.+Because Naturals also hide inside SNat/Nat/KnownNats, and those can be bigger then 64bits.+But they're ultimately monomorphic and thus static and will be evaluated.+We just have to make sure that evaluation happens before we do elimCaseBigNum.++For an example of where this can happen see foldableSNat in tests/shouldwork/Issues/T3157_IntegerNaturalInternals.hs+-}++{-+Note [zeroWidthSpec enabling transformations]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+When zeroWidthSpec fires, it can lead to better results in normalization, but+this is somewhat incidental. The extra transformations which fire are typically+from++  * calls to transformations like caseCon which occur after constantPropagation+    (e.g. caseCon run after ANF conversion).++  * flattening / inlining which happens late in normalization (after regular+    normalization has occurred)++  * normalizing another function due to being marked NOINLINE++If we consider the following:++    data AB = A | B++    ab :: KnownNat n => Index n -> AB -> AB+    ab n A = if n >  0 then A else B+    ab n B = if n == 0 then B else A+    {-# NOINLINE ab #-}++    topEntity = ab @1+    {-# NOINLINE topEntity #-}++The zeroWidthSpec transformation fires on the topEntity, giving a+post-normalization topEntity of++    \(x :: Index 1) ->+      \(y :: AB) ->+        letrec result :: AB = ab' y in result++where++    ab' = ab (fromInteger# 0)++The extra transformations which fire happen later when ab' is normalized.+Removing the NOINLINE from ab gives the same result, but the extra+transformations fire in flattening instead.+-}++{- [Note] bottom-up traversal for liftNonRep+We used to say:++"The liftNonRep transformation must be applied in a topDown traversal because+of what Clash considers tail calls in its join-point analysis."++Consider:++> let fail = \x -> ...+> in  case ... of+>       A -> let fail1 = \y -> case ... of+>                                 X -> fail ...+>                                 Y -> ...+>            in case ... of+>                 P -> fail1 ...+>                 Q -> ...+>       B -> fail ...++under "normal" tail call rules, the local 'fail' functions is not a join-point+because it is used in a let-binding. However, we apply "special" tail call rules+in Clash. Because 'fail' is used in a TC position within 'fail1', and 'fail1' is+only used in a TC position, in Clash, we consider 'tail' also only to be used+in a TC position.++Now image we apply 'liftNonRep' in a bottom up traversal, we will end up with:++> fail1 = \fail y -> case ... of+>   X -> fail ...+>   Y -> ...++> let fail = \x -> ...+> in  case ... of+>       A -> case ... of+>                 P -> fail1 fail ...+>                 Q -> ...+>       B -> fail ...++Suddenly, 'fail' ends up in an argument position, because it occurred as a+_locally_ bound variable within 'fail1'. And because of that 'fail' stops being+a join-point.++However, when we apply 'liftNonRep' in a top down traversal we end up with:++> fail = \x -> ...+>+> fail1 = \y -> case ... of+>   X -> fail ...+>   Y -> ...+>+> let ...+> in  case ... of+>       A -> let+>            in case ... of+>                 P -> fail1 ...+>                 Q -> ...+>       B -> fail ...++and all is well with the world.++UPDATE:+We can now just perform liftNonRep in a bottom-up traversal again, because+liftNonRep no longer checks that if the binding that is lifted is a join-point.+However, for this to work, bindNonRep must always have been exhaustively applied+before liftNonRep. See also: [Note] bindNonRep before liftNonRep.+-}++{- [Note] bindNonRep before liftNonRep+The combination of liftNonRep and nonRepSpec can lead to non-termination in an+unchecked rewrite system (without termination measures in place) on the+following:++> main = f not+> f    = \a x -> (a x) && (f a x)++nonRepSpec will lead to:++> main = f'+> f    = \a x -> (a x) && (f a x)+> f'   = (\a x -> (a x) && (f a x)) not++then lamApp leads to:++> main = f'+> f    = \a x -> (a x) && (f a x)+> f'   = let a = not in (\x -> (a x) && (f a x))++then liftNonRep leads to:++> main = f'+> f    = \a x -> (a x) && (f a x)+> f'   = \x -> (g x) && (f g x)+> g    = not++and nonRepSepc leads to:++> main = f'+> f    = \a x -> (a x) && (f a x)+> f'   = \x -> (g x) && (f'' g x)+> g    = not+> f''  = (\a x -> (a x) && (f a x)) g++This cycle continues indefinitely, as liftNonRep creates a new global variable,+which is never alpha-equivalent to the previous global variable introduced by+liftNonRep.++That is why bindNonRep must always be applied before liftNonRep. When we end up+in the situation after lamApp:++> main = f'+> f    = \a x -> (a x) && (f a x)+> f'   = let a = not in (\x -> (a x) && (f a x))++bindNonRep will now lead to:++> main = f'+> f    = \a x -> (a x) && (f a x)+> f'   = \x -> (not x) && (f not x)++Because `f` has already been specialized on the alpha-equivalent-to-itself `not`+function, liftNonRep leads to:++> main = f'+> f    = \a x -> (a x) && (f a x)+> f'   = \x -> (not x) && (f' x)++And there is no non-terminating rewriting cycle.++That is why bindNonRep must always be exhaustively applied before we apply+liftNonRep.+-}
src/Clash/Normalize/Transformations/ANF.hs view
@@ -2,19 +2,23 @@   Copyright  :  (C) 2012-2016, University of Twente,                     2016-2017, Myrtle Software Ltd,                     2017-2018, Google Inc.,-                    2021,      QBayLogic B.V.+                    2021,2026, QBayLogic B.V.   License    :  BSD2 (see the file LICENSE)   Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>    Transformations for converting to A-Normal Form. -} +{-# LANGUAGE MagicHash #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TemplateHaskellQuotes #-}+{-# LANGUAGE UnboxedTuples #-}  module Clash.Normalize.Transformations.ANF   ( makeANF   , nonRepANF+  , nonRepANFWorker   ) where  import Control.Arrow ((***))@@ -26,6 +30,7 @@ import Data.Bifunctor (second) import qualified Data.Monoid as Monoid (Any(..)) import qualified Data.Text.Extra as Text (showt)+import GHC.Exts (State#) import GHC.Stack (HasCallStack)  import Clash.Explicit.SimIO (SimIO)@@ -49,6 +54,7 @@ import Clash.Normalize.Transformations.Specialize (specialize) import Clash.Normalize.Types (NormRewrite, NormalizeSession) import Clash.Rewrite.Combinators (bottomupR)+import Clash.Rewrite.StrategyDSL (Transformation, onApp, toTransformation) import Clash.Rewrite.Types   (Transform, TransformContext(..), tcCache) import Clash.Rewrite.Util@@ -186,7 +192,7 @@   TyConApp tcNm args     | nameOcc tcNm == Text.showt ''SimIO     -> True-    | nameOcc tcNm == "GHC.Prim.(#,#)"+    | nameOcc tcNm == Text.showt ''(# , #)     , [_,_,st,_] <- args     -> isStateTokenTy tcm st   FunTy _ res -> isSimIOTy tcm res@@ -199,7 +205,7 @@   -- ^ Type to check for state tokenness   -> Bool isStateTokenTy tcm ty = case tyView (coreView tcm ty) of-  TyConApp tcNm _ -> nameOcc tcNm == "GHC.Prim.State#"+  TyConApp tcNm _ -> nameOcc tcNm == Text.showt ''State#   _ -> False  -- | Note [ANF InScopeSet]@@ -394,8 +400,14 @@  -- | Bring an application of a DataCon or Primitive in ANF, when the argument is -- is considered non-representable-nonRepANF :: HasCallStack => NormRewrite-nonRepANF ctx@(TransformContext is0 _) e@(App appConPrim arg)+nonRepANF :: Transformation+nonRepANF = toTransformation "nonRepANF" (onApp 'nonRepANFWorker)++-- | The 'App' handler of 'nonRepANF'.+nonRepANFWorker+  :: HasCallStack+  => TransformContext -> Term -> Term -> Term -> NormalizeSession Term+nonRepANFWorker ctx@(TransformContext is0 _) e appConPrim arg   | (conPrim, _) <- collectArgs e   , isCon conPrim || isPrim conPrim   = do@@ -410,5 +422,5 @@       (True,TyLam {}) -> specialize ctx e       _               -> return e -nonRepANF _ e = return e-{-# SCC nonRepANF #-}+nonRepANFWorker _ e _ _ = return e+{-# SCC nonRepANFWorker #-}
src/Clash/Normalize/Transformations/Case.hs view
@@ -15,22 +15,31 @@ {-# LANGUAGE MagicHash #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TemplateHaskellQuotes #-}  module Clash.Normalize.Transformations.Case   ( caseCase+  , caseCaseWorker   , caseCon+  , caseConWorker   , caseEliminateNonReachable+  , caseEliminateNonReachableWorker   , caseFlat+  , caseFlatWorker   , caseLet+  , caseLetWorker   , caseOneAlt   , elimExistentials+  , elimExistentialsWorker   , elimCaseBigNumInternals+  , elimCaseBigNumInternalsWorker   ) where  import Control.Exception.Base (patError) import GHC.Prim.Panic (absentError) import qualified Control.Lens as Lens-+import qualified Control.Monad.Writer as Writer+import qualified Data.Monoid as Monoid import Data.Bifunctor (second) import Data.Coerce (coerce) import qualified Data.Either as Either@@ -39,6 +48,8 @@ import qualified Data.Maybe as Maybe import qualified Data.Primitive.ByteArray as BA import qualified Data.Text.Extra as Text (showt)+import qualified GHC.Classes+import GHC.Exts (Int(..)) import GHC.Stack (HasCallStack)  import GHC.Num.Integer (Integer(..))@@ -71,8 +82,8 @@ import Clash.Netlist.Types (FilteredHWType(..), HWType(..)) import Clash.Netlist.Util (coreTypeToHWType) import qualified Clash.Normalize.Primitives as NP (undefined, undefinedX)-import Clash.Normalize.Types (NormRewrite, NormalizeSession)-import Clash.Rewrite.Combinators ((>-!))+import Clash.Normalize.Types (NormalizeSession)+import Clash.Rewrite.StrategyDSL (Transformation, onCase, toTransformation) import Clash.Rewrite.Types   ( TransformContext(..), bindings, customReprs, debugOpts, tcCache   , typeTranslator, workFreeBinders)@@ -85,8 +96,14 @@  -- | Move a Case-decomposition from the subject of a Case-decomposition to the -- alternatives-caseCase :: HasCallStack => NormRewrite-caseCase (TransformContext is0 _) e@(Case (stripTicks -> Case scrut alts1Ty alts1) alts2Ty alts2) = do+caseCase :: Transformation+caseCase = toTransformation "caseCase" (onCase 'caseCaseWorker)++-- | The 'Case' handler of 'caseCase'.+caseCaseWorker+  :: HasCallStack+  => TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term+caseCaseWorker (TransformContext is0 _) e (stripTicks -> Case scrut alts1Ty alts1) alts2Ty alts2 = do   ty1Rep <- not <$> isUntranslatableType False alts1Ty    -- This is only worth doing if the inner case-expression has a@@ -116,8 +133,8 @@                       (fmap (deShadowAlt is0) alts1)      in changed $ Case scrut alts2Ty newAlts -caseCase _ e = return e-{-# SCC caseCase #-}+caseCaseWorker _ e _ _ _ = return e+{-# SCC caseCaseWorker #-}  {- NOTE: caseOneAlt before caseCon'@@ -140,9 +157,25 @@ By trying caseOneAlt first clash can instead drop the case and use the body of the single alternative. -}-caseCon :: HasCallStack => NormRewrite-caseCon = const caseOneAlt >-! caseCon'+caseCon :: Transformation+caseCon = toTransformation "caseCon" (onCase 'caseConWorker) +-- | The 'Case' handler of 'caseCon': tries 'caseOneAlt' first and only when+-- that did not fire, 'caseCon''. See NOTE: caseOneAlt before caseCon'.+caseConWorker+  :: HasCallStack+  => TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term+caseConWorker ctx node subj ty alts = do+  (node1, oneAltChanged) <- Writer.listen (caseOneAlt node)+  if Monoid.getAny oneAltChanged+    then return node1+    else caseCon' ctx node subj ty alts++-- | Apply 'caseCon' to a freshly constructed case-expression; used by the+-- recursive calls inside 'caseCon''.+caseConOn :: TransformContext -> Term -> Type -> [Alt] -> NormalizeSession Term+caseConOn ctx subj ty alts = caseConWorker ctx (Case subj ty alts) subj ty alts+ -- | Specialize a Case-decomposition (replace by the RHS of an alternative) if -- the subject is (an application of) a DataCon; or if there is only a single -- alternative that doesn't reference variables bound by the pattern.@@ -172,8 +205,10 @@ -- let a1 = f a b -- in  h a1 -- @-caseCon' :: HasCallStack => NormRewrite-caseCon' ctx@(TransformContext is0 _) e@(Case subj ty alts) = do+caseCon'+  :: HasCallStack+  => TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term+caseCon' ctx@(TransformContext is0 _) e subj ty alts = do  tcm <- Lens.view tcCache  case collectArgsTicks subj of   -- The subject is an applied data constructor@@ -258,9 +293,9 @@     -- We try to reduce the applied primitive to WHNF     whnfRW True ctx subj $ \ctx1 subj1 -> case collectArgsTicks subj1 of       -- WHNF of subject is a literal, try `caseCon` with that-      (Literal l,_,_) -> caseCon ctx1 (Case (Literal l) ty alts)+      (Literal l,_,_) -> caseConOn ctx1 (Literal l) ty alts       -- WHNF of subject is a data-constructor, try `caseCon` with that-      (Data _,_,_) -> caseCon ctx1 (Case subj1 ty alts)+      (Data _,_,_) -> caseConOn ctx1 subj1 ty alts       -- WHNF of subject is _|_, in the form of `error`: that means that the       -- entire case-expression is evaluates to _|_       (Prim pInfo,repTy:_:callStack:msg:_,ticks)@@ -312,7 +347,7 @@             -- one of the Clash number types. Then the only valid alternative is             -- the one that can match on the literal "0", so try 'caseCon' with             -- that.-            -> caseCon ctx1 (Case (Literal (IntegerLiteral 0)) ty alts)+            -> caseConOn ctx1 (Literal (IntegerLiteral 0)) ty alts           _ -> do             opts <- Lens.view debugOpts             -- When invariants are being checked, report missing evaluation@@ -330,7 +365,7 @@     -- one of the Clash number types. Then the only valid alternative is     -- the one that can match on the literal "0", so try 'caseCon' with     -- that.-    caseCon ctx (Case (Literal (IntegerLiteral 0)) ty alts)+    caseConOn ctx (Literal (IntegerLiteral 0)) ty alts    where     isNum0 (tyView -> TyConApp (nameOcc -> tcNm) [arg])       | tcNm `elem`@@ -351,8 +386,6 @@   -- Otherwise check whether the entire case-expression has a single   -- alternative, and pick that one.   _ -> caseOneAlt e--caseCon' _ e = return e {-# SCC caseCon' #-}  {- [Note: Name re-creation]@@ -458,17 +491,23 @@ -- @f@ is always specialized on @STy Int@. The SBool alternatives are therefore -- unreachable. Additional information can be found at: -- https://github.com/clash-lang/clash-compiler/pull/465-caseEliminateNonReachable :: HasCallStack => NormRewrite-caseEliminateNonReachable _ case0@(Case scrut altsTy alts0) = do+caseEliminateNonReachable :: Transformation+caseEliminateNonReachable =+  toTransformation "caseEliminateNonReachable"+    (onCase 'caseEliminateNonReachableWorker)++-- | The 'Case' handler of 'caseEliminateNonReachable'.+caseEliminateNonReachableWorker+  :: HasCallStack+  => TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term+caseEliminateNonReachableWorker _ case0 scrut altsTy alts0 = do   tcm <- Lens.view tcCache    let (altsAbsurd, altsOther) = List.partition (isAbsurdPat tcm . fst) alts0   case altsAbsurd of     [] -> return case0     _  -> changed =<< caseOneAlt (Case scrut altsTy altsOther)--caseEliminateNonReachable _ e = return e-{-# SCC caseEliminateNonReachable #-}+{-# SCC caseEliminateNonReachableWorker #-}  -- | Flatten ridiculous case-statements generated by GHC --@@ -510,14 +549,20 @@ --        2 -> fromInteger 1 --        3 -> fromInteger 0 -- @-caseFlat :: HasCallStack => NormRewrite-caseFlat (TransformContext is0 _) e@(Case (collectEqArgs -> Just (scrut',val)) ty _) =+caseFlat :: Transformation+caseFlat = toTransformation "caseFlat" (onCase 'caseFlatWorker)++-- | The 'Case' handler of 'caseFlat'.+caseFlatWorker+  :: HasCallStack+  => TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term+caseFlatWorker (TransformContext is0 _) e (collectEqArgs -> Just (scrut',val)) ty _ =   case collectFlat scrut' e of     Just alts' -> case collectArgs val of       -- When we're pattern matching on `Int`, extract the `Int#` first before       -- we do the Literal matching branches.       (Data dc,_)-        | nameOcc (dcName dc) == "GHC.Types.I#"+        | nameOcc (dcName dc) == Text.showt 'I#         , [argTy] <- dcArgTys dc         -> do           wild <- mkInternalVar is0 "wild" argTy@@ -527,8 +572,8 @@       _ -> changed (Case scrut' ty (last alts' : init alts'))     Nothing -> return e -caseFlat _ e = return e-{-# SCC caseFlat #-}+caseFlatWorker _ e _ _ _ = return e+{-# SCC caseFlatWorker #-}  collectFlat :: Term -> Term -> Maybe [Alt] collectFlat scrut (Case (collectEqArgs -> Just (scrut', val)) _ty [lAlt,rAlt])@@ -536,7 +581,7 @@   = case collectArgs val of       (Prim p,args') | isFromInt (primName p) ->         go (last args')-      (Data dc,args') | nameOcc (dcName dc) == "GHC.Types.I#" ->+      (Data dc,args') | nameOcc (dcName dc) == Text.showt 'I# ->         go (last args')       _ -> Nothing   where@@ -557,11 +602,11 @@     go _ = Nothing      isFalseDcPat (DataPat p _ _)-      = ((== "GHC.Types.False") . nameOcc . dcName) p+      = ((== Text.showt 'False) . nameOcc . dcName) p     isFalseDcPat _ = False      isTrueDcPat (DataPat p _ _)-      = ((== "GHC.Types.True") . nameOcc . dcName) p+      = ((== Text.showt 'True) . nameOcc . dcName) p     isTrueDcPat _ = False  collectFlat _ _ = Nothing@@ -579,7 +624,7 @@     = case args of         [_,Left scrut,Left val] -> Just (mkTicks scrut ticks,val)         _ -> error (show nm <> " expects 3 arguments, but got: " <> showPpr f)-  | nm == "GHC.Classes.eqInt"+  | nm == Text.showt 'GHC.Classes.eqInt     = case args of         [Left scrut,Left val] -> Just (mkTicks scrut ticks,val)         _ -> error ("eqInt expects 2 arguments, but got: " <> showPpr f)@@ -589,8 +634,14 @@ collectEqArgs _ = Nothing  -- | Lift the let-bindings out of the subject of a Case-decomposition-caseLet :: HasCallStack => NormRewrite-caseLet (TransformContext is0 _) (Case (collectTicks -> (Let xes e,ticks)) ty alts) = do+caseLet :: Transformation+caseLet = toTransformation "caseLet" (onCase 'caseLetWorker)++-- | The 'Case' handler of 'caseLet'.+caseLetWorker+  :: HasCallStack+  => TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term+caseLetWorker (TransformContext is0 _) _node (collectTicks -> (Let xes e,ticks)) ty alts = do   -- Note [CaseLet deshadow]   -- Imagine   --@@ -622,8 +673,8 @@   changed (Let (fmap (`mkTicks` ticks) xes1)                   (Case (mkTicks e1 ticks) ty alts)) -caseLet _ e = return e-{-# SCC caseLet #-}+caseLetWorker _ e _ _ _ = return e+{-# SCC caseLetWorker #-}  caseOneAlt :: Term -> NormalizeSession Term caseOneAlt e@(Case _ _ [(pat,altE)]) =@@ -671,36 +722,41 @@ -- This function solves 'n1' and replaces every occurrence with its solution. A -- very limited number of solutions are currently recognized: only adds (such -- as in the example) will be solved.-elimExistentials :: HasCallStack => NormRewrite-elimExistentials (TransformContext is0 _) (Case scrut altsTy alts0) = do+elimExistentials :: Transformation+elimExistentials =+  toTransformation "elimExistentials" (onCase 'elimExistentialsWorker)++-- | The 'Case' handler of 'elimExistentials'.+elimExistentialsWorker+  :: HasCallStack+  => TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term+elimExistentialsWorker (TransformContext is0 _) _node scrut altsTy alts0 = do   tcm <- Lens.view tcCache   alts1 <- traverse (go is0 tcm) alts0   caseOneAlt (Case scrut altsTy alts1)  where-    -- Eliminate free type variables if possible-    go :: InScopeSet -> TyConMap -> Alt -> NormalizeSession Alt-    go is2 tcm alt@(pat@(DataPat dc exts0 xs0), term0) =-      case solveNonAbsurds tcm (mkVarSet exts0) (patEqs tcm pat) of-        -- No equations solved:-        [] -> return alt-        -- One or more equations solved:-        sols ->-          changed =<< go is2 tcm (DataPat dc exts1 xs1, term1)-          where-            -- Substitute solution in existentials and applied types-            is3 = extendInScopeSetList is2 exts0-            xs1 = fmap (substTyInVar (extendTvSubstList (mkSubst is3) sols)) xs0-            exts1 = substInExistentialsList is2 exts0 sols--            -- Substitute solution in term.-            is4 = extendInScopeSetList is3 xs1-            subst = extendTvSubstList (mkSubst is4) sols-            term1 = substTm "Replacing tyVar due to solved eq" subst term0+  -- Eliminate free type variables if possible+  go :: InScopeSet -> TyConMap -> Alt -> NormalizeSession Alt+  go is2 tcm alt@(pat@(DataPat dc exts0 xs0), term0) =+    case solveNonAbsurds tcm (mkVarSet exts0) (patEqs tcm pat) of+      -- No equations solved:+      [] -> return alt+      -- One or more equations solved:+      sols ->+        changed =<< go is2 tcm (DataPat dc exts1 xs1, term1)+        where+          -- Substitute solution in existentials and applied types+          is3 = extendInScopeSetList is2 exts0+          xs1 = fmap (substTyInVar (extendTvSubstList (mkSubst is3) sols)) xs0+          exts1 = substInExistentialsList is2 exts0 sols -    go _ _ alt = return alt+          -- Substitute solution in term.+          is4 = extendInScopeSetList is3 xs1+          subst = extendTvSubstList (mkSubst is4) sols+          term1 = substTm "Replacing tyVar due to solved eq" subst term0 -elimExistentials _ e = return e-{-# SCC elimExistentials #-}+  go _ _ alt = return alt+{-# SCC elimExistentialsWorker #-}  -- | This finds cases on Integers and Naturals and rewrites them -- to remove the alternatives with bignums/bytearrays in them.@@ -720,8 +776,15 @@ -- -- This is as "safe" as the rest of the Natural/Integer handling that clash does in HDL, -- because numbers bigger then Word/Int can't exist there anyway.-elimCaseBigNumInternals :: HasCallStack => NormRewrite-elimCaseBigNumInternals _ e@(Case scrut altsTy alts0@(_:_:_)) =+elimCaseBigNumInternals :: Transformation+elimCaseBigNumInternals =+  toTransformation "elimCaseBigNum" (onCase 'elimCaseBigNumInternalsWorker)++-- | The 'Case' handler of 'elimCaseBigNumInternals'.+elimCaseBigNumInternalsWorker+  :: HasCallStack+  => TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term+elimCaseBigNumInternalsWorker _ e scrut altsTy alts0@(_:_:_) =   go alts0  where   go [] = return e@@ -738,4 +801,4 @@    where     fvs = Lens.foldMapOf freeLocalIds unitVarSet altE -elimCaseBigNumInternals _ e = return e+elimCaseBigNumInternalsWorker _ e _ _ _ = return e
src/Clash/Normalize/Transformations/Cast.hs view
@@ -1,12 +1,18 @@ {-# LANGUAGE LambdaCase #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TemplateHaskellQuotes #-}  module Clash.Normalize.Transformations.Cast   ( argCastSpec+  , argCastSpecWorker   , caseCast+  , caseCastWorker   , elimCastCast+  , elimCastCastWorker   , letCast+  , letCastWorker   , splitCastWork+  , splitCastWorkWorker   ) where  import Control.Exception (throw)@@ -17,14 +23,17 @@  import Clash.Core.Name (nameOcc) import Clash.Core.Pretty (showPpr)-import Clash.Core.Term (LetBinding, Term(..), collectArgs, stripTicks)+import Clash.Core.Term+  (Bind, LetBinding, Term(..), bindToList, collectArgs, stripTicks) import Clash.Core.TermInfo (isCast)-import Clash.Core.Type (normalizeType)+import Clash.Core.Type (Type, normalizeType) import Clash.Core.Var (isGlobalId, varName) import Clash.Core.VarEnv (InScopeSet) import Clash.Debug (trace) import Clash.Normalize.Transformations.Specialize (specialize)-import Clash.Normalize.Types (NormRewrite, NormalizeSession)+import Clash.Normalize.Types (NormalizeSession)+import Clash.Rewrite.StrategyDSL+  (Transformation, onApp, onCast, onLet, toTransformation) import Clash.Rewrite.Types   (TransformContext(..), bindings, curFun, tcCache, workFreeBinders) import Clash.Rewrite.Util (changed, mkDerivedName, mkTmBinderFor)@@ -48,46 +57,64 @@ -- The reason d'etre for this transformation is that we hope to end up with -- and expression where two casts are "back-to-back" after which we can -- eliminate them in 'elimCastCast'.-argCastSpec :: HasCallStack => NormRewrite-argCastSpec ctx e@(App f (stripTicks -> Cast e' _ _))- -- Don't specialise when the arguments are casts-of-casts, these casts-of-casts- -- will be eliminated by 'elimCastCast' during the normalization of the- -- "current" function. We thus prevent the unnecessary introduction of a- -- specialized version of 'f'.+argCastSpec :: Transformation+argCastSpec = toTransformation "argCastSpec" (onApp 'argCastSpecWorker)++-- | The 'App' handler of 'argCastSpec'.+argCastSpecWorker+  :: HasCallStack+  => TransformContext -> Term -> Term -> Term -> NormalizeSession Term+argCastSpecWorker ctx node f (stripTicks -> Cast e' _ _)+ -- Don't specialise when the arguments are casts-of-casts, these+ -- casts-of-casts will be eliminated by 'elimCastCast' during the+ -- normalization of the "current" function. We thus prevent the unnecessary+ -- introduction of a specialized version of 'f'.  | not (isCast e')  -- We can only push casts into global binders  , (Var g, _) <- collectArgs f  , isGlobalId g = do   bndrs <- Lens.use bindings   isWorkFree workFreeBinders bndrs e' >>= \case-    True -> go-    False -> warn go+    True -> specializeNode+    False -> warn specializeNode  where-  go = specialize ctx e+  specializeNode = specialize ctx node   warn = trace (unwords     [ "WARNING:", $(curLoc), "specializing a function on a non work-free"     , "cast. Generated HDL implementation might contain duplicate work."     , "Please report this as a bug.", "\n\nExpression where this occured:"-    , "\n\n" ++ showPpr e+    , "\n\n" ++ showPpr node     ])-argCastSpec _ e = return e-{-# SCC argCastSpec #-}+argCastSpecWorker _ctx node _function _argument = return node+{-# SCC argCastSpecWorker #-}  -- | Push a cast over a case into it's alternatives.-caseCast :: HasCallStack => NormRewrite-caseCast _ (Cast (stripTicks -> Case subj ty alts) ty1 ty2) = do+caseCast :: Transformation+caseCast = toTransformation "caseCast" (onCast 'caseCastWorker)++-- | The 'Cast' handler of 'caseCast'.+caseCastWorker+  :: HasCallStack+  => TransformContext -> Term -> Term -> Type -> Type -> NormalizeSession Term+caseCastWorker _ctx _node (stripTicks -> Case subj ty alts) ty1 ty2 = do   let alts' = map (\(p,e) -> (p, Cast e ty1 ty2)) alts   changed (Case subj ty alts')-caseCast _ e = return e-{-# SCC caseCast #-}+caseCastWorker _ctx node _body _fromType _toType = return node+{-# SCC caseCastWorker #-}  -- | Eliminate two back to back casts where the type going in and coming out are the same -- -- @ --   (cast :: b -> a) $ (cast :: a -> b) x   ==> x -- @-elimCastCast :: HasCallStack => NormRewrite-elimCastCast _ c@(Cast (stripTicks -> Cast e tyA tyB) tyB' tyC) = do+elimCastCast :: Transformation+elimCastCast = toTransformation "elimCastCast" (onCast 'elimCastCastWorker)++-- | The 'Cast' handler of 'elimCastCast'.+elimCastCastWorker+  :: HasCallStack+  => TransformContext -> Term -> Term -> Type -> Type -> NormalizeSession Term+elimCastCastWorker _ctx node (stripTicks -> Cast e tyA tyB) tyB' tyC = do   tcm <- Lens.view tcCache   let ntyA  = normalizeType tcm tyA       ntyB  = normalizeType tcm tyB@@ -95,22 +122,28 @@       ntyC  = normalizeType tcm tyC   if ntyB == ntyB' && ntyA == ntyC then changed e                                    else throwError-  where throwError = do-          (nm,sp) <- Lens.use curFun-          throw (ClashException sp ($(curLoc) ++ showPpr nm-                  ++ ": Found 2 nested casts whose types don't line up:\n"-                  ++ showPpr c)-                Nothing)--elimCastCast _ e = return e-{-# SCC elimCastCast #-}+ where+  throwError = do+    (nm,sp) <- Lens.use curFun+    throw (ClashException sp ($(curLoc) ++ showPpr nm+            ++ ": Found 2 nested casts whose types don't line up:\n"+            ++ showPpr node)+          Nothing)+elimCastCastWorker _ctx node _body _fromType _toType = return node+{-# SCC elimCastCastWorker #-}  -- | Push a cast over a Let into it's body-letCast :: HasCallStack => NormRewrite-letCast _ (Cast (stripTicks -> Let binds body) ty1 ty2) =+letCast :: Transformation+letCast = toTransformation "letCast" (onCast 'letCastWorker)++-- | The 'Cast' handler of 'letCast'.+letCastWorker+  :: HasCallStack+  => TransformContext -> Term -> Term -> Type -> Type -> NormalizeSession Term+letCastWorker _ctx _node (stripTicks -> Let binds body) ty1 ty2 =   changed $ Let binds (Cast body ty1 ty2)-letCast _ e = return e-{-# SCC letCast #-}+letCastWorker _ctx node _body _fromType _toType = return node+{-# SCC letCastWorker #-}  -- | Make a cast work-free by splitting the work of to a separate binding --@@ -120,27 +153,32 @@ -- let x  = cast x' --     x' = f a b -- @-splitCastWork :: HasCallStack => NormRewrite-splitCastWork ctx@(TransformContext is0 _) unchanged@(Letrec vs e') = do-  (vss', Monoid.getAny -> hasChanged) <- listen (mapM (splitCastLetBinding is0) vs)-  let vs' = concat vss'-  if hasChanged then changed (Letrec vs' e')-                else return unchanged-  where-    splitCastLetBinding-      :: InScopeSet-      -> LetBinding-      -> NormalizeSession [LetBinding]-    splitCastLetBinding isN x@(nm, e) = case stripTicks e of-      Cast (Var {}) _ _  -> return [x]  -- already work-free-      Cast (Cast {}) _ _ -> return [x]  -- casts will be eliminated-      Cast e0 ty1 ty2 -> do-        tcm <- Lens.view tcCache-        nm' <- mkTmBinderFor isN tcm (mkDerivedName ctx (nameOcc $ varName nm)) e0-        changed [(nm',e0)-                ,(nm, Cast (Var nm') ty1 ty2)-                ]-      _ -> return [x]+splitCastWork :: Transformation+splitCastWork = toTransformation "splitCastWork" (onLet 'splitCastWorkWorker) -splitCastWork _ e = return e-{-# SCC splitCastWork #-}+-- | The 'Let' handler of 'splitCastWork'.+splitCastWorkWorker+  :: HasCallStack+  => TransformContext -> Term -> Bind Term -> Term -> NormalizeSession Term+splitCastWorkWorker ctx@(TransformContext is0 _) node bind body = do+  (vss', Monoid.getAny -> hasChanged) <-+    listen (mapM (splitCastLetBinding is0) (bindToList bind))+  let vs' = concat vss'+  if hasChanged then changed (Letrec vs' body)+                else return node+ where+  splitCastLetBinding+    :: InScopeSet+    -> LetBinding+    -> NormalizeSession [LetBinding]+  splitCastLetBinding isN x@(nm, e) = case stripTicks e of+    Cast (Var {}) _ _  -> return [x]  -- already work-free+    Cast (Cast {}) _ _ -> return [x]  -- casts will be eliminated+    Cast e0 ty1 ty2 -> do+      tcm <- Lens.view tcCache+      nm' <- mkTmBinderFor isN tcm (mkDerivedName ctx (nameOcc $ varName nm)) e0+      changed [(nm',e0)+              ,(nm, Cast (Var nm') ty1 ty2)+              ]+    _ -> return [x]+{-# SCC splitCastWorkWorker #-}
src/Clash/Normalize/Transformations/DEC.hs view
@@ -1,6 +1,6 @@ {-|   Copyright  :  (C) 2015-2016, University of Twente,-                    2021-2024, QBayLogic B.V.+                    2021-2024,2026, QBayLogic B.V.                     2022,      LumiGuide Fietsdetectie B.V.   License    :  BSD2 (see the file LICENSE)   Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>@@ -33,8 +33,11 @@ {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE MagicHash #-} +--{-# OPTIONS_GHC -ddump-splices #-}+ module Clash.Normalize.Transformations.DEC   ( disjointExpressionConsolidation+  , disjointExpressionConsolidationWorker   ) where  import Control.Lens ((^.), _1)@@ -87,8 +90,10 @@ import qualified Clash.Data.UniqMap as UniqMap import qualified Clash.Normalize.Primitives as NP import Clash.Normalize.Transformations.Letrec (deadCode)-import Clash.Normalize.Types (NormRewrite, NormalizeSession)+import Clash.Normalize.Types (NormalizeSession) import Clash.Rewrite.Combinators (bottomupR)+import Clash.Rewrite.StrategyDSL (Transformation, onCase, toTransformation)+import Clash.Rewrite.StrategyDSL.TH (asRewriteQ) import Clash.Rewrite.Types import Clash.Rewrite.Util (changed, isFromInt, isUntranslatableType) import Clash.Rewrite.WorkFree (isConstant)@@ -146,8 +151,15 @@ -- and to share the /decoder/ circuit that logic synthesis will create to map the -- bits of the subject expression to the bits needed to make the selection in the -- multiplexer.-disjointExpressionConsolidation :: HasCallStack => NormRewrite-disjointExpressionConsolidation ctx@(TransformContext isCtx _) e@(Case _scrut _ty _alts@(_:_:_)) = do+disjointExpressionConsolidation :: Transformation+disjointExpressionConsolidation =+  toTransformation "DEC" (onCase 'disjointExpressionConsolidationWorker)++-- | The 'Case' handler of 'disjointExpressionConsolidation'.+disjointExpressionConsolidationWorker+  :: HasCallStack+  => TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term+disjointExpressionConsolidationWorker ctx@(TransformContext isCtx _) e _scrut _ty _alts@(_:_:_) = do     -- Collect all (the applications of) global binders (and certain primitives)     -- that would be interesting to share out of the case-alternatives.     (_,isCollected,collected) <- collectGlobals isCtx [] [] e@@ -194,7 +206,7 @@          let lb = Letrec (zip funOutIds lifted1) e1          -- Do an initial dead-code elimination pass, as `mkDisJoint` doesn't          -- clean-up unused let-binders.-         lb1 <- bottomupR deadCode ctx lb+         lb1 <- bottomupR $(asRewriteQ deadCode) ctx lb          changed lb1   where     -- Make the let-binder for the lifted expressions@@ -253,8 +265,7 @@       go _  []     = []       go xs (y:ys) = (xs ++ ys) : go (xs ++ [y]) ys -disjointExpressionConsolidation _ e = return e-{-# SCC disjointExpressionConsolidation #-}+disjointExpressionConsolidationWorker _ e _ _ _ = return e  decFunName :: Term -> OccName decFunName fun = last . Text.splitOn "." $ case collectArgs fun of
src/Clash/Normalize/Transformations/EtaExpand.hs view
@@ -2,7 +2,7 @@   Copyright  :  (C) 2012-2016, University of Twente,                     2016-2017, Myrtle Software Ltd,                     2017-2018, Google Inc.,-                    2021     , QBayLogic B.V.+                    2021,2026, QBayLogic B.V.   License    :  BSD2 (see the file LICENSE)   Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> @@ -12,9 +12,11 @@ {-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TemplateHaskellQuotes #-}  module Clash.Normalize.Transformations.EtaExpand   ( etaExpandSyn+  , etaExpandSynWorker   , etaExpansionTL   ) where @@ -30,14 +32,25 @@ import Clash.Core.Var (Id) import Clash.Core.VarEnv (elemVarSet, extendInScopeSet, extendInScopeSetList) import Clash.Normalize.Types (NormRewrite)+import Clash.Rewrite.StrategyDSL+  ( Transformation, onAppNode, onTickNode, onTyAppNode, onVarNode+  , toTransformation+  ) import Clash.Rewrite.Types (TransformContext(..), tcCache, topEntities) import Clash.Rewrite.Util (changed) import Clash.Util (curLoc)  -- | Eta-expand functions with a Synthesize annotation, needed to allow such -- functions to appear as arguments to higher-order primitives.-etaExpandSyn :: HasCallStack => NormRewrite-etaExpandSyn (TransformContext is0 ctx) e@(collectArgs -> (Var f, _)) = do+etaExpandSyn :: Transformation+etaExpandSyn =+  toTransformation "etaExpandSyn"+    (onVarNode 'etaExpandSynWorker <> onAppNode 'etaExpandSynWorker+      <> onTyAppNode 'etaExpandSynWorker <> onTickNode 'etaExpandSynWorker)++-- | The application-spine handler of 'etaExpandSyn'.+etaExpandSynWorker :: HasCallStack => NormRewrite+etaExpandSynWorker (TransformContext is0 ctx) e@(collectArgs -> (Var f, _)) = do   topEnts <- Lens.view topEntities   tcm <- Lens.view tcCache   let isTopEnt = f `elemVarSet` topEnts@@ -53,8 +66,8 @@       changed (Lam newId (App e (Var newId)))     _ -> return e -etaExpandSyn _ e = return e-{-# SCC etaExpandSyn #-}+etaExpandSynWorker _ e = return e+{-# SCC etaExpandSynWorker #-}  stripLambda :: Term -> ([Id], Term) stripLambda (Lam bndr e) =
src/Clash/Normalize/Transformations/Inline.hs view
@@ -18,18 +18,27 @@ {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TemplateHaskellQuotes #-}  module Clash.Normalize.Transformations.Inline   ( bindConstantVar+  , bindConstantVarWorker   , inlineBndrsCleanup   , inlineCast+  , inlineCastWorker   , inlineCleanup+  , inlineCleanupWorker   , collapseRHSNoops+  , collapseRHSNoopsWorker   , inlineNonRep   , inlineOrLiftNonRep+  , inlineOrLiftNonRepWorker   , inlineSimIO+  , inlineSimIOWorker   , inlineSmall+  , inlineSmallWorker   , inlineWorkFree+  , inlineWorkFreeWorker   ) where  import qualified Control.Lens as Lens@@ -39,7 +48,7 @@ import Control.Monad.Trans.Maybe (MaybeT(..)) import Control.Monad.Writer (lift,listen) import Data.Default (Default(..))-import Data.Either  (lefts)+import Data.Either  (lefts, rights) import qualified Data.HashMap.Lazy as HashMap import qualified Data.List as List import qualified Data.Maybe as Maybe@@ -63,8 +72,9 @@ import Clash.Core.Subst import qualified Clash.Core.Term as Term import Clash.Core.Term-  ( CoreContext(..), Pat(..), PrimInfo(..), Term(..), WorkInfo(..), collectArgs-  , collectArgsTicks, collectTicks, mkApps , mkTicks, stripTicks)+  ( Bind, CoreContext(..), Pat(..), PrimInfo(..), Term(..), WorkInfo(..)+  , bindToList, collectArgs, collectArgsTicks, collectTicks, mkApps , mkTicks+  , stripTicks) import Clash.Core.TermInfo (isLocalVar, termSizeSmallerThan) import Clash.Core.Type   (TypeView(..), isClassTy, isPolyFunCoreTy, tyView)@@ -80,6 +90,9 @@ import Clash.Primitives.Types   (CompiledPrimMap, Primitive(..), TemplateKind(..)) import Clash.Rewrite.Combinators (allR)+import Clash.Rewrite.StrategyDSL+  ( Transformation, onAppNode, onLet, onTickNode, onTyAppNode, onVarNode+  , toTransformation) import Clash.Rewrite.Types   ( TransformContext(..), bindings, curFun, tcCache, topEntities   , inlineConstantLimit, inlineFunctionLimit, inlineLimit@@ -88,10 +101,10 @@   ( changed, inlineBinders, inlineOrLiftBinders, isJoinPointIn   , isUntranslatable, isUntranslatableType, isVoidWrapper, zoomExtra) import Clash.Rewrite.WorkFree (isWorkFreeIsh)-import Clash.Normalize.Types ( NormRewrite, NormalizeSession)+import Clash.Normalize.Types (NormRewrite, NormalizeSession) import Clash.Normalize.Util   ( addNewInline, alreadyInlined, isRecursiveBndr, mkInlineTick-  , normalizeTopLvlBndr)+  , normalizeTopLvlBndr, normalizeWorkFreeApp) import Clash.Unique (Unique) import Clash.Util (curLoc) import qualified Clash.Util.Interpolate as I@@ -113,8 +126,15 @@  -- | Inline let-bindings when the RHS is either a local variable reference or -- is constant (except clock or reset generators)-bindConstantVar :: HasCallStack => NormRewrite-bindConstantVar = inlineBinders test+bindConstantVar :: Transformation+bindConstantVar =+  toTransformation "bindConstantVar" (onLet 'bindConstantVarWorker)++-- | The 'Let' handler of 'bindConstantVar'.+bindConstantVarWorker+  :: HasCallStack+  => TransformContext -> Term -> Bind Term -> Term -> NormalizeSession Term+bindConstantVarWorker = inlineBinders test   where     test _ (i,stripTicks -> e) = case isLocalVar e of       -- Don't inline `let x = x in x`, it throws  us in an infinite loop@@ -134,7 +154,7 @@               0 -> return True               n -> return (termSizeSmallerThan (n + 1) e)             _ -> return False-{-# SCC bindConstantVar #-}+{-# SCC bindConstantVarWorker #-}  -- | Mark to track progress of 'reduceBindersCleanup' data Mark = Temp | Done | Rec@@ -279,12 +299,18 @@  -- | Only inline casts that just contain a 'Var', because these are guaranteed work-free. -- These are the result of the 'splitCastWork' transformation.-inlineCast :: HasCallStack => NormRewrite-inlineCast = inlineBinders test+inlineCast :: Transformation+inlineCast = toTransformation "inlineCast" (onLet 'inlineCastWorker)++-- | The 'Let' handler of 'inlineCast'.+inlineCastWorker+  :: HasCallStack+  => TransformContext -> Term -> Bind Term -> Term -> NormalizeSession Term+inlineCastWorker = inlineBinders test   where     test _ (_, (Cast (stripTicks -> Var {}) _ _)) = return True     test _ _ = return False-{-# SCC inlineCast #-}+{-# SCC inlineCastWorker #-}  -- | Given a function in the desired normal form, inline all the following -- let-bindings:@@ -295,8 +321,14 @@ --   * a projection case-expression (1 alternative) --   * a data constructor --   * I/O actions-inlineCleanup :: HasCallStack => NormRewrite-inlineCleanup (TransformContext is0 _) (Letrec binds body) = do+inlineCleanup :: Transformation+inlineCleanup = toTransformation "inlineCleanup" (onLet 'inlineCleanupWorker)++-- | The 'Let' handler of 'inlineCleanup'.+inlineCleanupWorker+  :: HasCallStack+  => TransformContext -> Term -> Bind Term -> Term -> NormalizeSession Term+inlineCleanupWorker (TransformContext is0 _) _node (bindToList -> binds) body = do   prims <- Lens.view primitives   -- For all let-bindings, count the number of times they are referenced.   -- We only inline let-bindings which are referenced only once, otherwise@@ -375,8 +407,12 @@                in -- Inlines WW projection that exposes internals of the BitVector types                   nm == Text.showt 'BV.BV  ||                   nm == Text.showt 'BV.Bit ||-                  -- Inlines projections out of constraint-tuples (e.g. HiddenClockReset)-                  "GHC.Classes" `Text.isPrefixOf` nm+                  -- Inlines projections out of constraint-tuples (e.g. HiddenClockReset).+                  -- The 'GHC.Classes' module hosts these on GHC <= 9.12; on+                  -- GHC >= 9.14 'base'\''s GHC.Classes re-exports them from+                  -- 'ghc-internal:GHC.Internal.Classes'.+                  "GHC.Classes" `Text.isPrefixOf` nm ||+                  "GHC.Internal.Classes" `Text.isPrefixOf` nm           Case _ aTy (_:_:_)             | TyConApp nm _ <- tyView aTy             , nameOcc nm == Text.showt ''SimIO.SimIO@@ -384,9 +420,7 @@           _ -> False      isInteresting _ _ _ _ = False--inlineCleanup _ e = return e-{-# SCC inlineCleanup #-}+{-# SCC inlineCleanupWorker #-}  {- [Note] relation `collapseRHSNoops` and `inlineCleanup` The `collapseRHSNoops` transformation replaces functions/primitives that are the identity@@ -398,8 +432,15 @@ -- | Takes a binding and collapses its term if it is a noop. Only runs at -- synthesis boundaries (NOINLINE/OPAQUE functions) to avoid running too early -- on functions that might be inlined later. See #3036.-collapseRHSNoops :: HasCallStack => NormRewrite-collapseRHSNoops _ letrec@(Let letBind body) = do+collapseRHSNoops :: Transformation+collapseRHSNoops =+  toTransformation "collapseRHSNoops" (onLet 'collapseRHSNoopsWorker)++-- | The 'Let' handler of 'collapseRHSNoops'.+collapseRHSNoopsWorker+  :: HasCallStack+  => TransformContext -> Term -> Bind Term -> Term -> NormalizeSession Term+collapseRHSNoopsWorker _ letrec letBind body = do   (curFunId, _) <- Lens.use curFun   curBinding <- lookupVarEnv curFunId <$> Lens.use bindings   case curBinding of@@ -471,9 +512,7 @@       arg@(App {}) <- getTermArg (lefts args) 1       isNoopApp x (collectArgs arg)     isNoopApp _ _ = return False--collapseRHSNoops _ e = return e-{-# SCC collapseRHSNoops #-}+{-# SCC collapseRHSNoopsWorker #-}  -- | Inline function with a non-representable result if it's the subject -- of a Case-decomposition. It's a custom topdown traversal that -for efficiency@@ -566,9 +605,16 @@ inlineNonRepWorker e = pure e {-# SCC inlineNonRepWorker #-} -inlineOrLiftNonRep :: HasCallStack => NormRewrite-inlineOrLiftNonRep ctx eLet@(Letrec _ body) =-    inlineOrLiftBinders nonRepTest inlineTest ctx eLet+inlineOrLiftNonRep :: Transformation+inlineOrLiftNonRep =+  toTransformation "bindOrLiftNonRep" (onLet 'inlineOrLiftNonRepWorker)++-- | The 'Let' handler of 'inlineOrLiftNonRep'.+inlineOrLiftNonRepWorker+  :: HasCallStack+  => TransformContext -> Term -> Bind Term -> Term -> NormalizeSession Term+inlineOrLiftNonRepWorker ctx eLet bind body =+    inlineOrLiftBinders nonRepTest inlineTest ctx eLet bind body   where     bodyFreeOccs = countFreeOccurances body @@ -590,18 +636,22 @@           -- XXX: Check whether we can extend this to the binders as well         , maybe False (>1) (lookupVarEnv id_ bodyFreeOccs)         ]--inlineOrLiftNonRep _ e = return e-{-# SCC inlineOrLiftNonRep #-}+{-# SCC inlineOrLiftNonRepWorker #-}  -- | Inline anything of type `SimIO`: IO actions cannot be shared-inlineSimIO :: HasCallStack => NormRewrite-inlineSimIO = inlineBinders test+inlineSimIO :: Transformation+inlineSimIO = toTransformation "bindSimIO" (onLet 'inlineSimIOWorker)++-- | The 'Let' handler of 'inlineSimIO'.+inlineSimIOWorker+  :: HasCallStack+  => TransformContext -> Term -> Bind Term -> Term -> NormalizeSession Term+inlineSimIOWorker = inlineBinders test   where     test _ (i,_) = case tyView (coreTypeOf i) of       TyConApp tc _ -> return $! nameOcc tc == Text.showt ''SimIO.SimIO       _ -> return False-{-# SCC inlineSimIO #-}+{-# SCC inlineSimIOWorker #-}  -- | True when @e@, appearing at context @cc@, is an inner (partial) position -- of a Var-headed application spine. That is, for a fully applied function call:@@ -638,12 +688,19 @@   isSpineNode _ = False  -- | Inline small functions-inlineSmall :: HasCallStack => NormRewrite-inlineSmall (TransformContext _ (cc:_)) e+inlineSmall :: Transformation+inlineSmall =+  toTransformation "inlineSmall"+    (onVarNode 'inlineSmallWorker <> onAppNode 'inlineSmallWorker+      <> onTyAppNode 'inlineSmallWorker <> onTickNode 'inlineSmallWorker)++-- | The application-spine handler of 'inlineSmall'.+inlineSmallWorker :: HasCallStack => NormRewrite+inlineSmallWorker (TransformContext _ (cc:_)) e   | isPartOfVarAppSpine cc e   = return e -inlineSmall _ e@(collectArgsTicks -> (Var f,args,ticks))+inlineSmallWorker _ e@(collectArgsTicks -> (Var f,args,ticks))   | isLocalId f = return e   | otherwise = do       -- XXX: This is deeply nested to short-circuit expensive checks@@ -672,17 +729,25 @@              _ -> return e -inlineSmall _ e = return e-{-# SCC inlineSmall #-}+inlineSmallWorker _ e = return e+{-# SCC inlineSmallWorker #-}  -- | Inline work-free functions, i.e. fully applied functions that evaluate to--- a constant-inlineWorkFree :: HasCallStack => NormRewrite-inlineWorkFree (TransformContext _ (cc:_)) e+-- a constant. Applications to closed arguments are normalized before they're+-- inlined, see 'normalizeWorkFreeApp'.+inlineWorkFree :: Transformation+inlineWorkFree =+  toTransformation "inlineWorkFree"+    (onVarNode 'inlineWorkFreeWorker <> onAppNode 'inlineWorkFreeWorker+      <> onTyAppNode 'inlineWorkFreeWorker <> onTickNode 'inlineWorkFreeWorker)++-- | The application-spine handler of 'inlineWorkFree'.+inlineWorkFreeWorker :: HasCallStack => NormRewrite+inlineWorkFreeWorker (TransformContext _ (cc:_)) e   | isPartOfVarAppSpine cc e   = return e -inlineWorkFree _ e@(collectArgsTicks -> (Var f,args@(_:_),ticks))+inlineWorkFreeWorker _ e@(collectArgsTicks -> (Var f,args@(_:_),ticks))   | isLocalId f = return e   | otherwise   = do@@ -708,9 +773,15 @@                   else do                     -- Don't inline recursive expressions                     isRecBndr <- isRecursiveBndr f-                    if isRecBndr-                       then return e-                       else do+                    if | isRecBndr -> return e+                       -- Type arguments can still mention type variables bound+                       -- in the context, which rules out caching. Note that+                       -- closedness for the term is already checked in+                      -- 'expressionHasWork'.+                       | all isClosed (rights args) -> do+                         tm <- normalizeWorkFreeApp f b args+                         changed (mkTicks tm (mkInlineTick f : ticks))+                       | otherwise -> do                          let tm = mkTicks (bindingTerm b) (mkInlineTick f : ticks)                          changed $ mkApps tm args @@ -728,7 +799,7 @@           let e'Ty = inferCoreTypeOf tcm e'           return (isSignalType tcm e'Ty) -inlineWorkFree _ e@(collectTicks -> (Var f, ticks))+inlineWorkFreeWorker _ e@(collectTicks -> (Var f, ticks))   | isLocalId f = return e   | otherwise = do       topEnts <- Lens.view topEntities@@ -761,5 +832,5 @@                         changed (mkTicks (bindingTerm b) ticks)                 _ -> return e -inlineWorkFree _ e = return e-{-# SCC inlineWorkFree #-}+inlineWorkFreeWorker _ e = return e+{-# SCC inlineWorkFreeWorker #-}
src/Clash/Normalize/Transformations/Letrec.hs view
@@ -16,11 +16,17 @@  module Clash.Normalize.Transformations.Letrec   ( deadCode+  , deadCodeWorker   , flattenLet+  , flattenLetWorker   , recToLetRec   , removeUnusedExpr+  , removeUnusedExprCase+  , removeUnusedExprSpine   , simpleCSE+  , simpleCSEWorker   , topLet+  , topLetWorker   ) where  import qualified Control.Lens as Lens@@ -50,9 +56,10 @@ import Clash.Core.Name (mkUnsafeSystemName, nameOcc) import Clash.Core.Subst import Clash.Core.Term-  ( CoreContext(..), LetBinding, Pat(..), PrimInfo(..), Term(..), collectArgs, collectArgsTicks-  , collectTicks, isLambdaBodyCtx, isTickCtx, mkApps, mkLams, mkTicks, Bind(..)-  , partitionTicks, stripAllTicks)+  ( Alt, CoreContext(..), LetBinding, Pat(..), PrimInfo(..), Term(..)+  , bindToList, collectArgs, collectArgsTicks, collectTicks, isLambdaBodyCtx+  , isTickCtx, mkApps, mkLams, mkTicks, Bind(..), partitionTicks+  , stripAllTicks) import Clash.Core.TermInfo (isCon, isLet, isLocalVar, isTick) import Clash.Core.TyCon (TyConMap, tyConDataCons) import Clash.Core.Type@@ -71,6 +78,10 @@ import Clash.Normalize.Transformations.Reduce (reduceBinders) import Clash.Normalize.Types (NormRewrite, NormalizeSession) import Clash.Primitives.Types (Primitive(..), UsedArguments(..))+import Clash.Rewrite.StrategyDSL+  ( Transformation, anyConstructor, onAppNode, onCase, onLet, onLetNode+  , onPrimNode, onTickNode, onTyAppNode, toTransformation+  ) import Clash.Rewrite.Types   (TransformContext(..), bindings, curFun, tcCache, workFreeBinders, primitives) import Clash.Rewrite.Util@@ -84,17 +95,42 @@ -}  -- | Remove unused let-bindings-deadCode :: HasCallStack => NormRewrite-deadCode _ e@(Let binds body) =+deadCode :: Transformation+deadCode = toTransformation "deadCode" (onLet 'deadCodeWorker)++-- | The 'Let' handler of 'deadCode'.+deadCodeWorker+  :: HasCallStack+  => TransformContext -> Term -> Bind Term -> Term -> NormalizeSession Term+deadCodeWorker _ e binds body =   case removeUnusedBinders binds body of     Just t -> changed t     Nothing -> return e-deadCode _ e = return e-{-# SCC deadCode #-}+{-# SCC deadCodeWorker #-} -removeUnusedExpr :: HasCallStack => NormRewrite--- The primitive and data-constructor equations below collect the whole--- application spine with 'collectArgsTicks'. Say we have an application:+removeUnusedExpr :: Transformation+removeUnusedExpr = toTransformation "removeUnusedExpr"+  (  onPrimNode 'removeUnusedExprSpine+  <> onAppNode 'removeUnusedExprSpine+  <> onTyAppNode 'removeUnusedExprSpine+  <> onTickNode 'removeUnusedExprSpine+  <> onCase 'removeUnusedExprCase)++-- | The 'Case' handler of 'removeUnusedExpr': a single-alternative case whose+-- pattern binds no used variables is replaced by the alternative.+removeUnusedExprCase+  :: TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term+removeUnusedExprCase _ e _subj _ty [(DataPat _ [] xs,altExpr)] =+  if mkVarSet xs `disjointFreeVars` altExpr+     then changed altExpr+     else return e+removeUnusedExprCase _ e _subj _ty _alts = return e++-- | The application-spine handlers of 'removeUnusedExpr': replace unused+-- arguments of primitives (and 'Vec's 'Vec.Cons') with 'removedArg'.+removeUnusedExprSpine :: HasCallStack => NormRewrite+-- The equations below collect the whole application spine with+-- 'collectArgsTicks'. Say we have an application: -- --     f a b c --@@ -104,16 +140,15 @@ -- @[a, b]@) at the same argument indices. So any argument an inner node could -- remove, the root removes too, which makes the inner attempts wasted work. -- This holds through ticks and type applications as well, since--- 'collectArgsTicks' looks through both.------ We therefore skip a node that is itself a spine node (@App@, @TyApp@, @Prim@,--- or @Tick@) sitting under a parent that continues the spine (@AppFun@,--- @TyAppC@, or @TickC@). The single-alternative-Case equation is unaffected:--- the spine only threads through applications, type applications, and ticks, so--- a Case is never an inner node of a spine.-removeUnusedExpr (TransformContext _ (cc:_)) e+-- 'collectArgsTicks' looks through both. We therefore skip any node whose parent+-- continues the spine (an @AppFun@, @TyAppC@, or @TickC@ context);+-- 'removeUnusedExpr' only routes spine nodes (@App@, @TyApp@, @Prim@, @Tick@)+-- here, so no explicit node-constructor check is needed. The+-- single-alternative-Case handling lives in 'removeUnusedExprCase' and is+-- unaffected: the spine only threads through applications, type applications,+-- and ticks, so a Case is never an inner node of a spine.+removeUnusedExprSpine (TransformContext _ (cc:_)) e   | isSpineCtx cc-  , isSpineNode e   = return e  where   isSpineCtx AppFun = True@@ -121,13 +156,7 @@   isSpineCtx (TickC _) = True   isSpineCtx _ = False -  isSpineNode App {} = True-  isSpineNode TyApp {} = True-  isSpineNode Prim {} = True-  isSpineNode Tick {} = True-  isSpineNode _ = False--removeUnusedExpr _ e@(collectArgsTicks -> (p@(Prim pInfo),args,ticks)) = do+removeUnusedExprSpine _ e@(collectArgsTicks -> (p@(Prim pInfo),args,ticks)) = do   bbM <- HashMap.lookup (primName pInfo) <$> Lens.view primitives   let     usedArgs0 =@@ -179,14 +208,9 @@              then changed (Left p' : args'')              else return  (Left tm : args'') -removeUnusedExpr _ e@(Case _ _ [(DataPat _ [] xs,altExpr)]) =-  if mkVarSet xs `disjointFreeVars` altExpr-     then changed altExpr-     else return e- -- Replace any expression that creates a Vector of size 0 within the application -- of the Cons constructor, by the Nil constructor.-removeUnusedExpr _ e@(collectArgsTicks -> (Data dc, [_,Right aTy,Right nTy,_,Left a,Left nil],ticks))+removeUnusedExprSpine _ e@(collectArgsTicks -> (Data dc, [_,Right aTy,Right nTy,_,Left a,Left nil],ticks))   | nameOcc (dcName dc) == Text.showt 'Vec.Cons   = do     tcm <- Lens.view tcCache@@ -203,8 +227,8 @@            in  changed v       _ -> return e -removeUnusedExpr _ e = return e-{-# SCC removeUnusedExpr #-}+removeUnusedExprSpine _ e = return e+{-# SCC removeUnusedExprSpine #-}  -- | Flatten's letrecs after `inlineCleanup` --@@ -213,17 +237,22 @@ -- flattens those nested let-bindings again. -- -- NB: must only be called in the cleaning up phase.-flattenLet :: HasCallStack => NormRewrite-flattenLet ctx@(TransformContext is0 _) (Letrec binds0 body0@Letrec{}) = do+flattenLet :: Transformation+flattenLet = toTransformation "flattenLet" (onLetNode 'flattenLetWorker)++-- | The 'Let' handler of 'flattenLet'; recurses on the rebuilt let-expression+-- after merging nested bindings.+flattenLetWorker :: HasCallStack => NormRewrite+flattenLetWorker ctx@(TransformContext is0 _) (Letrec binds0 body0@Letrec{}) = do   -- deshadow binds1, so binds0 and binds1 don't conflict when merged   let is1 = extendInScopeSetList is0 (fmap fst binds0)   case deShadowTerm is1 body0 of     Letrec binds1 body1 -> do       setChanged-      flattenLet ctx{tfInScope=is1} (Letrec (binds0 <> binds1) body1)+      flattenLetWorker ctx{tfInScope=is1} (Letrec (binds0 <> binds1) body1)     _ -> error "internal error" -flattenLet (TransformContext is0 _) (Letrec binds body) = do+flattenLetWorker (TransformContext is0 _) (Letrec binds body) = do   let is1 = extendInScopeSetList is0 (map fst binds)       bodyOccs = Lens.foldMapByOf                    freeLocalIds (unionVarEnvWith (+))@@ -294,8 +323,8 @@                               ,mkTicks body2 srcTicks)])     go isN b = return (isN,[b]) -flattenLet _ e = return e-{-# SCC flattenLet #-}+flattenLetWorker _ e = return e+{-# SCC flattenLetWorker #-}  -- | Turn a  normalized recursive function, where the recursive calls only pass -- along the unchanged original arguments, into let-recursive function. This@@ -425,8 +454,9 @@  isClassConstraint :: Type -> Bool isClassConstraint (tyView -> TyConApp nm0 _) =-  if -- Constraint tuple:-     | "GHC.Classes.(%" `Text.isInfixOf` nm1 -> True+  if -- Constraint tuple. The host module is 'GHC.Classes' on GHC <= 9.12 and+     -- 'GHC.Internal.Classes' on GHC >= 9.14; both end in '.Classes.(%'.+     | ".Classes.(%" `Text.isInfixOf` nm1 -> True      -- Constraint class:      | "C:" `Text.isInfixOf` nm2 -> True      | otherwise -> False@@ -446,8 +476,14 @@ -- be really helpful if we tracked circuit size in the regression/test suite. -- On the two examples that were tested, Reducer and PipelinesViaFolds, this new -- version of CSE removed the same amount of let-binders.-simpleCSE :: HasCallStack => NormRewrite-simpleCSE (TransformContext is0 _) term@(Letrec bndrsX body) = do+simpleCSE :: Transformation+simpleCSE = toTransformation "CSE" (onLet 'simpleCSEWorker)++-- | The 'Let' handler of 'simpleCSE'.+simpleCSEWorker+  :: HasCallStack+  => TransformContext -> Term -> Bind Term -> Term -> NormalizeSession Term+simpleCSEWorker (TransformContext is0 _) term (bindToList -> bndrsX) body = do   let bndrs = inverseTopSortLetBindings bndrsX   let is1 = extendInScopeSetList is0 (map fst bndrs)   ((subst,bndrs1), change) <- listen $ reduceBinders (mkSubst is1) [] bndrs@@ -467,14 +503,16 @@         in changed (Letrec bndrs2 body1)      else        return term--simpleCSE _ e = return e-{-# SCC simpleCSE #-}+{-# SCC simpleCSEWorker #-}  -- | Ensure that top-level lambda's eventually bind a let-expression of which -- the body is a variable-reference.-topLet :: HasCallStack => NormRewrite-topLet (TransformContext is0 ctx) e+topLet :: Transformation+topLet = anyConstructor "topLet" 'topLetWorker++-- | The worker of 'topLet': a plain rewrite, offered at every node.+topLetWorker :: HasCallStack => NormRewrite+topLetWorker (TransformContext is0 ctx) e   | all (\c -> isLambdaBodyCtx c || isTickCtx c) ctx && not (isLet e) && not (isTick e)   = do   untranslatable <- isUntranslatable False e@@ -484,7 +522,7 @@             argId <- mkTmBinderFor is0 tcm (mkUnsafeSystemName "result" 0) e             changed (Let (NonRec argId e) (Var argId)) -topLet (TransformContext is0 ctx) e@(Letrec binds body)+topLetWorker (TransformContext is0 ctx) e@(Letrec binds body)   | all (\c -> isLambdaBodyCtx c || isTickCtx c) ctx   = do     let localVar = isLocalVar body@@ -503,5 +541,5 @@         -- but this makes tests/shouldwork/SimIO/Test00.hs fail.         changed (Letrec (binds ++ [(argId, body)]) (Var argId)) -topLet _ e = return e-{-# SCC topLet #-}+topLetWorker _ e = return e+{-# SCC topLetWorker #-}
src/Clash/Normalize/Transformations/MultiPrim.hs view
@@ -2,7 +2,7 @@   Copyright  :  (C) 2012-2016, University of Twente,                     2016-2017, Myrtle Software Ltd,                     2017-2018, Google Inc.-                    2022     , QBayLogic B.V.+                    2022,2026, QBayLogic B.V.   License    :  BSD2 (see the file LICENSE)   Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> @@ -11,9 +11,11 @@  {-# LANGUAGE NamedFieldPuns #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskellQuotes #-}  module Clash.Normalize.Transformations.MultiPrim   ( setupMultiResultPrim+  , setupMultiResultPrimWorker   ) where  import qualified Control.Lens as Lens@@ -31,9 +33,10 @@ import Clash.Core.Type (Type(..), mkPolyFunTy, splitFunForallTy) import Clash.Core.Util (listToLets) import Clash.Core.Var (mkLocalId)-import Clash.Normalize.Types (NormRewrite)+import Clash.Normalize.Types (NormalizeSession) import Clash.Primitives.Types (Primitive(..))-import Clash.Rewrite.Types (tcCache, primitives)+import Clash.Rewrite.StrategyDSL (Transformation, onPrim, toTransformation)+import Clash.Rewrite.Types (TransformContext, tcCache, primitives) import Clash.Rewrite.Util (changed)  -- Note [MultiResult type]@@ -74,8 +77,15 @@ -- types, not any product type. It will error if it sees a multi result primitive -- with a non-tuple return type. ---setupMultiResultPrim :: HasCallStack => NormRewrite-setupMultiResultPrim _ctx e@(Prim pInfo@PrimInfo{primMultiResult=SingleResult}) = do+setupMultiResultPrim :: Transformation+setupMultiResultPrim =+  toTransformation "setupMultiResultPrim" (onPrim 'setupMultiResultPrimWorker)++-- | The 'Prim' handler of 'setupMultiResultPrim'.+setupMultiResultPrimWorker+  :: HasCallStack+  => TransformContext -> Term -> PrimInfo -> NormalizeSession Term+setupMultiResultPrimWorker _ctx node pInfo@PrimInfo{primMultiResult=SingleResult} = do   tcm <- Lens.view tcCache   prim <- Lens.view (primitives . Lens.at (primName pInfo)) @@ -85,9 +95,8 @@     Just (BlackBox{multiResult=True}) ->       changed (setupMultiResultPrim' tcm pInfo)     _ ->-      return e--setupMultiResultPrim _ e = return e+      return node+setupMultiResultPrimWorker _ctx node _primInfo = return node  setupMultiResultPrim' :: HasCallStack => TyConMap -> PrimInfo -> Term setupMultiResultPrim' tcm primInfo@PrimInfo{primType} =
src/Clash/Normalize/Transformations/Reduce.hs view
@@ -18,7 +18,9 @@ module Clash.Normalize.Transformations.Reduce   ( reduceBinders   , reduceConst-  , reduceNonRepPrim+  , reduceConstWorker+  , reducePrim+  , reducePrimWorker   ) where  import qualified Control.Lens as Lens@@ -47,8 +49,9 @@ import qualified Clash.Data.UniqMap as UniqMap import Clash.Normalize.PrimitiveReductions import Clash.Normalize.Primitives (removedArg)-import Clash.Normalize.Types (NormRewrite, NormalizeSession)+import Clash.Normalize.Types (NormalizeSession) import Clash.Normalize.Util (shouldReduce)+import Clash.Rewrite.StrategyDSL (Transformation, onApp, toTransformation) import Clash.Rewrite.Types (TransformContext(..), tcCache, normalizeUltra) import Clash.Rewrite.Util (changed, isUntranslatableType, setChanged, whnfRW) import qualified Clash.Sized.Internal.BitVector@@ -85,27 +88,39 @@   = reduceBinders subst ((i,e):processed) rest {-# SCC reduceBinders #-} -reduceConst :: HasCallStack => NormRewrite+reduceConst :: Transformation+reduceConst = toTransformation "reduceConst" (onApp 'reduceConstWorker)++-- | The 'App' handler of 'reduceConst'.+reduceConstWorker+  :: HasCallStack+  => TransformContext -> Term -> Term -> Term -> NormalizeSession Term -- An 'App' in an 'AppFun' context is an inner node of an application spine, -- e.g. the @f a@ inside @f a b c@. Only evaluate at the root (@f a b c@): -- an under-applied primitive cannot fold, and if @f@ is itself an application -- (@(g x) a b c@) the evaluator reduces the whole thing to WHNF anyway, so it -- folds @g x@ as part of folding the root. Skip the evaluator call here.-reduceConst (TransformContext _ (AppFun:_)) e = return e-reduceConst ctx e@(App _ _)+reduceConstWorker (TransformContext _ (AppFun:_)) e _appFunction _appArgument = return e+reduceConstWorker ctx e _appFunction _appArgument   | (Prim p0, _) <- collectArgs e   = whnfRW False ctx e $ \_ctx1 e1 -> case e1 of       (collectArgs -> (Prim p1, _)) | primName p0 == primName p1 -> return e       _ -> changed e1 -reduceConst _ e = return e-{-# SCC reduceConst #-}+reduceConstWorker _ e _ _ = return e+{-# SCC reduceConstWorker #-}  -- | Replace primitives by their "definition" if they would lead to let-bindings -- with a non-representable type when a function is in ANF. This happens for -- example when Clash.Size.Vector.map consumes or produces a vector of -- non-representable elements. --+-- This transformation used to be called @reduceNonRepPrim@, but nowadays it+-- also replaces primitives for other reasons: e.g., because they are applied+-- to short vectors, because they occur in a context that should be reduced+-- (see 'shouldReduce'), or because @-fclash-ultra@ is enabled. The conditions+-- differ per primitive, see the handlers in 'reducePrimImpls'.+-- -- Basically what this transformation does is replace a primitive the completely -- unrolled recursive definition that it represents. e.g. --@@ -121,7 +136,7 @@ -- >     (y1  :: Int                 = case yr0 of (:>) _ y yr -> y -- > in  (($) x0 y0 :> ($) x1 y1 :> Nil) ----- Currently, it only handles the functions in 'reduceNonRepPrimImpls'.+-- Currently, it only handles the functions in 'reducePrimImpls'. -- -- Note [Unroll shouldSplit types] -- 1. Certain higher-order functions over Vec, such as map, have specialized@@ -142,16 +157,23 @@ -- It's easier to just unroll the recursive definitions. -- -- See https://github.com/clash-lang/clash-compiler/issues/1606-reduceNonRepPrim :: HasCallStack => NormRewrite+reducePrim :: Transformation+reducePrim =+  toTransformation "reducePrim" (onApp 'reducePrimWorker)++-- | The 'Clash.Core.Term.App' handler of 'reducePrim'.+reducePrimWorker+  :: HasCallStack+  => TransformContext -> Term -> Term -> Term -> NormalizeSession Term -- Only consider the root of an application spine (see 'reduceConst'): the root -- sees all arguments, and the @Vec 0@-to-@Nil@ rewrite below is only -- type-correct at the root, where no more arguments follow.-reduceNonRepPrim (TransformContext _ (AppFun:_)) e = return e-reduceNonRepPrim c e@(App _ _)+reducePrimWorker (TransformContext _ (AppFun:_)) e _appFunction _appArgument = return e+reducePrimWorker c e _appFunction _appArgument   | (Prim p, args, ticks) <- collectArgsTicks e   = do     tcm <- Lens.view tcCache-    let handlerM = HashMap.lookup (primName p) reduceNonRepPrimImpls+    let handlerM = HashMap.lookup (primName p) reducePrimImpls     -- Every primitive whose result type is @Vec 0 a@ reduces to @Nil@, not     -- just the ones with a handler. That takes the type of the applied     -- primitive, which is expensive to infer, so for a primitive without a@@ -178,7 +200,7 @@           Nothing -> return e           Just handler -> do             ultraArg <- Lens.view normalizeUltra-            handler ReduceNonRepPrimContext+            handler ReducePrimContext               { transformContext = c               , originalTerm = e               , primInfo = p@@ -191,8 +213,8 @@               , resultTypeView = tv               } -reduceNonRepPrim _ e = return e-{-# SCC reduceNonRepPrim #-}+reducePrimWorker _ e _ _ = return e+{-# SCC reducePrimWorker #-}  -- | The name of the 'Clash.Sized.Vector.Vec' type constructor. vecTcName :: Text@@ -204,7 +226,7 @@   | TyConApp vecTcNm [nTy, aTy] <- tv   , nameOcc vecTcNm == vecTcName   , Right 0 <- runExcept (tyNatSize tcm nTy)-  = Just $ fromMaybe (error "reduceNonRepPrim: unable to create Vec DCs") $ do+  = Just $ fromMaybe (error "reducePrim: unable to create Vec DCs") $ do       vecTc <- UniqMap.lookup vecTcNm tcm       [nilCon,consCon] <- pure (tyConDataCons vecTc)       return (mkVec nilCon consCon aTy 0 [])@@ -219,7 +241,7 @@ -- A result headed by a concrete type constructor other than @Vec@ can never -- instantiate to a @Vec@. Everything else -- type variables, type families, -- type constructors we know nothing about -- might, and yields 'True'.--- Over-approximating is sound: a 'True' only makes 'reduceNonRepPrim' infer+-- Over-approximating is sound: a 'True' only makes 'reducePrim' infer -- the type of the applied primitive and ask 'zeroLengthVecTerm' for a verdict. mayReturnVec :: TyConMap -> Type -> Bool mayReturnVec tcm ty = case tyView (snd (splitFunForallTy ty)) of@@ -232,9 +254,9 @@         Nothing -> True   _ -> True --- | Everything the handlers in 'reduceNonRepPrimImpls' receive from the--- dispatch site in 'reduceNonRepPrim'.-data ReduceNonRepPrimContext = ReduceNonRepPrimContext+-- | Everything the handlers in 'reducePrimImpls' receive from the+-- dispatch site in 'reducePrim'.+data ReducePrimContext = ReducePrimContext   { transformContext :: TransformContext   , originalTerm :: Term     -- ^ The primitive applied to its arguments@@ -252,16 +274,16 @@     -- ^ 'tyView' of 'resultType'   } --- | A handler for a specific primitive in 'reduceNonRepPrimImpls'.-type ReduceNonRepPrimHandler-  = ReduceNonRepPrimContext -> NormalizeSession Term+-- | A handler for a specific primitive in 'reducePrimImpls'.+type ReducePrimHandler+  = ReducePrimContext -> NormalizeSession Term --- | The primitives 'reduceNonRepPrim' can reduce, keyed on primitive+-- | The primitives 'reducePrim' can reduce, keyed on primitive -- name. The handlers are the arms of the @case@ expression this map replaced; -- a handler whose guards do not apply returns 'originalTerm' unchanged, like -- the fall-through of the @case@ did.-reduceNonRepPrimImpls :: HashMap Text ReduceNonRepPrimHandler-reduceNonRepPrimImpls = HashMap.fromList+reducePrimImpls :: HashMap Text ReducePrimHandler+reducePrimImpls = HashMap.fromList   [ ($(textNameLit 'Clash.Sized.Vector.zipWith), reduceZipWithHandler)   , ($(textNameLit 'Clash.Sized.Vector.map), reduceMapHandler)   , ($(textNameLit 'Clash.Sized.Vector.traverse#), reduceTraverseHandler)@@ -290,69 +312,73 @@   , ($(textNameLit 'Clash.Sized.Internal.BitVector.eq#), reduceEqHandler)   ] -reduceZipWithHandler :: ReduceNonRepPrimHandler-reduceZipWithHandler ReduceNonRepPrimContext{..}+reduceZipWithHandler :: ReducePrimHandler+reduceZipWithHandler ReducePrimContext{..}   | (tmArgs,[lhsElTy,rhsElty,resElTy,nTy]) <- Either.partitionEithers primArguments   , TyConApp vecTcNm _ <- resultTypeView   , let lhsTy = mkTyConApp vecTcNm [nTy,lhsElTy]   , let rhsTy = mkTyConApp vecTcNm [nTy,rhsElty]   = case runExcept (tyNatSize tyConMap nTy) of       Right n -> do+        lhsNonRep <- isUntranslatableType_not_poly lhsElTy+        rhsNonRep <- isUntranslatableType_not_poly rhsElty+        resNonRep <- isUntranslatableType_not_poly resElTy         shouldReduce1 <- List.orM [ pure (ultra || n < 2)                              , shouldReduce (tfContext transformContext)-                             , List.anyM isUntranslatableType_not_poly-                                    [lhsElTy,rhsElty,resElTy]+                             , pure (lhsNonRep || rhsNonRep || resNonRep)                              -- Note [Unroll shouldSplit types]                              , pure (any (Maybe.isJust . shouldSplit tyConMap)                                          [lhsTy,rhsTy,resultType]) ]         if shouldReduce1            then abstractOverMissingArgs primTicks tmArgs termType transformContext-                  (reduceZipWith primInfo n lhsElTy rhsElty resElTy)+                  (reduceZipWith primInfo n lhsElTy rhsElty resElTy+                     (not lhsNonRep) (not rhsNonRep))            else return originalTerm       _ -> return originalTerm   | length primArguments >= 4-  = error ("reduceNonRepPrim: zipWith bad args" <> showPpr originalTerm)+  = error ("reducePrim: zipWith bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceMapHandler :: ReduceNonRepPrimHandler-reduceMapHandler ReduceNonRepPrimContext{..}+reduceMapHandler :: ReducePrimHandler+reduceMapHandler ReducePrimContext{..}   | (tmArgs,[argElTy,resElTy,nTy]) <- Either.partitionEithers primArguments   , TyConApp vecTcNm _ <- resultTypeView   , let argTy = mkTyConApp vecTcNm [nTy,argElTy]   = case runExcept (tyNatSize tyConMap nTy) of       Right n -> do+        argNonRep <- isUntranslatableType_not_poly argElTy+        resNonRep <- isUntranslatableType_not_poly resElTy         shouldReduce1 <- List.orM [ pure (ultra || n < 2 )                              , shouldReduce (tfContext transformContext)-                             , List.anyM isUntranslatableType_not_poly-                                    [argElTy,resElTy]+                             , pure (argNonRep || resNonRep)                              -- Note [Unroll shouldSplit types]                              , pure (any (Maybe.isJust . shouldSplit tyConMap)                                          [argTy,resultType]) ]         if shouldReduce1            then abstractOverMissingArgs primTicks tmArgs termType transformContext-                  (reduceMap primInfo n argElTy resElTy)+                  (reduceMap primInfo n argElTy resElTy (not argNonRep))            else return originalTerm       _ -> return originalTerm   | length primArguments >= 3-  = error ("reduceNonRepPrim: map bad args" <> showPpr originalTerm)+  = error ("reducePrim: map bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceTraverseHandler :: ReduceNonRepPrimHandler-reduceTraverseHandler ReduceNonRepPrimContext{..}+reduceTraverseHandler :: ReducePrimHandler+reduceTraverseHandler ReducePrimContext{..}   | (tmArgs,[aTy,fTy,bTy,nTy]) <- Either.partitionEithers primArguments   = case runExcept (tyNatSize tyConMap nTy) of       Right n -> abstractOverMissingArgs primTicks tmArgs termType transformContext                    (reduceTraverse n aTy fTy bTy)       _ -> return originalTerm   | length primArguments >= 4-  = error ("reduceNonRepPrim: traverse# bad args" <> showPpr originalTerm)+  = error ("reducePrim: traverse# bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceFoldHandler :: ReduceNonRepPrimHandler-reduceFoldHandler ReduceNonRepPrimContext{..}+reduceFoldHandler :: ReducePrimHandler+reduceFoldHandler ReducePrimContext{..}   | (tmArgs,[nTy,aTy]) <- Either.partitionEithers primArguments   , (_:Right argTy:_) <- fst (splitFunForallTy (piResultTys tyConMap (primType primInfo) [nTy,aTy]))   = case runExcept (tyNatSize tyConMap nTy) of@@ -368,45 +394,47 @@         else return originalTerm       _ -> return originalTerm   | length primArguments >= 2-  = error ("reduceNonRepPrim: fold bad args" <> showPpr originalTerm)+  = error ("reducePrim: fold bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceFoldrHandler :: ReduceNonRepPrimHandler-reduceFoldrHandler ReduceNonRepPrimContext{..}+reduceFoldrHandler :: ReducePrimHandler+reduceFoldrHandler ReducePrimContext{..}   | (tmArgs,[aTy,bTy,nTy]) <- Either.partitionEithers primArguments   , (_:_:Right argTy:_) <- fst (splitFunForallTy (piResultTys tyConMap (primType primInfo) [aTy,bTy,nTy]))   = case runExcept (tyNatSize tyConMap nTy) of       Right n -> do+        aNonRep <- isUntranslatableType_not_poly aTy+        bNonRep <- isUntranslatableType_not_poly bTy         shouldReduce1 <- List.orM [ pure ultra                              , shouldReduce (tfContext transformContext)-                             , List.anyM isUntranslatableType_not_poly [aTy,bTy]+                             , pure (aNonRep || bNonRep)                              -- Note [Unroll shouldSplit types]                              , pure (Maybe.isJust (shouldSplit tyConMap argTy)) ]         if shouldReduce1           then abstractOverMissingArgs primTicks tmArgs termType transformContext-                 (reduceFoldr primInfo n aTy)+                 (reduceFoldr primInfo n aTy (not aNonRep))           else return originalTerm       _ -> return originalTerm   | length primArguments >= 3-  = error ("reduceNonRepPrim: foldr bad args" <> showPpr originalTerm)+  = error ("reducePrim: foldr bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceDFoldHandler :: ReduceNonRepPrimHandler-reduceDFoldHandler ReduceNonRepPrimContext{..}+reduceDFoldHandler :: ReducePrimHandler+reduceDFoldHandler ReducePrimContext{..}   | (tmArgs,[_mTy,nTy,aTy]) <- Either.partitionEithers primArguments   = case runExcept (tyNatSize tyConMap nTy) of       Right n -> abstractOverMissingArgs primTicks tmArgs termType transformContext                    (reduceDFold n aTy)       _ -> return originalTerm   | length primArguments >= 3-  = error ("reduceNonRepPrim: dfold bad args" <> showPpr originalTerm)+  = error ("reducePrim: dfold bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceAppendHandler :: ReduceNonRepPrimHandler-reduceAppendHandler ReduceNonRepPrimContext{..}+reduceAppendHandler :: ReducePrimHandler+reduceAppendHandler ReducePrimContext{..}   | (tmArgs,[nTy,aTy,mTy]) <- Either.partitionEithers primArguments   = case (runExcept (tyNatSize tyConMap nTy), runExcept (tyNatSize tyConMap mTy)) of       (Right n, Right m) -> do@@ -422,12 +450,12 @@                else return originalTerm       _ -> return originalTerm   | length primArguments >= 3-  = error ("reduceNonRepPrim: ++ bad args" <> showPpr originalTerm)+  = error ("reducePrim: ++ bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceHeadHandler :: ReduceNonRepPrimHandler-reduceHeadHandler ReduceNonRepPrimContext{..}+reduceHeadHandler :: ReducePrimHandler+reduceHeadHandler ReducePrimContext{..}   | (tmArgs,[nTy,aTy]) <- Either.partitionEithers primArguments   , (Right argTy:_) <- fst (splitFunForallTy (piResultTys tyConMap (primType primInfo) [nTy,aTy]))   = case runExcept (tyNatSize tyConMap nTy) of@@ -442,12 +470,12 @@            else return originalTerm       _ -> return originalTerm   | length primArguments >= 2-  = error ("reduceNonRepPrim: head bad args" <> showPpr originalTerm)+  = error ("reducePrim: head bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceTailHandler :: ReduceNonRepPrimHandler-reduceTailHandler ReduceNonRepPrimContext{..}+reduceTailHandler :: ReducePrimHandler+reduceTailHandler ReducePrimContext{..}   | (tmArgs,[nTy,aTy]) <- Either.partitionEithers primArguments   , (Right argTy:_) <- fst (splitFunForallTy (piResultTys tyConMap (primType primInfo) [nTy,aTy]))   = case runExcept (tyNatSize tyConMap nTy) of@@ -462,12 +490,12 @@            else return originalTerm       _ -> return originalTerm   | length primArguments >= 2-  = error ("reduceNonRepPrim: tail bad args" <> showPpr originalTerm)+  = error ("reducePrim: tail bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceLastHandler :: ReduceNonRepPrimHandler-reduceLastHandler ReduceNonRepPrimContext{..}+reduceLastHandler :: ReducePrimHandler+reduceLastHandler ReducePrimContext{..}   | (tmArgs,[nTy,aTy]) <- Either.partitionEithers primArguments   , (Right argTy:_) <- fst (splitFunForallTy (piResultTys tyConMap (primType primInfo) [nTy,aTy]))   = case runExcept (tyNatSize tyConMap nTy) of@@ -483,32 +511,33 @@            else return originalTerm       _ -> return originalTerm   | length primArguments >= 2-  = error ("reduceNonRepPrim: last bad args" <> showPpr originalTerm)+  = error ("reducePrim: last bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceInitHandler :: ReduceNonRepPrimHandler-reduceInitHandler ReduceNonRepPrimContext{..}+reduceInitHandler :: ReducePrimHandler+reduceInitHandler ReducePrimContext{..}   | (tmArgs,[nTy,aTy]) <- Either.partitionEithers primArguments   , (Right argTy:_) <- fst (splitFunForallTy (piResultTys tyConMap (primType primInfo) [nTy,aTy]))   = case runExcept (tyNatSize tyConMap nTy) of       Right n -> do+        aNonRep <- isUntranslatableType_not_poly aTy         shouldReduce1 <- List.orM [ shouldReduce (tfContext transformContext)-                             , isUntranslatableType_not_poly aTy+                             , pure aNonRep                              -- Note [Unroll shouldSplit types]                              , pure (Maybe.isJust (shouldSplit tyConMap argTy)) ]         if shouldReduce1            then abstractOverMissingArgs primTicks tmArgs termType transformContext-                  (reduceInit primInfo n aTy)+                  (reduceInit primInfo n aTy (not aNonRep))            else return originalTerm       _ -> return originalTerm   | length primArguments >= 2-  = error ("reduceNonRepPrim: init bad args" <> showPpr originalTerm)+  = error ("reducePrim: init bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceUnconcatHandler :: ReduceNonRepPrimHandler-reduceUnconcatHandler ReduceNonRepPrimContext{..}+reduceUnconcatHandler :: ReducePrimHandler+reduceUnconcatHandler ReducePrimContext{..}   | (tmArgs,[nTy,mTy,aTy]) <- Either.partitionEithers primArguments   , (_:_:Right argTy:_) <- fst (splitFunForallTy (piResultTys tyConMap (primType primInfo) [nTy,mTy,aTy]))   = case (runExcept (tyNatSize tyConMap nTy), runExcept (tyNatSize tyConMap mTy)) of@@ -526,24 +555,24 @@           return originalTerm       _ -> return originalTerm   | length primArguments >= 3-  = error ("reduceNonRepPrim: unconcat bad args" <> showPpr originalTerm)+  = error ("reducePrim: unconcat bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceTransposeHandler :: ReduceNonRepPrimHandler-reduceTransposeHandler ReduceNonRepPrimContext{..}+reduceTransposeHandler :: ReducePrimHandler+reduceTransposeHandler ReducePrimContext{..}   | (tmArgs,[mTy,nTy,aTy]) <- Either.partitionEithers primArguments   = case (runExcept (tyNatSize tyConMap nTy), runExcept (tyNatSize tyConMap mTy)) of       (Right n, Right 0) -> abstractOverMissingArgs primTicks tmArgs termType transformContext                               (reduceTranspose n 0 aTy)       _ -> return originalTerm   | length primArguments >= 3-  = error ("reduceNonRepPrim: transpose bad args" <> showPpr originalTerm)+  = error ("reducePrim: transpose bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceReplicateHandler :: ReduceNonRepPrimHandler-reduceReplicateHandler ReduceNonRepPrimContext{..}+reduceReplicateHandler :: ReducePrimHandler+reduceReplicateHandler ReducePrimContext{..}   | (tmArgs,[nTy,aTy]) <- Either.partitionEithers primArguments   = case runExcept (tyNatSize tyConMap nTy) of       Right n -> do@@ -558,13 +587,13 @@            else return originalTerm       _ -> return originalTerm   | length primArguments >= 2-  = error ("reduceNonRepPrim: replicate bad args" <> showPpr originalTerm)+  = error ("reducePrim: replicate bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm  -- replace_int :: KnownNat n => Vec n a -> Int -> a -> Vec n a-reduceReplaceIntHandler :: ReduceNonRepPrimHandler-reduceReplaceIntHandler ReduceNonRepPrimContext{..}+reduceReplaceIntHandler :: ReducePrimHandler+reduceReplaceIntHandler ReducePrimContext{..}   | (tmArgs,[nTy,aTy]) <- Either.partitionEithers primArguments   = case runExcept (tyNatSize tyConMap nTy) of       Right n -> do@@ -580,12 +609,12 @@            else return originalTerm       _ -> return originalTerm   | length primArguments >= 2-  = error ("reduceNonRepPrim: replace_int bad args" <> showPpr originalTerm)+  = error ("reducePrim: replace_int bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceIndexIntHandler :: ReduceNonRepPrimHandler-reduceIndexIntHandler ReduceNonRepPrimContext{..}+reduceIndexIntHandler :: ReducePrimHandler+reduceIndexIntHandler ReducePrimContext{..}   | (tmArgs,[nTy,aTy]) <- Either.partitionEithers primArguments   , (_:Right argTy:_) <- fst (splitFunForallTy (piResultTys tyConMap (primType primInfo) [nTy,aTy]))   = case runExcept (tyNatSize tyConMap nTy) of@@ -601,12 +630,12 @@            else return originalTerm       _ -> return originalTerm   | length primArguments >= 2-  = error ("reduceNonRepPrim: index_int bad args" <> showPpr originalTerm)+  = error ("reducePrim: index_int bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceImapHandler :: ReduceNonRepPrimHandler-reduceImapHandler ReduceNonRepPrimContext{..}+reduceImapHandler :: ReducePrimHandler+reduceImapHandler ReducePrimContext{..}   | (tmArgs,[nTy,argElTy,resElTy]) <- Either.partitionEithers primArguments   , TyConApp vecTcNm _ <- resultTypeView   , let argTy = mkTyConApp vecTcNm [nTy,argElTy]@@ -624,12 +653,12 @@            else return originalTerm       _ -> return originalTerm   | length primArguments >= 3-  = error ("reduceNonRepPrim: imap bad args" <> showPpr originalTerm)+  = error ("reducePrim: imap bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceIterateIHandler :: ReduceNonRepPrimHandler-reduceIterateIHandler ReduceNonRepPrimContext{..}+reduceIterateIHandler :: ReducePrimHandler+reduceIterateIHandler ReducePrimContext{..}   | (tmArgs,[nTy,aTy]) <- Either.partitionEithers primArguments   = case runExcept (tyNatSize tyConMap nTy) of       Right n -> do@@ -647,24 +676,24 @@           return originalTerm       _ -> return originalTerm   | length primArguments >= 2-  = error ("reduceNonRepPrim: iterateI bad args" <> showPpr originalTerm)+  = error ("reducePrim: iterateI bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceDTFoldHandler :: ReduceNonRepPrimHandler-reduceDTFoldHandler ReduceNonRepPrimContext{..}+reduceDTFoldHandler :: ReducePrimHandler+reduceDTFoldHandler ReducePrimContext{..}   | (tmArgs,[_mTy,nTy,aTy]) <- Either.partitionEithers primArguments   = case runExcept (tyNatSize tyConMap nTy) of       Right n -> abstractOverMissingArgs primTicks tmArgs termType transformContext                    (reduceDTFold n aTy)       _ -> return originalTerm   | length primArguments >= 3-  = error ("reduceNonRepPrim: dtfold bad args" <> showPpr originalTerm)+  = error ("reducePrim: dtfold bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceReverseHandler :: ReduceNonRepPrimHandler-reduceReverseHandler ReduceNonRepPrimContext{..}+reduceReverseHandler :: ReducePrimHandler+reduceReverseHandler ReducePrimContext{..}   | ultra   , (tmArgs,[nTy,aTy]) <- Either.partitionEithers primArguments   , Right n <- runExcept (tyNatSize tyConMap nTy)@@ -673,20 +702,20 @@   | otherwise   = return originalTerm -reduceTDFoldHandler :: ReduceNonRepPrimHandler-reduceTDFoldHandler ReduceNonRepPrimContext{..}+reduceTDFoldHandler :: ReducePrimHandler+reduceTDFoldHandler ReducePrimContext{..}   | (tmArgs,[_mTy,nTy,aTy]) <- Either.partitionEithers primArguments   = case runExcept (tyNatSize tyConMap nTy) of       Right n -> abstractOverMissingArgs primTicks tmArgs termType transformContext                    (reduceTFold n aTy)       _ -> return originalTerm   | length primArguments >= 3-  = error ("reduceNonRepPrim: tdfold bad args" <> showPpr originalTerm)+  = error ("reducePrim: tdfold bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceTReplicateHandler :: ReduceNonRepPrimHandler-reduceTReplicateHandler ReduceNonRepPrimContext{..}+reduceTReplicateHandler :: ReducePrimHandler+reduceTReplicateHandler ReducePrimContext{..}   | (tmArgs,[nTy,aTy]) <- Either.partitionEithers primArguments   = case runExcept (tyNatSize tyConMap nTy) of       Right n -> do@@ -698,12 +727,12 @@            else return originalTerm       _ -> return originalTerm   | length primArguments >= 2-  = error ("reduceNonRepPrim: treplicate bad args" <> showPpr originalTerm)+  = error ("reducePrim: treplicate bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceSplitHandler :: ReduceNonRepPrimHandler-reduceSplitHandler ReduceNonRepPrimContext{..}+reduceSplitHandler :: ReducePrimHandler+reduceSplitHandler ReducePrimContext{..}   | (tmArgs,[nTy,mTy]) <- Either.partitionEithers primArguments   = case (runExcept (tyNatSize tyConMap nTy), runExcept (tyNatSize tyConMap mTy), resultTypeView) of       (Right n, Right m, TyConApp tupTcNm [lTy,rTy])@@ -728,23 +757,23 @@                (changed (mkTicks tup primTicks) :: NormalizeSession Term)        where-        tupDc = fromMaybe (error "reduceNonRepPrim: faield to create tup DC") $ do+        tupDc = fromMaybe (error "reducePrim: faield to create tup DC") $ do                 tupTc <- UniqMap.lookup tupTcNm tyConMap                 listToMaybe (tyConDataCons tupTc)       _ -> return originalTerm   | length primArguments >= 3-  = error ("reduceNonRepPrim: split# bad args" <> showPpr originalTerm)+  = error ("reducePrim: split# bad args" <> showPpr originalTerm)   | otherwise   = return originalTerm -reduceEqHandler :: ReduceNonRepPrimHandler-reduceEqHandler ReduceNonRepPrimContext{..}+reduceEqHandler :: ReducePrimHandler+reduceEqHandler ReducePrimContext{..}   | (tmArgs,[nTy]) <- Either.partitionEithers primArguments   , Right 0 <- runExcept (tyNatSize tyConMap nTy)   , TyConApp boolTcNm [] <- resultTypeView   = abstractOverMissingArgs primTicks tmArgs termType transformContext $       \(_kn :: Term) (_l :: Term) (_r :: Term) (_ctx :: TransformContext) ->-        let trueDc = fromMaybe (error "reduceNonRepPrim: failed to create True DC") $ do+        let trueDc = fromMaybe (error "reducePrim: failed to create True DC") $ do               boolTc <- UniqMap.lookup boolTcNm tyConMap               [_falseDc,dc] <- pure (tyConDataCons boolTc)               return dc@@ -769,7 +798,7 @@     [Term] ->     -- | The type of the expression containing the applied primitive     Type ->-    -- | The context in which reduceNonRepPrim was called+    -- | The context in which reducePrim was called     TransformContext ->     a ->     NormalizeSession Term
src/Clash/Normalize/Transformations/SeparateArgs.hs view
@@ -2,16 +2,19 @@   Copyright  :  (C) 2012-2016, University of Twente,                     2016-2017, Myrtle Software Ltd,                     2017-2018, Google Inc.,-                    2021     , QBayLogic B.V.+                    2021,2026, QBayLogic B.V.   License    :  BSD2 (see the file LICENSE)   Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>   The separating arguments transformation -}  {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskellQuotes #-}  module Clash.Normalize.Transformations.SeparateArgs   ( separateArguments+  , separateArgumentsLambdaWorker+  , separateArgumentsSpineWorker   ) where  import qualified Control.Lens as Lens@@ -30,6 +33,9 @@ import Clash.Core.Var (Id, TyVar, Var (..), isGlobalId, mkLocalId) import Clash.Core.VarEnv (extendInScopeSet, uniqAway) import Clash.Normalize.Types (NormRewrite, NormalizeSession)+import Clash.Rewrite.StrategyDSL+  ( Transformation, onAppNode, onLam, onTickNode, onTyAppNode, onVarNode+  , toTransformation) import Clash.Rewrite.Types (TransformContext(..), tcCache) import Clash.Rewrite.Util (changed, mkDerivedName) @@ -43,14 +49,29 @@ -- into -- -- > f :: Clock System -> Reset System -> Signal System Int-separateArguments :: HasCallStack => NormRewrite-separateArguments ctx e0@(Lam b eb) = do+separateArguments :: Transformation+separateArguments = toTransformation "separateArguments"+  (  onLam 'separateArgumentsLambdaWorker+  <> onVarNode 'separateArgumentsSpineWorker+  <> onAppNode 'separateArgumentsSpineWorker+  <> onTyAppNode 'separateArgumentsSpineWorker+  <> onTickNode 'separateArgumentsSpineWorker)++-- | The 'Lam' handler of 'separateArguments'.+separateArgumentsLambdaWorker+  :: HasCallStack+  => TransformContext -> Term -> Id -> Term -> NormalizeSession Term+separateArgumentsLambdaWorker ctx node b eb = do   tcm <- Lens.view tcCache   case separateLambda tcm ctx b eb of     Just e1 -> changed e1-    Nothing -> return e0+    Nothing -> return node+{-# SCC separateArgumentsLambdaWorker #-} -separateArguments (TransformContext is0 _) e@(collectArgsTicks -> (Var g, args, ticks))+-- | The application spine ('Var', 'App', 'TyApp', 'Tick') handler of+-- 'separateArguments'.+separateArgumentsSpineWorker :: HasCallStack => NormRewrite+separateArgumentsSpineWorker (TransformContext is0 _) e@(collectArgsTicks -> (Var g, args, ticks))   | isGlobalId g = do   -- We ensure that both the type of the global variable reference is updated   -- to take into account the changed arguments, and that we apply the global@@ -84,8 +105,8 @@       _ ->         return [(ty,arg)] -separateArguments _ e = return e-{-# SCC separateArguments #-}+separateArgumentsSpineWorker _ e = return e+{-# SCC separateArgumentsSpineWorker #-}  -- | Worker function of 'separateArguments'. separateLambda
src/Clash/Normalize/Transformations/Specialize.hs view
@@ -20,11 +20,16 @@  module Clash.Normalize.Transformations.Specialize   ( appProp+  , appPropWorker   , constantSpec+  , constantSpecWorker   , specialize   , nonRepSpec+  , nonRepSpecWorker   , typeSpec+  , typeSpecWorker   , zeroWidthSpec+  , zeroWidthSpecWorker   ) where  import Control.Arrow ((***), (&&&))@@ -47,6 +52,8 @@ import qualified Data.Text.Extra as Text import GHC.BasicTypes.Extra (isNoInline) import GHC.Stack (HasCallStack)+import GHC.Num.Integer (Integer(IS))+import GHC.Num.Natural (Natural(NS))  import GHC.Types.Basic (InlineSpec (..)) @@ -65,7 +72,7 @@ import Clash.Core.Subst import Clash.Core.Term   ( Term(..), TickInfo, collectArgs, collectArgsTicks, mkApps, mkTmApps, mkTicks, patIds, Bind(..)-  , patVars, mkAbstraction, PrimInfo(..), WorkInfo(..), IsMultiPrim(..), PrimUnfolding(..), stripAllTicks)+  , patVars, mkAbstraction, PrimInfo(..), WorkInfo(..), IsMultiPrim(..), PrimUnfolding(..)) import Clash.Core.TermInfo (isLocalVar, isVar, isPolyFun) import Clash.Core.TyCon (TyConMap, tyConDataCons) import Clash.Core.Type@@ -75,12 +82,16 @@ import Clash.Core.Util (listToLets) import Clash.Core.Var (Var(..), Id, TyVar, mkTyVar) import Clash.Core.VarEnv-  ( InScopeSet, emptyVarEnv, extendInScopeSet, extendInScopeSetList-  , lookupVarEnv, mkInScopeSet, mkVarSet, unionInScope, unitVarEnv, elemVarSet)+  ( InScopeSet, extendInScopeSet, extendInScopeSetList+  , lookupVarEnv, mkInScopeSet, mkVarSet, unionInScope, elemVarSet) import qualified Clash.Data.UniqMap as UniqMap import Clash.Debug (traceIf, traceM) import Clash.Driver.Types (Binding(..), TransformationInfo(..), hasTransformationInfo) import Clash.Rewrite.Combinators (topdownR)+import Clash.Rewrite.StrategyDSL+  ( Transformation, onApp, onAppNode, onLam, onTyApp, onTyAppNode+  , toTransformation+  ) import Clash.Rewrite.Types   ( TransformContext(..), bindings, censor, curFun, extra, tcCache   , workFreeBinders, debugOpts, topEntities, specializationLimit)@@ -178,22 +189,26 @@ -- of the application w.r.t. the free variables in the argument part of the -- application. It is okay to over-approximate in this case and deshadow w.r.t -- the current InScopeSet.-appProp :: HasCallStack => NormRewrite-appProp ctx@(TransformContext is _) = \case-  e@App {}-    | let (fun,args,ticks) = collectArgsTicks e-    -> do (eN,hasChanged) <- Writer.listen (go is (deShadowTerm is fun) args ticks)-          if Monoid.getAny hasChanged-            then return eN-            else return e-  e@TyApp {}-    | let (fun,args,ticks) = collectArgsTicks e-    -> do (eN,hasChanged) <- Writer.listen (go is (deShadowTerm is fun) args ticks)-          if Monoid.getAny hasChanged-            then return eN-            else return e-  e          -> return e+appProp :: Transformation+appProp = toTransformation "applicationPropagation"+  (onAppNode 'appPropWorker <> onTyAppNode 'appPropWorker)++-- | The application-spine handler of 'appProp'. Matches the constructors it+-- is registered for itself, so it can also be used as a plain uninstrumented+-- rewrite in the traversal inside 'inlineInternalSpecialisationArgument'.+appPropWorker :: HasCallStack => NormRewrite+appPropWorker ctx@(TransformContext is _) node = case node of+  App{} -> propagate+  TyApp{} -> propagate+  _ -> return node  where+  propagate = do+    let (fun,args,ticks) = collectArgsTicks node+    (eN,hasChanged) <- Writer.listen (go is (deShadowTerm is fun) args ticks)+    if Monoid.getAny hasChanged+      then return eN+      else return node+   go :: InScopeSet -> Term -> [Either Term Type] -> [TickInfo] -> NormalizeSession Term   go is0 (collectArgsTicks -> (fun,args0@(_:_),ticks0)) args1 ticks1 =     go is0 fun (args0 ++ args1) (ticks0 ++ ticks1)@@ -203,14 +218,8 @@     bndrs <- Lens.use bindings     orM [pure (isVar arg), isWorkFree workFreeBinders bndrs arg] >>= \case       True ->-        -- 'e' is deshadowed w.r.t. an in-scope set that contains the free-        -- variables of 'arg': 'appProp' deshadows the function expression-        -- w.r.t. 'is0' up front, and 'go' re-deshadows whenever it extends the-        -- in-scope set. So no binder in 'e' shadows 'v' — the binder of the-        -- enclosing lambda -- nor captures a free variable of 'arg', which is-        -- exactly the precondition of 'unsafeSubstTm'.-        (`mkTicks` ticks)-          <$> go is0 (unsafeSubstTm emptyVarEnv (unitVarEnv v arg) e) args []+        let subst = extendIdSubst (mkSubst is0) v arg in+        (`mkTicks` ticks) <$> go is0 (substTm "appProp.AppLam" subst e) args []       False ->         let is1 = extendInScopeSet is0 v in         Let (NonRec v arg) <$> go is1 (deShadowTerm is1 e) args ticks@@ -283,12 +292,18 @@         return (ty2,(boundArg,arg):ls1,Left (Var boundArg):args1)    goCaseArg _ ty ls [] = return (ty,ls,[])-{-# SCC appProp #-}+{-# SCC appPropWorker #-}  -- | Specialize functions on arguments which are constant, except when they -- are clock, reset generators.-constantSpec :: HasCallStack => NormRewrite-constantSpec ctx@(TransformContext is0 tfCtx) e@(App e1 e2)+constantSpec :: Transformation+constantSpec = toTransformation "constantSpec" (onApp 'constantSpecWorker)++-- | The 'App' handler of 'constantSpec'.+constantSpecWorker+  :: HasCallStack+  => TransformContext -> Term -> Term -> Term -> NormalizeSession Term+constantSpecWorker ctx@(TransformContext is0 tfCtx) e e1 e2   | (Var {}, args) <- collectArgs e1   , (_, []) <- Either.partitionEithers args   , null $ Lens.toListOf termFreeTyVars e2@@ -319,8 +334,8 @@        else         -- e2 has no constant parts         return e-constantSpec _ e = return e-{-# SCC constantSpec #-}+constantSpecWorker _ e _ _ = return e+{-# SCC constantSpecWorker #-}  -- | Specialize an application on its argument specialize :: NormRewrite@@ -342,8 +357,8 @@  If one of these had been specialized, the other two would hit that term in the specialization cache, saving Clash from having to re-do work which is in effect-the same. To preserve this behavior, we use 'stripAllTicks' on the keys for-the specialization cache.+the same. To preserve this behavior, we strip all ticks from the keys for the+specialization cache, see 'specCacheKey'.  TODO While this preserves the old behavior, the old behavior is likely not quite what we want. Using a value from the specialization cache may change the@@ -352,6 +367,45 @@ miss on virtually every lookup which could add to normalization time. -} +{-+Note [bignum literals and specialization]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+GHC represents a small 'Natural' or 'Integer' constant as a constructor applied+to a literal, e.g. @NS 8000##@. The evaluator reads such a constant back as a+plain literal, @8000@, so a constant that went through 'reduceConst' looks+different from one that didn't, even though they're the same value. Both forms+reach 'specialize', for example when a 'KnownDomain' dictionary built by GHC is+passed to a function at one call site, while at another call site the same+dictionary is the result of normalizing an application of a work-free function+(see 'Clash.Normalize.Util.normalizeWorkFreeApp'). To prevent creating two+identical specializations, we use the literal form in the keys of the+specialization cache.+-}++-- | Prepare a term for use as a key in the specialization cache: strip all+-- ticks (see Note [ticks and specialization]) and replace small bignum+-- constants by literals (see Note [bignum literals and specialization]).+specCacheKey :: Term -> Term+specCacheKey = go+ where+  go (Lam i x) = Lam i (go x)+  go (TyLam i x) = TyLam i (go x)+  go (App f x) = case (go f, go x) of+    (Prim p, Literal (WordLiteral w))+      | primName p == Text.showt 'NS -> Literal (NaturalLiteral w)+    (Prim p, Literal (IntLiteral i))+      | primName p == Text.showt 'IS -> Literal (IntegerLiteral i)+    (f', x') -> App f' x'+  go (TyApp f a) = TyApp (go f) a+  go (Let bs x) = Let (goBinds bs) (go x)+  go (Case x ty alts) = Case (go x) ty (fmap go <$> alts)+  go (Cast x a b) = Cast (go x) a b+  go (Tick _ x) = go x+  go x = x++  goBinds (NonRec i x) = NonRec i (go x)+  goBinds (Rec ixs) = Rec (fmap go <$> ixs)+ -- | Given two 'InlineSpec's, return the \"strongest\" one. I.e., the one that's -- closest to @NoInline@ (or @Opaque@ for newer GHCs). preferNoInline :: InlineSpec -> InlineSpec -> InlineSpec@@ -409,9 +463,10 @@       specBndrs :: [Either Id TyVar]       specBndrs = map (Lens.over Lens._Left (normalizeId tcm)) specBndrsIn -      -- See Note [ticks and specialization]+      -- See Note [ticks and specialization] and+      -- Note [bignum literals and specialization]       specAbs :: Either Term Type-      specAbs = either (Left . stripAllTicks . (`mkAbstraction` specBndrs)) (Right . id) specArg+      specAbs = either (Left . specCacheKey . (`mkAbstraction` specBndrs)) (Right . id) specArg   -- Determine if 'f' has already been specialized on (a type-normalized) 'specArg'   specM <- Map.lookup (f,argLen,specAbs) <$> Lens.use (extra.specialisationCache)   case specM of@@ -605,8 +660,14 @@   in  (specTyBndrs ++ specTmBndrs,specTyVars ++ specTmVars)  -- | Specialize functions on their non-representable argument-nonRepSpec :: HasCallStack => NormRewrite-nonRepSpec ctx e@(App e1 e2)+nonRepSpec :: Transformation+nonRepSpec = toTransformation "nonRepSpec" (onApp 'nonRepSpecWorker)++-- | The 'App' handler of 'nonRepSpec'.+nonRepSpecWorker+  :: HasCallStack+  => TransformContext -> Term -> Term -> Term -> NormalizeSession Term+nonRepSpecWorker ctx e e1 e2   | (Var {}, args) <- collectArgs e1   , (_, [])     <- Either.partitionEithers args   , null $ Lens.toListOf termFreeTyVars e2@@ -638,24 +699,30 @@           Just b             | nameSort (varName (bindingId b)) == Internal             -> censor (const mempty)-                      (topdownR appProp ctx+                      (topdownR appPropWorker ctx                         (mkApps (mkTicks (bindingTerm b) ticks) fArgs))           _ -> return app       | otherwise = return app -nonRepSpec _ e = return e-{-# SCC nonRepSpec #-}+nonRepSpecWorker _ e _ _ = return e+{-# SCC nonRepSpecWorker #-}  -- | Specialize functions on their type-typeSpec :: HasCallStack => NormRewrite-typeSpec ctx e@(TyApp e1 ty)+typeSpec :: Transformation+typeSpec = toTransformation "typeSpec" (onTyApp 'typeSpecWorker)++-- | The 'TyApp' handler of 'typeSpec'.+typeSpecWorker+  :: HasCallStack+  => TransformContext -> Term -> Term -> Type -> NormalizeSession Term+typeSpecWorker ctx e e1 ty   | (Var {},  args) <- collectArgs e1   , null $ Lens.toListOf typeFreeVars ty   , (_, []) <- Either.partitionEithers args   = specialize ctx e -typeSpec _ e = return e-{-# SCC typeSpec #-}+typeSpecWorker _ e _ _ = return e+{-# SCC typeSpecWorker #-}  -- | Specialize functions on arguments which are zero-width. These arguments -- can have only one possible value, and specializing on this value may create@@ -665,8 +732,14 @@ -- the type of a term), we instead substitute all occurances of a lambda-bound -- variable with a zero-width type with the only value of that type. ---zeroWidthSpec :: HasCallStack => NormRewrite-zeroWidthSpec (TransformContext is _) e@(Lam i x0) = do+zeroWidthSpec :: Transformation+zeroWidthSpec = toTransformation "zeroWidthSpec" (onLam 'zeroWidthSpecWorker)++-- | The 'Lam' handler of 'zeroWidthSpec'.+zeroWidthSpecWorker+  :: HasCallStack+  => TransformContext -> Term -> Id -> Term -> NormalizeSession Term+zeroWidthSpecWorker (TransformContext is _) e i x0 = do   tcm <- Lens.view tcCache   let bndrTy = normalizeType tcm (coreTypeOf i) @@ -678,9 +751,7 @@      Nothing ->       return e--zeroWidthSpec _ e = return e-{-# SCC zeroWidthSpec #-}+{-# SCC zeroWidthSpecWorker #-}  -- Get the only element of a type, if it is zero-width. --
src/Clash/Normalize/Transformations/XOptimize.hs view
@@ -2,7 +2,7 @@   Copyright  :  (C) 2012-2016, University of Twente,                     2016-2017, Myrtle Software Ltd,                     2017-2018, Google Inc.,-                    2021-2022, QBayLogic B.V.+                    2021-2022,2026, QBayLogic B.V.   License    :  BSD2 (see the file LICENSE)   Maintainer :  QBayLogic B.V. <devops@qbaylogic.com> @@ -11,9 +11,11 @@  {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE TemplateHaskellQuotes #-}  module Clash.Normalize.Transformations.XOptimize   ( xOptimize+  , xOptimizeWorker   ) where  import qualified Control.Lens as Lens@@ -36,8 +38,9 @@ import Clash.Core.VarEnv (InScopeSet) import Clash.Netlist.BlackBox.Types (Element(Err)) import Clash.Netlist.Types (BlackBox(..))-import Clash.Normalize.Types (NormRewrite, NormalizeSession)+import Clash.Normalize.Types (NormalizeSession) import Clash.Primitives.Types (Primitive(..))+import Clash.Rewrite.StrategyDSL (Transformation, onCase, toTransformation) import Clash.Rewrite.Types   (TransformContext(..), aggressiveXOpt, tcCache, primitives) import Clash.Rewrite.Util (changed)@@ -66,23 +69,27 @@ -- where fieldN is an internal variable referring to the nth argument of a -- data constructor. ---xOptimize :: HasCallStack => NormRewrite-xOptimize (TransformContext is0 _) e@(Case subj ty alts) = do+xOptimize :: Transformation+xOptimize = toTransformation "xOptimize" (onCase 'xOptimizeWorker)++-- | The 'Case' handler of 'xOptimize'.+xOptimizeWorker+  :: HasCallStack+  => TransformContext -> Term -> Term -> Type -> [Alt] -> NormalizeSession Term+xOptimizeWorker (TransformContext is0 _) node subj ty alts = do   runXOpt <- Lens.view aggressiveXOpt    if runXOpt then do     defPart <- List.partitionM (isPrimError . snd) alts      case defPart of-      ([], _)    -> return e+      ([], _)    -> return node       (_, [])    -> changed (Prim (PrimInfo (Text.showt 'errorX) ty WorkConstant SingleResult NoUnfolding))       (_, [alt]) -> xOptimizeSingle is0 subj alt       (_, defs)  -> xOptimizeMany is0 subj ty defs   else-    return e--xOptimize _ e = return e-{-# SCC xOptimize #-}+    return node+{-# SCC xOptimizeWorker #-}  -- Return an expression equivalent to the alternative given. When only one -- alternative is defined the result of this function is used to replace the
src/Clash/Normalize/Types.hs view
@@ -14,6 +14,7 @@  import qualified Control.Lens as Lens import Control.Monad.State.Strict (State)+import Data.HashMap.Strict        (HashMap) import Data.Map                   (Map) import Data.Set                   (Set) import Data.Text                  (Text)@@ -51,6 +52,24 @@   --   -- NB: there are only no mutually-recursive component, only self-recursive   -- ones.+  , _normalizationStrategy :: Rewrite NormalizeState+  -- ^ The compiled 'Clash.Normalize.Strategy.normalization' strategy. Carried+  -- in the state so transformations can normalize other binders+  -- ('Clash.Normalize.Util.normalizeTopLvlBndr') without importing the+  -- strategy module. Breaking that import cycle would need an hs-boot file,+  -- and GHC rejects Template Haskell splices in a module cycle.+  , _constantPropagationStrategy :: Rewrite NormalizeState+  -- ^ The compiled 'Clash.Normalize.Strategy.constantPropagation' strategy,+  -- for "Clash.Normalize.PrimitiveReductions". See '_normalizationStrategy'.+  , _workFreeAppCache :: HashMap Term Term+  -- ^ Cache of normalized work-free applications, i.e. global functions+  -- applied to closed arguments:+  --+  -- * Key: the application, e.g. @f \@7 dict@+  --+  -- * Elem: the normalized body of @f@ applied to the arguments+  --+  -- See 'Clash.Normalize.Util.normalizeWorkFreeApp'.   }  Lens.makeLenses ''NormalizeState
src/Clash/Normalize/Util.hs view
@@ -26,6 +26,7 @@  , isNonRecursiveGlobalVar  , constantSpecInfo  , normalizeTopLvlBndr+ , normalizeWorkFreeApp  , rewriteExpr  , mkInlineTick  , substWithTyEq@@ -64,7 +65,7 @@    splitTyConAppM, mkPolyFunTy) import           Clash.Core.Util   (isClockOrReset)-import           Clash.Core.Var          (Id, TyVar, Var (..), isGlobalId)+import           Clash.Core.Var          (Id, TyVar, Var (..), isGlobalId, mkGlobalId) import           Clash.Core.VarEnv   (VarEnv, emptyInScopeSet, emptyVarEnv, extendVarEnv, extendVarEnvWith,    lookupVarEnv, unionVarEnvWith, unitVarEnv, extendInScopeSetList, mkInScopeSet, mkVarSet)@@ -73,16 +74,15 @@ import           Clash.Driver.Types   (BindingMap, Binding(..), TransformationInfo(FinalTerm), hasTransformationInfo) import           Clash.Normalize.Primitives (removedArg)-import {-# SOURCE #-} Clash.Normalize.Strategy (normalization) import           Clash.Normalize.Types import           Clash.Primitives.Util   (constantArgs) import           Clash.Rewrite.Types   (RewriteMonad, TransformContext(..), bindings, curFun, debugOpts, extra,    tcCache, primitives) import           Clash.Rewrite.Util-  (runRewrite, mkTmBinderFor, mkDerivedName)+  (cloneNameWithBindingMap, runRewrite, mkTmBinderFor, mkDerivedName) import           Clash.Unique-import           Clash.Util              (SrcSpan, makeCachedU)+import           Clash.Util              (SrcSpan, makeCached, makeCachedU)  -- | Determine if argument should reduce to a constant given a primitive and -- an argument number. Caches results.@@ -414,11 +414,65 @@   let tm1 = deShadowTerm emptyInScopeSet tm       tm2 = if isTop then substWithTyEq tm1 else tm1   old <- Lens.use curFun+  -- See the documentation of '_normalizationStrategy' for why the strategy+  -- comes out of the state instead of an import.+  normalization <- Lens.use (extra . normalizationStrategy)   tm3 <- rewriteExpr ("normalization",normalization) (nmS,tm2) (nm',sp)   curFun .= old   let ty' = inferCoreTypeOf tcm tm3   let r' = nm' `globalIdOccursIn` tm3   return (Binding nm'{varType = ty'} sp inl pr tm3 r')++-- | Normalize a global function applied to closed arguments, i.e. a work-free+-- application such as @f \@7 dict@. 'inlineWorkFree' inlines the result at+-- every occurrence of the application. Results are cached.+--+-- Unlike unapplied work-free binders (see 'inlineWFCacheLimit'), applications+-- are cached regardless of the size of @f@: most of the work is in the arguments+-- and in the functions @f@ calls, so even tiny functions such as dictionary+-- selectors benefit.+--+-- Note that a normalized constant can look different from its unnormalized+-- form, see Note [bignum literals and specialization].+normalizeWorkFreeApp+  :: Id+  -- ^ Global function+  -> Binding Term+  -- ^ Binding of the global function+  -> [Either Term Type]+  -- ^ Closed arguments+  -> NormalizeSession Term+normalizeWorkFreeApp f b args =+  -- Caching is sound because the application is closed: it means the same in any+  -- context, so its normalized form is a valid replacement anywhere. The cache is+  -- keyed on the application modulo alpha-equivalence, which suffices because the+  -- binding of @f@ never changes during normalization. Every occurrence still gets+  -- its own copy, so the circuit doesn't change. Only names in the HDL can:+  -- binders lifted out of the application are named after @f@, not after the+  -- function the application occurs in.+  makeCached app (extra.workFreeAppCache) $ do+    tcm <- Lens.view tcCache+    bndrs <- Lens.use bindings+    -- The application is normalized as if it were the body of a binder of+    -- its own. That binder is never referenced, so it isn't added to+    -- 'bindings'. It is named after 'f', so binders lifted out of the+    -- application are named after 'f' too.+    nm <- cloneNameWithBindingMap bndrs (varName f)+    let g = mkGlobalId (inferCoreTypeOf tcm app) nm+        -- Normalize the beta-redex rather than 'app': normalizing 'app'+        -- would bring us right back here. We deshadow for the same reason+        -- 'normalizeTopLvlBndr' does.+        --+        -- XXX: This seems outdated? Investigate.+        redex = deShadowTerm emptyInScopeSet (mkApps (bindingTerm b) args)+    old <- Lens.use curFun+    normalization <- Lens.use (extra . normalizationStrategy)+    tm <- rewriteExpr ("normalization",normalization)+                      (showPpr (varName f),redex) (g,bindingLoc b)+    curFun .= old+    return tm+ where+  app = mkApps (Var f) args  -- | Turn type equality constraints into substitutions and apply them. --
src/Clash/Primitives/DSL.hs view
@@ -46,8 +46,13 @@   -- ** Literals   , bvLit   , LitHDL (..)+#if __GLASGOW_HASKELL__ >= 914+  , data High+  , data Low+#else   , pattern High   , pattern Low+#endif   , constructProduct   , tuple   , vec
src/Clash/Primitives/GHC/Int.hs view
@@ -12,6 +12,8 @@  module Clash.Primitives.GHC.Int (intTF) where +import           Data.List.NonEmpty           (NonEmpty(..))+ import           Clash.Core.Literal           (Literal(..)) import           Clash.Core.Term              (Term(Literal)) import           Clash.Core.Type              (Type)@@ -37,7 +39,8 @@  -- | Template function for Int8,Int16,.. Constructs "clean" literals. intTF :: BlackBoxFunction-intTF = literalTF "GHC.Int.I" intTF'+-- 'GHC.Internal.Int.I' covers GHC >= 9.14; 'GHC.Int.I' covers earlier versions.+intTF = literalTF ("GHC.Int.I" :| ["GHC.Internal.Int.I"]) intTF'  intTF'   :: Bool
src/Clash/Primitives/GHC/Literal.hs view
@@ -17,6 +17,8 @@  )  where +import           Data.List.NonEmpty           (NonEmpty)+import qualified Data.List.NonEmpty           as NE import qualified Data.Text.Lazy               as LT import           Data.Text   (Text, stripPrefix, stripSuffix, unpack)@@ -55,23 +57,29 @@                   ])  -- | Parse integer in strings of the form "GHC.Word.WordX#" where--- "GHC.Word.Word" is the prefix given.-readSize :: Text -> Text -> Maybe Int-readSize prefix nm0 = do-  nm1 <- stripPrefix prefix nm0+-- "GHC.Word.Word" is the prefix given. The first prefix that matches wins.+readSize :: NonEmpty Text -> Text -> Maybe Int+readSize prefixes nm0 = do+  let go [] = Nothing+      go (p:ps) = case stripPrefix p nm0 of+        Just nm1 -> Just nm1+        Nothing  -> go ps+  nm1 <- go (NE.toList prefixes)   nm2 <- stripSuffix "#" nm1   readMaybe (unpack nm2)  -- | Constructs "clean" literals. literalTF-  :: Text-  -- ^ Base name of constructors (for example: "GHC.Word.W")+  :: NonEmpty Text+  -- ^ Base names of constructors (for example: @"GHC.Word.W" :| ["GHC.Internal.Word.W"]@).+  -- The 'GHC.Internal.*' variant is needed for GHC >= 9.14, which moved the+  -- constructors into 'ghc-internal'; 'base' re-exports them.   -> (Bool -> [Either Term Type] -> Int -> (BlackBoxMeta, BlackBox))   -- ^ Functions processing   -> BlackBoxFunction-literalTF baseName tf isDecl primName args _resTy = return $-  case readSize baseName primName of+literalTF baseNames tf isDecl primName args _resTy = return $+  case readSize baseNames primName of     Nothing ->-      Left (concat ["Can only make blackboxes for '", unpack baseName, "X#'"])+      Left (concat ["Can only make blackboxes for '", unpack (NE.head baseNames), "X#'"])     Just n ->       Right (tf isDecl args n)
src/Clash/Primitives/GHC/Word.hs view
@@ -11,6 +11,8 @@  module Clash.Primitives.GHC.Word (wordTF) where +import           Data.List.NonEmpty           (NonEmpty(..))+ import           Clash.Core.Literal           (Literal(..)) import           Clash.Core.Term              (Term(Literal)) import           Clash.Core.Type              (Type)@@ -24,7 +26,8 @@ -- | Template function for Word8,Word16,.. Constructs "clean" literals. This -- function generates valid (System)Verilog only! wordTF :: BlackBoxFunction-wordTF = literalTF "GHC.Word.W" wordTF'+-- 'GHC.Internal.Word.W' covers GHC >= 9.14; 'GHC.Word.W' covers earlier versions.+wordTF = literalTF ("GHC.Word.W" :| ["GHC.Internal.Word.W"]) wordTF'  getWordLit   :: Literal
src/Clash/Primitives/Sized/Vector.hs view
@@ -7,6 +7,7 @@   Blackbox implementations for functions in "Clash.Sized.Vector". -} {-# LANGUAGE CPP #-}+{-# LANGUAGE MagicHash #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-}@@ -24,6 +25,7 @@ import           Data.Text.Prettyprint.Doc.Extra   (Doc, string, renderLazy, layoutPretty, LayoutOptions(..),    PageWidth(AvailablePerLine))+import           GHC.Exts                           (Int(..)) import           Text.Trifecta.Result               (Result(Success)) import qualified Data.String.Interpolate            as I import           GHC.Stack                          (HasCallStack)@@ -299,7 +301,8 @@             fromInteger j           DataCon (Signed _) (DC (Void{},_)) [Literal (Just (Signed _,_)) (NumLit j)] ->             fromInteger j-          BlackBoxE "GHC.Types.I#" _lib _use _incl _templ Context{bbInputs=[(Literal _ (NumLit j),_,_)]} _paren ->+          BlackBoxE nm _lib _use _incl _templ Context{bbInputs=[(Literal _ (NumLit j),_,_)]} _paren+            | nm == showt 'I# ->             fromInteger j           _ ->             error ($(curLoc) ++ "Unexpected literal: " ++ show ix)
src/Clash/Primitives/Types.hs view
@@ -26,6 +26,7 @@   , GuardedResolvedPrimitive   , PrimMap   , UnresolvedPrimitive+  , UnresolvedPrimitiveEntry(..)   , ResolvedPrimitive   , ResolvedPrimMap   , CompiledPrimitive@@ -41,7 +42,7 @@ import           Control.DeepSeq              (NFData) import           Control.Monad                (when) import           Data.Aeson-  (FromJSON (..), Value (..), (.:), (.:?), (.!=))+  (FromJSON (..), Object, Value (..), (.:), (.:?), (.!=)) import           Data.Aeson.Types             (Parser) import           Data.Binary                  (Binary) import           Data.Char                    (isUpper, isLower, isAlphaNum)@@ -49,6 +50,8 @@ import           Data.Hashable                (Hashable) import qualified Data.HashMap.Strict          as H import           Data.List                    (intercalate)+import           Data.List.NonEmpty           (NonEmpty (..))+import qualified Data.List.NonEmpty           as NE import           Data.Maybe                   (isJust) import qualified Data.Text                    as S import           Data.Text.Lazy               (Text)@@ -234,7 +237,40 @@   }   deriving (Show, Generic, NFData, Binary, Eq, Hashable, Functor) -instance FromJSON UnresolvedPrimitive where+-- | A single YAML/JSON primitive entry. Unlike 'UnresolvedPrimitive', this+-- newtype can represent multiple primitive records emitted from a single+-- YAML entry whose @name@ field is a list of names rather than a single+-- string. For example+--+-- @+-- - Primitive:+--     name: ["GHC.Num.Integer.IS", "GHC.Internal.Bignum.Integer.IS"]+--     primType: Constructor+--     workInfo: Never+-- @+--+-- yields two 'UnresolvedPrimitive's with the same body but different+-- names. This lets us register one primitive under multiple qualified+-- names without duplicating the YAML body — useful when GHC moves+-- wired-in symbols between modules across versions (e.g. 'GHC.Num.Integer'+-- on GHC <= 9.12 vs 'GHC.Internal.Bignum.Integer' on GHC >= 9.14).+--+-- The single-string form @name: "foo"@ still parses; it produces a+-- 'NonEmpty' of length one.+newtype UnresolvedPrimitiveEntry =+  UnresolvedPrimitiveEntry { unUnresolvedPrimitiveEntry :: NonEmpty UnresolvedPrimitive }++-- | Read the @name@ field as either a single string or a non-empty list of+-- strings.+parseNames :: Object -> Parser (NonEmpty S.Text)+parseNames v =+      (do n <- v .: "name"; pure (n :| []))+  <|> (do ns <- v .: "name"+          case ns of+            []     -> fail "[10] 'name' list must be non-empty"+            x:xs   -> pure (x :| xs))++instance FromJSON UnresolvedPrimitiveEntry where   parseJSON (Object v) =     case KeyMap.toList v of       [(conKey,Object conVal)] ->@@ -250,7 +286,7 @@                 (Just _, Just _) ->                   fail "[8] Don't use both 'usedArguments' and 'ignoredArguments'" -            name' <- conVal .: "name"+            names <- parseNames conVal             wf    <- ((conVal .:? "workInfo" >>= maybe (pure Nothing) parseWorkInfo) .!= WorkVariable)             fName <- conVal .: "templateFunction"             isMultiResult <- conVal .:? "multiResult" .!= False@@ -258,7 +294,8 @@                  <|> (Just . TFile   <$> conVal .: "file")                  <|> (pure Nothing)             fName' <- either fail return (parseBBFN fName)-            return (BlackBoxHaskell name' wf args isMultiResult fName' templ)+            pure $ UnresolvedPrimitiveEntry $ flip NE.map names $ \name' ->+              BlackBoxHaskell name' wf args isMultiResult fName' templ           "BlackBox"  -> do             outReg <- conVal .:? "outputReg" :: Parser (Maybe Bool) @@ -268,24 +305,28 @@                 , "Use 'outputUsage: Continuous|NonBlocking|Blocking' instead."                 ] -            BlackBox <$> conVal .: "name"-                     <*> (conVal .:? "workInfo" >>= maybe (pure Nothing) parseWorkInfo) .!= WorkVariable-                     <*> conVal .:? "renderVoid" .!= NoRenderVoid-                     <*> conVal .:? "multiResult" .!= False-                     <*> (conVal .: "kind" >>= parseTemplateKind)-                     <*> conVal .:? "warning"-                     <*> conVal .:? "outputUsage" .!= Cont-                     <*> conVal .:? "libraries" .!= []-                     <*> conVal .:? "imports" .!= []-                     <*> pure [] -- functionPlurality not supported in json-                     <*> (conVal .:? "includes" .!= [] >>= traverse parseInclude)-                     <*> (conVal .:? "resultName" >>= maybe (pure Nothing) parseResult) .!= []-                     <*> (conVal .:? "resultInit" >>= maybe (pure Nothing) parseResult) .!= []-                     <*> parseTemplate conVal-          "Primitive" ->-            Primitive <$> conVal .: "name"-                      <*> (conVal .:? "workInfo" >>= maybe (pure Nothing) parseWorkInfo) .!= WorkVariable-                      <*> conVal .: "primType"+            names <- parseNames conVal+            wf <- (conVal .:? "workInfo" >>= maybe (pure Nothing) parseWorkInfo) .!= WorkVariable+            rv <- conVal .:? "renderVoid" .!= NoRenderVoid+            mr <- conVal .:? "multiResult" .!= False+            k  <- conVal .: "kind" >>= parseTemplateKind+            w  <- conVal .:? "warning"+            ou <- conVal .:? "outputUsage" .!= Cont+            ls <- conVal .:? "libraries" .!= []+            is <- conVal .:? "imports" .!= []+            inc <- conVal .:? "includes" .!= [] >>= traverse parseInclude+            rn  <- (conVal .:? "resultName" >>= maybe (pure Nothing) parseResult) .!= []+            ri  <- (conVal .:? "resultInit" >>= maybe (pure Nothing) parseResult) .!= []+            tmpl <- parseTemplate conVal+            -- functionPlurality not supported in json+            pure $ UnresolvedPrimitiveEntry $ flip NE.map names $ \name' ->+              BlackBox name' wf rv mr k w ou ls is [] inc rn ri tmpl+          "Primitive" -> do+            names <- parseNames conVal+            wf <- (conVal .:? "workInfo" >>= maybe (pure Nothing) parseWorkInfo) .!= WorkVariable+            ps <- conVal .: "primType"+            pure $ UnresolvedPrimitiveEntry $ flip NE.map names $ \name' ->+              Primitive name' wf ps            e -> fail $ "[1] Expected: BlackBox or Primitive object, got: " ++ show e       e -> fail $ "[2] Expected: BlackBox or Primitive object, got: " ++ show e@@ -331,3 +372,15 @@    parseJSON unexpected =     fail $ "[3] Expected: BlackBox or Primitive object, got: " ++ show unexpected++-- | Backwards-compatible: parse a single 'UnresolvedPrimitive' from a YAML+-- entry. Fails if the entry's @name@ field is a list (use+-- 'UnresolvedPrimitiveEntry' instead).+instance FromJSON UnresolvedPrimitive where+  parseJSON v = do+    UnresolvedPrimitiveEntry ne <- parseJSON v+    case ne of+      p :| [] -> pure p+      _ -> fail $ "[11] 'name' must be a single string when decoding to "+                ++ "UnresolvedPrimitive; got a list. Decode to "+                ++ "UnresolvedPrimitiveEntry to handle multi-name entries."
src/Clash/Primitives/Util.hs view
@@ -47,10 +47,13 @@   , extractPrim, extractWarnings) import           Clash.Core.Term        (Term) import           Clash.Core.Type        (Type)+import qualified Data.List.NonEmpty     as NE+ import           Clash.Primitives.Types   ( Primitive(BlackBox), CompiledPrimitive, ResolvedPrimitive, ResolvedPrimMap   , includes, template, TemplateSource(TFile, TInline), Primitive(..)-  , UnresolvedPrimitive, CompiledPrimMap, GuardedResolvedPrimitive)+  , UnresolvedPrimitive, UnresolvedPrimitiveEntry(..)+  , CompiledPrimMap, GuardedResolvedPrimitive) import           Clash.Netlist.Types    (BlackBox(..), NetlistMonad) import           Clash.Netlist.Util     (preserveState) import           Clash.Netlist.BlackBox.Util@@ -113,12 +116,18 @@  -- | Interprets contents of json file as list of @Primitive@s. Throws -- exception if it fails.+--+-- Each YAML/JSON entry may bind one or more @name@s (when the @name@ field+-- is a list), in which case a separate 'UnresolvedPrimitive' is produced+-- per name. See 'UnresolvedPrimitiveEntry'. resolvePrimitive   :: HasCallStack   => FilePath   -> IO [(TS.Text, GuardedResolvedPrimitive)] resolvePrimitive fileName = do-  prims <- decoder fileName <$> LZ.readFile fileName+  entries <- (decoder fileName :: LZ.ByteString -> [UnresolvedPrimitiveEntry])+               <$> LZ.readFile fileName+  let prims = concatMap (NE.toList . unUnresolvedPrimitiveEntry) entries   mapM (resolvePrimitive' fileName) prims  where   decoder
src/Clash/Rewrite/Combinators.hs view
@@ -14,9 +14,11 @@   , (>-!->)   , (>->)   , bottomupR+  , innerMost   , repeatR   , topdownR   , topdownFixR+  , topdownSucR   ) where  import           Control.DeepSeq             (deepseq)@@ -76,6 +78,7 @@   Tick sp <$> trans (TransformContext is (TickC sp:c)) e  allR _ _ tm = pure tm+{-# INLINABLE allR #-}  infixr 6 >-> -- | Apply two transformations in succession@@ -114,10 +117,41 @@ Then we must repeat the transformation to let it also inline y. -} +{-+Note [combinator inlining]+~~~~~~~~~~~~~~~~~~~~~~~~~~+The traversal combinators carry INLINE pragmas so that a call site applying+them to a statically-known transformation gets its own copy of the traversal+loop: GHC then fuses the RWST/Writer plumbing into an unboxed state loop and+calls the transformation directly instead of through a function argument.++That only works when two conditions hold:++* The combinator is not (mutually) recursive at the top level. GHC picks a+  loop-breaker in every top-level recursive group and never inlines it, so an+  INLINE pragma on such a function is silently ignored. The recursion has to+  go through a local binding instead.++* The local loop closes over the transformation rather than passing it along+  as an argument. GHC does not specialize a loop on an invariant argument+  (the static argument transformation is off by default), so with+  'go r = r !-> go r' the call to 'r' stays a call to an unknown function;+  with 'go = r !-> go' the simplifier sees the concrete 'r' once the+  combinator is inlined.++'allR' is INLINABLE rather than INLINE: specializing it to the concrete monad+removes the per-node Monad-dictionary dispatch, while full inlining would+duplicate its per-constructor case alternatives at every call site for no+extra benefit.+-}+ -- | Apply a transformation in a topdown traversal topdownR :: Rewrite m -> Rewrite m--- See Note [topdown repeatR]-topdownR r = repeatR r >-> allR (topdownR r)+-- See Note [topdown repeatR] and Note [combinator inlining]+topdownR r = go+ where+  go = repeatR r >-> allR go+{-# INLINE topdownR #-}  {- Note [topdownFixR]@@ -207,7 +241,11 @@  -- | Apply a transformation in a bottomup traversal bottomupR :: Monad m => Transform m -> Transform m-bottomupR r = allR (bottomupR r) >-> r+-- See Note [combinator inlining]+bottomupR r = go+ where+  go = allR go >-> r+{-# INLINE bottomupR #-}  infixr 5 !-> -- | Only apply the second transformation if the first one succeeds.@@ -231,5 +269,25 @@  -- | Keep applying a transformation until it fails. repeatR :: Rewrite m -> Rewrite m-repeatR = let go r = r !-> repeatR r in go+-- See Note [combinator inlining]+repeatR r = go+ where+  go = r !-> go {-# INLINE repeatR #-}++-- | Topdown traversal, stops upon first success+topdownSucR :: Rewrite extra -> Rewrite extra+-- See Note [combinator inlining]+topdownSucR r = go+ where+  go = r >-! allR go+{-# INLINE topdownSucR #-}++-- | Bottomup traversal; when the transformation succeeds, re-traverse the+-- result until the innermost fixpoint is reached.+innerMost :: Rewrite extra -> Rewrite extra+-- See Note [combinator inlining]+innerMost r = go+ where+  go = bottomupR (r !-> go)+{-# INLINE innerMost #-}
+ src/Clash/Rewrite/StrategyDSL.hs view
@@ -0,0 +1,286 @@+{-|+  Copyright  :  (C) 2026, QBayLogic B.V.+  License    :  BSD2 (see the file LICENSE)+  Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>++  A pure description language for rewrite strategies. A strategy written in+  this DSL is compiled by "Clash.Rewrite.StrategyDSL.TH" into a fused+  traversal that matches each node's constructor once and runs only the+  transformations registered for that constructor.++  The DSL has two layers:++  * 'Step': what runs at a single node inside a fused traversal. An ordered+    'chain' of transformations, sequencing and success/failure conditionals+    between chain segments, or a whole 'nested' strategy embedded as one node+    action.++  * 'Strat': a complete strategy. Fused traversals over a 'Step', whole-term+    passes, and the usual combinators ('>->', '!->', '>-!', '>-!->',+    'repeatR') between them.+-}++{-# LANGUAGE DisambiguateRecordFields #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NoFieldSelectors #-}+{-# LANGUAGE OverloadedRecordDot #-}++module Clash.Rewrite.StrategyDSL+  ( -- * Transformation metadata+    Constructor (..)+  , TransformationWorker (..)+  , Transformation (..)+  , toTransformation+  , anyConstructor+  , named+    -- ** Worker builders: workers receiving the constructor's fields+  , onVar+  , onData+  , onLiteral+  , onPrim+  , onLam+  , onTyLam+  , onApp+  , onTyApp+  , onLet+  , onCase+  , onCast+  , onTick+    -- ** Worker builders: workers receiving the node itself+  , onVarNode+  , onPrimNode+  , onAppNode+  , onTyAppNode+  , onLetNode+  , onTickNode+    -- * Node layer+  , Step (..)+  , chain+  , one+  , nested+    -- * Strategy layer+  , Strat (..)+  , topdown+  , bottomup+  , topdownFix+  , topdownSuc+  , innerMost+  , pass+  , callStrategy+  , repeatR+    -- * Combinators+  , Strategic (..)+  , (>-!->)+  , ToStep (..)+  ) where++import Language.Haskell.TH.Syntax (Name)++-- | One 'Clash.Core.Term.Term' constructor.+data Constructor+  = CVar | CData | CLiteral | CPrim | CLam | CTyLam+  | CApp | CTyApp | CLet | CCase | CCast | CTick+  deriving (Eq, Ord, Show, Enum, Bounded)++-- | A single function separated by the constructor it fires on. Note that this+-- isn't a single transformation per se, as one transformation might fire on+-- multiple constructors. 'Transformation' ties together multiple workers into+-- a single transformation.+--+-- The 'Name' must refer to an exported top-level worker so the generated+-- dispatch code can reference it from the splice site.+--+-- A worker that returns a term other than the one it was given must say so+-- with 'Clash.Rewrite.Util.changed': a 'chain' hands the fields it matched to+-- the next member as long as no change was signaled.+data TransformationWorker+  = FieldWorker !Constructor !Name+  -- ^ @worker :: TransformContext -> Term -> \<fields of the constructor\>+  -- -> RewriteMonad extra Term@. The worker receives the matched node (to+  -- return on the unchanged path with sharing intact) followed by the+  -- constructor's fields.+  | Worker !Constructor !Name+  -- ^ @worker :: Rewrite extra@. A worker that fires only at the given+  -- constructor, like the per-constructor worker above, but receives the+  -- whole node instead of its deconstructed fields. For transformations that+  -- decompose the node themselves, e.g. by collecting the entire application+  -- spine rather than one @App@ layer.+  | AnyWorker !Name+  -- ^ @worker :: Rewrite extra@, applied at all constructors. For a+  -- transformation whose firing condition lives in the+  -- 'Clash.Rewrite.Types.TransformContext' rather than the constructor+  -- (@topLet@).+  deriving (Eq, Show)++-- | Single, named transformation. Can consist of multiple workers (see+-- 'TransformationWorker').+data Transformation = Transformation+  { name :: !String+  -- ^ Canonical name, used for debug tracing, transformation counters, and+  -- the rewrite history.+  , workers :: ![TransformationWorker]+  } deriving (Eq, Show)++-- | Declare a transformation's workers: at most one per constructor, and+-- either an 'AnyWorker' or per-constructor workers, never both. Checked when+-- the transformation is compiled.+toTransformation :: String -> [TransformationWorker] -> Transformation+toTransformation = Transformation++-- | Declare a transformation that fires at any constructor. See 'AnyWorker'.+anyConstructor :: String -> Name -> Transformation+anyConstructor name worker = Transformation name [AnyWorker worker]++-- | Give a transformation a different name; used for deliberate debug+-- aliases of a transformation that runs at several strategy positions (the+-- transformation counters and rewrite history key on the name).+named :: String -> Transformation -> Transformation+named alias transformation = transformation { name = alias }++onVar, onData, onLiteral, onPrim, onLam, onTyLam, onApp, onTyApp, onLet,+  onCase, onCast, onTick :: Name -> [TransformationWorker]+onVar     = pure . FieldWorker CVar+onData    = pure . FieldWorker CData+onLiteral = pure . FieldWorker CLiteral+onPrim    = pure . FieldWorker CPrim+onLam     = pure . FieldWorker CLam+onTyLam   = pure . FieldWorker CTyLam+onApp     = pure . FieldWorker CApp+onTyApp   = pure . FieldWorker CTyApp+onLet     = pure . FieldWorker CLet+onCase    = pure . FieldWorker CCase+onCast    = pure . FieldWorker CCast+onTick    = pure . FieldWorker CTick++onVarNode, onPrimNode, onAppNode, onTyAppNode, onLetNode,+  onTickNode :: Name -> [TransformationWorker]+onVarNode   = pure . Worker CVar+onPrimNode  = pure . Worker CPrim+onAppNode   = pure . Worker CApp+onTyAppNode = pure . Worker CTyApp+onLetNode   = pure . Worker CLet+onTickNode  = pure . Worker CTick++-- | What runs at a single node inside a fused traversal.+data Step+  = Chain [Transformation]+  -- ^ One constructor match dispatches the members registered for that+  -- constructor, in list order. Equivalent to the sequential+  -- @apply n1 t1 '>->' apply n2 t2 …@ chain over all members.+  | SeqS Step Step+  -- ^ '>->' at the node: the right side re-dispatches on the left side's+  -- result.+  | OnChangeS Step Step+  -- ^ '!->' at the node: the right side runs only when the left side+  -- signaled change.+  | OnNoChangeS Step Step+  -- ^ '>-!' at the node: the right side runs only when the left side did+  -- not signal change.+  | EmbedS Strat+  -- ^ A whole strategy as one node action.+  deriving (Eq, Show)++-- | A complete rewriting strategy.+data Strat+  = TopDown Step+  -- ^ Fused 'Clash.Rewrite.Combinators.topdownR': repeat the step at each+  -- node until it no longer fires, then descend.+  | BottomUp Step+  -- ^ Fused 'Clash.Rewrite.Combinators.bottomupR': descend first, run the+  -- step once on the rebuilt node.+  | TopDownFix Step+  -- ^ Fused 'Clash.Rewrite.Combinators.topdownFixR'. Mind its soundness+  -- precondition (Note [topdownFixR] in "Clash.Rewrite.Combinators").+  | TopDownSuc Step+  -- ^ Fused 'Clash.Rewrite.Combinators.topdownSucR': stop at the first+  -- success, neither repeating nor descending below it.+  | InnerMost Step+  -- ^ Fused 'Clash.Rewrite.Combinators.innerMost': bottom-up; when the step+  -- fires, re-traverse the result until the innermost fixpoint is reached.+  | Pass String Name+  -- ^ A whole-term pass: @apply \<name\> \<rewrite\>@, for transformations+  -- that traverse the term themselves (@makeANF@, @etaExpansionTL@, …).+  | CallStrategy Name+  -- ^ Reference to another compiled strategy binding.+  | Seq Strat Strat            -- ^ '>->'+  | DeepSeqS Strat Strat       -- ^ '>-!->'+  | OnChange Strat Strat       -- ^ '!->'+  | OnNoChange Strat Strat     -- ^ '>-!'+  | Repeat Strat               -- ^ 'repeatR'+  deriving (Eq, Show)++-- | Things that can be used where a 'Step' is expected; a bare+-- 'Transformation' lifts to a singleton 'chain'.+class ToStep s where+  toStep :: s -> Step++instance ToStep Step where+  toStep = id++instance ToStep Transformation where+  toStep = one++-- | An ordered chain of transformations, dispatched per constructor. See+-- 'Chain'.+chain :: [Transformation] -> Step+chain = Chain++-- | A singleton 'chain', for use as an operand of the node-level operators.+one :: Transformation -> Step+one = Chain . pure++-- | Embed a whole strategy as a single node action.+nested :: Strat -> Step+nested = EmbedS++topdown, bottomup, topdownFix, topdownSuc, innerMost :: ToStep s => s -> Strat+topdown    = TopDown . toStep+bottomup   = BottomUp . toStep+topdownFix = TopDownFix . toStep+topdownSuc = TopDownSuc . toStep+innerMost  = InnerMost . toStep++-- | A whole-term pass, run as @apply \<name\> \<rewrite\>@.+pass :: String -> Name -> Strat+pass = Pass++-- | Reference another compiled strategy by the name of its binding.+callStrategy :: Name -> Strat+callStrategy = CallStrategy++-- | Keep applying a strategy until it no longer fires.+repeatR :: Strat -> Strat+repeatR = Repeat++infixr 6 >->+infixr 5 !->+infixr 5 >-!++-- | The combinators shared by both DSL layers. Fixities match+-- "Clash.Rewrite.Combinators"; a strategy spec module should import only+-- this module, so the names are unambiguous there.+class Strategic a where+  -- | Apply two strategies in succession.+  (>->) :: a -> a -> a+  -- | Only apply the second strategy if the first one succeeds.+  (!->) :: a -> a -> a+  -- | Only apply the second strategy if the first one fails.+  (>-!) :: a -> a -> a++instance Strategic Strat where+  (>->) = Seq+  (!->) = OnChange+  (>-!) = OnNoChange++instance Strategic Step where+  (>->) = SeqS+  (!->) = OnChangeS+  (>-!) = OnNoChangeS++infixr 6 >-!->++-- | Apply two strategies in succession, with a @deepseq@ of the term in+-- between. Strategy layer only.+(>-!->) :: Strat -> Strat -> Strat+(>-!->) = DeepSeqS
+ src/Clash/Rewrite/StrategyDSL/TH.hs view
@@ -0,0 +1,695 @@+{-|+  Copyright  :  (C) 2026, QBayLogic B.V.+  License    :  BSD2 (see the file LICENSE)+  Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>++  Compile a "Clash.Rewrite.StrategyDSL" strategy into executable dispatch+  code. 'compileStrategy' produces the fused fast path: one constructor match+  per node drives both the dispatch of the node program and the descent into+  the node's children.+-}++{-# LANGUAGE DisambiguateRecordFields #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NoFieldSelectors #-}+{-# LANGUAGE OverloadedRecordDot #-}+{-# LANGUAGE TemplateHaskellQuotes #-}++module Clash.Rewrite.StrategyDSL.TH+  ( compileStrategy+  , compileStrategyReference+  , dispatchQ+  , asRewriteQ+  ) where++import Data.Char (isAlphaNum)+import Data.Foldable (traverse_)+import Data.List (tails)+import Language.Haskell.TH hiding (Prim)++import Clash.Core.Term+  (Bind (..), CoreContext (..), Term (..), bindToList, patIds, primArg)+import Clash.Core.VarEnv (extendInScopeSet, extendInScopeSetList)+import Clash.Rewrite.StrategyDSL+  ( Constructor (..), Step (..), Strat (..), Transformation (..)+  , TransformationWorker (..)+  )+import Clash.Rewrite.Types (TransformContext (..))+import Clash.Rewrite.Util (apply, applyWith)++import qualified Clash.Rewrite.Combinators as Comb+import qualified Control.Monad as Monad+import qualified Control.Monad.Writer as Writer+import qualified Data.Monoid as Monoid++-- | The term constructor belonging to a 'Constructor'.+constructorName :: Constructor -> Name+constructorName con = case con of+  CVar -> 'Var+  CData -> 'Data+  CLiteral -> 'Literal+  CPrim -> 'Prim+  CLam -> 'Lam+  CTyLam -> 'TyLam+  CApp -> 'App+  CTyApp -> 'TyApp+  CLet -> 'Let+  CCase -> 'Case+  CCast -> 'Cast+  CTick -> 'Tick++-- | Binder hints for a constructor's fields. Underscore-prefixed because not+-- every generated arm uses every field.+constructorFieldHints :: Constructor -> [String]+constructorFieldHints con = case con of+  CVar -> ["_i"]+  CData -> ["_dc"]+  CLiteral -> ["_lit"]+  CPrim -> ["_p"]+  CLam -> ["_v", "_e"]+  CTyLam -> ["_tv", "_e"]+  CApp -> ["_fun", "_arg"]+  CTyApp -> ["_fun", "_argTy"]+  CLet -> ["_bnd", "_body"]+  CCase -> ["_subj", "_altsTy", "_alts"]+  CCast -> ["_e", "_fromTy", "_toTy"]+  CTick -> ["_tick", "_e"]++constructorFieldNames :: Constructor -> Q [Name]+constructorFieldNames = traverse newName . constructorFieldHints++allConstructors :: [Constructor]+allConstructors = [minBound .. maxBound]++-- | Constructors whose nodes have no subterms to descend into.+isLeafConstructor :: Constructor -> Bool+isLeafConstructor con = con `elem` [CVar, CData, CLiteral, CPrim]++-- | How a bucket member is invoked once the constructor has matched.+data Invoke+  = InvokeFields Name -- ^ worker applied to ctx, node, and the node's fields+  | InvokeNode Name   -- ^ worker applied to ctx and the node only++-- | The member's invocation at this constructor, if it is in the+-- constructor's bucket.+invokeAt :: Constructor -> Transformation -> Maybe Invoke+invokeAt con transformation = go transformation.workers+ where+  go [] = Nothing+  go (FieldWorker con' worker : rest)+    | con' == con = Just (InvokeFields worker)+    | otherwise = go rest+  go (Worker con' worker : rest)+    | con' == con = Just (InvokeNode worker)+    | otherwise = go rest+  go (AnyWorker worker : _) = Just (InvokeNode worker)++invokeE :: Invoke -> Q Exp -> Q Exp -> [Q Exp] -> Q Exp+invokeE (InvokeFields worker) ctxE nodeE fieldEs =+  foldl appE (varE worker) (ctxE : nodeE : fieldEs)+invokeE (InvokeNode worker) ctxE nodeE _fieldEs =+  [| $(varE worker) $ctxE $nodeE |]++validateChain :: [Transformation] -> Q ()+validateChain members = do+  Monad.when (null members) (fail "compileStrategy: empty chain")+  case [name | name : rest <- tails (map (.name) members), name `elem` rest] of+    name : _ ->+      fail ("compileStrategy: duplicate transformation name in one chain: "+            <> show name <> " (alias one occurrence with 'named')")+    [] -> pure ()+  traverse_ validateTransformation members++-- | A transformation's worker table must be non-empty, register at most one+-- worker per constructor, and not mix 'AnyWorker' with per-constructor+-- workers: a transformation either fires at any constructor or at specific+-- ones, never both.+validateTransformation :: Transformation -> Q ()+validateTransformation transformation+  | null workers = failWith "declares no workers"+  | any isAnyWorker workers, any (not . isAnyWorker) workers+  = failWith "mixes AnyWorker with per-constructor workers"+  | length (filter isAnyWorker workers) > 1 = failWith "has a duplicate AnyWorker"+  | con : _ <- duplicateConstructors = failWith ("has two workers for " <> show con)+  | otherwise = pure ()+ where+  workers = transformation.workers++  failWith reason =+    fail ("compileStrategy: transformation " <> show transformation.name+          <> " " <> reason)++  isAnyWorker AnyWorker{} = True+  isAnyWorker _ = False++  duplicateConstructors =+    [ con+    | con : rest <- tails [c | Just c <- map workerConstructor workers]+    , con `elem` rest+    ]++  workerConstructor (FieldWorker con _) = Just con+  workerConstructor (Worker con _) = Just con+  workerConstructor (AnyWorker _) = Nothing++-- | Bind the result and change flag of an action:+-- @do { (t, w) <- Writer.listen action; \<continue t (getAny w)\> }@+withListen :: Q Exp -> (Q Exp -> Q Exp -> Q Exp) -> Q Exp+withListen action continue = do+  t <- newName "t"+  w <- newName "w"+  doE+    [ bindS (tupP [varP t, varP w]) [| Writer.listen $action |]+    , noBindS (continue (varE t) [| Monoid.getAny $(varE w) |])+    ]++-- | Bind an expression so a continuation can use it more than once.+bindTo :: String -> Q Exp -> (Q Exp -> Q Exp) -> Q Exp+bindTo hint bound continue = do+  x <- newName hint+  letE [valD (varP x) (normalB bound) []] (continue (varE x))++-- | A fresh name for a generated let-binding, derived from a transformation+-- name. Underscore-prefixed: not every generated binding ends up used.+freshBinding :: String -> Q Name+freshBinding hint = newName ('_' : map sanitize hint)+ where+  sanitize c = if isAlphaNum c then c else '_'++-- | @\\ctx tm -> case tm of { \<arm per constructor with a program\>;+-- _ -> pure tm }@+-- The wildcard is omitted when every constructor has an arm.+nodeCaseExp+  :: (Constructor -> Maybe (Q Exp -> Q Exp -> [Q Exp] -> Q Exp)) -> Q Exp+nodeCaseExp armFor = do+  ctx <- newName "ctx"+  tm <- newName "tm"+  let arms =+        [ do fieldNames <- constructorFieldNames con+             match (conP (constructorName con) (map varP fieldNames))+                   (normalB (armBody (varE ctx) (varE tm) (map varE fieldNames)))+                   []+        | con <- allConstructors+        , Just armBody <- [armFor con]+        ]+      fallthrough+        | length arms == length allConstructors = []+        | otherwise = [match wildP (normalB [| pure $(varE tm) |]) []]+  lamE [varP ctx, varP tm] (caseE (varE tm) (arms <> fallthrough))++-- | A compiled node program. 'known' is the program entered with the+-- node's constructor statically known and its fields in scope; 'Nothing'+-- means the program is the identity at that constructor. 'dispatch'+-- references a generated binding running the program on a term of unknown+-- constructor.+data CompiledStep = CompiledStep+  { decs :: [Q Dec]+  , known :: Constructor -> Maybe (Q Exp -> Q Exp -> [Q Exp] -> Q Exp)+  , dispatch :: Q Exp+  }++compileStep :: Step -> Q CompiledStep+compileStep step = case step of+  Chain members -> compileChain members+  SeqS a b -> compileStep2 a b seqKnown seqDispatch+  OnChangeS a b -> compileStep2 a b onChangeKnown (combinatorDispatch [| (Comb.!->) |])+  OnNoChangeS a b -> compileStep2 a b onNoChangeKnown (combinatorDispatch [| (Comb.>-!) |])++  EmbedS strat -> do+    embedded <- freshBinding "embedded"+    let dec = valD (varP embedded) (normalB (compileStrategy strat)) []+    pure CompiledStep+      { decs = [dec]+      , known = \_con ->+          Just (\ctxE nodeE _fieldEs -> [| $(varE embedded) $ctxE $nodeE |])+      , dispatch = varE embedded+      }+ where+  -- These need signatures: without them the record selectors below are+  -- inferred as 'HasField' constraints rather than resolved against+  -- 'CompiledStep'.+  seqKnown, onChangeKnown, onNoChangeKnown+    :: CompiledStep -> CompiledStep -> Constructor+    -> Maybe (Q Exp -> Q Exp -> [Q Exp] -> Q Exp)+  seqDispatch :: CompiledStep -> CompiledStep -> Q Exp+  combinatorDispatch :: Q Exp -> CompiledStep -> CompiledStep -> Q Exp+  compileStep2+    :: Step -> Step+    -> (CompiledStep -> CompiledStep -> Constructor+        -> Maybe (Q Exp -> Q Exp -> [Q Exp] -> Q Exp))+    -> (CompiledStep -> CompiledStep -> Q Exp)+    -> Q CompiledStep++  seqKnown ca cb con = case (ca.known con, cb.known con) of+    (Nothing, Nothing) -> Nothing+    (Nothing, Just kb) -> Just kb+    (Just ka, Nothing) -> Just $ \ctxE nodeE fieldEs ->+      withListen (ka ctxE nodeE fieldEs) $ \tE changedE ->+        condE changedE [| $(cb.dispatch) $ctxE $tE |] [| pure $tE |]+    (Just ka, Just kb) -> Just $ \ctxE nodeE fieldEs ->+      withListen (ka ctxE nodeE fieldEs) $ \tE changedE ->+        -- When the left side did not signal change the term is untouched,+        -- so the right side can still run on the statically matched fields.+        condE changedE [| $(cb.dispatch) $ctxE $tE |] (kb ctxE tE fieldEs)++  seqDispatch ca cb =+    [| \ctx tm -> $(ca.dispatch) ctx tm >>= $(cb.dispatch) ctx |]++  onChangeKnown ca cb con = case ca.known con of+    Nothing -> Nothing+    Just ka -> Just $ \ctxE nodeE fieldEs ->+      withListen (ka ctxE nodeE fieldEs) $ \tE changedE ->+        condE changedE [| $(cb.dispatch) $ctxE $tE |] [| pure $tE |]++  onNoChangeKnown ca cb con = case (ca.known con, cb.known con) of+    (Nothing, kb) -> kb+    (Just ka, Nothing) -> Just ka+    (Just ka, Just kb) -> Just $ \ctxE nodeE fieldEs ->+      withListen (ka ctxE nodeE fieldEs) $ \tE changedE ->+        condE changedE [| pure $tE |] (kb ctxE tE fieldEs)++  combinatorDispatch op ca cb = [| $op $(ca.dispatch) $(cb.dispatch) |]++  compileStep2 a b mkKnown mkDispatch = do+    ca <- compileStep a+    cb <- compileStep b+    dispatch <- freshBinding "dispatch"+    let dispatchDec = valD (varP dispatch) (normalB (mkDispatch ca cb)) []+    pure CompiledStep+      { decs = ca.decs <> cb.decs <> [dispatchDec]+      , known = mkKnown ca cb+      , dispatch = varE dispatch+      }++compileChain :: [Transformation] -> Q CompiledStep+compileChain members = do+  validateChain members+  guardNames <- traverse (\member -> freshBinding ("g_" <> member.name)) members+  let guardDecs = zipWith memberGuardDec guardNames members+  dispatch <- freshBinding "dispatch"+  let -- The constructor's bucket, each member paired with the guards of all+      -- members after it in the chain (the member's guarded suffix).+      bucketAt con =+        [ (member, invoke, map snd rest)+        | (member, _guardName) : rest <- tails (zip members guardNames)+        , Just invoke <- [invokeAt con member]+        ]+      known con = case bucketAt con of+        [] -> Nothing+        bucket -> Just (chainArm bucket)+      dispatchDec = valD (varP dispatch) (normalB (nodeCaseExp known)) []+  pure CompiledStep+    { decs = guardDecs <> [dispatchDec]+    , known+    , dispatch = varE dispatch+    }++-- | A bucket entered with the constructor statically known: run the members+-- in order on the original fields; after the first change, hand the term to+-- the remaining chain members' guards.+chainArm+  :: [(Transformation, Invoke, [Name])]+  -> Q Exp -> Q Exp -> [Q Exp] -> Q Exp+chainArm bucket0 ctxE nodeE0 fieldEs = go nodeE0 bucket0+ where+  go :: Q Exp -> [(Transformation, Invoke, [Name])] -> Q Exp+  go nodeE [] = [| pure $nodeE |]+  go nodeE ((member, invoke, suffixGuards) : rest) = do+    t <- newName "t"+    changed <- newName "changed"+    doE+      [ bindS (tupP [varP t, varP changed])+          [| applyWith $(stringE member.name) $ctxE $nodeE+               $(invokeE invoke ctxE nodeE fieldEs) |]+      , noBindS $ condE (varE changed)+          (guardedSuffix suffixGuards ctxE (varE t))+          (go (varE t) rest)+      ]++-- | @g1 ctx t >>= g2 ctx >>= …@: offer the term to each remaining chain+-- member through its full worker table.+guardedSuffix :: [Name] -> Q Exp -> Q Exp -> Q Exp+guardedSuffix [] _ctxE nodeE = [| pure $nodeE |]+guardedSuffix (g : gs) ctxE nodeE =+  foldl (\acc g' -> [| $acc >>= $(varE g') $ctxE |])+        [| $(varE g) $ctxE $nodeE |]+        gs++-- | One member's guard: match the term against the member's full worker+-- table; run the member instrumented on a match, return the term untouched+-- (without instrumentation) otherwise.+memberGuardDec :: Name -> Transformation -> Q Dec+memberGuardDec guardName transformation =+  valD (varP guardName) (normalB (guardExp instrumented transformation)) []+ where+  instrumented invoke ctxE nodeE fieldEs =+    [| fmap fst (applyWith $(stringE transformation.name) $ctxE $nodeE+                   $(invokeE invoke ctxE nodeE fieldEs)) |]++-- | @\\ctx tm -> case tm of …@ over a transformation's worker table, with the+-- given wrapper around each invocation.+guardExp+  :: (Invoke -> Q Exp -> Q Exp -> [Q Exp] -> Q Exp)+  -> Transformation+  -> Q Exp+guardExp wrap transformation =+  nodeCaseExp $ \con -> wrap <$> invokeAt con transformation++{-+Note [NonRec erasure during descent]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+'Clash.Rewrite.Combinators.allR' matches let-expressions through the 'Letrec'+pattern synonym and rebuilds them with 'Rec' bindings, so any 'NonRec' let a+traversal descends into comes back as a 'Rec' let. The generated descent+replicates that behavior deliberately: preserving 'NonRec' is a real behavior+change (downstream code branches on 'Rec'/'NonRec', and netlist rendering+order can shift) that must be validated on its own, separately from this+dispatch machinery.+-}++-- | The one-level descent for one constructor, replicating+-- 'Clash.Rewrite.Combinators.allR' exactly: same 'CoreContext' pushes, same+-- 'InScopeSet' extensions, and the argument's context computed from the+-- already-rewritten function. The continuation receives the rebuilt node's+-- fields and the rebuilt node itself; descent preserves the constructor, so+-- the continuation may run a statically matched program on the result.+genDescend+  :: Constructor+  -> Q Exp            -- ^ recursion function @:: TransformContext -> Term -> m Term@+  -> (Q Exp, Q Exp)   -- ^ the context's InScopeSet and CoreContext stack+  -> Q Exp            -- ^ the node+  -> [Q Exp]          -- ^ the node's fields+  -> ([Q Exp] -> Q Exp -> Q Exp)  -- ^ continuation: rebuilt fields, rebuilt node+  -> Q Exp+genDescend con go (isE, cE) nodeE fieldEs continue = case (con, fieldEs) of+  (CVar, _) -> leaf+  (CData, _) -> leaf+  (CLiteral, _) -> leaf+  (CPrim, _) -> leaf++  (CLam, [v, e]) -> do+    e' <- newName "e'"+    doE+      [ bindS (varP e')+          [| $go (TransformContext (extendInScopeSet $isE $v) (LamBody $v : $cE)) $e |]+      , continueWith [v, varE e'] [| Lam $v $(varE e') |]+      ]++  (CTyLam, [tv, e]) -> do+    e' <- newName "e'"+    doE+      [ bindS (varP e')+          [| $go (TransformContext (extendInScopeSet $isE $tv) (TyLamBody $tv : $cE)) $e |]+      , continueWith [tv, varE e'] [| TyLam $tv $(varE e') |]+      ]++  (CApp, [fun, arg]) -> do+    fun' <- newName "fun'"+    arg' <- newName "arg'"+    doE+      [ bindS (varP fun') [| $go (TransformContext $isE (AppFun : $cE)) $fun |]+        -- The argument's context is computed from the already rewritten+        -- function, so the function has to be rewritten first.+      , bindS (varP arg')+          [| $go (TransformContext $isE (AppArg (primArg $(varE fun')) : $cE)) $arg |]+      , continueWith [varE fun', varE arg'] [| App $(varE fun') $(varE arg') |]+      ]++  (CTyApp, [fun, argTy]) -> do+    fun' <- newName "fun'"+    doE+      [ bindS (varP fun') [| $go (TransformContext $isE (TyAppC : $cE)) $fun |]+      , continueWith [varE fun', argTy] [| TyApp $(varE fun') $argTy |]+      ]++  (CLet, [bnd, body]) -> do+    -- See Note [NonRec erasure during descent]+    bs <- newName "bs"+    bndrs <- newName "bndrs"+    is' <- newName "is'"+    bs' <- newName "bs'"+    body' <- newName "body'"+    doE+      [ letS+          [ valD (varP bs) (normalB [| bindToList $bnd |]) []+          , valD (varP bndrs) (normalB [| map fst $(varE bs) |]) []+          , valD (varP is') (normalB [| extendInScopeSetList $isE $(varE bndrs) |]) []+          ]+      , bindS (varP bs')+          [| traverse+               (\(b, rhs) ->+                  fmap ((,) b)+                    ($go (TransformContext $(varE is')+                            (LetBinding b $(varE bndrs) : $cE))+                         rhs))+               $(varE bs) |]+      , bindS (varP body')+          [| $go (TransformContext $(varE is') (LetBody $(varE bs) : $cE)) $body |]+      , continueWith [[| Rec $(varE bs') |], varE body']+          [| Let (Rec $(varE bs')) $(varE body') |]+      ]++  (CCase, [subj, altsTy, alts]) -> do+    subj' <- newName "subj'"+    alts' <- newName "alts'"+    doE+      [ bindS (varP subj') [| $go (TransformContext $isE (CaseScrut : $cE)) $subj |]+      , bindS (varP alts')+          [| traverse+               (\(p, e) ->+                  let (tvs, ids) = patIds p+                      isAlt = extendInScopeSetList (extendInScopeSetList $isE tvs) ids+                  in fmap ((,) p) ($go (TransformContext isAlt (CaseAlt p : $cE)) e))+               $alts |]+      , continueWith [varE subj', altsTy, varE alts']+          [| Case $(varE subj') $altsTy $(varE alts') |]+      ]++  (CCast, [e, fromTy, toTy]) -> do+    e' <- newName "e'"+    doE+      [ bindS (varP e') [| $go (TransformContext $isE (CastBody : $cE)) $e |]+      , continueWith [varE e', fromTy, toTy] [| Cast $(varE e') $fromTy $toTy |]+      ]++  (CTick, [tick, e]) -> do+    e' <- newName "e'"+    doE+      [ bindS (varP e') [| $go (TransformContext $isE (TickC $tick : $cE)) $e |]+      , continueWith [tick, varE e'] [| Tick $tick $(varE e') |]+      ]++  _ -> fail ("genDescend: field count mismatch for " <> show con)+ where+  leaf = continue fieldEs nodeE+  continueWith fieldEs' rebuiltE = noBindS (continue fieldEs' rebuiltE)++-- | What a traversal does at one node: given the recursion function, the+-- node program for the matched constructor ('Nothing' when the program is the+-- identity there), the context, the node, its fields, and a descent builder,+-- produce the body of @go@'s clause for that constructor.+type NodeArm+  =  Q Exp                                  -- ^ the traversal's @go@+  -> Maybe (Q Exp -> Q Exp -> [Q Exp] -> Q Exp)+  -> Q Exp                                  -- ^ ctx+  -> Q Exp                                  -- ^ the node+  -> [Q Exp]                                -- ^ its fields+  -> (([Q Exp] -> Q Exp -> Q Exp) -> Q Exp) -- ^ descend with a continuation+  -> Q Exp++-- | Generate a fused traversal: a recursive @go@ whose single constructor+-- match drives both the node program and the descent. The recursion+-- structure of each traversal is pinned to its "Clash.Rewrite.Combinators"+-- counterpart, with the node program as @r@:+--+-- * 'TopDown': @'Comb.topdownR' r = 'Comb.repeatR' r '>->' 'Comb.allR' …@. On+--   change, re-enter @go@ at this node (which also re-matches the+--   constructor); otherwise descend. See Note [topdown repeatR] in+--   "Clash.Rewrite.Combinators".+-- * 'BottomUp': descend first, run the program once on the rebuilt node,+--   whose constructor is already known, so no re-match.+-- * 'TopDownSuc': run the program once; when it fired, stop, neither+--   repeating nor descending.+-- * 'InnerMost': bottom-up; when the program fires, re-enter @go@ on the+--   result until the innermost fixpoint is reached.+-- * 'TopDownFix': see 'genTopDownFix'.+genTraversal :: Strat -> Q Exp+genTraversal strat = case strat of+  TopDown step -> fused step $ \goE known ctxE tmE fieldEs descend ->+    case known of+      Nothing -> descend rebuildOnly+      Just ka ->+        withListen (ka ctxE tmE fieldEs) $ \tE changedE ->+          condE changedE [| $goE $ctxE $tE |] (descend rebuildOnly)++  TopDownSuc step -> fused step $ \_goE known ctxE tmE fieldEs descend ->+    case known of+      Nothing -> descend rebuildOnly+      Just ka ->+        withListen (ka ctxE tmE fieldEs) $ \tE changedE ->+          condE changedE [| pure $tE |] (descend rebuildOnly)++  BottomUp step -> fused step $ \_goE known ctxE _tmE _fieldEs descend ->+    descend $ \fieldEs' rebuiltE ->+      case known of+        Nothing -> [| pure $rebuiltE |]+        Just ka -> bindTo "tm'" rebuiltE $ \tmE' -> ka ctxE tmE' fieldEs'++  InnerMost step -> fused step $ \goE known ctxE _tmE _fieldEs descend ->+    descend $ \fieldEs' rebuiltE ->+      case known of+        Nothing -> [| pure $rebuiltE |]+        Just ka -> bindTo "tm'" rebuiltE $ \tmE' ->+          withListen (ka ctxE tmE' fieldEs') $ \tE changedE ->+            condE changedE [| $goE $ctxE $tE |] [| pure $tE |]++  TopDownFix step -> do+    cs <- compileStep step+    genTopDownFix cs++  _ -> fail "genTraversal: not a traversal"+ where+  rebuildOnly :: [Q Exp] -> Q Exp -> Q Exp+  rebuildOnly _fieldEs' rebuiltE = [| pure $rebuiltE |]++  fused :: Step -> NodeArm -> Q Exp+  fused step mkArm = do+    cs <- compileStep step+    go <- newName "go"+    clauses <- traverse (goClause cs (varE go) mkArm) allConstructors+    letE (cs.decs <> [pure (FunD go clauses)]) (varE go)++  goClause :: CompiledStep -> Q Exp -> NodeArm -> Constructor -> Q Clause+  goClause cs goE mkArm con = do+    ctx <- newName "_ctx"+    is <- newName "_is"+    c <- newName "_c"+    tm <- newName "_tm"+    fieldNames <- constructorFieldNames con+    let fieldEs = map varE fieldNames+        descend = genDescend con goE (varE is, varE c) (varE tm) fieldEs+    body <- mkArm goE (cs.known con) (varE ctx) (varE tm) fieldEs descend+    pats <- sequence+      [ asP ctx (conP 'TransformContext [varP is, varP c])+      , asP tm (conP (constructorName con) (map varP fieldNames))+      ]+    pure (Clause pats (NormalB body) [])++-- | 'Comb.topdownFixR' with the node program as @r@: a local @settle@+-- (@'Comb.repeatR' r@) plus the tryParent\/childChanged\/parentChanged loop+-- from Note [topdownFixR] in "Clash.Rewrite.Combinators", over a generated+-- 'Comb.allR' replica.+genTopDownFix :: CompiledStep -> Q Exp+genTopDownFix cs = do+  goFix <- newName "goFix"+  settle <- newName "settle"+  descendD <- newName "descendD"+  descendClauses <- traverse descendClause allConstructors+  let settleDec = valD (varP settle) (normalB+        [| let loop ctx tm = do+                 (t1, w) <- Writer.listen ($(cs.dispatch) ctx tm)+                 if Monoid.getAny w then loop ctx t1 else pure t1+           in loop |]) []+      descendDec = pure (FunD descendD descendClauses)+      goFixDec = valD (varP goFix) (normalB+        [| let loop tryParent ctx tm = do+                 t1 <- if tryParent then $(varE settle) ctx tm else pure tm+                 (t2, w1) <- Writer.listen+                   ($(varE descendD) (loop True) ctx t1)+                 if Monoid.getAny w1+                   then do+                     (t3, w2) <- Writer.listen ($(varE settle) ctx t2)+                     if Monoid.getAny w2+                       then loop False ctx t3+                       else pure t3+                   else pure t2+           in loop |]) []+  letE (cs.decs <> [settleDec, descendDec, goFixDec]) [| $(varE goFix) True |]+ where+  descendClause con = do+    -- Leaf clauses never call the recursion argument; the underscore hint+    -- keeps -Wunused-matches quiet there.+    rec' <- newName (if isLeafConstructor con then "_rec" else "rec'")+    is <- newName "_is"+    c <- newName "_c"+    tm <- newName "_tm"+    fieldNames <- constructorFieldNames con+    body <- genDescend con (varE rec') (varE is, varE c) (varE tm)+              (map varE fieldNames) (\_fieldEs' rebuiltE -> [| pure $rebuiltE |])+    pats <- sequence+      [ varP rec'+      , conP 'TransformContext [varP is, varP c]+      , asP tm (conP (constructorName con) (map varP fieldNames))+      ]+    pure (Clause pats (NormalB body) [])++-- | Compile a strategy into its fused dispatch code. The result is an+-- expression of type @Rewrite extra@, with @extra@ fixed by the workers the+-- spec references.+compileStrategy :: Strat -> Q Exp+compileStrategy strat = case strat of+  Seq a b -> [| $(compileStrategy a) Comb.>-> $(compileStrategy b) |]+  DeepSeqS a b -> [| $(compileStrategy a) Comb.>-!-> $(compileStrategy b) |]+  OnChange a b -> [| $(compileStrategy a) Comb.!-> $(compileStrategy b) |]+  OnNoChange a b -> [| $(compileStrategy a) Comb.>-! $(compileStrategy b) |]+  Repeat a -> [| Comb.repeatR $(compileStrategy a) |]+  Pass name rewriteName -> [| apply $(stringE name) $(varE rewriteName) |]+  CallStrategy name -> varE name+  TopDown{} -> genTraversal strat+  BottomUp{} -> genTraversal strat+  TopDownFix{} -> genTraversal strat+  TopDownSuc{} -> genTraversal strat+  InnerMost{} -> genTraversal strat++-- | Compile a strategy into its unfused reference: the same transformations,+-- run as a plain @apply@ chain through the "Clash.Rewrite.Combinators"+-- traversals. Agrees with 'compileStrategy' on results, transformation+-- counts, and change flags.+compileStrategyReference :: Strat -> Q Exp+compileStrategyReference = goStrat+ where+  goStrat strat = case strat of+    Seq a b -> [| $(goStrat a) Comb.>-> $(goStrat b) |]+    DeepSeqS a b -> [| $(goStrat a) Comb.>-!-> $(goStrat b) |]+    OnChange a b -> [| $(goStrat a) Comb.!-> $(goStrat b) |]+    OnNoChange a b -> [| $(goStrat a) Comb.>-! $(goStrat b) |]+    Repeat a -> [| Comb.repeatR $(goStrat a) |]+    Pass name rewriteName -> [| apply $(stringE name) $(varE rewriteName) |]+    CallStrategy name -> varE name+    TopDown step -> [| Comb.topdownR $(goStep step) |]+    BottomUp step -> [| Comb.bottomupR $(goStep step) |]+    TopDownFix step -> [| Comb.topdownFixR $(goStep step) |]+    TopDownSuc step -> [| Comb.topdownSucR $(goStep step) |]+    InnerMost step -> [| Comb.innerMost $(goStep step) |]++  goStep step = case step of+    SeqS a b -> [| $(goStep a) Comb.>-> $(goStep b) |]+    OnChangeS a b -> [| $(goStep a) Comb.!-> $(goStep b) |]+    OnNoChangeS a b -> [| $(goStep a) Comb.>-! $(goStep b) |]+    EmbedS strat -> goStrat strat+    Chain members -> do+      validateChain members+      -- The sequential apply chain over all members, each guarded on its full+      -- worker table.+      foldr1 (\x y -> [| $x Comb.>-> $y |]) (map memberApplyE members)++  memberApplyE member =+    [| apply $(stringE member.name) $(asRewriteQ member) |]++-- | A node program as a plain rewrite: match the constructor once and run+-- that constructor's program, without traversing. For composing a 'Step'+-- with plain combinators, and for testing chains in isolation.+dispatchQ :: Step -> Q Exp+dispatchQ step = do+  cs <- compileStep step+  letE cs.decs cs.dispatch++-- | A transformation as a plain uninstrumented rewrite: match the term+-- against the worker table, run the worker on a match, return the term+-- untouched otherwise. Splice this where a transformation is invoked from+-- inside another transformation (any instrumentation is the caller's).+asRewriteQ :: Transformation -> Q Exp+asRewriteQ transformation = do+  validateTransformation transformation+  guardExp invokeE transformation
src/Clash/Rewrite/Types.hs view
@@ -22,7 +22,7 @@ module Clash.Rewrite.Types where  import Control.DeepSeq                       (NFData)-import Control.Lens                          (Lens', use, (.=))+import Control.Lens                          (use, (.=)) import qualified Control.Lens as Lens import Control.Monad.Fix                     (MonadFix) import Control.Monad.IO.Class                (MonadIO)@@ -50,7 +50,6 @@ import Clash.Driver.Types        (ClashEnv(..), ClashOpts(..), BindingMap, DebugOpts) import Clash.Netlist.Types       (FilteredHWType, HWMap) import Clash.Primitives.Types    (CompiledPrimMap)-import Clash.Rewrite.WorkFree    (isWorkFree) import Clash.Util import Clash.Util.Supply         (Supply, freshId) @@ -215,9 +214,11 @@ type Rewrite extra = Transform (RewriteMonad extra)  -- Moved into Clash.Rewrite.WorkFree-{-# SPECIALIZE isWorkFree-      :: Lens' (RewriteState extra) (VarEnv Bool)-      -> BindingMap-      -> Term-      -> RewriteMonad extra Bool-  #-}++-- TODO:+-- {-# SPECIALIZE isWorkFree+--       :: Lens' (RewriteState extra) (VarEnv Bool)+--       -> BindingMap+--       -> Term+--       -> RewriteMonad extra Bool+--   #-}
src/Clash/Rewrite/Util.hs view
@@ -152,11 +152,26 @@   -> Rewrite extra   -- ^ Transformation to be applied   -> Rewrite extra-apply = \s rewrite ctx expr0 -> do+apply = \s rewrite ctx expr0 -> fst <$> applyWith s ctx expr0 (rewrite ctx expr0)+{-# INLINE apply #-}++-- | The instrumentation core of 'apply' (debug tracing, transformation+-- counter, rewrite history, invariant checks) around an already-applied+-- transformation action. Also returns whether the action signaled change.+applyWith+  :: String+  -- ^ Name of the transformation+  -> TransformContext+  -> Term+  -- ^ The node the transformation was offered+  -> RewriteMonad extra Term+  -- ^ The transformation, applied to that node+  -> RewriteMonad extra (Term, Bool)+applyWith = \s ctx expr0 action -> do   opts <- Lens.view debugOpts   traceIf (hasDebugInfo TryName s opts) ("Trying: " <> s) (pure ()) -  (!expr1,anyChanged) <- Writer.listen (rewrite ctx expr0)+  (!expr1,anyChanged) <- Writer.listen action   let hasChanged = Monoid.getAny anyChanged   Monad.when hasChanged (transformCounter += 1) @@ -176,9 +191,9 @@           }    if isDebugging opts-    then applyDebug ctx s expr0 hasChanged expr1-    else return expr1-{-# INLINE apply #-}+    then (, hasChanged) <$> applyDebug ctx s expr0 hasChanged expr1+    else return (expr1, hasChanged)+{-# INLINE applyWith #-}  applyDebug   :: TransformContext@@ -376,12 +391,19 @@   let ki = inferCoreKindOf tcm ty   return (Right (mkTyVar ki (coerce name'))) --- | Inline the binders in a let-binding that have a certain property+-- | Inline the binders in a let-binding that have a certain property. This is+-- a 'Clash.Rewrite.StrategyDSL.onLet' handler: it receives the let-expression+-- itself, its bindings, and its body. inlineBinders   :: (Term -> LetBinding -> RewriteMonad extra Bool)   -- ^ Property test-  -> Rewrite extra-inlineBinders condition (TransformContext inScope0 _) expr@(Let (NonRec i x) res)+  -> TransformContext+  -> Term+  -- ^ The let-expression+  -> Bind Term+  -> Term+  -> RewriteMonad extra Term+inlineBinders condition (TransformContext inScope0 _) expr (NonRec i x) res   -- Substitution would be a no-op for a binder that does not occur in the   -- body, so the (potentially expensive) property test can be skipped.   | notElemFreeVars i res = changed res@@ -395,7 +417,7 @@       else         return expr -inlineBinders condition (TransformContext inScope0 _) expr@(Let (Rec xes) res) = do+inlineBinders condition (TransformContext inScope0 _) expr (Rec xes) res = do   (toInline,toKeep) <- partitionM (condition expr) xes   case toInline of     [] -> return expr@@ -407,8 +429,6 @@         []   -> changed res1         xes1 -> changed (Letrec xes1 res1) -inlineBinders _ _ e = return e- -- | Determine whether a binder is a join-point created for a complex case -- expression. --@@ -551,6 +571,9 @@                nm == "Clash.Sized.Internal.Signed.fromInteger#" ||                nm == "Clash.Sized.Internal.Unsigned.fromInteger#" +-- | Inline or lift the binders in a let-binding that have a certain property.+-- This is a 'Clash.Rewrite.StrategyDSL.onLet' handler: it receives the+-- let-expression itself, its bindings, and its body. inlineOrLiftBinders   :: (LetBinding -> RewriteMonad extra Bool)   -- ^ Property test@@ -559,8 +582,13 @@   --   -- * True: inline   -- * False: lift-  -> Rewrite extra-inlineOrLiftBinders condition inlineOrLift (TransformContext inScope0 _) e@(Letrec bndrs body) = do+  -> TransformContext+  -> Term+  -- ^ The let-expression+  -> Bind Term+  -> Term+  -> RewriteMonad extra Term+inlineOrLiftBinders condition inlineOrLift (TransformContext inScope0 _) e (bindToList -> bndrs) body = do   (toReplace,toKeep) <- partitionM condition bndrs   case toReplace of     [] -> return e@@ -580,8 +608,6 @@         [] -> changed body2         _  -> changed (Letrec toKeep2 body2) -inlineOrLiftBinders _ _ _ e = return e- -- | Create a global function for a Let-binding and return a Let-binding where -- the RHS is a reference to the new global function applied to the free -- variables of the original RHS@@ -821,7 +847,7 @@     -- † https://github.com/clash-lang/clash-compiler/pull/1354#issuecomment-635430374     -- ‡ https://www.microsoft.com/en-us/research/wp-content/uploads/2016/07/supercomp-by-eval.pdf     bs <- Lens.use bindings-    inlineBinders (inlineTest bs) ctx0 (Letrec bndrs e1) >>= \case+    inlineBinders (inlineTest bs) ctx0 (Letrec bndrs e1) (Rec bndrs) e1 >>= \case       e2@(Let bnders1 e3) ->         pure (fromMaybe e2 (removeUnusedBinders bnders1 e3))       e2 ->
src/Clash/Unique.hs view
@@ -11,7 +11,11 @@  module Clash.Unique   ( Unique+#if __GLASGOW_HASKELL__ >= 914+  , data Unique#+#else   , pattern Unique#+#endif   , Unique#   , Uniquable (..)   , fromGhcUnique
src/Clash/Util/Interpolate.hs view
@@ -241,7 +241,7 @@   }   where     err name =-      error ("Clash.Util.Interpolate.i: This QuasiQuoter can not be used as a "+      error ("Clash.Util.Interpolate.i: This QuasiQuoter cannot be used as a "            ++ name ++ "!")      toExp:: [Node] -> Q Exp
src/Clash/Util/Supply.hs view
@@ -42,7 +42,11 @@ import Data.IORef import GHC.IO (unsafeDupablePerformIO, unsafePerformIO) +#if __GLASGOW_HASKELL__ >= 914+import Clash.Unique (Unique, Unique#, data Unique#)+#else import Clash.Unique (Unique, Unique#, pattern Unique#)+#endif  infixr 5 :- data Stream a = a :- Stream a
src/GHC/BasicTypes/Extra.hs view
@@ -11,7 +11,9 @@ module GHC.BasicTypes.Extra where  import GHC.Types.Basic+#if !MIN_VERSION_ghc(9,14,0) import Control.DeepSeq+#endif import Data.Binary import GHC.Generics @@ -24,7 +26,9 @@ #endif  deriving instance Generic InlineSpec+#if !MIN_VERSION_ghc(9,14,0) instance NFData InlineSpec+#endif instance Binary InlineSpec  #if MIN_VERSION_ghc(9,8,0)
tests/Clash/Tests/Normalize/Transformations.hs view
@@ -7,18 +7,22 @@  module Clash.Tests.Normalize.Transformations where +import Data.Default (def) import Data.Maybe (fromMaybe)  import Clash.Normalize.Transformations (inlineBndrsCleanup)+import Clash.Normalize.Transformations.Specialize (appPropWorker) import Clash.Core.VarEnv   (mkInScopeSet, mkVarSet, mkVarEnv, emptyVarEnv) import Clash.Core.FreeVars (countFreeOccurances)+import Clash.Core.Pretty (showPpr) import Clash.Core.Term  import Test.Tasty import Test.Tasty.HUnit -import Test.Clash.Rewrite (parseToTermQQ, parseToTerm)+import Test.Clash.Rewrite+  (parseToTermQQ, parseToTerm, runSingleTransformation)  t1337a :: Term t1337a = fromMaybe (error "failed to build term") $ do@@ -124,6 +128,21 @@     result_1 |] +-- | @(\f -> f) (\k x -> k) x y@ reduces to the free variable @x@. The first+-- argument binds @x_2@, which is also free in the second argument. 'appProp'+-- substitutes work-free arguments using 'unsafeSubstTm', which does not avoid+-- capture: after substituting the first argument for @f_1@, that argument is+-- the head of the application, and substituting @x_2@ for @k_4@ puts it under+-- the binder @x_2@.+appPropCapture :: IO Term+appPropCapture = do+  Var x <- pure (parseToTerm "x_2 :: Int")+  Var y <- pure (parseToTerm "y_5 :: Int")+  let is = mkInScopeSet (mkVarSet [x, y])+  runSingleTransformation def def is appPropWorker [parseToTermQQ|+    (\(f_1 :: Int) -> f_1) (\(k_4 :: Int) (x_2 :: Int) -> k_4) (x_2 :: Int) (y_5 :: Int)+  |]+ tests :: TestTree tests =   testGroup@@ -131,4 +150,8 @@     [ testCase "T1337a" $ t1337a_result @=? t1337a     , testCase "T1337b" $ t1337b_result @=? t1337b     , testCase "T1337c" $ t1337c_result @=? t1337c+    , testCase "appProp does not capture free variables" $ do+        actual <- appPropCapture+        assertBool ("Expected the free variable x, but got: " <> showPpr actual)+          (actual == parseToTerm "x_2 :: Int")     ]
+ tests/Clash/Tests/Rewrite/StrategyDSL.hs view
@@ -0,0 +1,296 @@+{-|+  Copyright  :  (C) 2026, QBayLogic B.V.+  License    :  BSD2 (see the file LICENSE)+  Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>++  Tests for "Clash.Rewrite.StrategyDSL.TH": the chain semantics of compiled+  dispatch (bucket order, the guarded suffix after a mid-chain constructor+  change) and the equivalence of every compiled strategy with its unfused+  reference (both generated from the same spec) and with hand-written+  'Clash.Rewrite.Combinators' compositions.+-}++{-# LANGUAGE DisambiguateRecordFields #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NoFieldSelectors #-}+{-# LANGUAGE OverloadedRecordDot #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}++--{-# OPTIONS_GHC -ddump-splices #-}++module Clash.Tests.Rewrite.StrategyDSL (tests) where++import Data.Default (def)++import Clash.Core.Literal (Literal (..))+import Clash.Core.Term (Bind (..), Term (..))+import Clash.Core.VarEnv (emptyInScopeSet)+import Clash.Rewrite.StrategyDSL+import Clash.Rewrite.StrategyDSL.TH+import Clash.Rewrite.Types (Rewrite, RewriteState (..), TransformContext (..), runR)+import Clash.Rewrite.Util (apply)+import Clash.Tests.Rewrite.StrategyDSL.Stubs+import Test.Clash.Rewrite ()++import Test.Tasty+import Test.Tasty.HUnit++import qualified Clash.Rewrite.Combinators as Comb+import qualified Data.List as List+import qualified Data.Monoid as Monoid++-- * Running rewrites in a default environment++emptyContext :: TransformContext+emptyContext = TransformContext emptyInScopeSet []++-- | Run a rewrite on a term in the default (silent) environment, returning+-- the result term, the transformation counter, and the change flag.+runRewriteOn :: Rewrite () -> Term -> IO (Term, Word, Bool)+runRewriteOn rewrite term = do+  (result, state, anyChanged) <- runR (rewrite emptyContext term) def def+  pure (result, _transformCounter state, Monoid.getAny anyChanged)++-- | Assert that two rewrites agree on a term: same result (syntactically),+-- same transformation count, same change flag.+assertAgree :: Rewrite () -> Rewrite () -> Term -> Assertion+assertAgree candidate reference term = do+  (candidateTerm, candidateCount, candidateChanged) <- runRewriteOn candidate term+  (referenceTerm, referenceCount, referenceChanged) <- runRewriteOn reference term+  assertEqual "result" (show referenceTerm) (show candidateTerm)+  assertEqual "transformation count" referenceCount candidateCount+  assertEqual "change flag" referenceChanged candidateChanged++-- * Compiled strategies referenced by other compiled strategies++calleeFast :: Rewrite ()+calleeFast = $(compileStrategy (topdown literalStep))++calleeReference :: Rewrite ()+calleeReference = $(compileStrategyReference (topdown literalStep))++-- * Tests++tests :: TestTree+tests = testGroup "Clash.Tests.Rewrite.StrategyDSL"+  [ testGroup "singleton dispatch equals apply"+      [ testCase "Let transformation fires" $+          assertAgree+            $(dispatchQ (one inlineTrivialLet))+            (apply "inlineTrivialLet" inlineTrivialLetRewrite)+            (Let (NonRec (someId 0) (integer 5)) (Var (someId 0)))+      , testCase "Let transformation offered a non-Let node" $+          assertAgree+            $(dispatchQ (one inlineTrivialLet))+            (apply "inlineTrivialLet" inlineTrivialLetRewrite)+            simpleApplication+      , testCase "App transformation fires" $+          assertAgree+            $(dispatchQ (one collapseApplication))+            (apply "collapseApplication" collapseApplicationRewrite)+            simpleApplication+      , testCase "multi-constructor transformation, both constructors" $ do+          assertAgree+            $(dispatchQ (one incrementBoth))+            (apply "incrementBoth" incrementBothRewrite)+            simpleApplication+          assertAgree+            $(dispatchQ (one incrementBoth))+            (apply "incrementBoth" incrementBothRewrite)+            (integer 3)+      ]++  , testGroup "bucket chain semantics"+      [ testCase+          "guarded suffix: later same-bucket member fires on changed constructor"+          $ do+          -- collapseApplication turns @f 3@ into @3@; incrementBoth is later+          -- in the App bucket and must still fire on the literal, through its+          -- own Literal worker.+          (result, count, changedFlag) <- runRewriteOn+            $(dispatchQ (chain [collapseApplication, incrementBoth]))+            simpleApplication+          assertEqual "result" (show (integer 4)) (show result)+          assertEqual "count" 2 count+          assertEqual "changed" True changedFlag+      , testCase "guarded suffix includes members of other buckets" $ do+          -- incrementOdd is registered for Literal only, so it is not in the+          -- App bucket. It must still be offered the literal that+          -- collapseApplication left behind, like a plain apply chain would.+          (result, count, _) <- runRewriteOn+            $(dispatchQ (chain [collapseApplication, incrementOdd]))+            simpleApplication+          assertEqual "result" (show (integer 4)) (show result)+          assertEqual "count" 2 count+      , testCase "earlier members do not rerun after a change" $ do+          -- incrementBoth (App worker) fires first, turning @f 3@ into @f 4@;+          -- collapseApplication is later in the App bucket and collapses to+          -- @4@. incrementBoth must not see the literal again.+          (result, count, _) <- runRewriteOn+            $(dispatchQ (chain [incrementBoth, collapseApplication]))+            simpleApplication+          assertEqual "result" (show (integer 4)) (show result)+          assertEqual "count" 2 count+      , testCase "no members for the node's constructor: untouched, no change" $ do+          (result, count, changedFlag) <- runRewriteOn+            $(dispatchQ (one inlineTrivialLet))+            simpleApplication+          assertEqual "result" (show simpleApplication) (show result)+          assertEqual "count" 0 count+          assertEqual "changed" False changedFlag+      , testCase "anyConstructor member joins every bucket" $ do+          -- collapseApplication turns @f 3@ into @3@; incrementOddAny is+          -- constructor-agnostic, so it is in the App bucket too and fires on the+          -- literal through its own match.+          (result, count, _) <- runRewriteOn+            $(dispatchQ (chain [collapseApplication, incrementOddAny]))+            simpleApplication+          assertEqual "result" (show (integer 4)) (show result)+          assertEqual "count" 2 count+      ]++  , testGroup "compiled strategies equal their references" $+      let+        scenarios =+          [ ( "constructor-changing chain on nested term"+            , $(allTraversals constructorChangingStep)+            , nestedTerm+            )+          , ( "literal chain on nested term"+            , $(allTraversals literalStep)+            , nestedTerm+            )+          , ( "context probe on all constructors"+            , $(allTraversals contextProbeStep)+            , allConstructorsTerm+            )+          , ( "AppArg context tracks the rewritten function"+            , $(allTraversals appArgProbeStep)+            , appArgProbeTerm+            )+          , ( "no-op chain on all constructors"+            , $(allTraversals noOpStep)+            , allConstructorsTerm+            )+          , ( "anyConstructor member"+            , $(allTraversals anyWorkerStep)+            , nestedTerm+            )+          , ( "node-worker member"+            , $(allTraversals nodeWorkerStep)+            , nestedTerm+            )+          , ( "mid-traversal conditional"+            , $(allTraversals conditionalStep)+            , nestedTerm+            )+          , ( "embedded nested traversal"+            , $(allTraversals nestedTraversalStep)+            , nestedTerm+            )+          ]+      in+        [ testCase (scenarioName <> ": " <> traversalName) $+            assertAgree fast reference term+        | (scenarioName, traversals, term) <- scenarios+        , (traversalName, fast, reference) <- traversals+        ]++  , testGroup "compiled strategies equal hand-written compositions"+      [ testCase "topdown chain vs sequential apply chain" $+          assertAgree+            $(compileStrategy (topdown constructorChangingStep))+            (Comb.topdownR+              (apply "collapseApplication" collapseApplicationRewrite Comb.>->+               apply "incrementBoth" incrementBothRewrite Comb.>->+               apply "inlineTrivialLet" inlineTrivialLetRewrite))+            nestedTerm+      , testCase "topdown anyConstructor vs plain rewrite" $+          assertAgree+            $(compileStrategy (topdown incrementOddAny))+            (Comb.topdownR (apply "incrementOddAny" incrementOddAnyWorker))+            nestedTerm+      ]++  , testGroup "strategy combinators"+      [ testCase "whole-term pass" $+          assertAgree+            $(compileStrategy (pass "incrementOddAny" 'incrementOddAnyWorker))+            $(compileStrategyReference (pass "incrementOddAny" 'incrementOddAnyWorker))+            nestedTerm+      , testCase "repeatR over sequenced traversals" $+          assertAgree+            $(compileStrategy+                (repeatR (topdown collapseApplication >-> bottomup incrementOdd)))+            $(compileStrategyReference+                (repeatR (topdown collapseApplication >-> bottomup incrementOdd)))+            nestedTerm+      , testCase "success and failure conditionals between strategies" $ do+          assertAgree+            $(compileStrategy (topdown collapseApplication !-> bottomup incrementOdd))+            $(compileStrategyReference+                (topdown collapseApplication !-> bottomup incrementOdd))+            nestedTerm+          assertAgree+            $(compileStrategy (topdown inlineTrivialLet >-! bottomup incrementOdd))+            $(compileStrategyReference+                (topdown inlineTrivialLet >-! bottomup incrementOdd))+            nestedTerm+      , testCase "deepseq between strategies" $+          assertAgree+            $(compileStrategy (topdown collapseApplication >-!-> bottomup incrementOdd))+            $(compileStrategyReference+                (topdown collapseApplication >-!-> bottomup incrementOdd))+            nestedTerm+      , testCase "calling another compiled strategy" $+          assertAgree+            $(compileStrategy (callStrategyStrat 'calleeFast))+            $(compileStrategyReference (callStrategyStrat 'calleeReference))+            nestedTerm+      ]++  , testGroup "descent"+      [ testCase "NonRec lets are rebuilt as Rec, like allR" $ do+          -- See Note [NonRec erasure during descent] in+          -- Clash.Rewrite.StrategyDSL.TH.+          let term = Let (NonRec (someId 0) (integer 3)) (integer 5)+          (result, _, _) <- runRewriteOn+            $(compileStrategy (topdown literalStep)) term+          case result of+            Let (Rec [(_, boundTerm)]) _body ->+              assertEqual "binder rewritten" (show (integer 4)) (show boundTerm)+            _ -> assertFailure ("expected a Rec let, got: " <> show result)+      , testCase "AppArg context in the probe result mentions the primitive" $ do+          -- The argument is probed after the function position rewrote to a+          -- primitive; its recorded context must carry that primitive's+          -- 'primArg' information, proving the argument context is computed+          -- from the rewritten function.+          (result, _, _) <- runRewriteOn+            $(compileStrategy (topdown appArgProbeStep))+            appArgProbeTerm+          case result of+            App _function (Literal (StringLiteral recordedContext)) ->+              assertBool ("recorded context mentions somePrim: " <> recordedContext)+                ("somePrim" `List.isInfixOf` recordedContext)+            _ -> assertFailure ("expected a probed argument, got: " <> show result)+      ]++  , testGroup "asRewriteQ"+      [ testCase "fires without instrumentation" $ do+          (result, count, changedFlag) <- runRewriteOn+            $(asRewriteQ inlineTrivialLet)+            (Let (NonRec (someId 0) (integer 5)) (Var (someId 0)))+          assertEqual "result" (show (integer 5)) (show result)+          assertEqual "count" 0 count+          assertEqual "changed" True changedFlag+      , testCase "non-matching node untouched" $ do+          (result, count, changedFlag) <- runRewriteOn+            $(asRewriteQ inlineTrivialLet)+            simpleApplication+          assertEqual "result" (show simpleApplication) (show result)+          assertEqual "count" 0 count+          assertEqual "changed" False changedFlag+      ]+  ]
+ tests/Clash/Tests/Rewrite/StrategyDSL/Stubs.hs view
@@ -0,0 +1,275 @@+{-|+  Copyright  :  (C) 2026, QBayLogic B.V.+  License    :  BSD2 (see the file LICENSE)+  Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>++  Stub transformations, test terms, and strategy fragments for+  "Clash.Tests.Rewrite.StrategyDSL". They live in their own module because+  Template Haskell splices can only evaluate imported values: the test module+  splices 'Clash.Rewrite.StrategyDSL.TH.compileStrategy' over the 'Step's and+  helpers defined here.+-}++{-# LANGUAGE DisambiguateRecordFields #-}+{-# LANGUAGE DuplicateRecordFields #-}+{-# LANGUAGE NamedFieldPuns #-}+{-# LANGUAGE NoFieldSelectors #-}+{-# LANGUAGE OverloadedRecordDot #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskellQuotes #-}++module Clash.Tests.Rewrite.StrategyDSL.Stubs where++import Language.Haskell.TH (Exp, Name, Q, listE, stringE)++import Clash.Core.Literal (Literal (..))+import Clash.Core.Name (mkUnsafeSystemName)+import Clash.Core.Term+  (Bind (..), IsMultiPrim (..), Pat (..), PrimInfo (..), PrimUnfolding (..),+   Term (..), TickInfo (..), WorkInfo (..))+import Clash.Core.Type (ConstTy (..), Type (..))+import Clash.Core.Var (Id, mkLocalId, mkTyVar)+import Clash.Rewrite.StrategyDSL+import Clash.Rewrite.StrategyDSL.TH (compileStrategy, compileStrategyReference)+import Clash.Rewrite.Types (Rewrite, RewriteMonad, TransformContext (..))+import Clash.Rewrite.Util (changed)+import Clash.Unique (Unique)++-- * Term construction helpers++someType :: Type+someType = ConstTy (TyCon (mkUnsafeSystemName "T" 0))++someId :: Unique -> Id+someId unique = mkLocalId someType (mkUnsafeSystemName "x" unique)++somePrim :: PrimInfo+somePrim = PrimInfo+  { primName = "somePrim"+  , primType = someType+  , primWorkInfo = WorkConstant+  , primMultiResult = SingleResult+  , primUnfolding = NoUnfolding+  }++integer :: Integer -> Term+integer = Literal . IntLiteral++-- * Stub transformations+--+-- Each stub is a worker plus its 'Transformation'; some also come with a+-- hand-written 'Rewrite' doing its own constructor match, to compare the+-- compiled dispatch against.++-- | @f 3@ becomes @3@: fires on an application whose argument is an integer+-- literal, changing the node's constructor.+collapseApplicationWorker+  :: TransformContext -> Term -> Term -> Term -> RewriteMonad () Term+collapseApplicationWorker _ctx _node _function argument@(Literal IntLiteral{}) =+  changed argument+collapseApplicationWorker _ctx node _function _argument = pure node++collapseApplication :: Transformation+collapseApplication =+  toTransformation "collapseApplication" (onApp 'collapseApplicationWorker)++collapseApplicationRewrite :: Rewrite ()+collapseApplicationRewrite _ctx (App _function argument@(Literal IntLiteral{})) =+  changed argument+collapseApplicationRewrite _ctx term = pure term++-- | Like 'collapseApplication', but as a node-receiving worker registered at+-- 'App', the way spine transformations are registered.+collapseSpineWorker :: Rewrite ()+collapseSpineWorker _ctx (App _function argument@(Literal IntLiteral{})) =+  changed argument+collapseSpineWorker _ctx term = pure term++collapseSpine :: Transformation+collapseSpine =+  toTransformation "collapseSpine" (onAppNode 'collapseSpineWorker)++-- | Increments odd integer literals (even results keep repeated traversals+-- terminating).+incrementOddWorker+  :: TransformContext -> Term -> Literal -> RewriteMonad () Term+incrementOddWorker _ctx _node (IntLiteral i) | odd i = changed (integer (i + 1))+incrementOddWorker _ctx node _literal = pure node++incrementOdd :: Transformation+incrementOdd = toTransformation "incrementOdd" (onLiteral 'incrementOddWorker)++-- | Like 'incrementOdd', but constructor-agnostic: a plain rewrite offered at+-- every node, with its own match.+incrementOddAnyWorker :: Rewrite ()+incrementOddAnyWorker _ctx (Literal (IntLiteral i))+  | odd i = changed (integer (i + 1))+incrementOddAnyWorker _ctx term = pure term++incrementOddAny :: Transformation+incrementOddAny = anyConstructor "incrementOddAny" 'incrementOddAnyWorker++-- | Multi-constructor: increments an odd integer literal, either as the+-- argument of an application or bare. Registered for App and Literal, to+-- observe the guarded suffix.+incrementBothAppWorker+  :: TransformContext -> Term -> Term -> Term -> RewriteMonad () Term+incrementBothAppWorker _ctx _node function (Literal (IntLiteral i))+  | odd i = changed (App function (integer (i + 1)))+incrementBothAppWorker _ctx node _function _argument = pure node++incrementBothLiteralWorker+  :: TransformContext -> Term -> Literal -> RewriteMonad () Term+incrementBothLiteralWorker _ctx _node (IntLiteral i)+  | odd i = changed (integer (i + 1))+incrementBothLiteralWorker _ctx node _literal = pure node++incrementBoth :: Transformation+incrementBoth = toTransformation "incrementBoth"+  (onApp 'incrementBothAppWorker <> onLiteral 'incrementBothLiteralWorker)++incrementBothRewrite :: Rewrite ()+incrementBothRewrite _ctx (App function (Literal (IntLiteral i)))+  | odd i = changed (App function (integer (i + 1)))+incrementBothRewrite _ctx (Literal (IntLiteral i))+  | odd i = changed (integer (i + 1))+incrementBothRewrite _ctx term = pure term++-- | Inlines a let binder into its body when the body is exactly that+-- variable: @let x = e in x@ becomes @e@. Fires on 'Let'.+inlineTrivialLetWorker+  :: TransformContext -> Term -> Bind Term -> Term -> RewriteMonad () Term+inlineTrivialLetWorker _ctx node bind body = case (bind, body) of+  (NonRec i boundTerm, Var v) | v == i -> changed boundTerm+  (Rec [(i, boundTerm)], Var v) | v == i -> changed boundTerm+  _ -> pure node++inlineTrivialLet :: Transformation+inlineTrivialLet =+  toTransformation "inlineTrivialLet" (onLet 'inlineTrivialLetWorker)++inlineTrivialLetRewrite :: Rewrite ()+inlineTrivialLetRewrite _ctx node@(Let bind body) = case (bind, body) of+  (NonRec i boundTerm, Var v) | v == i -> changed boundTerm+  (Rec [(i, boundTerm)], Var v) | v == i -> changed boundTerm+  _ -> pure node+inlineTrivialLetRewrite _ctx term = pure term++-- | Replaces variable references with a string literal spelling out the full+-- 'Clash.Core.Term.CoreContext' path, exposing every context push of the+-- descent arms to the equivalence tests.+reifyContextWorker+  :: TransformContext -> Term -> Id -> RewriteMonad () Term+reifyContextWorker ctx _node _i =+  changed (Literal (StringLiteral (show (tfContext ctx))))++reifyContext :: Transformation+reifyContext = toTransformation "reifyContext" (onVar 'reifyContextWorker)++-- | Rewrites references to one specific variable to a primitive, so the+-- 'Clash.Core.Term.AppArg' context a sibling argument sees is computed from+-- an already rewritten function.+functionToPrimWorker+  :: TransformContext -> Term -> Id -> RewriteMonad () Term+functionToPrimWorker _ctx node i+  | i == someId 2 = changed (Prim somePrim)+  | otherwise = pure node++functionToPrim :: Transformation+functionToPrim = toTransformation "functionToPrim" (onVar 'functionToPrimWorker)++-- * Test terms++-- | @(let x = f 3 in x) (let y = 5 in y)@: exercises App, Let (both binder+-- and body positions), and literals at several depths.+nestedTerm :: Term+nestedTerm =+  App+    (Let (NonRec x (App (Var f) (integer 3))) (Var x))+    (Let (Rec [(y, integer 5)]) (Var y))+ where+  x = someId 0+  y = someId 1+  f = someId 2++-- | A term covering every recursive constructor: Lam, TyLam, App, TyApp,+-- Let, Case (subject and alternatives), Cast, and Tick.+allConstructorsTerm :: Term+allConstructorsTerm =+  Lam lamBinder+    (TyLam tyVariable+      (Tick DeDup+        (Case+          (Cast (App (Var lamBinder) subject) someType someType)+          someType+          [ (DefaultPat, integer 3)+          , (LitPat (IntLiteral 0), TyApp (Var lamBinder) someType)+          ])))+ where+  lamBinder = someId 3+  tyVariable = mkTyVar someType (mkUnsafeSystemName "a" 100)+  subject = Let (NonRec (someId 5) (integer 7)) (Var (someId 5))++simpleApplication :: Term+simpleApplication = App (Var (someId 6)) (integer 3)++-- | The function position rewrites to a primitive; the argument's probed+-- context must show the 'Clash.Core.Term.AppArg' of that primitive.+appArgProbeTerm :: Term+appArgProbeTerm = App (Var (someId 2)) (Var (someId 7))++-- * Strategy fragments compared across all traversals++constructorChangingStep :: Step+constructorChangingStep =+  chain [collapseApplication, incrementBoth, inlineTrivialLet]++literalStep :: Step+literalStep = chain [incrementOdd]++contextProbeStep :: Step+contextProbeStep = chain [reifyContext]++appArgProbeStep :: Step+appArgProbeStep = chain [functionToPrim, reifyContext]++noOpStep :: Step+noOpStep = chain [inlineTrivialLet]++anyWorkerStep :: Step+anyWorkerStep = chain [collapseApplication, incrementOddAny]++nodeWorkerStep :: Step+nodeWorkerStep = chain [collapseSpine, incrementBoth]++-- | A cross-constructor conditional between chain segments inside one+-- traversal, the @flatten@ strategy's structure.+conditionalStep :: Step+conditionalStep =+  (one collapseApplication !-> one incrementOdd) >-> chain [inlineTrivialLet]++-- | A whole nested traversal embedded as one node action, the @conSpec@+-- strategy's structure.+nestedTraversalStep :: Step+nestedTraversalStep =+  (one collapseApplication !-> nested (bottomup incrementOdd))+  >-! one incrementBoth++-- | A strategy calling another compiled strategy, parameterized over the+-- callee so the test module can point it at either compilation of it.+callStrategyStrat :: Name -> Strat+callStrategyStrat callee = callStrategy callee >-> topdown collapseApplication++-- | Every fused traversal of a 'Step' next to its unfused reference:+-- @[(name, fast, reference)]@. Spliced by the test module.+allTraversals :: Step -> Q Exp+allTraversals step = listE+  [ [| ($(stringE name), $(compileStrategy strat), $(compileStrategyReference strat)) |]+  | (name, strat) <-+      [ ("topdown", topdown step)+      , ("bottomup", bottomup step)+      , ("topdownFix", topdownFix step)+      , ("topdownSuc", topdownSuc step)+      , ("innerMost", innerMost step)+      ]+  ]
tests/Test/Clash/Rewrite.hs view
@@ -26,6 +26,7 @@ import Clash.Driver.Types (ClashEnv(..), ClashOpts(..), defClashOpts, debugSilent) import Clash.Rewrite.Types import Clash.Rewrite.Util (runRewrite)+import Clash.Normalize.Strategy (constantPropagation, normalization) import Clash.Normalize.Types import qualified Clash.Util.Interpolate as I import Clash.Util.Supply (newSupply)@@ -108,6 +109,9 @@     , _inlineHistory=emptyVarEnv     , _primitiveArgs=Map.empty     , _recursiveComponents=emptyVarEnv+    , _normalizationStrategy=normalization+    , _constantPropagationStrategy=constantPropagation+    , _workFreeAppCache=HashMap.empty     }  instance Default InScopeSet where
tests/unittests.hs view
@@ -11,6 +11,7 @@ import qualified Clash.Tests.Driver.Manifest import qualified Clash.Tests.Netlist.Id import qualified Clash.Tests.Normalize.Transformations+import qualified Clash.Tests.Rewrite.StrategyDSL import qualified Clash.Tests.Util.Interpolate import qualified Test.Clash.Rewrite @@ -30,6 +31,7 @@   , Clash.Tests.Driver.Manifest.tests   , Clash.Tests.Netlist.Id.tests   , Clash.Tests.Normalize.Transformations.tests+  , Clash.Tests.Rewrite.StrategyDSL.tests   , Clash.Tests.Util.Interpolate.tests   , Test.Clash.Rewrite.tests   ]