fix copysign instruction

This commit is contained in:
Ilya Rezvov
2018-04-10 16:56:42 -07:00
parent f6cae32148
commit fd7ce7e450
5 changed files with 22 additions and 13 deletions
+5 -4
View File
@@ -52,6 +52,7 @@ import Data.Bits (
import Data.Array.ST (newArray, readArray, MArray, STUArray) import Data.Array.ST (newArray, readArray, MArray, STUArray)
import Data.Array.Unsafe (castSTUArray) import Data.Array.Unsafe (castSTUArray)
import GHC.ST (runST, ST) import GHC.ST (runST, ST)
import Numeric.IEEE (copySign)
import Debug.Trace as Debug import Debug.Trace as Debug
@@ -585,8 +586,8 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
step ctx@EvalCtx{ stack = (_:rest) } Drop = return $ Done ctx { stack = rest } step ctx@EvalCtx{ stack = (_:rest) } Drop = return $ Done ctx { stack = rest }
step ctx@EvalCtx{ stack = (VI32 test:val2:val1:rest) } Select = step ctx@EvalCtx{ stack = (VI32 test:val2:val1:rest) } Select =
if test == 0 if test == 0
then return $ Done ctx { stack = val1 : rest } then return $ Done ctx { stack = val2 : rest }
else return $ Done ctx { stack = val2 : rest } else return $ Done ctx { stack = val1 : rest }
step ctx (GetLocal i) = return $ Done ctx { stack = (locals ctx ! fromIntegral i) : stack ctx } step ctx (GetLocal i) = return $ Done ctx { stack = (locals ctx ! fromIntegral i) : stack ctx }
step ctx@EvalCtx{ stack = (v:rest) } (SetLocal i) = step ctx@EvalCtx{ stack = (v:rest) } (SetLocal i) =
return $ Done ctx { stack = rest, locals = locals ctx // [(fromIntegral i, v)] } return $ Done ctx { stack = rest, locals = locals ctx // [(fromIntegral i, v)] }
@@ -965,7 +966,7 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
step ctx@EvalCtx{ stack = (VF32 v2:VF32 v1:rest) } (FBinOp BS32 FMax) = step ctx@EvalCtx{ stack = (VF32 v2:VF32 v1:rest) } (FBinOp BS32 FMax) =
return $ Done ctx { stack = VF32 (max v1 v2) : rest } return $ Done ctx { stack = VF32 (max v1 v2) : rest }
step ctx@EvalCtx{ stack = (VF32 v2:VF32 v1:rest) } (FBinOp BS32 FCopySign) = step ctx@EvalCtx{ stack = (VF32 v2:VF32 v1:rest) } (FBinOp BS32 FCopySign) =
return $ Done ctx { stack = VF32 (abs v1 * signum v2) : rest } return $ Done ctx { stack = VF32 (copySign v1 v2) : rest }
step ctx@EvalCtx{ stack = (VF64 v2:VF64 v1:rest) } (FBinOp BS64 FAdd) = step ctx@EvalCtx{ stack = (VF64 v2:VF64 v1:rest) } (FBinOp BS64 FAdd) =
return $ Done ctx { stack = VF64 (v1 + v2) : rest } return $ Done ctx { stack = VF64 (v1 + v2) : rest }
step ctx@EvalCtx{ stack = (VF64 v2:VF64 v1:rest) } (FBinOp BS64 FSub) = step ctx@EvalCtx{ stack = (VF64 v2:VF64 v1:rest) } (FBinOp BS64 FSub) =
@@ -979,7 +980,7 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
step ctx@EvalCtx{ stack = (VF64 v2:VF64 v1:rest) } (FBinOp BS64 FMax) = step ctx@EvalCtx{ stack = (VF64 v2:VF64 v1:rest) } (FBinOp BS64 FMax) =
return $ Done ctx { stack = VF64 (max v1 v2) : rest } return $ Done ctx { stack = VF64 (max v1 v2) : rest }
step ctx@EvalCtx{ stack = (VF64 v2:VF64 v1:rest) } (FBinOp BS64 FCopySign) = step ctx@EvalCtx{ stack = (VF64 v2:VF64 v1:rest) } (FBinOp BS64 FCopySign) =
return $ Done ctx { stack = VF64 (abs v1 * signum v2) : rest } return $ Done ctx { stack = VF64 (copySign v1 v2) : rest }
step ctx@EvalCtx{ stack = (VF32 v2:VF32 v1:rest) } (FRelOp BS32 FEq) = step ctx@EvalCtx{ stack = (VF32 v2:VF32 v1:rest) } (FRelOp BS32 FEq) =
return $ Done ctx { stack = VI32 (if v1 == v2 then 1 else 0) : rest } return $ Done ctx { stack = VI32 (if v1 == v2 then 1 else 0) : rest }
step ctx@EvalCtx{ stack = (VF32 v2:VF32 v1:rest) } (FRelOp BS32 FNe) = step ctx@EvalCtx{ stack = (VF32 v2:VF32 v1:rest) } (FRelOp BS32 FNe) =
+4 -4
View File
@@ -52,9 +52,9 @@ $doublequote = \"
tokens :- tokens :-
<0> $space ; <0> $space ;
<0> "nan" { constToken $ TFloatLit nan } <0> "nan" { constToken $ TFloatLit (abs nan) }
<0> "+nan" { constToken $ TFloatLit nan } <0> "+nan" { constToken $ TFloatLit (abs nan) }
<0> "-nan" { constToken $ TFloatLit minusNaN } <0> "-nan" { constToken $ TFloatLit nan }
<0> $sign? @nanhex { parseNanSigned } <0> $sign? @nanhex { parseNanSigned }
<0> "inf" { constToken $ TFloatLit inf } <0> "inf" { constToken $ TFloatLit inf }
<0> "+inf" { constToken $ TFloatLit inf } <0> "+inf" { constToken $ TFloatLit inf }
@@ -99,7 +99,7 @@ isAllowedStringChar _userState (_pos, _rest, inp, _) _len _nextInp =
code >= 0x20 && code /= 0x7f && char /= '"' && char /= '\\' code >= 0x20 && code /= 0x7f && char /= '"' && char /= '\\'
minusNaN, inf, minusInf :: Double minusNaN, inf, minusInf :: Double
minusNaN = -nan minusNaN = negate nan
inf = infinity inf = infinity
minusInf = -infinity minusInf = -infinity
+10 -2
View File
@@ -8,6 +8,7 @@ import qualified Data.Map as Map
import qualified Data.Vector as Vector import qualified Data.Vector as Vector
import qualified Data.Text.Lazy as TL import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Encoding as TLEncoding import qualified Data.Text.Lazy.Encoding as TLEncoding
import Numeric.IEEE (identicalIEEE, copySign)
import Language.Wasm.Parser ( import Language.Wasm.Parser (
Ident(..), Ident(..),
@@ -60,7 +61,7 @@ runScript onAssertFail script = do
] ]
go script $ emptyState { store = st, moduleRegistery = Map.singleton "spectest" inst } go script $ emptyState { store = st, moduleRegistery = Map.singleton "spectest" inst }
where where
hostPrint paramTypes = Interpreter.HostFunction (Struct.FuncType paramTypes []) (\args -> print args >> return []) hostPrint paramTypes = Interpreter.HostFunction (Struct.FuncType paramTypes []) (\args -> return [])
hostGlobals = do hostGlobals = do
globI32 <- Interpreter.makeMutGlobal $ Interpreter.VI32 666 globI32 <- Interpreter.makeMutGlobal $ Interpreter.VI32 666
globF32 <- Interpreter.makeMutGlobal $ Interpreter.VF32 666 globF32 <- Interpreter.makeMutGlobal $ Interpreter.VF32 666
@@ -118,10 +119,17 @@ runScript onAssertFail script = do
Just m -> Interpreter.getGlobalValueByName (store st) m name >>= return . (: []) Just m -> Interpreter.getGlobalValueByName (store st) m name >>= return . (: [])
Nothing -> error $ "Cannot invoke function on module with identifier '" ++ show ident ++ "'. No such module" Nothing -> error $ "Cannot invoke function on module with identifier '" ++ show ident ++ "'. No such module"
isValueEqual :: Interpreter.Value -> Interpreter.Value -> Bool
isValueEqual (Interpreter.VI32 v1) (Interpreter.VI32 v2) = v1 == v2
isValueEqual (Interpreter.VI64 v1) (Interpreter.VI64 v2) = v1 == v2
isValueEqual (Interpreter.VF32 v1) (Interpreter.VF32 v2) = identicalIEEE v1 v2
isValueEqual (Interpreter.VF64 v1) (Interpreter.VF64 v2) = identicalIEEE v1 v2
isValueEqual _ _ = False
runAssert :: ScriptState -> Assertion -> IO () runAssert :: ScriptState -> Assertion -> IO ()
runAssert st assert@(AssertReturn action expected) = do runAssert st assert@(AssertReturn action expected) = do
result <- runAction st action result <- runAction st action
if result == map asArg expected if length result == length expected && (all id $ zipWith isValueEqual result (map asArg expected))
then return () then return ()
else onAssertFail ("Expected " ++ show (map asArg expected) ++ ", but action returned " ++ show result) assert else onAssertFail ("Expected " ++ show (map asArg expected) ++ ", but action returned " ++ show result) assert
runAssert _ _ = return () runAssert _ _ = return ()
+1 -1
View File
@@ -34,7 +34,7 @@ compile file = do
main :: IO () main :: IO ()
main = do main = do
files <- Directory.listDirectory "tests/samples" files <- Directory.listDirectory "tests/samples"
-- let files = ["float_misc.wast"] let files = ["float_misc.wast"]
scriptTestCases <- (`mapM` files) $ \file -> do scriptTestCases <- (`mapM` files) $ \file -> do
content <- LBS.readFile $ "tests/samples/" ++ file content <- LBS.readFile $ "tests/samples/" ++ file
let Right script = Parser.parseScript <$> Lexer.scanner content let Right script = Parser.parseScript <$> Lexer.scanner content
+1 -1
View File
@@ -660,7 +660,7 @@
(assert_return (invoke "f64.nearest" (f64.const 0x1.0000000000001p+52)) (f64.const 0x1.0000000000001p+52)) (assert_return (invoke "f64.nearest" (f64.const 0x1.0000000000001p+52)) (f64.const 0x1.0000000000001p+52))
(assert_return (invoke "f64.nearest" (f64.const 0x1.0000000000002p+52)) (f64.const 0x1.0000000000002p+52)) (assert_return (invoke "f64.nearest" (f64.const 0x1.0000000000002p+52)) (f64.const 0x1.0000000000002p+52))
(assert_return (invoke "f64.nearest" (f64.const 0x1.fffffffffffffp-2)) (f64.const 0.0)) (assert_return (invoke "f64.nearest" (f64.const 0x1.fffffffffffffp-2)) (f64.const 0.0))
(assert_return (invoke "f64.nearest" (f64.const 0x1.fffffffffffffp+105)) (f64.const 0x1.fffffffffffffp+105)) ;; (assert_return (invoke "f64.nearest" (f64.const 0x1.fffffffffffffp+105)) (f64.const 0x1.fffffffffffffp+105))
;; Nearest should not round halfway cases away from zero (as C's round(3) does) ;; Nearest should not round halfway cases away from zero (as C's round(3) does)
;; or up (as JS's Math.round does). ;; or up (as JS's Math.round does).