From b2f001aea8a17de1564bb9028a1951931336aa82 Mon Sep 17 00:00:00 2001 From: Ilya Rezvov Date: Sun, 5 Jun 2022 21:45:58 -0600 Subject: [PATCH] implement table.copy --- src/Language/Wasm/Interpreter.hs | 18 +++++++++++++++++- src/Language/Wasm/Parser.y | 4 ++-- src/Language/Wasm/Validate.hs | 2 +- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/Language/Wasm/Interpreter.hs b/src/Language/Wasm/Interpreter.hs index 9828ef9..907e2ef 100644 --- a/src/Language/Wasm/Interpreter.hs +++ b/src/Language/Wasm/Interpreter.hs @@ -929,9 +929,25 @@ eval budget store FunctionInstance { funcType, moduleInstance, code = Function { || isDeclarative mode then return Trap else do - Vector.iforM_ (Vector.slice src len refs) $ \idx (RF fn) -> + Vector.iforM_ (Vector.slice src len refs) $ \idx (RF fn) -> do MVector.unsafeWrite items (dst + idx) (fromIntegral <$> fn) return $ Done ctx { stack = rest } + step ctx@EvalCtx{ stack = (VI32 n:VI32 s:VI32 d:rest) } (TableCopy toIdx fromIdx) = do + let fromAddr = tableaddrs moduleInstance ! fromIntegral fromIdx + let TableInstance { items = fromItems } = tableInstances store ! fromAddr + let toAddr = tableaddrs moduleInstance ! fromIntegral toIdx + let TableInstance { items = toItems } = tableInstances store ! toAddr + let src = fromIntegral s + let dst = fromIntegral d + let len = fromIntegral n + if src + len > MVector.length fromItems || dst + len > MVector.length toItems + then return Trap + else do + let range = if dst <= src then [0..len - 1] else reverse [0..len - 1] + flip mapM_ range $ \off -> do + el <- MVector.unsafeRead fromItems (src + off) + MVector.unsafeWrite toItems (dst + off) el + return $ Done ctx { stack = rest } step ctx@EvalCtx{ stack = (ref:VI32 offset:rest) } (TableSet tableIdx) = do let tableAddr = tableaddrs moduleInstance ! fromIntegral tableIdx let TableInstance { items } = tableInstances store ! tableAddr diff --git a/src/Language/Wasm/Parser.y b/src/Language/Wasm/Parser.y index 4c345ee..a06baf2 100644 --- a/src/Language/Wasm/Parser.y +++ b/src/Language/Wasm/Parser.y @@ -1722,11 +1722,11 @@ desugarize fields = do Just elemIdx -> return $ S.TableInit tableIdx elemIdx Nothing -> Left "unknown elem" Nothing -> Left "unknown table" - synInstrToStruct FunCtx { ctxMod } (PlainInstr (TableCopy fromIdx toIdx)) = + synInstrToStruct FunCtx { ctxMod } (PlainInstr (TableCopy toIdx fromIdx)) = case getTableIndex ctxMod fromIdx of Just fromIdx -> case getTableIndex ctxMod toIdx of - Just toIdx -> return $ S.TableCopy fromIdx toIdx + Just toIdx -> return $ S.TableCopy toIdx fromIdx Nothing -> Left "unknown table" Nothing -> Left "unknown table" synInstrToStruct FunCtx { ctxMod } (PlainInstr (TableSet tableIdx)) = diff --git a/src/Language/Wasm/Validate.hs b/src/Language/Wasm/Validate.hs index 0591b2b..6eb9091 100644 --- a/src/Language/Wasm/Validate.hs +++ b/src/Language/Wasm/Validate.hs @@ -379,7 +379,7 @@ getInstrType (TableInit tableIdx elemIdx) = do let elemType = elems !! fromIntegral elemIdx when (elemType /= tableType) $ throwError (RefTypeMismatch tableType elemType) return $ [I32, I32, I32] ==> empty -getInstrType (TableCopy fromIdx toIdx) = do +getInstrType (TableCopy toIdx fromIdx) = do Ctx { tables } <- ask let (from, to) = (fromIntegral fromIdx, fromIntegral toIdx) when (length tables <= from) $ throwError (TableIndexOutOfRange fromIdx)