diff --git a/lvtrun/app/OpCodes.hs b/lvtrun/app/OpCodes.hs new file mode 100644 index 0000000..8f35c18 --- /dev/null +++ b/lvtrun/app/OpCodes.hs @@ -0,0 +1,143 @@ +{- +-- EPITECH PROJECT, 2023 +-- Leviator Run +-- File description: +-- OpCodes +-} + +module OpCodes +( + extractOpCode, + createInstruction +) +where + +import qualified Data.ByteString.Lazy as BSL +import Control.Exception (throw) +import Data.Word (Word8) + +import Leb128 +import Types +import Errors + +extractOpCode :: BSL.ByteString -> ([Word8], BSL.ByteString) +extractOpCode bytes + | (head $ BSL.unpack bytes) == 0x03 = ([0x00], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x11 = ([0x00], BSL.drop 3 bytes) + | (head $ BSL.unpack bytes) == 0x00 = ([0x00], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x0b = ([0x0b], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x0d = ([0x0d], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x0c = ([0x0c], BSL.drop 2 bytes) + | (head $ BSL.unpack bytes) == 0x02 = ([0x02], BSL.drop 2 bytes) + | (head $ BSL.unpack bytes) == 0x01 = ([0x01], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x0f = ([0x0f], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x10 = ([0x10], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x41 = ([0x41], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x42 = ([0x42], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x6c = ([0x6c], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x6d = ([0x6d], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x43 = ([0x43], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x44 = ([0x44], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x28 = ([0x28], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x29 = ([0x29], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x22 = ([0x22], BSL.drop 2 bytes) + | (head $ BSL.unpack bytes) == 0x36 = ([0x36], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x37 = ([0x37], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x4b = ([0x4b], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x37 = ([0x37], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x20 = ([0x20], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x4d = ([0x4d], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x21 = ([0x21], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x23 = ([0x23], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x24 = ([0x24], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x6a = ([0x6a], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x6b = ([0x6b], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x45 = ([0x45], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x46 = ([0x46], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x71 = ([0x00], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x48 = ([0x48], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x4a = ([0x4a], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x4c = ([0x4c], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x4e = ([0x4e], BSL.drop 1 bytes) + | (head $ BSL.unpack bytes) == 0x47 = ([0x47], BSL.drop 1 bytes) + | (BSL.unpack $ BSL.take 2 bytes) == [0x3f, 0x00] = ([0x3f, 0x00], BSL.drop 2 bytes) + | (BSL.unpack $ BSL.take 2 bytes) == [0x40, 0x00] = ([0x40, 0x00], BSL.drop 2 bytes) + | otherwise = throw $ WasmError "ExtractOpCode2: bad opcode" + +createInstruction :: OpCode -> BSL.ByteString -> (Instruction, BSL.ByteString) +createInstruction [0x03] bytes = (Nop, bytes) +createInstruction [0x11] bytes = (Nop, bytes) +createInstruction [0x00] bytes = (Unreachable, bytes) +createInstruction [0x01] bytes = (Nop, bytes) +createInstruction [0x02] bytes = (Block EmptyType, bytes) +createInstruction [0x0b] bytes = (End, bytes) +createInstruction [0x48] bytes = (I32Lts, bytes) +createInstruction [0x0f] bytes = (Return, bytes) +createInstruction [0x4b] bytes = (I32Gtu, bytes) +createInstruction [0x6a] bytes = (I32Add, bytes) +createInstruction [0x6c] bytes = (I32Mul, bytes) +createInstruction [0x6d] bytes = (I32Divs, bytes) +createInstruction [0x47] bytes = (I32Ne, bytes) +createInstruction [0x6b] bytes = (I32Sub, bytes) +createInstruction [0x4a] bytes = (I32Gts, bytes) +createInstruction [0x46] bytes = (I32Eqz, bytes) +createInstruction [0x45] bytes = (I32Eqz, bytes) +createInstruction [0x4d] bytes = (I32Leu, bytes) +createInstruction [0x4e] bytes = (I32Ges, bytes) +createInstruction [0x4c] bytes = (I32Les, bytes) +createInstruction [0x71] bytes = (I32And, bytes) +createInstruction [0x0d] bytes = do + let (value, rest) = getLEB128ToI32 bytes + (BrIf value, rest) +createInstruction [0x0c] bytes = do + let (value, rest) = getLEB128ToI32 bytes + (Br value, rest) +createInstruction [0x22] bytes = do + let (value, rest) = getLEB128ToI32 bytes + (LocalTee value, rest) +createInstruction [0x10] bytes = do + let (value, rest) = getLEB128ToI32 bytes + (Call value, rest) +createInstruction [0x41] bytes = do + let (value, rest) = getLEB128ToI32 bytes + (I32Const value, rest) +createInstruction [0x42] bytes = do + let (value, rest) = getLEB128ToI64 bytes + (I64Const value, rest) +createInstruction [0x43] bytes = do + let (value, rest) = getLEB128ToI64 bytes + (F32Const (fromIntegral value), rest) +createInstruction [0x44] bytes = do + let (value, rest) = getLEB128ToI64 bytes + (F64Const (fromIntegral value), rest) +createInstruction [0x28] bytes = do + let (align, rest) = getLEB128ToI32 bytes + let (offset, rest2) = getLEB128ToI32 rest + (I32Load (MemArg offset align), rest2) +createInstruction [0x29] bytes = do + let (align, rest) = getLEB128ToI32 bytes + let (offset, rest2) = getLEB128ToI32 rest + (I64Load (MemArg offset align), rest2) +createInstruction [0x36] bytes = do + let (align, rest) = getLEB128ToI32 bytes + let (offset, rest2) = getLEB128ToI32 rest + (I32Store (MemArg offset align), rest2) +createInstruction [0x37] bytes = do + let (align, rest) = getLEB128ToI32 bytes + let (offset, rest2) = getLEB128ToI32 rest + (I64Store (MemArg offset align), rest2) +createInstruction [0x20] bytes = do + let (value, rest) = getLEB128ToI32 bytes + (GetLocal value, rest) +createInstruction [0x24] bytes = do + let (value, rest) = getLEB128ToI32 bytes + (SetGlobal value, rest) +createInstruction [0x23] bytes = do + let (value, rest) = getLEB128ToI32 bytes + (GetGlobal value, rest) +createInstruction [0x21] bytes = do + let (value, rest) = getLEB128ToI32 bytes + (SetLocal value, rest) +createInstruction [0x3f, 0x00] bytes = (MemorySize, bytes) +createInstruction [0x40, 0x00] bytes = (MemoryGrow, bytes) +createInstruction _ _ = throw $ WasmError "createInstruction: bad instruction" diff --git a/lvtrun/app/Parsing/Code.hs b/lvtrun/app/Parsing/Code.hs index df63896..d79411f 100644 --- a/lvtrun/app/Parsing/Code.hs +++ b/lvtrun/app/Parsing/Code.hs @@ -6,23 +6,19 @@ -} module Parsing.Code - ( - getFuncCode, - ) +( + getFuncCode, +) where import qualified Data.ByteString.Lazy as BSL import Control.Exception (throw) -import Control.Monad (when) -import Data.Word (Word8) -import Data.Int (Int64, Int32) -import Numeric (showHex) +import Data.Int (Int64) import Leb128 import Types import Errors - --- GET LOCALS +import OpCodes diviseBytes :: BSL.ByteString -> [BSL.ByteString] diviseBytes bytes @@ -55,136 +51,11 @@ extractLocals id idMax bytes ------------------------- -extractOpCode :: BSL.ByteString -> ([Word8], Int64, BSL.ByteString) -extractOpCode bytes - | (head $ BSL.unpack bytes) == 0x03 = ([0x00], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x11 = ([0x00], 1, BSL.drop 3 bytes) - - | (head $ BSL.unpack bytes) == 0x00 = ([0x00], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x0b = ([0x0b], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x0d = ([0x0d], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x0c = ([0x0c], 1, BSL.drop 2 bytes) - | (head $ BSL.unpack bytes) == 0x02 = ([0x02], 1, BSL.drop 2 bytes) - - | (head $ BSL.unpack bytes) == 0x01 = ([0x01], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x0f = ([0x0f], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x10 = ([0x10], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x41 = ([0x41], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x42 = ([0x42], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x6c = ([0x6c], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x6d = ([0x6d], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x43 = ([0x43], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x44 = ([0x44], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x28 = ([0x28], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x29 = ([0x29], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x22 = ([0x22], 1, BSL.drop 2 bytes) - | (head $ BSL.unpack bytes) == 0x36 = ([0x36], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x37 = ([0x37], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x4b = ([0x4b], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x37 = ([0x37], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x20 = ([0x20], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x4d = ([0x4d], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x21 = ([0x21], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x23 = ([0x23], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x24 = ([0x24], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x6a = ([0x6a], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x6b = ([0x6b], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x45 = ([0x45], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x46 = ([0x46], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x71 = ([0x00], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x48 = ([0x48], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x4a = ([0x4a], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x4c = ([0x4c], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x4e = ([0x4e], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x47 = ([0x47], 1, BSL.drop 1 bytes) - | (BSL.unpack $ BSL.take 2 bytes) == [0x3f, 0x00] = ([0x3f, 0x00], 2, BSL.drop 2 bytes) - | (BSL.unpack $ BSL.take 2 bytes) == [0x40, 0x00] = ([0x40, 0x00], 2, BSL.drop 2 bytes) - | otherwise = throw $ WasmError "ExtractOpCode2: bad opcode" - -createInstruction :: OpCode -> BSL.ByteString -> (Instruction, BSL.ByteString) -createInstruction [0x03] bytes = (Nop, bytes) -createInstruction [0x11] bytes = (Nop, bytes) - -createInstruction [0x00] bytes = (Unreachable, bytes) -createInstruction [0x01] bytes = (Nop, bytes) -createInstruction [0x02] bytes = (Block EmptyType, bytes) -createInstruction [0x0b] bytes = (End, bytes) -createInstruction [0x48] bytes = (I32Lts, bytes) -createInstruction [0x0f] bytes = (Return, bytes) -createInstruction [0x4b] bytes = (I32Gtu, bytes) -createInstruction [0x6a] bytes = (I32Add, bytes) -createInstruction [0x6c] bytes = (I32Mul, bytes) -createInstruction [0x6d] bytes = (I32Divs, bytes) -createInstruction [0x47] bytes = (I32Ne, bytes) -createInstruction [0x6b] bytes = (I32Sub, bytes) -createInstruction [0x4a] bytes = (I32Gts, bytes) -createInstruction [0x46] bytes = (I32Eqz, bytes) -createInstruction [0x45] bytes = (I32Eqz, bytes) -createInstruction [0x4d] bytes = (I32Leu, bytes) -createInstruction [0x4e] bytes = (I32Ges, bytes) -createInstruction [0x4c] bytes = (I32Les, bytes) -createInstruction [0x71] bytes = (I32And, bytes) -createInstruction [0x0d] bytes = do - let (value, rest) = getLEB128ToI32 bytes - (BrIf value, rest) -createInstruction [0x0c] bytes = do - let (value, rest) = getLEB128ToI32 bytes - (Br value, rest) -createInstruction [0x22] bytes = do - let (value, rest) = getLEB128ToI32 bytes - (LocalTee value, rest) -createInstruction [0x10] bytes = do - let (value, rest) = getLEB128ToI32 bytes - (Call value, rest) -createInstruction [0x41] bytes = do - let (value, rest) = getLEB128ToI32 bytes - (I32Const value, rest) -createInstruction [0x42] bytes = do - let (value, rest) = getLEB128ToI64 bytes - (I64Const value, rest) -createInstruction [0x43] bytes = do - let (value, rest) = getLEB128ToI64 bytes - (F32Const (fromIntegral value), rest) -createInstruction [0x44] bytes = do - let (value, rest) = getLEB128ToI64 bytes - (F64Const (fromIntegral value), rest) -createInstruction [0x28] bytes = do - let (align, rest) = getLEB128ToI32 bytes - let (offset, rest2) = getLEB128ToI32 rest - (I32Load (MemArg offset align), rest2) -createInstruction [0x29] bytes = do - let (align, rest) = getLEB128ToI32 bytes - let (offset, rest2) = getLEB128ToI32 rest - (I64Load (MemArg offset align), rest2) -createInstruction [0x36] bytes = do - let (align, rest) = getLEB128ToI32 bytes - let (offset, rest2) = getLEB128ToI32 rest - (I32Store (MemArg offset align), rest2) -createInstruction [0x37] bytes = do - let (align, rest) = getLEB128ToI32 bytes - let (offset, rest2) = getLEB128ToI32 rest - (I64Store (MemArg offset align), rest2) -createInstruction [0x20] bytes = do - let (value, rest) = getLEB128ToI32 bytes - (GetLocal value, rest) -createInstruction [0x24] bytes = do - let (value, rest) = getLEB128ToI32 bytes - (SetGlobal value, rest) -createInstruction [0x23] bytes = do - let (value, rest) = getLEB128ToI32 bytes - (GetGlobal value, rest) -createInstruction [0x21] bytes = do - let (value, rest) = getLEB128ToI32 bytes - (SetLocal value, rest) -createInstruction [0x3f, 0x00] bytes = (MemorySize, bytes) -createInstruction [0x40, 0x00] bytes = (MemoryGrow, bytes) -createInstruction opCode _ = throw $ WasmError "createInstruction: bad instruction" - parseInstruction :: BSL.ByteString -> (Instruction, BSL.ByteString) parseInstruction bytes | BSL.length bytes == 0 = throw $ WasmError "ParseInstruction: no instruction" | otherwise = do - let (opCode, nbParams, rest) = extractOpCode bytes + let (opCode, rest) = extractOpCode bytes let (instruction, rest2) = createInstruction opCode rest (instruction, rest2) @@ -195,14 +66,6 @@ extractCode bytes let (instruction, rest) = parseInstruction bytes instruction : extractCode rest ------------------------- - -showBytes :: BSL.ByteString -> String -showBytes bytes = do - let bytesList = BSL.unpack bytes - let hexList = map (\x -> showHex x " ") bytesList - foldl (\acc x -> acc ++ x) " " hexList - parseFunction :: BSL.ByteString -> Function -> Function parseFunction bytes func = do let (nbLocalsTypes, rest) = getLEB128ToI64 bytes diff --git a/lvtrun/app/Parsing/Exports.hs b/lvtrun/app/Parsing/Exports.hs index 640aa2b..ea4c375 100644 --- a/lvtrun/app/Parsing/Exports.hs +++ b/lvtrun/app/Parsing/Exports.hs @@ -6,9 +6,9 @@ -} module Parsing.Exports - ( - getExports - ) +( + getExports +) where import qualified Data.ByteString.Lazy as Bs @@ -58,10 +58,6 @@ parseExports idx maxIdx content let export = createExport (Bs.unpack name) exportType exportValue export : parseExports (idx + 1) maxIdx rest3 -printHex :: [Word8] -> String -printHex [] = [] -printHex (x:xs) = showHex x " " ++ printHex xs - getExports :: Section -> [Export] getExports (Section ExportID _ content) = do let (exprtsNb, rest) = getExportNb content diff --git a/lvtrun/app/Parsing/FuncTypes.hs b/lvtrun/app/Parsing/FuncTypes.hs index 0ddf465..18c69eb 100644 --- a/lvtrun/app/Parsing/FuncTypes.hs +++ b/lvtrun/app/Parsing/FuncTypes.hs @@ -6,19 +6,18 @@ -} module Parsing.FuncTypes - ( - getFuncTypes - ) +( + getFuncTypes +) where import qualified Data.ByteString.Lazy as Bs import Control.Exception (throw) import Data.Int (Int64, Int32) -import Data.Word (Word8) -import Leb128 -import Errors -import Types +import Leb128 (getLEB128ToI64) +import Errors (CustomException(..)) +import Types (TypeName(..), FuncType(..), Section(..), SectionID(..), getTypeFromByte) getVectorSize :: Bs.ByteString -> (Int64, Bs.ByteString) getVectorSize content = getLEB128ToI64 content @@ -29,10 +28,10 @@ extractTypes (idx, content) = (getTypeFromByte (head $ Bs.unpack content) : type where (types, rest) = extractTypes (idx - 1, Bs.drop 1 content) parseFuncType :: Int32 -> Bs.ByteString -> (FuncType, Bs.ByteString) -parseFuncType id content = do +parseFuncType id content = let (params, rest) = extractTypes (getVectorSize content) - let (results, rest2) = extractTypes (getVectorSize rest) - ((FuncType id params results), rest2) + (results, rest2) = extractTypes (getVectorSize rest) + in (FuncType id params results, rest2) parseFuncTypes :: Int32 -> Int64 -> Bs.ByteString -> [FuncType] parseFuncTypes idx maxIdx content diff --git a/lvtrun/app/Parsing/Functions.hs b/lvtrun/app/Parsing/Functions.hs index 184c130..beb429f 100644 --- a/lvtrun/app/Parsing/Functions.hs +++ b/lvtrun/app/Parsing/Functions.hs @@ -14,7 +14,6 @@ where import qualified Data.ByteString.Lazy as BSL import Control.Exception (throw) import Data.Int (Int64, Int32) -import Data.Word (Word8) import Types import Errors @@ -26,7 +25,11 @@ parseFunctionsIndex idx maxIdx content | BSL.length content == 0 = [] | otherwise = do let (typeIdx, rest) = getLEB128ToI32 content - Function {funcType = fromIntegral typeIdx, funcIdx = idx, body = []} : parseFunctionsIndex (idx + 1) maxIdx rest + Function { + funcType = fromIntegral typeIdx, + funcIdx = idx, + body = [] + } : parseFunctionsIndex (idx + 1) maxIdx rest getFunctions :: Section -> [Function] getFunctions (Section FunctionID _ content) = do diff --git a/lvtrun/app/Parsing/Global.hs b/lvtrun/app/Parsing/Global.hs index b28b820..0d9cfe0 100644 --- a/lvtrun/app/Parsing/Global.hs +++ b/lvtrun/app/Parsing/Global.hs @@ -13,113 +13,19 @@ where import qualified Data.ByteString.Lazy as BSL import Control.Exception (throw) -import Control.Monad (when) import Data.Word (Word8) import Data.Int (Int64) import Leb128 import Types import Errors - -extractOpCode :: BSL.ByteString -> ([Word8], Int64, BSL.ByteString) -extractOpCode bytes - | (head $ BSL.unpack bytes) == 0x00 = ([0x00], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x01 = ([0x01], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x0f = ([0x0f], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x10 = ([0x10], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x41 = ([0x41], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x42 = ([0x42], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x43 = ([0x43], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x44 = ([0x44], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x28 = ([0x28], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x29 = ([0x29], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x36 = ([0x36], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x37 = ([0x37], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x37 = ([0x37], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x20 = ([0x20], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x6c = ([0x6c], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x6d = ([0x6d], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x21 = ([0x21], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x23 = ([0x23], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x24 = ([0x24], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x6a = ([0x6a], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x6b = ([0x6b], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x46 = ([0x46], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x48 = ([0x48], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x4a = ([0x4a], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x4c = ([0x4c], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x4e = ([0x4e], 1, BSL.drop 1 bytes) - | (head $ BSL.unpack bytes) == 0x47 = ([0x47], 1, BSL.drop 1 bytes) - | (BSL.unpack $ BSL.take 2 bytes) == [0x3f, 0x00] = ([0x3f, 0x00], 2, BSL.drop 2 bytes) - | (BSL.unpack $ BSL.take 2 bytes) == [0x40, 0x00] = ([0x40, 0x00], 2, BSL.drop 2 bytes) - | otherwise = throw $ WasmError "ExtractOpCode2: bad opcode" - -createInstruction :: OpCode -> BSL.ByteString -> (Instruction, BSL.ByteString) -createInstruction [0x01] bytes = (Unreachable, bytes) -createInstruction [0x01] bytes = (Nop, bytes) -createInstruction [0x0f] bytes = (Return, bytes) -createInstruction [0x6a] bytes = (I32Add, bytes) -createInstruction [0x6b] bytes = (I32Sub, bytes) -createInstruction [0x48] bytes = (I32Lts, bytes) -createInstruction [0x6c] bytes = (I32Mul, bytes) -createInstruction [0x6d] bytes = (I32Divs, bytes) -createInstruction [0x4e] bytes = (I32Ges, bytes) -createInstruction [0x4c] bytes = (I32Les, bytes) -createInstruction [0x4a] bytes = (I32Gts, bytes) -createInstruction [0x46] bytes = (I32Eqz, bytes) -createInstruction [0x47] bytes = (I32Ne, bytes) -createInstruction [0x10] bytes = do - let (value, rest) = getLEB128ToI32 bytes - (Call value, rest) -createInstruction [0x41] bytes = do - let (value, rest) = getLEB128ToI32 bytes - (I32Const value, rest) -createInstruction [0x42] bytes = do - let (value, rest) = getLEB128ToI64 bytes - (I64Const value, rest) -createInstruction [0x43] bytes = do - let (value, rest) = getLEB128ToI64 bytes - (F32Const (fromIntegral value), rest) -createInstruction [0x44] bytes = do - let (value, rest) = getLEB128ToI64 bytes - (F64Const (fromIntegral value), rest) -createInstruction [0x28] bytes = do - let (align, rest) = getLEB128ToI32 bytes - let (offset, rest2) = getLEB128ToI32 rest - (I32Load (MemArg align offset), rest2) -createInstruction [0x29] bytes = do - let (align, rest) = getLEB128ToI32 bytes - let (offset, rest2) = getLEB128ToI32 rest - (I64Load (MemArg align offset), rest2) -createInstruction [0x36] bytes = do - let (align, rest) = getLEB128ToI32 bytes - let (offset, rest2) = getLEB128ToI32 rest - (I32Store (MemArg align offset), rest2) -createInstruction [0x37] bytes = do - let (align, rest) = getLEB128ToI32 bytes - let (offset, rest2) = getLEB128ToI32 rest - (I64Store (MemArg align offset), rest2) -createInstruction [0x20] bytes = do - let (value, rest) = getLEB128ToI32 bytes - (GetLocal value, rest) -createInstruction [0x24] bytes = do - let (value, rest) = getLEB128ToI32 bytes - (SetGlobal value, rest) -createInstruction [0x23] bytes = do - let (value, rest) = getLEB128ToI32 bytes - (GetGlobal value, rest) -createInstruction [0x21] bytes = do - let (value, rest) = getLEB128ToI32 bytes - (SetLocal value, rest) -createInstruction [0x3f, 0x00] bytes = (MemorySize, bytes) -createInstruction [0x40, 0x00] bytes = (MemoryGrow, bytes) -createInstruction _ _ = throw $ WasmError "CreateInstruction: bad instruction" +import OpCodes parseInstruction :: BSL.ByteString -> (Instruction, BSL.ByteString) parseInstruction bytes | BSL.length bytes == 0 = throw $ WasmError "ParseInstruction: no instruction" | otherwise = do - let (opCode, nbParams, rest) = extractOpCode bytes + let (opCode, rest) = extractOpCode bytes let (instruction, rest2) = createInstruction opCode rest (instruction, rest2) diff --git a/lvtrun/app/Parsing/Header.hs b/lvtrun/app/Parsing/Header.hs index d6aeecc..15f1a63 100644 --- a/lvtrun/app/Parsing/Header.hs +++ b/lvtrun/app/Parsing/Header.hs @@ -6,18 +6,20 @@ -} module Parsing.Header - ( - getModHeader, - isHeaderValid - ) +( + getModHeader, + isHeaderValid +) where -import qualified Data.ByteString.Lazy as BSL (ByteString, take, drop, pack) +import qualified Data.ByteString.Lazy as BSL (take, drop, pack) -import Types +import Types (ModHeader(..), Section(..)) getModHeader :: Section -> ModHeader -getModHeader bytes = ModHeader (BSL.take 4 $ content bytes) (BSL.take 4 $ BSL.drop 4 $ content bytes) +getModHeader bytes = ModHeader + (BSL.take 4 $ content bytes) + (BSL.take 4 $ BSL.drop 4 $ content bytes) isHeaderValid :: ModHeader -> Bool isHeaderValid header = diff --git a/lvtrun/app/Parsing/Memory.hs b/lvtrun/app/Parsing/Memory.hs index 5a42cc6..455681f 100644 --- a/lvtrun/app/Parsing/Memory.hs +++ b/lvtrun/app/Parsing/Memory.hs @@ -6,17 +6,16 @@ -} module Parsing.Memory - ( - getMemories - ) where +( + getMemories +) where -import qualified Data.ByteString.Lazy as BS import Control.Exception (throw) -import Control.Monad (when) +import qualified Data.ByteString.Lazy as BS (ByteString, drop, unpack, empty) -import Leb128 import Types -import Errors +import Leb128 (getLEB128ToI32) +import Errors (CustomException(..)) parseMinMax :: BS.ByteString -> Memory parseMinMax content @@ -44,5 +43,3 @@ getMemories (Section MemoryID _ content) | head (BS.unpack content) == 0x01 = parseMemory (BS.drop 1 content) | otherwise = throw $ WasmError "getMemories: v1 allow 1 memory only" getMemories _ = throw $ WasmError "getMemories: bad memory section" - ---https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances diff --git a/lvtrun/app/Parsing/Parser.hs b/lvtrun/app/Parsing/Parser.hs index b5e067b..bf0b226 100644 --- a/lvtrun/app/Parsing/Parser.hs +++ b/lvtrun/app/Parsing/Parser.hs @@ -12,23 +12,28 @@ module Parsing.Parser where import Types -import Parsing.Sections -import Parsing.Header -import Parsing.Memory -import Parsing.FuncTypes -import Parsing.Global -import Parsing.Exports -import Parsing.Functions -import Parsing.Code +import qualified Parsing.Header as PH +import qualified Parsing.FuncTypes as FT +import qualified Parsing.Functions as FN +import qualified Parsing.Memory as M +import qualified Parsing.Exports as E +import qualified Parsing.Sections as S +import qualified Parsing.Global as G +import qualified Parsing.Code as C parseModule :: FileContent -> WasmModule -parseModule bytes = do - let sections = getSections bytes - WasmModule (getModHeader (getSectionWithId sections CustomID)) - (getFuncTypes (getSectionWithId sections TypeID)) - [] - ((getFuncCode (getSectionWithId sections CodeID) (getFunctions (getSectionWithId sections FunctionID)))) - [] - (getMemories (getSectionWithId sections MemoryID)) - [] - (getExports (getSectionWithId sections ExportID)) +parseModule bytes = + WasmModule { + header = PH.getModHeader (S.getSectionWithId sections CustomID), + types = FT.getFuncTypes (S.getSectionWithId sections TypeID), + imports = [], + functions = C.getFuncCode codeSection funcs, + tables = [], + globals = G.getGlobals (S.getSectionWithId sections GlobalID), + memory = M.getMemories (S.getSectionWithId sections MemoryID), + exports = E.getExports (S.getSectionWithId sections ExportID) + } + where + sections = S.getSections bytes + codeSection = S.getSectionWithId sections CodeID + funcs = FN.getFunctions (S.getSectionWithId sections FunctionID) diff --git a/lvtrun/app/Parsing/Sections.hs b/lvtrun/app/Parsing/Sections.hs index b02daa5..9c333d4 100644 --- a/lvtrun/app/Parsing/Sections.hs +++ b/lvtrun/app/Parsing/Sections.hs @@ -12,12 +12,12 @@ module Parsing.Sections ) where -import qualified Data.ByteString.Lazy as BSL +import qualified Data.ByteString.Lazy as BSL (ByteString, length, unpack, take, drop, splitAt) import Control.Exception (throw) -import Types -import Errors -import Leb128 +import Types (FileContent, Section(..), SectionID(..)) +import Errors (CustomException(..)) +import Leb128 (getLEB128ToI64) extractHeader :: BSL.ByteString -> (Section, BSL.ByteString) extractHeader bytes @@ -26,39 +26,39 @@ extractHeader bytes getSectionId :: BSL.ByteString -> SectionID getSectionId bytes = case head (BSL.unpack $ BSL.take 1 bytes) of - 0 -> CustomID - 1 -> TypeID - 2 -> ImportID - 3 -> FunctionID - 4 -> TableID - 5 -> MemoryID - 6 -> GlobalID - 7 -> ExportID - 8 -> StartID - 9 -> ElementID - 10 -> CodeID - 11 -> DataID - _ -> throw (WasmError "Invalid section id") + 0 -> CustomID + 1 -> TypeID + 2 -> ImportID + 3 -> FunctionID + 4 -> TableID + 5 -> MemoryID + 6 -> GlobalID + 7 -> ExportID + 8 -> StartID + 9 -> ElementID + 10 -> CodeID + 11 -> DataID + _ -> throw (WasmError "Invalid section id") extractSection :: BSL.ByteString -> (Section, BSL.ByteString) -extractSection bytes = do - let sectionId = getSectionId bytes - let (size, rest) = getLEB128ToI64 (BSL.drop 1 bytes) - let (content, rest2) = BSL.splitAt size rest - (Section sectionId (fromIntegral size) content, rest2) +extractSection bytes = (Section sectionId (fromIntegral size) content, rest2) + where + sectionId = getSectionId bytes + (size, rest) = getLEB128ToI64 (BSL.drop 1 bytes) + (content, rest2) = BSL.splitAt size rest extractSections :: BSL.ByteString -> [Section] extractSections bytes - | BSL.null bytes = [] - | otherwise = do - let (section, rest) = extractSection bytes - section : extractSections rest + | BSL.length bytes == 0 = [] + | otherwise = section : extractSections rest + where + (section, rest) = extractSection bytes getSections :: FileContent -> [Section] -getSections bytes = do - let (header, rest) = extractHeader bytes - let sections = extractSections rest - header : sections +getSections bytes = header : sections + where + (header, rest) = extractHeader bytes + sections = extractSections rest getSectionWithId :: [Section] -> SectionID -> Section getSectionWithId [] _ = throw (WasmError "No section with this id") diff --git a/lvtrun/app/Run/Functions.hs b/lvtrun/app/Run/Functions.hs index ac52546..53631f4 100644 --- a/lvtrun/app/Run/Functions.hs +++ b/lvtrun/app/Run/Functions.hs @@ -6,12 +6,12 @@ -} module Run.Functions - ( - getStartFunctionId, - getFunctionFromId, - getStartFunction, - getFuncTypeFromId - ) +( + getStartFunctionId, + getFunctionFromId, + getStartFunction, + getFuncTypeFromId +) where import Data.Int (Int32) @@ -20,8 +20,6 @@ import Control.Exception (throw) import Types import Errors --------------------------------------- - getStartFunctionId :: [Export] -> Int32 getStartFunctionId [] = throw $ WasmError "No start function" getStartFunctionId (x:xs) @@ -30,10 +28,9 @@ getStartFunctionId (x:xs) ExportFunc idx -> idx _ -> throw $ WasmError "getStartFunctionId: bad export" | otherwise = getStartFunctionId xs -getStartFunctionId _ = throw $ WasmError "getStartFunctionId: bad export" getFunctionFromId :: Int32 -> [Function] -> Function -getFunctionFromId id [] = throw $ WasmError "getFunctionFromId: bad id" +getFunctionFromId _ [] = throw $ WasmError "getFunctionFromId: bad id" getFunctionFromId id (x:xs) | funcIdx x == id = x | otherwise = getFunctionFromId id xs @@ -43,7 +40,7 @@ getStartFunction exports functions = getFunctionFromId (getStartFunctionId exports) functions getFuncTypeFromId :: Int32 -> [FuncType] -> FuncType -getFuncTypeFromId id [] = throw $ WasmError "getFuncTypeFromId: bad id" +getFuncTypeFromId _ [] = throw $ WasmError "getFuncTypeFromId: bad id" getFuncTypeFromId id (x:xs) | typeId x == id = x | otherwise = getFuncTypeFromId id xs diff --git a/lvtrun/app/Run/Locals.hs b/lvtrun/app/Run/Locals.hs index 930f1a3..6b36957 100644 --- a/lvtrun/app/Run/Locals.hs +++ b/lvtrun/app/Run/Locals.hs @@ -15,8 +15,7 @@ module Run.Locals ) where -import Data.Int (Int32, Int64) -import Data.Word (Word8) +import Data.Int (Int32) import Control.Exception (throw) import Types @@ -42,21 +41,29 @@ setLocalWithId idx (x:xs) value id | idx == id = value : xs | otherwise = x : setLocalWithId (idx + 1) xs value id ---------------------------- +----------- INITIALISATION ---------------- initLocalsVar :: Locals -> [Local] -> Locals initLocalsVar newLocals [] = newLocals -initLocalsVar newLocals ((Local _ I32):xs) = initLocalsVar (I_32 0 : newLocals) xs -initLocalsVar newLocals ((Local _ I64):xs) = initLocalsVar (I_64 0 : newLocals) xs -initLocalsVar newLocals ((Local _ F32):xs) = initLocalsVar (F_32 0 : newLocals) xs -initLocalsVar newLocals ((Local _ F64):xs) = initLocalsVar (F_64 0 : newLocals) xs +initLocalsVar newLocals ((Local _ I32):xs) = + initLocalsVar (I_32 0 : newLocals) xs +initLocalsVar newLocals ((Local _ I64):xs) = + initLocalsVar (I_64 0 : newLocals) xs +initLocalsVar newLocals ((Local _ F32):xs) = + initLocalsVar (F_32 0 : newLocals) xs +initLocalsVar newLocals ((Local _ F64):xs) = + initLocalsVar (F_64 0 : newLocals) xs createLocalsParams :: [TypeName] -> [Value] -> Locals createLocalsParams [] [] = [] -createLocalsParams (I32:xs) (I_32 val:xs2) = (I_32 val : createLocalsParams xs xs2) -createLocalsParams (I64:xs) (I_64 val:xs2) = (I_64 val : createLocalsParams xs xs2) -createLocalsParams (F32:xs) (F_32 val:xs2) = (F_32 val : createLocalsParams xs xs2) -createLocalsParams (F64:xs) (F_64 val:xs2) = (F_64 val : createLocalsParams xs xs2) +createLocalsParams (I32:xs) (I_32 val:xs2) = + (I_32 val : createLocalsParams xs xs2) +createLocalsParams (I64:xs) (I_64 val:xs2) = + (I_64 val : createLocalsParams xs xs2) +createLocalsParams (F32:xs) (F_32 val:xs2) = + (F_32 val : createLocalsParams xs xs2) +createLocalsParams (F64:xs) (F_64 val:xs2) = + (F_64 val : createLocalsParams xs xs2) createLocalsParams _ _ = throw $ WasmError "createLocalsParams: bad type" initLocalsParams :: [TypeName] -> Stack -> (Locals, Stack) @@ -77,7 +84,11 @@ initLocals localVarTypes paramTypes stack = do createEmptyLocals :: Locals -> [Local] -> Locals createEmptyLocals newLocals [] = newLocals -createEmptyLocals newLocals ((Local _ I32):xs) = createEmptyLocals (I_32 0 : newLocals) xs -createEmptyLocals newLocals ((Local _ I64):xs) = createEmptyLocals (I_64 0 : newLocals) xs -createEmptyLocals newLocals ((Local _ F32):xs) = createEmptyLocals (F_32 0 : newLocals) xs -createEmptyLocals newLocals ((Local _ F64):xs) = createEmptyLocals (F_64 0 : newLocals) xs +createEmptyLocals newLocals ((Local _ I32):xs) = + createEmptyLocals (I_32 0 : newLocals) xs +createEmptyLocals newLocals ((Local _ I64):xs) = + createEmptyLocals (I_64 0 : newLocals) xs +createEmptyLocals newLocals ((Local _ F32):xs) = + createEmptyLocals (F_32 0 : newLocals) xs +createEmptyLocals newLocals ((Local _ F64):xs) = + createEmptyLocals (F_64 0 : newLocals) xs diff --git a/lvtrun/app/Run/Stack.hs b/lvtrun/app/Run/Stack.hs index 325809f..f1a24c7 100644 --- a/lvtrun/app/Run/Stack.hs +++ b/lvtrun/app/Run/Stack.hs @@ -18,37 +18,40 @@ where import Control.Exception (throw) -import Types -import Errors +import Types (Value(..), TypeName(..)) +import Errors (CustomException(..)) type Stack = [Value] pushResults :: Stack -> Stack -> [TypeName] -> Stack -pushResults stack1 stack2 [] = stack1 -pushResults stack1 stack2 ((I32):xs) = case stackTop stack2 of - I_32 val -> pushResults (stackPush stack1 (I_32 val)) (tail stack2) xs - _ -> throw $ WasmError "pushResults: bad type" -pushResults stack1 stack2 ((I64):xs) = case stackTop stack2 of - I_64 val -> pushResults (stackPush stack1 (I_64 val)) (tail stack2) xs - _ -> throw $ WasmError "pushResults: bad type" -pushResults stack1 stack2 ((F32):xs) = case stackTop stack2 of - F_32 val -> pushResults (stackPush stack1 (F_32 val)) (tail stack2) xs - _ -> throw $ WasmError "pushResults: bad type" -pushResults stack1 stack2 ((F64):xs) = case stackTop stack2 of - F_64 val -> pushResults (stackPush stack1 (F_64 val)) (tail stack2) xs - _ -> throw $ WasmError "pushResults: bad type" -pushResults stack1 stack2 _ = throw $ WasmError "pushResults: bad type" +pushResults toStack _ [] = toStack +pushResults toStack fromStack ((I32):xs) = + case stackTop fromStack of + I_32 val -> pushResults (stackPush toStack (I_32 val)) (tail fromStack) xs + _ -> throw $ RuntimeError "pushResults: bad type" +pushResults toStack fromStack ((I64):xs) = + case stackTop fromStack of + I_64 val -> pushResults (stackPush toStack (I_64 val)) (tail fromStack) xs + _ -> throw $ RuntimeError "pushResults: bad type" +pushResults toStack fromStack ((F32):xs) = + case stackTop fromStack of + F_32 val -> pushResults (stackPush toStack (F_32 val)) (tail fromStack) xs + _ -> throw $ RuntimeError "pushResults: bad type" +pushResults toStack fromStack ((F64):xs) = + case stackTop fromStack of + F_64 val -> pushResults (stackPush toStack (F_64 val)) (tail fromStack) xs + _ -> throw $ RuntimeError "pushResults: bad type" stackPush :: Stack -> Value -> Stack stackPush stack value = value:stack stackPop :: Stack -> (Value, Stack) -stackPop [] = throw $ WasmError "stackPop: empty stack" +stackPop [] = throw $ RuntimeError "stackPop: empty stack" stackPop (x:xs) = (x, xs) stackTop :: Stack -> Value -stackTop [] = throw $ WasmError "stackTop: empty stack" -stackTop (x:xs) = x +stackTop [] = throw $ RuntimeError "stackTop: empty stack" +stackTop (x:_) = x stackPopN :: Stack -> Int -> ([Value], Stack) stackPopN stack 0 = ([], stack) diff --git a/lvtrun/app/Run/Start.hs b/lvtrun/app/Run/Start.hs index 353a886..c8b3271 100644 --- a/lvtrun/app/Run/Start.hs +++ b/lvtrun/app/Run/Start.hs @@ -11,13 +11,17 @@ module Run.Start ) where -import Data.Int (Int32, Int64) -import Control.Exception (throw) - import Types -import Errors import Run.Vm import Run.Functions +import Run.Stack + +exitCorrectly :: Stack -> IO () +exitCorrectly [] = putStrLn "Exit correctly with code: 0" +exitCorrectly (x:_) = putStrLn $ "Exit correctly with code: " ++ show x startExecution :: WasmModule -> IO () -startExecution wasmMod = startExecution2 (createVm wasmMod) (getStartFunctionId (exports wasmMod)) +startExecution wasmMod = exitCorrectly $ vmAtEnd + where + vmAtEnd = runMain (createVm wasmMod) startFuncId + startFuncId = getStartFunctionId (exports wasmMod) diff --git a/lvtrun/app/Run/Vm.hs b/lvtrun/app/Run/Vm.hs index 668e053..fec8863 100644 --- a/lvtrun/app/Run/Vm.hs +++ b/lvtrun/app/Run/Vm.hs @@ -8,15 +8,13 @@ module Run.Vm ( VM(..), - startExecution2, + runMain, createVm ) where -import Data.Int (Int32, Int64) import Data.Word (Word8) import Control.Exception (throw) -import System.Exit import Types import Errors @@ -67,36 +65,33 @@ createVm wasmMod = VM { wasmModule = wasmMod } -addLabel :: CurrentExec -> CurrentExec -addLabel cEx = cEx { ceLabels = (ceLabels cEx) ++ [ceInstIdx cEx] } - incrementInstIdx :: CurrentExec -> CurrentExec incrementInstIdx cEx = cEx { ceInstIdx = ceInstIdx cEx + 1 } --------------------------- execOpCode :: VM -> CurrentExec -> Instruction -> CurrentExec -execOpCode vm cEx (I32Const val) = cEx { ceStack = stackPush (ceStack cEx) (I_32 val) } -execOpCode vm cEx (Block _) = cEx { crBlockIndents = (crBlockIndents cEx) + 1 } -execOpCode vm cEx (I32Eqz) = do +execOpCode _ cEx (I32Const val) = cEx { ceStack = stackPush (ceStack cEx) (I_32 val) } +execOpCode _ cEx (Block _) = cEx { crBlockIndents = (crBlockIndents cEx) + 1 } +execOpCode _ cEx (I32Eqz) = do let value = stackTop (ceStack cEx) case value of I_32 0 -> cEx { ceStack = stackPush (ceStack cEx) (I_32 1) } I_32 _ -> cEx { ceStack = stackPush (ceStack cEx) (I_32 0) } _ -> throw $ WasmError "exec I32eqz: bad type" -execOpCode vm cEx (I32Add) = do +execOpCode _ cEx (I32Add) = do let (value2, newStack1) = stackPop (ceStack cEx) let (value1, newStack2) = stackPop newStack1 case (value1, value2) of (I_32 val1, I_32 val2) -> cEx { ceStack = stackPush newStack2 (I_32 (val1 + val2)) } _ -> throw $ WasmError "exec I32Add: bad type" -execOpCode vm cEx (I32Sub) = do +execOpCode _ cEx (I32Sub) = do let (value2, newStack1) = stackPop (ceStack cEx) let (value1, newStack2) = stackPop newStack1 case (value1, value2) of (I_32 val1, I_32 val2) -> cEx { ceStack = stackPush newStack2 (I_32 (val1 - val2)) } _ -> throw $ WasmError "exec I32Sub: bad type" -execOpCode vm cEx (BrIf labelIdx) = do +execOpCode _ cEx (BrIf labelIdx) = do let (value, newStack) = stackPop (ceStack cEx) case value of I_32 0 -> cEx @@ -106,17 +101,17 @@ execOpCode vm cEx (Call funcIdx) = do let newVm = execFunctionWithIdx vm funcIdx (ceStack cEx) let newStack = pushResults (ceStack cEx) (vmStack newVm) (ceResults (currentExec newVm)) cEx { ceStack = newStack } -execOpCode vm cEx (End) = cEx { crBlockIndents = (crBlockIndents cEx) - 1 } -execOpCode vm cEx (Return) = cEx { crBlockIndents = (crBlockIndents cEx) - 1 } -execOpCode vm cEx (Unreachable) = throw $ WasmError "execOpCode: unreachable" -execOpCode vm cEx (GetLocal localIdx) = do +execOpCode _ cEx (End) = cEx { crBlockIndents = (crBlockIndents cEx) - 1 } +execOpCode _ cEx (Return) = cEx { crBlockIndents = (crBlockIndents cEx) - 1 } +execOpCode _ cEx (Unreachable) = throw $ WasmError "execOpCode: unreachable" +execOpCode _ cEx (GetLocal localIdx) = do let value = getLocalFromId (ceLocals cEx) localIdx cEx { ceStack = stackPush (ceStack cEx) value } -execOpCode vm cEx (SetLocal localIdx) = do +execOpCode _ cEx (SetLocal localIdx) = do let (value, newStack) = stackPop (ceStack cEx) let newLocals = setLocalWithId 0 (ceLocals cEx) value localIdx cEx { ceStack = newStack, ceLocals = newLocals } -execOpCode vm cEx _ = cEx +execOpCode _ cEx _ = cEx execOpCodes :: VM -> [Instruction] -> CurrentExec execOpCodes vm [] = currentExec vm @@ -152,8 +147,8 @@ execFunctionWithIdx vm funcIdx currentStack = do } execFunction vm { currentExec = cexec } -startExecution2 :: VM -> FuncIdx -> IO () -startExecution2 vm funcIdx = do +runMain :: VM -> FuncIdx -> Stack +runMain vm funcIdx = do let function = getFunctionFromId funcIdx (functions (wasmModule vm)) let funcTypee = getFuncTypeFromId (funcType function) (types (wasmModule vm)) let cexec = CurrentExec { @@ -167,11 +162,4 @@ startExecution2 vm funcIdx = do crBlockIndents = 0 } let newVm = execFunction vm { currentExec = cexec } - let resStack = [] - let res = pushResults resStack (vmStack newVm) (ceResults (currentExec newVm)) - let exitCode = case res of - [] -> 0 - (x:xs) -> case x of - I_32 val -> val - _ -> 0 - putStrLn $ "Exit correctly with code: " ++ show exitCode + pushResults [] (vmStack newVm) (ceResults (currentExec newVm)) diff --git a/lvtrun/app/Types.hs b/lvtrun/app/Types.hs index e82eb49..f1daba1 100644 --- a/lvtrun/app/Types.hs +++ b/lvtrun/app/Types.hs @@ -44,7 +44,6 @@ module Types import Data.Int (Int32, Int64) import Data.Word (Word8) -import Numeric (showHex) import Control.Exception (throw) import qualified Data.ByteString.Lazy as BSL @@ -187,7 +186,6 @@ instance Show Instruction where show (Br idx) = "\n\t\t\t\tbr " ++ (show idx) show End = "\n\t\t\t\tend" show (Block blockType) = "\n\t\t\t\tblock " ++ (show blockType) - show _ = throw $ WasmError "Show Instruction: bad instruction" -- Module section @@ -196,25 +194,24 @@ data Value = | I_64 Int64 | F_32 Float | F_64 Double - deriving (Show) + deriving (Eq) + +instance Show Value where + show (I_32 val) = show val + show (I_64 val) = show val + show (F_32 val) = show val + show (F_64 val) = show val data Local = Local { lcIdx :: LocalIdx, lcType :: TypeName -} - -instance Show Local where - show local = "\n\t\t(local idx:" ++ (show $ lcIdx local) ++ " type:" ++ (show $ lcType local) ++ ")" +} deriving (Show) data FuncType = FuncType { typeId :: TypeIdx, params :: [TypeName], results :: [TypeName] -} - -instance Show FuncType where - show funcType = "\n\t(type " ++ (show $ typeId funcType) ++ " (func " ++ - (show $ params funcType) ++ ") " ++ (show $ results funcType) ++ ")" +} deriving (Show) data Import = Import { mod :: String, @@ -232,10 +229,7 @@ data Function = Function { funcIdx :: FuncIdx, locals :: [Local], body :: [Instruction] -} - -instance Show Function where - show func = "\n\t(func idx:" ++ (show $ funcIdx func) ++ " typeId:" ++ (show $ funcType func) ++ " " ++ (show $ locals func) ++ "\nIntructions:\n" ++ (show $ body func) ++ ")" +} deriving (Show) type Memory = Limit @@ -245,12 +239,7 @@ data Global = Global { globalType :: TypeName, mutability :: Mutability, initExpr :: [Instruction] -} - -instance Show Global where - show global = "\n\t(global " ++ (show $ globalType global) ++ " " ++ - (show $ mutability global) ++ " " ++ (show $ initExpr global) ++ ")" - +} deriving (Show) data ExportDesc = ExportFunc FuncIdx @@ -262,10 +251,7 @@ data ExportDesc = data Export = Export { expName :: String, expDesc :: ExportDesc -} - -instance Show Export where - show export = "\n\t(export \"" ++ (expName export) ++ "\" " ++ (show $ expDesc export) ++ ")" +} deriving (Show) data Table = Table { notImpl :: String @@ -297,13 +283,7 @@ data Section = Section { identifier :: SectionID, size :: Int, content :: BSL.ByteString -} - -instance Show Section where - show section = - "\nSection " ++ (show $ identifier section) ++ - " Size: " ++ (show $ size section) ++ - " Content: " ++ (concat $ map (\x -> showHex x " ") (BSL.unpack $ content section)) +} deriving (Show) data WasmModule = WasmModule { header :: ModHeader, diff --git a/lvtrun/lvtrun.cabal b/lvtrun/lvtrun.cabal index 883926e..d6f248e 100644 --- a/lvtrun/lvtrun.cabal +++ b/lvtrun/lvtrun.cabal @@ -46,6 +46,7 @@ executable lvtrun-exe IO Leb128 Loader + OpCodes Parsing.Code Parsing.Exports Parsing.Functions