    {-|
      Copyright   :  (C) 2024, QBayLogic B.V.
      License     :  BSD2 (see the file LICENSE)
      Maintainer  :  QBayLogic B.V. <devops@qbaylogic.com>
    -}

    {-# LANGUAGE CPP #-}
    {-# LANGUAGE MagicHash #-}
    {-# LANGUAGE PatternSynonyms #-}
    {-# LANGUAGE TypeSynonymInstances #-}

    module Clash.Unique
      ( Unique
      , pattern Unique#
      , Unique#
      , Uniquable (..)
      , fromGhcUnique
      ) where

    #if MIN_VERSION_ghc(9,8,4) || (MIN_VERSION_ghc(9,6,7) && !MIN_VERSION_ghc(9,8,0))
    #define UNIQUE_IS_WORD64
    #endif

    import Data.Word (Word64)

    #ifdef UNIQUE_IS_WORD64
    import GHC.Word (Word64(W64#))
    import GHC.Exts (Word64#)
    #else
    import GHC.Int (Int(I#))
    import GHC.Exts (Int#)
    #endif
    #if MIN_VERSION_ghc(9,0,0)
    import qualified GHC.Types.Unique as GHC
    #else
    import qualified Unique as GHC
    #endif

    #ifdef UNIQUE_IS_WORD64
    type Unique = Word64
    type Unique# = Word64#

    pattern Unique#
      :: Unique#
      -- ^ Type of signal
      -> Unique
    pattern $mUnique# :: forall {r}. Unique -> (Unique# -> r) -> ((# #) -> r) -> r
    $bUnique# :: Unique# -> Unique
    Unique# u <- W64# u
      where
        Unique# Unique#
    u = Unique# -> Unique
    W64# Unique#
    u
    #else
    type Unique = Int
    type Unique# = Int#

    pattern Unique#
      :: Unique#
      -- ^ Type of signal
      -> Unique
    pattern Unique# u <- I# u
      where
        Unique# u = I# u
    #endif

    class Uniquable a where
      getUnique :: a -> Unique
      setUnique :: a -> Unique -> a

    instance Uniquable Unique where
      getUnique :: Unique -> Unique
    getUnique = Unique -> Unique
    forall a. a -> a
    id
      setUnique :: Unique -> Unique -> Unique
    setUnique = (Unique -> Unique -> Unique) -> Unique -> Unique -> Unique
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip Unique -> Unique -> Unique
    forall a b. a -> b -> a
    const

    #ifndef UNIQUE_IS_WORD64
    instance Uniquable Word64 where
      getUnique = fromIntegral
      setUnique _ = fromIntegral
    #endif

    fromGhcUnique :: GHC.Unique -> Unique
    fromGhcUnique :: Unique -> Unique
    fromGhcUnique = Unique -> Unique
    GHC.getKey