packages feed

mldsa-0.1.1.0: src/Barrier.hs

-- |
-- Module      : Barrier
-- License     : BSD-3-Clause
-- Copyright   : (c) 2026 Olivier Chéron
--
-- Utilities to block LLVM optimizations that are unwanted.  Currently this
-- targets the X86 CMOV conversion pass, to make sure constant-time masking
-- operations are preserved and not transformed into branches.
--
{-# LANGUAGE CPP #-}
#if (defined(i386_HOST_ARCH) || defined(x86_64_HOST_ARCH)) \
    && defined(__GLASGOW_HASKELL_LLVM__)
#define MLDSA_USE_VALUE_BARRIER 1
#endif
#ifdef MLDSA_USE_VALUE_BARRIER
{-# LANGUAGE MagicHash #-}
#endif
module Barrier
    ( barrier32
    ) where

import Data.Word

#ifdef MLDSA_USE_VALUE_BARRIER

#if MIN_VERSION_base(4,16,0)
import GHC.Exts (Word32#)
#else
import GHC.Exts (Word#)
#endif
import GHC.Word (Word32(W32#))

-- Implements a value barrier:  at call site the content of the function is
-- opaque to the optimizer, thus the call prevents optimizations that need
-- knowledge of the value.
--
-- We want to avoid memory allocations and use CPU registers so the mechanism
-- relies on unlifted values in and out.

barrier32 :: Word32 -> Word32
barrier32 (W32# x#) = W32# (barrier32# x#)
{-# INLINE barrier32 #-}

#if MIN_VERSION_base(4,16,0)
barrier32# :: Word32# -> Word32#
#else
barrier32# :: Word# -> Word#
#endif
barrier32# x# = x#
{-# NOINLINE barrier32# #-}

#else

-- When using the NCG, or not on X86, the call can be completely eliminated.

barrier32 :: Word32 -> Word32
barrier32 = id
{-# INLINE barrier32 #-}

#endif