diff --git a/src/Language/Wasm/Interpreter.hs b/src/Language/Wasm/Interpreter.hs index 497fe01..c40fee9 100644 --- a/src/Language/Wasm/Interpreter.hs +++ b/src/Language/Wasm/Interpreter.hs @@ -948,6 +948,23 @@ eval budget store FunctionInstance { funcType, moduleInstance, code = Function { el <- MVector.unsafeRead fromEls (src + off) MVector.unsafeWrite toEls (dst + off) el return $ Done ctx { stack = rest } + step ctx@EvalCtx{ stack = (VI32 n:ref:VI32 i:rest) } (TableFill tableIdx) = do + let tableAddr = tableaddrs moduleInstance ! fromIntegral tableIdx + let TableInstance { items, t } = tableInstances store ! tableAddr + let TableType (Limit _ max) _ = t + let inc = fromIntegral n + let from = fromIntegral i + let val = case ref of + RE extRef -> fromIntegral <$> extRef + RF fnRef -> (funcaddrs moduleInstance !) . fromIntegral <$> fnRef + v -> error "Impossible due to validation" + els <- readIORef items + if from + inc > MVector.length els + then return Trap + else do + Monad.forM_ [0..inc - 1] $ \off -> + MVector.unsafeWrite els (from + off) val + return $ Done ctx { stack = rest } step ctx@EvalCtx{ stack } (TableSize 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 9160142..5112ea0 100644 --- a/src/Language/Wasm/Parser.y +++ b/src/Language/Wasm/Parser.y @@ -482,6 +482,7 @@ plaininstr :: { PlainInstr } | 'table.get' opt(index) { TableGet (fromMaybe (Index 0) $2) } | 'table.set' opt(index) { TableSet (fromMaybe (Index 0) $2) } | 'table.copy' opt(index) opt(index) { TableCopy (fromMaybe (Index 0) $2) (fromMaybe (Index 0) $3) } + | 'table.fill' opt(index) { TableFill (fromMaybe (Index 0) $2) } | 'table.size' opt(index) { TableSize (fromMaybe (Index 0) $2) } | 'table.grow' opt(index) { TableGrow (fromMaybe (Index 0) $2) } | 'elem.drop' index { ElemDrop $2 } @@ -1736,6 +1737,10 @@ desugarize fields = do case getTableIndex ctxMod tableIdx of Just tableIdx -> return $ S.TableSize tableIdx Nothing -> Left "unknown table" + synInstrToStruct FunCtx { ctxMod } (PlainInstr (TableFill tableIdx)) = + case getTableIndex ctxMod tableIdx of + Just tableIdx -> return $ S.TableFill tableIdx + Nothing -> Left "unknown table" synInstrToStruct FunCtx { ctxMod } (PlainInstr (TableGrow tableIdx)) = case getTableIndex ctxMod tableIdx of Just tableIdx -> return $ S.TableGrow tableIdx diff --git a/src/Language/Wasm/Validate.hs b/src/Language/Wasm/Validate.hs index df54e5d..9d031ee 100644 --- a/src/Language/Wasm/Validate.hs +++ b/src/Language/Wasm/Validate.hs @@ -393,6 +393,11 @@ getInstrType (TableCopy toIdx fromIdx) = do let TableType _ toType = tables !! to when (fromType /= toType) $ throwError (RefTypeMismatch fromType toType) return $ [I32, I32, I32] ==> empty +getInstrType (TableFill tableIdx) = do + Ctx { tables } <- ask + when (length tables <= fromIntegral tableIdx) $ throwError (TableIndexOutOfRange tableIdx) + let TableType _ tableType = tables !! fromIntegral tableIdx + return $ [I32, elemTypeToRefType tableType, I32] ==> empty getInstrType (TableSize tableIdx) = do Ctx { tables } <- ask when (length tables <= fromIntegral tableIdx) $ throwError (TableIndexOutOfRange tableIdx) diff --git a/tests/Test.hs b/tests/Test.hs index 45f8ec1..7d9ba9e 100644 --- a/tests/Test.hs +++ b/tests/Test.hs @@ -19,7 +19,7 @@ main = do files <- filter (not . List.isPrefixOf "simd") . filter (List.isSuffixOf ".wast") <$> Directory.listDirectory "tests/spec" - -- let files = ["ref_func.wast"] + -- let files = ["table_fill.wast"] scriptTestCases <- (`mapM` files) $ \file -> do test <- LBS.readFile ("tests/spec/" ++ file) return $ testCase file $ do