check imported values types
This commit is contained in:
@@ -24,7 +24,7 @@ module Language.Wasm.Interpreter (
|
|||||||
import qualified Data.Map as Map
|
import qualified Data.Map as Map
|
||||||
import qualified Data.Text.Lazy as TL
|
import qualified Data.Text.Lazy as TL
|
||||||
import qualified Data.ByteString.Lazy as LBS
|
import qualified Data.ByteString.Lazy as LBS
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe, isNothing)
|
||||||
|
|
||||||
import Data.Vector (Vector, (!), (!?), (//))
|
import Data.Vector (Vector, (!), (!?), (//))
|
||||||
import Data.Vector.Storable.Mutable (IOVector)
|
import Data.Vector.Storable.Mutable (IOVector)
|
||||||
@@ -158,19 +158,25 @@ data Label = Label ResultType deriving (Show, Eq)
|
|||||||
type Address = Int
|
type Address = Int
|
||||||
|
|
||||||
data TableInstance = TableInstance {
|
data TableInstance = TableInstance {
|
||||||
elements :: Vector (Maybe Address),
|
lim :: Limit,
|
||||||
maxLen :: Maybe Int
|
elements :: Vector (Maybe Address)
|
||||||
}
|
}
|
||||||
|
|
||||||
data MemoryInstance = MemoryInstance {
|
data MemoryInstance = MemoryInstance {
|
||||||
memory :: IOVector Word8,
|
lim :: Limit,
|
||||||
maxLen :: Maybe Int -- in page size (64Ki)
|
memory :: IORef (IOVector Word8)
|
||||||
}
|
}
|
||||||
|
|
||||||
data GlobalInstance = GIConst Value | GIMut (IORef Value)
|
data GlobalInstance = GIConst ValueType Value | GIMut ValueType (IORef Value)
|
||||||
|
|
||||||
makeMutGlobal :: Value -> IO GlobalInstance
|
makeMutGlobal :: Value -> IO GlobalInstance
|
||||||
makeMutGlobal val = GIMut <$> newIORef val
|
makeMutGlobal val = GIMut (getValueType val) <$> newIORef val
|
||||||
|
|
||||||
|
getValueType :: Value -> ValueType
|
||||||
|
getValueType (VI32 _) = I32
|
||||||
|
getValueType (VI64 _) = I64
|
||||||
|
getValueType (VF32 _) = F32
|
||||||
|
getValueType (VF64 _) = F64
|
||||||
|
|
||||||
data ExportInstance = ExportInstance TL.Text ExternalValue deriving (Eq, Show)
|
data ExportInstance = ExportInstance TL.Text ExternalValue deriving (Eq, Show)
|
||||||
|
|
||||||
@@ -195,7 +201,7 @@ data FunctionInstance =
|
|||||||
data Store = Store {
|
data Store = Store {
|
||||||
funcInstances :: Vector FunctionInstance,
|
funcInstances :: Vector FunctionInstance,
|
||||||
tableInstances :: Vector TableInstance,
|
tableInstances :: Vector TableInstance,
|
||||||
memInstances :: Vector (IORef MemoryInstance),
|
memInstances :: Vector MemoryInstance,
|
||||||
globalInstances :: Vector GlobalInstance
|
globalInstances :: Vector GlobalInstance
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -327,14 +333,10 @@ calcInstance (Store fs ts ms gs) imps Module {functions, types, tables, mems, gl
|
|||||||
let tableLen = length ts
|
let tableLen = length ts
|
||||||
let memLen = length ms
|
let memLen = length ms
|
||||||
let globalLen = length gs
|
let globalLen = length gs
|
||||||
let getImpIdx (Import m n _) =
|
funImps <- mapM checkImportType $ filter isFuncImport imports
|
||||||
case Map.lookup (m, n) imps of
|
tableImps <- mapM checkImportType $ filter isTableImport imports
|
||||||
Just idx -> Right idx
|
memImps <- mapM checkImportType $ filter isMemImport imports
|
||||||
Nothing -> Left $ "Cannot find import from module " ++ show m ++ " with name " ++ show n
|
globalImps <- mapM checkImportType $ filter isGlobalImport imports
|
||||||
funImps <- mapM getImpIdx $ filter isFuncImport imports
|
|
||||||
tableImps <- mapM getImpIdx $ filter isTableImport imports
|
|
||||||
memImps <- mapM getImpIdx $ filter isMemImport imports
|
|
||||||
globalImps <- mapM getImpIdx $ filter isGlobalImport imports
|
|
||||||
let funs = Vector.fromList $ map (\(ExternFunction i) -> i) funImps ++ [funLen..funLen + length functions - 1]
|
let funs = Vector.fromList $ map (\(ExternFunction i) -> i) funImps ++ [funLen..funLen + length functions - 1]
|
||||||
let tbls = Vector.fromList $ map (\(ExternTable i) -> i) tableImps ++ [tableLen..tableLen + length tables - 1]
|
let tbls = Vector.fromList $ map (\(ExternTable i) -> i) tableImps ++ [tableLen..tableLen + length tables - 1]
|
||||||
let memories = Vector.fromList $ map (\(ExternMemory i) -> i) memImps ++ [memLen..memLen + length mems - 1]
|
let memories = Vector.fromList $ map (\(ExternMemory i) -> i) memImps ++ [memLen..memLen + length mems - 1]
|
||||||
@@ -356,6 +358,59 @@ calcInstance (Store fs ts ms gs) imps Module {functions, types, tables, mems, gl
|
|||||||
globaladdrs = globs,
|
globaladdrs = globs,
|
||||||
exports = Vector.fromList $ map refExport exports
|
exports = Vector.fromList $ map refExport exports
|
||||||
}
|
}
|
||||||
|
where
|
||||||
|
getImpIdx :: Import -> Either String ExternalValue
|
||||||
|
getImpIdx (Import m n _) =
|
||||||
|
case Map.lookup (m, n) imps of
|
||||||
|
Just idx -> Right idx
|
||||||
|
Nothing -> Left $ "Cannot find import from module " ++ show m ++ " with name " ++ show n
|
||||||
|
|
||||||
|
checkImportType :: Import -> Either String ExternalValue
|
||||||
|
checkImportType imp@(Import _ _ (ImportFunc typeIdx)) = do
|
||||||
|
idx <- getImpIdx imp
|
||||||
|
funcAddr <- case idx of
|
||||||
|
ExternFunction funcAddr -> Right funcAddr
|
||||||
|
other -> Left "incompatible import type"
|
||||||
|
let expectedType = types !! fromIntegral typeIdx
|
||||||
|
let actualType = Language.Wasm.Interpreter.funcType $ fs ! funcAddr
|
||||||
|
if expectedType == actualType
|
||||||
|
then Right idx
|
||||||
|
else Left "incompatible import type"
|
||||||
|
checkImportType imp@(Import _ _ (ImportGlobal globalType)) = do
|
||||||
|
let err = Left "incompatible import type"
|
||||||
|
idx <- getImpIdx imp
|
||||||
|
globalAddr <- case idx of
|
||||||
|
ExternGlobal globalAddr -> Right globalAddr
|
||||||
|
_ -> err
|
||||||
|
let globalInst = gs ! globalAddr
|
||||||
|
let vt = case globalType of
|
||||||
|
Const vt -> vt
|
||||||
|
Mut vt -> vt
|
||||||
|
let vt' = case globalInst of
|
||||||
|
GIConst vt _ -> vt
|
||||||
|
GIMut vt _ -> vt
|
||||||
|
if vt == vt' then Right idx else err
|
||||||
|
checkImportType imp@(Import _ _ (ImportMemory limit)) = do
|
||||||
|
idx <- getImpIdx imp
|
||||||
|
memAddr <- case idx of
|
||||||
|
ExternMemory memAddr -> Right memAddr
|
||||||
|
_ -> Left "incompatible import type"
|
||||||
|
let MemoryInstance { lim } = ms ! memAddr
|
||||||
|
if limitMatch lim limit
|
||||||
|
then Right idx
|
||||||
|
else Left "incompatible import type"
|
||||||
|
checkImportType imp@(Import _ _ (ImportTable (TableType limit _))) = do
|
||||||
|
idx <- getImpIdx imp
|
||||||
|
tableAddr <- case idx of
|
||||||
|
ExternTable tableAddr -> Right tableAddr
|
||||||
|
_ -> Left "incompatible import type"
|
||||||
|
let TableInstance { lim } = ts ! tableAddr
|
||||||
|
if limitMatch lim limit
|
||||||
|
then Right idx
|
||||||
|
else Left "incompatible import type"
|
||||||
|
|
||||||
|
limitMatch :: Limit -> Limit -> Bool
|
||||||
|
limitMatch (Limit n1 m1) (Limit n2 m2) = n1 >= n2 && (isNothing m2 || fromMaybe False ((<=) <$> m1 <*> m2))
|
||||||
|
|
||||||
type Imports = Map.Map (TL.Text, TL.Text) ExternalValue
|
type Imports = Map.Map (TL.Text, TL.Text) ExternalValue
|
||||||
|
|
||||||
@@ -374,8 +429,8 @@ getGlobalValue inst store idx =
|
|||||||
Nothing -> error "Global index is out of range. It can happen if initializer refs non-import global."
|
Nothing -> error "Global index is out of range. It can happen if initializer refs non-import global."
|
||||||
in
|
in
|
||||||
case globalInstances store ! addr of
|
case globalInstances store ! addr of
|
||||||
GIConst v -> return v
|
GIConst _ v -> return v
|
||||||
GIMut ref -> readIORef ref
|
GIMut _ ref -> readIORef ref
|
||||||
|
|
||||||
-- due the validation there can be only these instructions
|
-- due the validation there can be only these instructions
|
||||||
evalConstExpr :: ModuleInstance -> Store -> [Instruction] -> IO Value
|
evalConstExpr :: ModuleInstance -> Store -> [Instruction] -> IO Value
|
||||||
@@ -395,33 +450,34 @@ allocAndInitGlobals inst store globs = Vector.fromList <$> mapM allocGlob globs
|
|||||||
runIniter = evalConstExpr inst store
|
runIniter = evalConstExpr inst store
|
||||||
|
|
||||||
allocGlob :: Global -> IO GlobalInstance
|
allocGlob :: Global -> IO GlobalInstance
|
||||||
allocGlob (Global (Const _) initer) = GIConst <$> runIniter initer
|
allocGlob (Global (Const vt) initer) = GIConst vt <$> runIniter initer
|
||||||
allocGlob (Global (Mut _) initer) = do
|
allocGlob (Global (Mut vt) initer) = do
|
||||||
val <- runIniter initer
|
val <- runIniter initer
|
||||||
GIMut <$> newIORef val
|
GIMut vt <$> newIORef val
|
||||||
|
|
||||||
allocTables :: [Table] -> Vector TableInstance
|
allocTables :: [Table] -> Vector TableInstance
|
||||||
allocTables tables = Vector.fromList $ map allocTable tables
|
allocTables tables = Vector.fromList $ map allocTable tables
|
||||||
where
|
where
|
||||||
allocTable :: Table -> TableInstance
|
allocTable :: Table -> TableInstance
|
||||||
allocTable (Table (TableType (Limit from to) _)) =
|
allocTable (Table (TableType lim@(Limit from to) _)) =
|
||||||
TableInstance {
|
TableInstance {
|
||||||
elements = Vector.fromList $ replicate (fromIntegral from) Nothing,
|
lim,
|
||||||
maxLen = fromIntegral <$> to
|
elements = Vector.fromList $ replicate (fromIntegral from) Nothing
|
||||||
}
|
}
|
||||||
|
|
||||||
pageSize :: Int
|
pageSize :: Int
|
||||||
pageSize = 64 * 1024
|
pageSize = 64 * 1024
|
||||||
|
|
||||||
allocMems :: [Memory] -> IO (Vector (IORef MemoryInstance))
|
allocMems :: [Memory] -> IO (Vector MemoryInstance)
|
||||||
allocMems mems = Vector.fromList <$> mapM allocMem mems
|
allocMems mems = Vector.fromList <$> mapM allocMem mems
|
||||||
where
|
where
|
||||||
allocMem :: Memory -> IO (IORef MemoryInstance)
|
allocMem :: Memory -> IO MemoryInstance
|
||||||
allocMem (Memory (Limit from to)) = do
|
allocMem (Memory lim@(Limit from to)) = do
|
||||||
memory <- IOVector.replicate (fromIntegral from * pageSize) 0
|
mem <- IOVector.replicate (fromIntegral from * pageSize) 0
|
||||||
newIORef MemoryInstance {
|
memory <- newIORef mem
|
||||||
memory,
|
return MemoryInstance {
|
||||||
maxLen = fromIntegral <$> to
|
lim,
|
||||||
|
memory
|
||||||
}
|
}
|
||||||
|
|
||||||
initialize :: ModuleInstance -> Module -> Store -> IO (Either String Store)
|
initialize :: ModuleInstance -> Module -> Store -> IO (Either String Store)
|
||||||
@@ -446,12 +502,12 @@ initialize inst Module {elems, datas, start} store = do
|
|||||||
let funcs = map ((funcaddrs inst !) . fromIntegral) funcIndexes
|
let funcs = map ((funcaddrs inst !) . fromIntegral) funcIndexes
|
||||||
let idx = tableaddrs inst ! fromIntegral tableIndex
|
let idx = tableaddrs inst ! fromIntegral tableIndex
|
||||||
let last = from + length funcs
|
let last = from + length funcs
|
||||||
let TableInstance elems maxLen = tableInstances st ! idx
|
let TableInstance lim elems = tableInstances st ! idx
|
||||||
let len = Vector.length elems
|
let len = Vector.length elems
|
||||||
if last > len
|
if last > len
|
||||||
then return $ Left "elements segment does not fit"
|
then return $ Left "elements segment does not fit"
|
||||||
else do
|
else do
|
||||||
let table = TableInstance (elems // zip [from..] (map Just funcs)) maxLen
|
let table = TableInstance lim (elems // zip [from..] (map Just funcs))
|
||||||
return $ Right st { tableInstances = tableInstances st Vector.// [(idx, table)] }
|
return $ Right st { tableInstances = tableInstances st Vector.// [(idx, table)] }
|
||||||
|
|
||||||
initData :: Either String Store -> DataSegment -> IO (Either String Store)
|
initData :: Either String Store -> DataSegment -> IO (Either String Store)
|
||||||
@@ -461,7 +517,8 @@ initialize inst Module {elems, datas, start} store = do
|
|||||||
let from = fromIntegral val
|
let from = fromIntegral val
|
||||||
let idx = memaddrs inst ! fromIntegral memIndex
|
let idx = memaddrs inst ! fromIntegral memIndex
|
||||||
let last = from + (fromIntegral $ LBS.length chunk)
|
let last = from + (fromIntegral $ LBS.length chunk)
|
||||||
MemoryInstance mem maxLen <- readIORef $ memInstances st ! idx
|
let MemoryInstance _ memory = memInstances st ! idx
|
||||||
|
mem <- readIORef memory
|
||||||
let len = IOVector.length mem
|
let len = IOVector.length mem
|
||||||
if last > len
|
if last > len
|
||||||
then return $ Left "data segment does not fit"
|
then return $ Left "data segment does not fit"
|
||||||
@@ -611,17 +668,18 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
step ctx (GetGlobal i) = do
|
step ctx (GetGlobal i) = do
|
||||||
let globalInst = globalInstances store ! (globaladdrs moduleInstance ! fromIntegral i)
|
let globalInst = globalInstances store ! (globaladdrs moduleInstance ! fromIntegral i)
|
||||||
val <- case globalInst of
|
val <- case globalInst of
|
||||||
GIConst v -> return v
|
GIConst _ v -> return v
|
||||||
GIMut ref -> readIORef ref
|
GIMut _ ref -> readIORef ref
|
||||||
return $ Done ctx { stack = val : stack ctx }
|
return $ Done ctx { stack = val : stack ctx }
|
||||||
step ctx@EvalCtx{ stack = (v:rest) } (SetGlobal i) = do
|
step ctx@EvalCtx{ stack = (v:rest) } (SetGlobal i) = do
|
||||||
let globalInst = globalInstances store ! (globaladdrs moduleInstance ! fromIntegral i)
|
let globalInst = globalInstances store ! (globaladdrs moduleInstance ! fromIntegral i)
|
||||||
case globalInst of
|
case globalInst of
|
||||||
GIConst v -> error "Attempt of mutation of constant global"
|
GIConst _ v -> error "Attempt of mutation of constant global"
|
||||||
GIMut ref -> writeIORef ref v
|
GIMut _ ref -> writeIORef ref v
|
||||||
return $ Done ctx { stack = rest }
|
return $ Done ctx { stack = rest }
|
||||||
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I32Load MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I32Load MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ v + fromIntegral offset
|
let addr = fromIntegral $ v + fromIntegral offset
|
||||||
let readByte idx = do
|
let readByte idx = do
|
||||||
byte <- IOVector.read memory $ addr + idx
|
byte <- IOVector.read memory $ addr + idx
|
||||||
@@ -629,7 +687,8 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
val <- sum <$> mapM readByte [0..3]
|
val <- sum <$> mapM readByte [0..3]
|
||||||
return $ Done ctx { stack = VI32 val : rest }
|
return $ Done ctx { stack = VI32 val : rest }
|
||||||
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I64Load MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I64Load MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ v + fromIntegral offset
|
let addr = fromIntegral $ v + fromIntegral offset
|
||||||
let readByte idx = do
|
let readByte idx = do
|
||||||
byte <- IOVector.read memory $ addr + idx
|
byte <- IOVector.read memory $ addr + idx
|
||||||
@@ -637,7 +696,8 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
val <- sum <$> mapM readByte [0..7]
|
val <- sum <$> mapM readByte [0..7]
|
||||||
return $ Done ctx { stack = VI64 val : rest }
|
return $ Done ctx { stack = VI64 val : rest }
|
||||||
step ctx@EvalCtx{ stack = (VI32 v:rest) } (F32Load MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI32 v:rest) } (F32Load MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ v + fromIntegral offset
|
let addr = fromIntegral $ v + fromIntegral offset
|
||||||
let readByte idx = do
|
let readByte idx = do
|
||||||
byte <- IOVector.read memory $ addr + idx
|
byte <- IOVector.read memory $ addr + idx
|
||||||
@@ -645,7 +705,8 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
val <- wordToFloat . sum <$> mapM readByte [0..3]
|
val <- wordToFloat . sum <$> mapM readByte [0..3]
|
||||||
return $ Done ctx { stack = VF32 val : rest }
|
return $ Done ctx { stack = VF32 val : rest }
|
||||||
step ctx@EvalCtx{ stack = (VI32 v:rest) } (F64Load MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI32 v:rest) } (F64Load MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ v + fromIntegral offset
|
let addr = fromIntegral $ v + fromIntegral offset
|
||||||
let readByte idx = do
|
let readByte idx = do
|
||||||
byte <- IOVector.read memory $ addr + idx
|
byte <- IOVector.read memory $ addr + idx
|
||||||
@@ -653,18 +714,21 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
val <- wordToDouble . sum <$> mapM readByte [0..7]
|
val <- wordToDouble . sum <$> mapM readByte [0..7]
|
||||||
return $ Done ctx { stack = VF64 val : rest }
|
return $ Done ctx { stack = VF64 val : rest }
|
||||||
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I32Load8U MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I32Load8U MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ v + fromIntegral offset
|
let addr = fromIntegral $ v + fromIntegral offset
|
||||||
byte <- IOVector.read memory addr
|
byte <- IOVector.read memory addr
|
||||||
return $ Done ctx { stack = VI32 (fromIntegral byte) : rest }
|
return $ Done ctx { stack = VI32 (fromIntegral byte) : rest }
|
||||||
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I32Load8S MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I32Load8S MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ v + fromIntegral offset
|
let addr = fromIntegral $ v + fromIntegral offset
|
||||||
byte <- IOVector.read memory addr
|
byte <- IOVector.read memory addr
|
||||||
let val = asWord32 $ if byte >= 128 then -1 * fromIntegral (0xFF - byte + 1) else fromIntegral byte
|
let val = asWord32 $ if byte >= 128 then -1 * fromIntegral (0xFF - byte + 1) else fromIntegral byte
|
||||||
return $ Done ctx { stack = VI32 val : rest }
|
return $ Done ctx { stack = VI32 val : rest }
|
||||||
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I32Load16U MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I32Load16U MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ v + fromIntegral offset
|
let addr = fromIntegral $ v + fromIntegral offset
|
||||||
let readByte idx = do
|
let readByte idx = do
|
||||||
byte <- IOVector.read memory $ addr + idx
|
byte <- IOVector.read memory $ addr + idx
|
||||||
@@ -672,7 +736,8 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
val <- sum <$> mapM readByte [0..1]
|
val <- sum <$> mapM readByte [0..1]
|
||||||
return $ Done ctx { stack = VI32 val : rest }
|
return $ Done ctx { stack = VI32 val : rest }
|
||||||
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I32Load16S MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I32Load16S MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ v + fromIntegral offset
|
let addr = fromIntegral $ v + fromIntegral offset
|
||||||
let readByte idx = do
|
let readByte idx = do
|
||||||
byte <- IOVector.read memory $ addr + idx
|
byte <- IOVector.read memory $ addr + idx
|
||||||
@@ -681,18 +746,21 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
let signed = asWord32 $ if val >= 2 ^ 15 then -1 * fromIntegral (0xFFFF - val + 1) else fromIntegral val
|
let signed = asWord32 $ if val >= 2 ^ 15 then -1 * fromIntegral (0xFFFF - val + 1) else fromIntegral val
|
||||||
return $ Done ctx { stack = VI32 signed : rest }
|
return $ Done ctx { stack = VI32 signed : rest }
|
||||||
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I64Load8U MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I64Load8U MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ v + fromIntegral offset
|
let addr = fromIntegral $ v + fromIntegral offset
|
||||||
byte <- IOVector.read memory addr
|
byte <- IOVector.read memory addr
|
||||||
return $ Done ctx { stack = VI64 (fromIntegral byte) : rest }
|
return $ Done ctx { stack = VI64 (fromIntegral byte) : rest }
|
||||||
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I64Load8S MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I64Load8S MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ v + fromIntegral offset
|
let addr = fromIntegral $ v + fromIntegral offset
|
||||||
byte <- IOVector.read memory addr
|
byte <- IOVector.read memory addr
|
||||||
let val = asWord64 $ if byte >= 128 then -1 * fromIntegral (0xFF - byte + 1) else fromIntegral byte
|
let val = asWord64 $ if byte >= 128 then -1 * fromIntegral (0xFF - byte + 1) else fromIntegral byte
|
||||||
return $ Done ctx { stack = VI64 val : rest }
|
return $ Done ctx { stack = VI64 val : rest }
|
||||||
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I64Load16U MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I64Load16U MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ v + fromIntegral offset
|
let addr = fromIntegral $ v + fromIntegral offset
|
||||||
let readByte idx = do
|
let readByte idx = do
|
||||||
byte <- IOVector.read memory $ addr + idx
|
byte <- IOVector.read memory $ addr + idx
|
||||||
@@ -700,7 +768,8 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
val <- sum <$> mapM readByte [0..1]
|
val <- sum <$> mapM readByte [0..1]
|
||||||
return $ Done ctx { stack = VI64 val : rest }
|
return $ Done ctx { stack = VI64 val : rest }
|
||||||
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I64Load16S MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I64Load16S MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ v + fromIntegral offset
|
let addr = fromIntegral $ v + fromIntegral offset
|
||||||
let readByte idx = do
|
let readByte idx = do
|
||||||
byte <- IOVector.read memory $ addr + idx
|
byte <- IOVector.read memory $ addr + idx
|
||||||
@@ -709,7 +778,8 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
let signed = asWord64 $ if val >= 2 ^ 15 then -1 * fromIntegral (0xFFFF - val + 1) else fromIntegral val
|
let signed = asWord64 $ if val >= 2 ^ 15 then -1 * fromIntegral (0xFFFF - val + 1) else fromIntegral val
|
||||||
return $ Done ctx { stack = VI64 signed : rest }
|
return $ Done ctx { stack = VI64 signed : rest }
|
||||||
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I64Load32U MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I64Load32U MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ v + fromIntegral offset
|
let addr = fromIntegral $ v + fromIntegral offset
|
||||||
let readByte idx = do
|
let readByte idx = do
|
||||||
byte <- IOVector.read memory $ addr + idx
|
byte <- IOVector.read memory $ addr + idx
|
||||||
@@ -717,7 +787,8 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
val <- sum <$> mapM readByte [0..3]
|
val <- sum <$> mapM readByte [0..3]
|
||||||
return $ Done ctx { stack = VI64 val : rest }
|
return $ Done ctx { stack = VI64 val : rest }
|
||||||
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I64Load32S MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI32 v:rest) } (I64Load32S MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ v + fromIntegral offset
|
let addr = fromIntegral $ v + fromIntegral offset
|
||||||
let readByte idx = do
|
let readByte idx = do
|
||||||
byte <- IOVector.read memory $ addr + idx
|
byte <- IOVector.read memory $ addr + idx
|
||||||
@@ -726,7 +797,8 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
let signed = asWord64 $ fromIntegral $ asInt32 val
|
let signed = asWord64 $ fromIntegral $ asInt32 val
|
||||||
return $ Done ctx { stack = VI64 signed : rest }
|
return $ Done ctx { stack = VI64 signed : rest }
|
||||||
step ctx@EvalCtx{ stack = (VI32 v:VI32 va:rest) } (I32Store MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI32 v:VI32 va:rest) } (I32Store MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ va + fromIntegral offset
|
let addr = fromIntegral $ va + fromIntegral offset
|
||||||
let writeByte idx = do
|
let writeByte idx = do
|
||||||
let byte = fromIntegral $ v `shiftR` (idx * 8) .&. 0xFF
|
let byte = fromIntegral $ v `shiftR` (idx * 8) .&. 0xFF
|
||||||
@@ -734,7 +806,8 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
mapM_ writeByte [0..3]
|
mapM_ writeByte [0..3]
|
||||||
return $ Done ctx { stack = rest }
|
return $ Done ctx { stack = rest }
|
||||||
step ctx@EvalCtx{ stack = (VI64 v:VI32 va:rest) } (I64Store MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI64 v:VI32 va:rest) } (I64Store MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ va + fromIntegral offset
|
let addr = fromIntegral $ va + fromIntegral offset
|
||||||
let writeByte idx = do
|
let writeByte idx = do
|
||||||
let byte = fromIntegral $ v `shiftR` (idx * 8) .&. 0xFF
|
let byte = fromIntegral $ v `shiftR` (idx * 8) .&. 0xFF
|
||||||
@@ -742,7 +815,8 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
mapM_ writeByte [0..7]
|
mapM_ writeByte [0..7]
|
||||||
return $ Done ctx { stack = rest }
|
return $ Done ctx { stack = rest }
|
||||||
step ctx@EvalCtx{ stack = (VF32 f:VI32 va:rest) } (F32Store MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VF32 f:VI32 va:rest) } (F32Store MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ va + fromIntegral offset
|
let addr = fromIntegral $ va + fromIntegral offset
|
||||||
let v = floatToWord f
|
let v = floatToWord f
|
||||||
let writeByte idx = do
|
let writeByte idx = do
|
||||||
@@ -751,7 +825,8 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
mapM_ writeByte [0..3]
|
mapM_ writeByte [0..3]
|
||||||
return $ Done ctx { stack = rest }
|
return $ Done ctx { stack = rest }
|
||||||
step ctx@EvalCtx{ stack = (VF64 f:VI32 va:rest) } (F64Store MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VF64 f:VI32 va:rest) } (F64Store MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ va + fromIntegral offset
|
let addr = fromIntegral $ va + fromIntegral offset
|
||||||
let v = doubleToWord f
|
let v = doubleToWord f
|
||||||
let writeByte idx = do
|
let writeByte idx = do
|
||||||
@@ -760,7 +835,8 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
mapM_ writeByte [0..7]
|
mapM_ writeByte [0..7]
|
||||||
return $ Done ctx { stack = rest }
|
return $ Done ctx { stack = rest }
|
||||||
step ctx@EvalCtx{ stack = (VI32 v:VI32 va:rest) } (I32Store8 MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI32 v:VI32 va:rest) } (I32Store8 MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ va + fromIntegral offset
|
let addr = fromIntegral $ va + fromIntegral offset
|
||||||
let writeByte idx = do
|
let writeByte idx = do
|
||||||
let byte = fromIntegral $ v `shiftR` (idx * 8) .&. 0xFF
|
let byte = fromIntegral $ v `shiftR` (idx * 8) .&. 0xFF
|
||||||
@@ -768,7 +844,8 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
mapM_ writeByte [0]
|
mapM_ writeByte [0]
|
||||||
return $ Done ctx { stack = rest }
|
return $ Done ctx { stack = rest }
|
||||||
step ctx@EvalCtx{ stack = (VI32 v:VI32 va:rest) } (I32Store16 MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI32 v:VI32 va:rest) } (I32Store16 MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ va + fromIntegral offset
|
let addr = fromIntegral $ va + fromIntegral offset
|
||||||
let writeByte idx = do
|
let writeByte idx = do
|
||||||
let byte = fromIntegral $ v `shiftR` (idx * 8) .&. 0xFF
|
let byte = fromIntegral $ v `shiftR` (idx * 8) .&. 0xFF
|
||||||
@@ -776,7 +853,8 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
mapM_ writeByte [0, 1]
|
mapM_ writeByte [0, 1]
|
||||||
return $ Done ctx { stack = rest }
|
return $ Done ctx { stack = rest }
|
||||||
step ctx@EvalCtx{ stack = (VI64 v:VI32 va:rest) } (I64Store8 MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI64 v:VI32 va:rest) } (I64Store8 MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ va + fromIntegral offset
|
let addr = fromIntegral $ va + fromIntegral offset
|
||||||
let writeByte idx = do
|
let writeByte idx = do
|
||||||
let byte = fromIntegral $ v `shiftR` (idx * 8) .&. 0xFF
|
let byte = fromIntegral $ v `shiftR` (idx * 8) .&. 0xFF
|
||||||
@@ -784,7 +862,8 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
mapM_ writeByte [0]
|
mapM_ writeByte [0]
|
||||||
return $ Done ctx { stack = rest }
|
return $ Done ctx { stack = rest }
|
||||||
step ctx@EvalCtx{ stack = (VI64 v:VI32 va:rest) } (I64Store16 MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI64 v:VI32 va:rest) } (I64Store16 MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ va + fromIntegral offset
|
let addr = fromIntegral $ va + fromIntegral offset
|
||||||
let writeByte idx = do
|
let writeByte idx = do
|
||||||
let byte = fromIntegral $ v `shiftR` (idx * 8) .&. 0xFF
|
let byte = fromIntegral $ v `shiftR` (idx * 8) .&. 0xFF
|
||||||
@@ -792,7 +871,8 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
mapM_ writeByte [0, 1]
|
mapM_ writeByte [0, 1]
|
||||||
return $ Done ctx { stack = rest }
|
return $ Done ctx { stack = rest }
|
||||||
step ctx@EvalCtx{ stack = (VI64 v:VI32 va:rest) } (I64Store32 MemArg { offset }) = do
|
step ctx@EvalCtx{ stack = (VI64 v:VI32 va:rest) } (I64Store32 MemArg { offset }) = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let addr = fromIntegral $ va + fromIntegral offset
|
let addr = fromIntegral $ va + fromIntegral offset
|
||||||
let writeByte idx = do
|
let writeByte idx = do
|
||||||
let byte = fromIntegral $ v `shiftR` (idx * 8) .&. 0xFF
|
let byte = fromIntegral $ v `shiftR` (idx * 8) .&. 0xFF
|
||||||
@@ -800,19 +880,20 @@ eval store FunctionInstance { funcType, moduleInstance, code = Function { localT
|
|||||||
mapM_ writeByte [0..3]
|
mapM_ writeByte [0..3]
|
||||||
return $ Done ctx { stack = rest }
|
return $ Done ctx { stack = rest }
|
||||||
step ctx@EvalCtx{ stack = st } CurrentMemory = do
|
step ctx@EvalCtx{ stack = st } CurrentMemory = do
|
||||||
MemoryInstance { memory } <- readIORef $ memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
|
memory <- readIORef memoryRef
|
||||||
let size = fromIntegral $ IOVector.length memory `div` pageSize
|
let size = fromIntegral $ IOVector.length memory `div` pageSize
|
||||||
return $ Done ctx { stack = VI32 size : st }
|
return $ Done ctx { stack = VI32 size : st }
|
||||||
step ctx@EvalCtx{ stack = (VI32 n:rest) } GrowMemory = do
|
step ctx@EvalCtx{ stack = (VI32 n:rest) } GrowMemory = do
|
||||||
let ref = memInstances store ! (memaddrs moduleInstance ! 0)
|
let MemoryInstance { lim = limit@(Limit _ maxLen), memory = memoryRef } = memInstances store ! (memaddrs moduleInstance ! 0)
|
||||||
MemoryInstance { memory, maxLen } <- readIORef ref
|
memory <- readIORef memoryRef
|
||||||
let size = fromIntegral $ IOVector.length memory `quot` pageSize
|
let size = fromIntegral $ IOVector.length memory `quot` pageSize
|
||||||
let growTo = size + fromIntegral n
|
let growTo = size + fromIntegral n
|
||||||
result <- (
|
result <- (
|
||||||
if fromMaybe True ((growTo <=) <$> maxLen) && growTo <= 0xFFFF
|
if fromMaybe True ((growTo <=) . fromIntegral <$> maxLen) && growTo <= 0xFFFF
|
||||||
then do
|
then do
|
||||||
mem' <- IOVector.grow memory $ fromIntegral n * pageSize
|
mem' <- IOVector.grow memory $ fromIntegral n * pageSize
|
||||||
writeIORef ref $ MemoryInstance mem' maxLen
|
writeIORef memoryRef mem'
|
||||||
return size
|
return size
|
||||||
else return $ -1
|
else return $ -1
|
||||||
)
|
)
|
||||||
@@ -1085,6 +1166,6 @@ getGlobalValueByName store ModuleInstance { exports } name =
|
|||||||
Just (ExportInstance _ (ExternGlobal addr)) ->
|
Just (ExportInstance _ (ExternGlobal addr)) ->
|
||||||
let globalInst = globalInstances store ! addr in
|
let globalInst = globalInstances store ! addr in
|
||||||
case globalInst of
|
case globalInst of
|
||||||
GIConst v -> return v
|
GIConst _ v -> return v
|
||||||
GIMut ref -> readIORef ref
|
GIMut _ ref -> readIORef ref
|
||||||
_ -> error $ "Function with name " ++ show name ++ " was not found in module's exports"
|
_ -> error $ "Function with name " ++ show name ++ " was not found in module's exports"
|
||||||
Reference in New Issue
Block a user