start binary format support
This commit is contained in:
@@ -0,0 +1,120 @@
|
|||||||
|
{-# LANGUAGE NamedFieldPuns #-}
|
||||||
|
|
||||||
|
module Language.Wasm.Binary (
|
||||||
|
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Language.Wasm.Structure
|
||||||
|
|
||||||
|
import Numeric.Natural (Natural)
|
||||||
|
import Data.Bits
|
||||||
|
import Data.Word (Word8)
|
||||||
|
import Data.Serialize
|
||||||
|
import qualified Data.ByteString as BS
|
||||||
|
|
||||||
|
putULEB128 :: Natural -> Put
|
||||||
|
putULEB128 val =
|
||||||
|
if val < 128
|
||||||
|
then putWord8 $ fromIntegral val
|
||||||
|
else do
|
||||||
|
putWord8 $ 0x80 + (0x7F .&. fromIntegral val)
|
||||||
|
putULEB128 $ val `shiftR` 7
|
||||||
|
|
||||||
|
getULEB128 :: Get Natural
|
||||||
|
getULEB128 = do
|
||||||
|
val <- getWord8
|
||||||
|
if val < 2 ^ 7
|
||||||
|
then return $ fromIntegral val
|
||||||
|
else do
|
||||||
|
rest <- getULEB128
|
||||||
|
return $ (fromIntegral $ 0x7F .&. val) + 128 * rest
|
||||||
|
|
||||||
|
putVec :: Serialize a => [a] -> Put
|
||||||
|
putVec list = do
|
||||||
|
putULEB128 $ fromIntegral $ length list
|
||||||
|
mapM put list
|
||||||
|
return ()
|
||||||
|
|
||||||
|
getVec :: Serialize a => Get [a]
|
||||||
|
getVec = do
|
||||||
|
len <- getULEB128
|
||||||
|
sequence $ replicate (fromIntegral len) get
|
||||||
|
|
||||||
|
byteGuard :: Word8 -> Get ()
|
||||||
|
byteGuard expected = do
|
||||||
|
byte <- getWord8
|
||||||
|
if byte == expected
|
||||||
|
then return ()
|
||||||
|
else fail $ "Expected " ++ show expected ++ ", but encountered " ++ show byte
|
||||||
|
|
||||||
|
putSection :: Serialize a => SectionType -> a -> Put
|
||||||
|
putSection section content = do
|
||||||
|
put section
|
||||||
|
let payload = encode content
|
||||||
|
putULEB128 $ fromIntegral $ BS.length payload
|
||||||
|
putByteString payload
|
||||||
|
|
||||||
|
data SectionType =
|
||||||
|
CustomSection
|
||||||
|
| TypeSection
|
||||||
|
| ImportSection
|
||||||
|
| FunctionSection
|
||||||
|
| TableSection
|
||||||
|
| MemorySection
|
||||||
|
| GlobalSection
|
||||||
|
| ExportSection
|
||||||
|
| StartSection
|
||||||
|
| ElementSection
|
||||||
|
| CodeSection
|
||||||
|
| DataSection
|
||||||
|
deriving (Eq, Show, Enum)
|
||||||
|
|
||||||
|
instance Serialize SectionType where
|
||||||
|
put section = putWord8 $ fromIntegral $ fromEnum section
|
||||||
|
get = do
|
||||||
|
op <- fromIntegral `fmap` getWord8
|
||||||
|
if op <= fromEnum DataSection
|
||||||
|
then return $ toEnum op
|
||||||
|
else fail "Unexpected byte in section type position"
|
||||||
|
|
||||||
|
instance Serialize ValueType where
|
||||||
|
put I32 = putWord8 0x7F
|
||||||
|
put I64 = putWord8 0x7E
|
||||||
|
put F32 = putWord8 0x7D
|
||||||
|
put F64 = putWord8 0x7C
|
||||||
|
|
||||||
|
get = do
|
||||||
|
op <- getWord8
|
||||||
|
case op of
|
||||||
|
0x7F -> return I32
|
||||||
|
0x7E -> return I64
|
||||||
|
0x7D -> return F32
|
||||||
|
0x7C -> return F64
|
||||||
|
_ -> fail "unexpected byte in value type position"
|
||||||
|
|
||||||
|
instance Serialize FuncType where
|
||||||
|
put FuncType {params, results} = do
|
||||||
|
putWord8 0x60
|
||||||
|
putVec params
|
||||||
|
putVec results
|
||||||
|
get = do
|
||||||
|
byteGuard 0x60
|
||||||
|
params <- getVec
|
||||||
|
results <- getVec
|
||||||
|
return $ FuncType { params, results }
|
||||||
|
|
||||||
|
instance Serialize Module where
|
||||||
|
put mod = do
|
||||||
|
-- magic
|
||||||
|
putWord8 0x00
|
||||||
|
putWord8 0x61
|
||||||
|
putWord8 0x73
|
||||||
|
putWord8 0x6D
|
||||||
|
-- version
|
||||||
|
putWord8 0x01
|
||||||
|
putWord8 0x00
|
||||||
|
putWord8 0x00
|
||||||
|
putWord8 0x00
|
||||||
|
|
||||||
|
putSection TypeSection $ types mod
|
||||||
|
get = undefined
|
||||||
@@ -1172,7 +1172,7 @@ desugarize fields =
|
|||||||
start = extractStart fields,
|
start = extractStart fields,
|
||||||
exports = []
|
exports = []
|
||||||
} in
|
} in
|
||||||
S.emptyModule {
|
S.Module {
|
||||||
S.types = map synTypeDefToStruct $ types mod,
|
S.types = map synTypeDefToStruct $ types mod,
|
||||||
S.functions = map (synFunctionToStruct mod) $ functions mod,
|
S.functions = map (synFunctionToStruct mod) $ functions mod,
|
||||||
S.tables = map synTableToStruct $ tables mod,
|
S.tables = map synTableToStruct $ tables mod,
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
|
||||||
{-# LANGUAGE DuplicateRecordFields #-}
|
{-# LANGUAGE DuplicateRecordFields #-}
|
||||||
|
|
||||||
module Language.Wasm.Structure (
|
module Language.Wasm.Structure (
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
module Language.Wasm.Validate (
|
||||||
|
validate
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Language.Wasm.Structure
|
||||||
|
|
||||||
|
validate :: Module -> Either String Module
|
||||||
|
validate mod = Right mod
|
||||||
@@ -29,6 +29,7 @@ library
|
|||||||
, text >=1.1
|
, text >=1.1
|
||||||
, transformers >=0.4 && <0.6
|
, transformers >=0.4 && <0.6
|
||||||
, utf8-string >=1.0
|
, utf8-string >=1.0
|
||||||
|
, cereal >= 0.5
|
||||||
build-tools:
|
build-tools:
|
||||||
alex >=3.1.3
|
alex >=3.1.3
|
||||||
, happy >=1.9.4
|
, happy >=1.9.4
|
||||||
@@ -36,6 +37,8 @@ library
|
|||||||
Language.Wasm.Lexer
|
Language.Wasm.Lexer
|
||||||
Language.Wasm.Parser
|
Language.Wasm.Parser
|
||||||
Language.Wasm.Structure
|
Language.Wasm.Structure
|
||||||
|
Language.Wasm.Binary
|
||||||
|
Language.Wasm.Validate
|
||||||
Language.Wasm
|
Language.Wasm
|
||||||
other-modules:
|
other-modules:
|
||||||
Paths_wasm
|
Paths_wasm
|
||||||
|
|||||||
Reference in New Issue
Block a user