pack/unpack int values

This commit is contained in:
Ilya Rezvov
2018-02-19 12:52:20 -08:00
parent 0029c68115
commit 9d784d03bd
2 changed files with 53 additions and 22 deletions
+52 -21
View File
@@ -9,21 +9,14 @@ import Language.Wasm.Structure
import Numeric.Natural (Natural)
import Data.Bits
import Data.Word (Word8)
import Data.Int (Int8)
import Data.Serialize
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as LBS
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Encoding as TLEncoding
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 :: (Integral a, Bits a) => Get a
getULEB128 = do
val <- getWord8
if val < 2 ^ 7
@@ -32,16 +25,54 @@ getULEB128 = do
rest <- getULEB128
return $ (fromIntegral $ 0x7F .&. val) + 128 * rest
putULEB128 :: (Integral a, Bits a) => a -> Put
putULEB128 val =
if val < 128
then putWord8 $ fromIntegral val
else do
putWord8 $ 0x80 + (0x7F .&. fromIntegral val)
putULEB128 $ val `shiftR` 7
getSLEB128 :: (Integral a, Bits a) => Get a
getSLEB128 = do
let toInt8 :: Word8 -> Int8
toInt8 = fromIntegral
a <- getWord8
if not (testBit a 7)
then return . fromIntegral . toInt8 $ (a .&. 0x7f) .|. ((a .&. 0x40) `shiftL` 1)
else do
b <- getSLEB128
return $ (b `shiftL` 7) .|. (fromIntegral (a .&. 0x7f))
putSLEB128 :: (Integral a, Bits a) => a -> Put
putSLEB128 a = go a
where
ext = if a >= 0 then 0 else complement 0
go x = do
let
r = x `shiftR` 7
w = x .&. 0x7f
if r /= ext
then do
putWord8 (fromIntegral w .|. 0x80)
go r
else
if (testBit w 6 && a < 0) || (not (testBit w 6) && a >= 0)
then putWord8 (fromIntegral w)
else do
putWord8 (fromIntegral w .|. 0x80)
putWord8 (fromIntegral ext .&. 0x7F)
putVec :: Serialize a => [a] -> Put
putVec list = do
putULEB128 $ fromIntegral $ length list
putULEB128 $ length list
mapM put list
return ()
getVec :: Serialize a => Get [a]
getVec = do
len <- getULEB128
sequence $ replicate (fromIntegral len) get
sequence $ replicate len get
byteGuard :: Word8 -> Get ()
byteGuard expected = do
@@ -54,19 +85,19 @@ putSection :: Serialize a => SectionType -> a -> Put
putSection section content = do
put section
let payload = encode content
putULEB128 $ fromIntegral $ BS.length payload
putULEB128 $ BS.length payload
putByteString payload
putName :: TL.Text -> Put
putName txt = do
let bs = TLEncoding.encodeUtf8 txt
putULEB128 $ fromIntegral $ LBS.length bs
putULEB128 $ LBS.length bs
putLazyByteString bs
getName :: Get TL.Text
getName = do
len <- getULEB128
bytes <- getLazyByteString $ fromIntegral len
bytes <- getLazyByteString len
return $ TLEncoding.decodeUtf8 bytes
putResultType :: ResultType -> Put
@@ -222,24 +253,24 @@ instance Serialize Instruction where
put (Block result body) = do
putWord8 0x02
putResultType result
mapM put body
mapM_ put body
putWord8 0x0B -- END
put (Loop result body) = do
putWord8 0x03
putResultType result
mapM put body
mapM_ put body
putWord8 0x0B -- END
put If {result, true, false = []} = do
putWord8 0x04
putResultType result
mapM put true
mapM_ put true
putWord8 0x0B -- END
put If {result, true, false} = do
putWord8 0x04
putResultType result
mapM put true
mapM_ put true
putWord8 0x05 -- ELSE
mapM put false
mapM_ put false
putWord8 0x0B -- END
put (Br labelIdx) = putWord8 0x0C >> putULEB128 labelIdx
put (BrIf labelIdx) = putWord8 0x0D >> putULEB128 labelIdx
@@ -283,8 +314,8 @@ instance Serialize Instruction where
put CurrentMemory = putWord8 0x3F >> putWord8 0x00
put GrowMemory = putWord8 0x40 >> putWord8 0x00
-- Numeric instructions
put (I32Const val) = putWord8 0x41 -- TODO: PACK VALUE AS SIGNED LEB128
put (I64Const val) = putWord8 0x42 -- TODO: PACK VALUE AS SIGNED LEB128
put (I32Const val) = putWord8 0x41 >> putSLEB128 val
put (I64Const val) = putWord8 0x42 >> putSLEB128 val
put (F32Const val) = putWord8 0x43 >> putFloat32le val
put (F64Const val) = putWord8 0x44 >> putFloat64le val
put I32Eqz = putWord8 0x45