check if target and local type of call_indirect are the same

This commit is contained in:
Ilya Rezvov
2018-04-21 10:39:23 -07:00
parent 7726eb7505
commit 56f9aea99d
+46 -31
View File
@@ -588,26 +588,28 @@ data EvalResult =
eval :: Store -> FunctionInstance -> [Value] -> IO (Maybe [Value]) eval :: Store -> FunctionInstance -> [Value] -> IO (Maybe [Value])
eval store FunctionInstance { funcType, moduleInstance, code = Function { localTypes, body} } args = do eval store FunctionInstance { funcType, moduleInstance, code = Function { localTypes, body} } args = do
let checkedArgs = zipWith checkValType (params funcType) args case sequence $ zipWith checkValType (params funcType) args of
let initialContext = EvalCtx { Just checkedArgs -> do
locals = Vector.fromList $ checkedArgs ++ map initLocal localTypes, let initialContext = EvalCtx {
labels = [Label $ results funcType], locals = Vector.fromList $ checkedArgs ++ map initLocal localTypes,
stack = [] labels = [Label $ results funcType],
} stack = []
res <- go initialContext body }
case res of res <- go initialContext body
Done ctx -> return $ Just $ reverse $ stack ctx case res of
ReturnFn r -> return $ Just r Done ctx -> return $ Just $ reverse $ stack ctx
Break 0 r _ -> return $ Just $ reverse r ReturnFn r -> return $ Just r
Break _ _ _ -> error "Break is out of range" Break 0 r _ -> return $ Just $ reverse r
Trap -> return Nothing Break _ _ _ -> error "Break is out of range"
Trap -> return Nothing
Nothing -> return Nothing
where where
checkValType :: ValueType -> Value -> Value checkValType :: ValueType -> Value -> Maybe Value
checkValType I32 (VI32 v) = VI32 v checkValType I32 (VI32 v) = Just $ VI32 v
checkValType I64 (VI64 v) = VI64 v checkValType I64 (VI64 v) = Just $ VI64 v
checkValType F32 (VF32 v) = VF32 v checkValType F32 (VF32 v) = Just $ VF32 v
checkValType F64 (VF64 v) = VF64 v checkValType F64 (VF64 v) = Just $ VF64 v
checkValType _ _ = error "Value types do not match provided value" checkValType _ _ = Nothing
initLocal :: ValueType -> Value initLocal :: ValueType -> Value
initLocal I32 = VI32 0 initLocal I32 = VI32 0
@@ -652,7 +654,9 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
step ctx@EvalCtx{ stack, labels } (Br label) = do step ctx@EvalCtx{ stack, labels } (Br label) = do
let idx = fromIntegral label let idx = fromIntegral label
let Label resType = labels !! idx let Label resType = labels !! idx
return $ Break idx (zipWith checkValType resType $ take (length resType) stack) ctx case sequence $ zipWith checkValType resType $ take (length resType) stack of
Just result -> return $ Break idx result ctx
Nothing -> return Trap
step ctx@EvalCtx{ stack = (VI32 v): rest } (BrIf label) = step ctx@EvalCtx{ stack = (VI32 v): rest } (BrIf label) =
if v == 0 if v == 0
then return $ Done ctx { stack = rest } then return $ Done ctx { stack = rest }
@@ -663,14 +667,19 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
step ctx { stack = rest } (Br lbl) step ctx { stack = rest } (Br lbl)
step EvalCtx{ stack } Return = step EvalCtx{ stack } Return =
let resType = results funcType in let resType = results funcType in
return $ ReturnFn $ reverse $ zipWith checkValType resType $ take (length resType) stack case sequence $ zipWith checkValType resType $ take (length resType) stack of
Just result -> return $ ReturnFn $ reverse result
Nothing -> return Trap
step ctx (Call fun) = do step ctx (Call fun) = do
let funInst = funcInstances store ! (funcaddrs moduleInstance ! fromIntegral fun) let funInst = funcInstances store ! (funcaddrs moduleInstance ! fromIntegral fun)
let ft = Language.Wasm.Interpreter.funcType funInst let ft = Language.Wasm.Interpreter.funcType funInst
let args = params ft let args = params ft
res <- eval store funInst (zipWith checkValType args $ reverse $ take (length args) $ stack ctx) case sequence $ zipWith checkValType args $ reverse $ take (length args) $ stack ctx of
case res of Just params -> do
Just res -> return $ Done ctx { stack = reverse res ++ (drop (length args) $ stack ctx) } res <- eval store funInst params
case res of
Just res -> return $ Done ctx { stack = reverse res ++ (drop (length args) $ stack ctx) }
Nothing -> return Trap
Nothing -> return Trap Nothing -> return Trap
step ctx@EvalCtx{ stack = (VI32 v): rest } (CallIndirect typeIdx) = do step ctx@EvalCtx{ stack = (VI32 v): rest } (CallIndirect typeIdx) = do
let funcType = funcTypes moduleInstance ! fromIntegral typeIdx let funcType = funcTypes moduleInstance ! fromIntegral typeIdx
@@ -679,14 +688,20 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
case funcAddr of case funcAddr of
Just (Just addr) -> do Just (Just addr) -> do
let funInst = funcInstances store ! addr let funInst = funcInstances store ! addr
let args = params $ Language.Wasm.Interpreter.funcType funInst let targetType = Language.Wasm.Interpreter.funcType funInst
if length args > length rest if targetType == funcType
then return Trap then do
else do let args = params targetType
res <- eval store funInst (zipWith checkValType args $ reverse $ take (length args) rest) if length args > length rest
case res of then return Trap
Just res -> return $ Done ctx { stack = reverse res ++ (drop (length args) rest) } else case sequence $ zipWith checkValType args $ reverse $ take (length args) rest of
Just params -> do
res <- eval store funInst params
case res of
Just res -> return $ Done ctx { stack = reverse res ++ (drop (length args) rest) }
Nothing -> return Trap
Nothing -> return Trap Nothing -> return Trap
else return Trap
_ -> return Trap _ -> return Trap
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 =