llvm-party-12.1.0: test/LLVM/Test/FunctionAttribute.hs
{-# LANGUAGE LambdaCase #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
module LLVM.Test.FunctionAttribute where
import Test.Tasty
import Test.Tasty.QuickCheck hiding ( (.&.) )
import LLVM.Test.Support
import LLVM.AST.FunctionAttribute
import LLVM.Internal.Coding
import LLVM.Internal.Context
import LLVM.Internal.EncodeAST
import LLVM.Internal.DecodeAST
import qualified LLVM.Internal.FFI.Attribute as FFI
import Control.Applicative
import Data.Bits
import Data.List
import Text.Show.Pretty
import Control.Monad.IO.Class (liftIO)
import Prelude
import qualified Data.ByteString.Short as B
instance Arbitrary FunctionAttribute where
arbitrary = oneof
[ return AlwaysInline
, return ArgMemOnly
, return Builtin
, return Cold
, return Convergent
, return InaccessibleMemOnly
, return InaccessibleMemOrArgMemOnly
, return InlineHint
, return JumpTable
, return MinimizeSize
, return Naked
, return NoBuiltin
, return NoDuplicate
, return NoFree
, return NoImplicitFloat
, return NoInline
, return NonLazyBind
, return NoRecurse
, return NoRedZone
, return NoReturn
, return NoUnwind
, return OptimizeForSize
, return OptimizeNone
, return ReadNone
, return ReadOnly
, return ReturnsTwice
, return SafeStack
, return SanitizeAddress
, return SanitizeHWAddress
, return SanitizeMemory
, return SanitizeThread
, return Speculatable
, return StackProtect
, return StackProtectReq
, return StackProtectStrong
, return StrictFP
, return UWTable
, return WriteOnly
, StackAlignment <$> elements (map (2^) [0..8 :: Int])
, StringAttribute <$> (B.pack <$> arbitrary) <*> (B.pack <$> arbitrary)
, suchThat (AllocSize <$> arbitrary <*> arbitrary) (/= AllocSize 0 (Just 0))
]
shrink = \case
StackAlignment x -> map StackAlignment (nub [ v | u <- shrink x, let v = ceilPow2 u, v /= x ])
StringAttribute x y -> [ StringAttribute (B.pack x') y | x' <- shrink (B.unpack x) ]
++ [ StringAttribute x (B.pack y') | y' <- shrink (B.unpack y) ]
AllocSize x y -> [ AllocSize x' y | x' <- shrink x, not (x' == 0 && y == Just 0) ]
++ [ AllocSize x y' | y' <- shrink y, not (x == 0 && y' == Just 0) ]
_ -> []
tests :: TestTree
tests =
testGroup "FunctionAttribute"
[ testProperty "round-trip" $ \attr ->
ioProperty $ withContext $ \ctx -> do
attr' <- runEncodeAST ctx $ do
attrSet <- encodeM [attr] :: EncodeAST FFI.FunctionAttributeSet
liftIO (runDecodeAST (decodeM attrSet :: DecodeAST [FunctionAttribute]))
return $ counterexample (unlines [ "expected: " ++ ppShow [attr]
, "but got: " ++ ppShow attr'
])
([attr] == attr')
]
isPow2 :: (Bits a, Num a) => a -> Bool
isPow2 0 = True
isPow2 1 = False
isPow2 n = n .&. (n - 1) == 0
ceilPow2 :: (Bits a, Integral a) => a -> a
ceilPow2 n
| isPow2 n = n
| otherwise =
let x = logBase 2 (fromIntegral n) :: Double
y = floor x + 1
in
1 `shiftL` y