1-- SPDX-FileCopyrightText: 2025 Sören Tempel <soeren+git@soeren-tempel.net>2--3-- SPDX-License-Identifier: GPL-3.0-only45module Expression (exprTests) where67import Data.Int (Int64)8import Data.Maybe (fromJust)9import Language.QBE.Simulator.Default.Expression qualified as DE10import Language.QBE.Simulator.Expression qualified as E11import Language.QBE.Types qualified as Q12import Test.Tasty13import Test.Tasty.HUnit1415exprTests :: TestTree16exprTests =17 testGroup18 "Expression Tests"19 [ testCase "Test equality" $20 do21 let lhs = E.fromLit (Q.Base Q.Word) 23 :: DE.RegVal22 let rhs = E.fromLit (Q.Base Q.Word) 42 :: DE.RegVal2324 lhs `E.eq` lhs @?= truthValue25 lhs `E.ne` lhs @?= falseValue2627 lhs `E.eq` rhs @?= falseValue28 lhs `E.ne` rhs @?= truthValue,29 testCase "Test unsigned comparison" $30 do31 let lhs = E.fromLit (Q.Base Q.Word) 23 :: DE.RegVal32 let rhs = E.fromLit (Q.Base Q.Word) 42 :: DE.RegVal3334 lhs `E.ule` rhs @?= truthValue35 lhs `E.ule` lhs @?= truthValue36 lhs `E.ult` lhs @?= falseValue,37 testCase "Test signed comparision" $38 do39 let lhs = E.fromLit (Q.Base Q.Word) (fromIntegral (-1 :: Int64)) :: DE.RegVal40 let rhs = E.fromLit (Q.Base Q.Word) 0 :: DE.RegVal4142 lhs `E.slt` rhs @?= truthValue43 lhs `E.sle` lhs @?= truthValue44 lhs `E.ult` rhs @?= falseValue,45 testCase "sar preserves sign bit" $46 do47 let v = E.fromLit (Q.Base Q.Word) (fromIntegral (-256 :: Int64)) :: DE.RegVal48 let r = fromJust $ v `E.sar` E.fromLit (Q.Base Q.Word) 149 r @?= E.fromLit (Q.Base Q.Word) (fromIntegral (-128 :: Int64)),50 testCase "shr does not preserve sign bit" $51 do52 let v = E.fromLit (Q.Base Q.Word) (fromIntegral (-0x80000000 :: Int64)) :: DE.RegVal53 let r = fromJust $ v `E.shr` E.fromLit (Q.Base Q.Word) 854 r @?= E.fromLit (Q.Base Q.Word) 0x800000,55 testCase "extend byte to word" $56 do57 let v = E.fromLit Q.Byte 128 :: DE.RegVal5859 let signExt = E.fromLit (Q.Base Q.Word) 0xffffff80 :: DE.RegVal60 E.extend (Q.Base Q.Word) True v @?= Just signExt6162 let zeroExt = E.fromLit (Q.Base Q.Word) 128 :: DE.RegVal63 E.extend (Q.Base Q.Word) False v @?= Just zeroExt,64 testCase "extend float" $65 do66 let s = E.fromLit (Q.Base Q.Single) 2342 :: DE.RegVal67 E.extend (Q.Base Q.Long) False s @?= Nothing6869 let d = E.fromLit (Q.Base Q.Double) 2342 :: DE.RegVal70 E.extend (Q.Base Q.Long) False d @?= Nothing,71 testCase "current size exceeds extend" $72 do73 let s = E.fromLit (Q.Base Q.Word) 2342 :: DE.RegVal74 E.extend Q.Byte False s @?= Nothing,75 testCase "current size equals extend" $76 do77 let s = E.fromLit (Q.Base Q.Word) 2342 :: DE.RegVal78 E.extend (Q.Base Q.Word) True s @?= Nothing,79 testCase "extract from word" $80 do81 let v = E.fromLit (Q.Base Q.Word) 0xdeadbeef :: DE.RegVal8283 let e1 = E.fromLit Q.Byte 0xef :: DE.RegVal84 E.extract Q.Byte v @?= Just e18586 let e2 = E.fromLit Q.HalfWord 0xbeef :: DE.RegVal87 E.extract Q.HalfWord v @?= Just e2,88 testCase "extract from float" $89 do90 let d = E.fromLit (Q.Base Q.Double) 2342 :: DE.RegVal91 E.extract Q.Byte d @?= Nothing92 E.extract (Q.Base Q.Single) d @?= Nothing9394 let s = E.fromLit (Q.Base Q.Single) 2342 :: DE.RegVal95 E.extract Q.Byte s @?= Nothing96 E.extract (Q.Base Q.Single) s @?= Nothing,97 testCase "extract exceeds size" $98 do99 let v = E.fromLit (Q.Base Q.Word) 0xdeadbeef :: DE.RegVal100 E.extract (Q.Base Q.Long) v @?= Nothing101 ]102 where103 falseValue = Just (E.fromLit (Q.Base Q.Long) 0 :: DE.RegVal)104 truthValue = Just (E.fromLit (Q.Base Q.Long) 1 :: DE.RegVal)