Skip to content

Commit b816e04

Browse files
committed
type signature parsing for loop and if blocks
1 parent 2d58add commit b816e04

File tree

7 files changed

+145
-168
lines changed

7 files changed

+145
-168
lines changed

src/Language/Wasm/Binary.hs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -331,17 +331,17 @@ instance Serialize (Instruction Natural) where
331331
putWord8 0x02
332332
putBlockType blockType
333333
putExpression body
334-
put (Loop result body) = do
334+
put (Loop blockType body) = do
335335
putWord8 0x03
336-
putResultType result
336+
putBlockType blockType
337337
putExpression body
338-
put If {resultType, true, false = []} = do
338+
put If {blockType, true, false = []} = do
339339
putWord8 0x04
340-
putResultType resultType
340+
putBlockType blockType
341341
putExpression true
342-
put If {resultType, true, false} = do
342+
put If {blockType, true, false} = do
343343
putWord8 0x04
344-
putResultType resultType
344+
putBlockType blockType
345345
mapM_ put true
346346
putWord8 0x05 -- ELSE
347347
putExpression false
@@ -528,12 +528,12 @@ instance Serialize (Instruction Natural) where
528528
0x00 -> return Unreachable
529529
0x01 -> return Nop
530530
0x02 -> Block <$> getBlockType <*> getExpression
531-
0x03 -> Loop <$> getResultType <*> getExpression
531+
0x03 -> Loop <$> getBlockType <*> getExpression
532532
0x04 -> do
533-
resultType <- getResultType
533+
blockType <- getBlockType
534534
(true, hasElse) <- getTrueBranch
535535
false <- if hasElse then getExpression else return []
536-
return $ If resultType true false
536+
return $ If blockType true false
537537
0x0C -> Br <$> getULEB128 32
538538
0x0D -> BrIf <$> getULEB128 32
539539
0x0E -> BrTable <$> (map unIndex <$> getVec) <*> getULEB128 32

src/Language/Wasm/Builder.hs

Lines changed: 55 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ module Language.Wasm.Builder (
4141
memorySize, growMemory,
4242
nop, Language.Wasm.Builder.drop, select,
4343
call, callIndirect, finish, br, brIf, brTable,
44-
if', loop, {-block,-} when, for, while,
44+
{-if', loop, block, when, for, while,-}
4545
trap, unreachable,
4646
appendExpr, after,
4747
Producer, OutType, produce, Consumer, (.=)
@@ -681,7 +681,7 @@ finish val = do
681681
appendExpr [Return]
682682

683683
newtype Label i = Label Natural deriving (Show, Eq)
684-
684+
{-
685685
when :: (Producer pred, OutType pred ~ Proxy I32)
686686
=> pred
687687
-> GenFun ()
@@ -704,28 +704,28 @@ while pred body = do
704704
body
705705
loopLabel <- label
706706
if' () pred (br loopLabel) (return ())
707-
if' () pred (loop () loopBody) (return ())
707+
if' () pred (loop () loopBody) (return ())-}
708708

709709
label :: GenFun (Label t)
710710
label = Label <$> ask
711711

712-
if' :: (Producer pred, OutType pred ~ Proxy I32, Returnable res)
713-
=> res
714-
-> pred
715-
-> GenFun res
716-
-> GenFun res
717-
-> GenFun res
718-
if' res pred true false = do
719-
produce pred
720-
deep <- (+1) <$> ask
721-
appendExpr [If (asResultValue res) (genExpr deep $ true) (genExpr deep $ false)]
722-
return returnableValue
712+
-- if' :: (Producer pred, OutType pred ~ Proxy I32, Returnable res)
713+
-- => res
714+
-- -> pred
715+
-- -> GenFun res
716+
-- -> GenFun res
717+
-- -> GenFun res
718+
-- if' res pred true false = do
719+
-- produce pred
720+
-- deep <- (+1) <$> ask
721+
-- appendExpr [If (asResultValue res) (genExpr deep $ true) (genExpr deep $ false)]
722+
-- return returnableValue
723723

724-
loop :: (Returnable res) => res -> GenFun res -> GenFun res
725-
loop res body = do
726-
deep <- (+1) <$> ask
727-
appendExpr [Loop (asResultValue res) (genExpr deep $ body)]
728-
return returnableValue
724+
-- loop :: (Returnable res) => res -> GenFun res -> GenFun res
725+
-- loop res body = do
726+
-- deep <- (+1) <$> ask
727+
-- appendExpr [Loop (asResultValue res) (genExpr deep $ body)]
728+
-- return returnableValue
729729

730730
-- block :: (Returnable res) => res -> GenFun res -> GenFun res
731731
-- block res body = do
@@ -988,39 +988,39 @@ asWord64 i
988988
| i >= 0 = fromIntegral i
989989
| otherwise = 0xFFFFFFFFFFFFFFFF - (fromIntegral (abs i)) + 1
990990

991-
rts :: Module
992-
rts = genMod $ do
993-
gc <- importFunction "rts" "gc" () [I32]
994-
memory 10 Nothing
995-
996-
stackStart <- global Const i32 0
997-
stackEnd <- global Const i32 0
998-
stackBase <- global Mut i32 0
999-
stackTop <- global Mut i32 0
1000-
1001-
retReg <- global Mut i32 0
1002-
tmpReg <- global Mut i32 0
1003-
1004-
heapStart <- global Mut i32 0
1005-
heapNext <- global Mut i32 0
1006-
heapEnd <- global Mut i32 0
1007-
1008-
aligned <- fun i32 $ do
1009-
size <- param i32
1010-
(size `add` i32c 3) `and` i32c 0xFFFFFFFC
1011-
alloc <- funRec i32 $ \self -> do
1012-
size <- param i32
1013-
alignedSize <- local i32
1014-
addr <- local i32
1015-
alignedSize .= call aligned [arg size]
1016-
if' i32 ((heapNext `add` alignedSize) `lt_u` heapEnd)
1017-
(do
1018-
addr .= heapNext
1019-
heapNext .= heapNext `add` alignedSize
1020-
ret addr
1021-
)
1022-
(do
1023-
call gc []
1024-
call self [arg size]
1025-
)
1026-
return ()
991+
-- rts :: Module
992+
-- rts = genMod $ do
993+
-- gc <- importFunction "rts" "gc" () [I32]
994+
-- memory 10 Nothing
995+
996+
-- stackStart <- global Const i32 0
997+
-- stackEnd <- global Const i32 0
998+
-- stackBase <- global Mut i32 0
999+
-- stackTop <- global Mut i32 0
1000+
1001+
-- retReg <- global Mut i32 0
1002+
-- tmpReg <- global Mut i32 0
1003+
1004+
-- heapStart <- global Mut i32 0
1005+
-- heapNext <- global Mut i32 0
1006+
-- heapEnd <- global Mut i32 0
1007+
1008+
-- aligned <- fun i32 $ do
1009+
-- size <- param i32
1010+
-- (size `add` i32c 3) `and` i32c 0xFFFFFFFC
1011+
-- alloc <- funRec i32 $ \self -> do
1012+
-- size <- param i32
1013+
-- alignedSize <- local i32
1014+
-- addr <- local i32
1015+
-- alignedSize .= call aligned [arg size]
1016+
-- if' i32 ((heapNext `add` alignedSize) `lt_u` heapEnd)
1017+
-- (do
1018+
-- addr .= heapNext
1019+
-- heapNext .= heapNext `add` alignedSize
1020+
-- ret addr
1021+
-- )
1022+
-- (do
1023+
-- call gc []
1024+
-- call self [arg size]
1025+
-- )
1026+
-- return ()

src/Language/Wasm/Interpreter.hs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -646,14 +646,22 @@ eval budget store FunctionInstance { funcType, moduleInstance, code = Function {
646646
Break n r ctx' -> return $ Break (n - 1) r ctx'
647647
Done ctx'@EvalCtx{ labels = (_:rest) } -> return $ Done ctx' { labels = rest }
648648
command -> return command
649-
step ctx loop@(Loop resType expr) = do
649+
step ctx loop@(Loop blockType expr) = do
650+
let resType = case blockType of
651+
Inline Nothing -> []
652+
Inline (Just valType) -> [valType]
653+
TypeIndex typeIdx -> results $ funcTypes moduleInstance ! fromIntegral typeIdx
650654
res <- go ctx { labels = Label resType : labels ctx } expr
651655
case res of
652656
Break 0 r EvalCtx{ locals = ls } -> step ctx { locals = ls, stack = r ++ stack ctx } loop
653657
Break n r ctx' -> return $ Break (n - 1) r ctx'
654658
Done ctx'@EvalCtx{ labels = (_:rest) } -> return $ Done ctx' { labels = rest }
655659
command -> return command
656-
step ctx@EvalCtx{ stack = (VI32 v): rest } (If resType true false) = do
660+
step ctx@EvalCtx{ stack = (VI32 v): rest } (If blockType true false) = do
661+
let resType = case blockType of
662+
Inline Nothing -> []
663+
Inline (Just valType) -> [valType]
664+
TypeIndex typeIdx -> results $ funcTypes moduleInstance ! fromIntegral typeIdx
657665
let expr = if v /= 0 then true else false
658666
res <- go ctx { labels = Label resType : labels ctx, stack = rest } expr
659667
case res of

src/Language/Wasm/Parser.y

Lines changed: 50 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -660,68 +660,32 @@ raw_instr :: { [Instruction] }
660660
then Right $ [BlockInstr $2 tu (instr ++ instr')]
661661
else Left "Block labels have to match"
662662
}
663-
| 'loop' opt(ident) raw_loop {% (: []) `fmap` $3 $2 }
664-
| 'if' opt(ident) raw_if_result {% $3 $2 }
665-
666-
raw_loop :: { Maybe Ident -> Either String Instruction }
667-
: 'end' opt(ident) {
668-
\ident ->
669-
if ident == $2 || isNothing $2
670-
then Right $ LoopInstr ident [] []
671-
else Left "Loop labels have to match"
672-
}
673-
| raw_instr list(instruction) 'end' opt(ident) {
674-
\ident ->
675-
if ident == $4 || isNothing $4
676-
then Right $ LoopInstr ident [] ($1 ++ concat $2)
677-
else Left "Loop labels have to match"
678-
}
679-
| '(' raw_loop1 { $2 }
680-
681-
raw_loop1 :: { Maybe Ident -> Either String Instruction }
682-
: 'result' list(valtype) ')' list(instruction) 'end' opt(ident) {
683-
\ident ->
684-
if ident == $6 || isNothing $6
685-
then Right $ LoopInstr ident $2 (concat $4)
686-
else Left "Loop labels have to match"
687-
}
688-
| folded_instr1 list(instruction) 'end' opt(ident) {
689-
\ident ->
690-
if ident == $4 || isNothing $4
691-
then Right $ LoopInstr ident [] ($1 ++ concat $2)
692-
else Left "Loop labels have to match"
693-
}
694-
695-
raw_if_result :: { Maybe Ident -> Either String [Instruction] }
696-
: raw_else {
697-
\ident ->
698-
if ident == (snd $1) || isNothing (snd $1)
699-
then Right [IfInstr ident [] [] $ fst $1]
700-
else Left "If labels have to match"
663+
| 'loop' opt(ident) typeuse_cont(pair(folded_instr1_list, block_end), block_end) {%
664+
let (tu, rest) = $3 in
665+
let (instr, (instr', identAfter)) = either (\a -> ([], a)) id rest in
666+
if $2 == identAfter || isNothing identAfter
667+
then Right $ [LoopInstr $2 tu (instr ++ instr')]
668+
else Left "Block labels have to match"
701669
}
702-
| raw_instr list(instruction) raw_else {
703-
\ident ->
704-
if ident == (snd $3) || isNothing (snd $3)
705-
then Right [IfInstr ident [] ($1 ++ concat $2) $ fst $3]
706-
else Left "If labels have to match"
670+
| 'if' opt(ident) typeuse_cont(pair(folded_instr1_list, raw_if_end), raw_if_end) {%
671+
let (tu, rest) = $3 in
672+
let (trueBranch, falseBranch, identAfter) = either id (\(t, (t', f, i)) -> (t ++ t', f, i)) rest in
673+
if $2 == identAfter || isNothing identAfter
674+
then Right $ [IfInstr $2 tu trueBranch falseBranch]
675+
else Left "If labels have to match"
707676
}
708-
| '(' raw_if_result1 { $2 }
709677

710-
raw_if_result1 :: { Maybe Ident -> Either String [Instruction] }
711-
: 'result' list(valtype) ')' list(instruction) raw_else {
712-
\ident ->
713-
if ident == (snd $5) || isNothing (snd $5)
714-
then Right [IfInstr ident $2 (concat $4) $ fst $5]
715-
else Left "If labels have to match"
678+
raw_if_end
679+
: raw_if_else {
680+
let (falseBranch, ident) = $1 in
681+
([], falseBranch, ident)
716682
}
717-
| folded_instr1 list(instruction) raw_else {
718-
\ident ->
719-
if ident == (snd $3) || isNothing (snd $3)
720-
then Right [IfInstr ident [] ($1 ++ concat $2) $ fst $3]
721-
else Left "If labels have to match"
683+
| raw_instr list(instruction) raw_if_else {
684+
let (falseBranch, ident) = $3 in
685+
($1 ++ concat $2, falseBranch, ident)
722686
}
723687

724-
raw_else :: { ([Instruction], Maybe Ident) }
688+
raw_if_else :: { ([Instruction], Maybe Ident) }
725689
: 'end' opt(ident) { ([], $2) }
726690
| 'else' opt(ident) list(instruction) 'end' opt(ident) {%
727691
if matchIdents $2 $5
@@ -748,28 +712,14 @@ folded_instr1 :: { [Instruction] }
748712
let (instr, instr') = either (\a -> ([], a)) id rest in
749713
[BlockInstr $2 typeUse (instr ++ instr')]
750714
}
751-
| 'loop' opt(ident) folded_loop { [$3 $2] }
752-
| 'if' opt(ident) '(' folded_if_result { $4 $2 }
753-
754-
folded_loop :: { Maybe Ident -> Instruction }
755-
: ')' { \ident -> LoopInstr ident [] [] }
756-
| '(' folded_loop1 { $2 }
757-
| raw_instr list(instruction) ')' { \ident -> LoopInstr ident [] ($1 ++ concat $2) }
758-
759-
folded_loop1 :: { Maybe Ident -> Instruction }
760-
: 'result' list(valtype) ')' list(instruction) ')' { \ident -> LoopInstr ident $2 (concat $4) }
761-
| folded_instr1 list(instruction) ')' { \ident -> LoopInstr ident [] ($1 ++ concat $2) }
762-
763-
folded_if_result :: { Maybe Ident -> [Instruction] }
764-
: 'result' list(valtype) ')' '(' folded_then_else {
765-
\ident ->
766-
let (pred, (trueBranch, falseBranch)) = $5 in
767-
pred ++ [IfInstr ident $2 trueBranch falseBranch]
715+
| 'loop' opt(ident) typeuse_cont(pair(folded_instr1_list, instr_list_closed), instr_list_closed) {
716+
let (typeUse, rest) = $3 in
717+
let (instr, instr') = either (\a -> ([], a)) id rest in
718+
[LoopInstr $2 typeUse (instr ++ instr')]
768719
}
769-
| folded_then_else {
770-
\ident ->
771-
let (pred, (trueBranch, falseBranch)) = $1 in
772-
pred ++ [IfInstr ident [] trueBranch falseBranch]
720+
| 'if' opt(ident) '(' typeuse1_cont(folded_then_else, never) {
721+
let (typeUse, Right (pred, (trueBranch, falseBranch))) = $4 in
722+
pred ++ [IfInstr $2 typeUse trueBranch falseBranch]
773723
}
774724

775725
folded_then_else :: { ([Instruction], ([Instruction], [Instruction])) }
@@ -1225,12 +1175,12 @@ data Instruction =
12251175
}
12261176
| LoopInstr {
12271177
label :: Maybe Ident,
1228-
resultType :: [ValueType],
1178+
blockType :: TypeUse,
12291179
body :: [Instruction]
12301180
}
12311181
| IfInstr {
12321182
label :: Maybe Ident,
1233-
resultType :: [ValueType],
1183+
blockType :: TypeUse,
12341184
trueBranch :: [Instruction],
12351185
falseBranch :: [Instruction]
12361186
}
@@ -1503,10 +1453,10 @@ desugarize fields = do
15031453
matchTypeUse defs typeUse
15041454
extractTypeDefFromInstruction defs (BlockInstr { body, blockType }) =
15051455
extractTypeDefFromInstructions (matchTypeUse defs blockType) body
1506-
extractTypeDefFromInstruction defs (LoopInstr { body }) =
1507-
extractTypeDefFromInstructions defs body
1508-
extractTypeDefFromInstruction defs (IfInstr { trueBranch, falseBranch }) =
1509-
extractTypeDefFromInstructions defs $ trueBranch ++ falseBranch
1456+
extractTypeDefFromInstruction defs (LoopInstr { body, blockType }) =
1457+
extractTypeDefFromInstructions (matchTypeUse defs blockType) body
1458+
extractTypeDefFromInstruction defs (IfInstr { blockType, trueBranch, falseBranch }) =
1459+
extractTypeDefFromInstructions (matchTypeUse defs blockType) $ trueBranch ++ falseBranch
15101460
extractTypeDefFromInstruction defs _ = defs
15111461
15121462
funcTypesEq :: FuncType -> FuncType -> Bool
@@ -1659,14 +1609,26 @@ desugarize fields = do
16591609
Just idx -> return $ S.TypeIndex idx
16601610
Nothing -> Left "unknown type"
16611611
S.Block bt <$> mapM (synInstrToStruct ctx') body
1662-
synInstrToStruct ctx LoopInstr {label, resultType, body} =
1663-
let ctx' = ctx { ctxLabels = label : ctxLabels ctx } in
1664-
S.Loop resultType <$> mapM (synInstrToStruct ctx') body
1665-
synInstrToStruct ctx IfInstr {label, resultType, trueBranch, falseBranch} = do
1612+
synInstrToStruct ctx@FunCtx { ctxMod = Module { types } } LoopInstr {label, blockType, body} = do
1613+
let ctx' = ctx { ctxLabels = label : ctxLabels ctx }
1614+
bt <- case blockType of
1615+
AnonimousTypeUse (FuncType [] []) -> return $ S.Inline Nothing
1616+
AnonimousTypeUse (FuncType [] [vt]) -> return $ S.Inline (Just vt)
1617+
typed -> case getTypeIndex types typed of
1618+
Just idx -> return $ S.TypeIndex idx
1619+
Nothing -> Left "unknown type"
1620+
S.Loop bt <$> mapM (synInstrToStruct ctx') body
1621+
synInstrToStruct ctx@FunCtx { ctxMod = Module { types } } IfInstr {label, blockType, trueBranch, falseBranch} = do
16661622
let ctx' = ctx { ctxLabels = label : ctxLabels ctx }
1623+
bt <- case blockType of
1624+
AnonimousTypeUse (FuncType [] []) -> return $ S.Inline Nothing
1625+
AnonimousTypeUse (FuncType [] [vt]) -> return $ S.Inline (Just vt)
1626+
typed -> case getTypeIndex types typed of
1627+
Just idx -> return $ S.TypeIndex idx
1628+
Nothing -> Left "unknown type"
16671629
trueBranch' <- mapM (synInstrToStruct ctx') trueBranch
16681630
falseBranch' <- mapM (synInstrToStruct ctx') falseBranch
1669-
return $ S.If resultType trueBranch' falseBranch'
1631+
return $ S.If bt trueBranch' falseBranch'
16701632

16711633
synFunctionToStruct :: Module -> Function -> Either String S.Function
16721634
synFunctionToStruct mod Function { funcType, locals, body } = do

0 commit comments

Comments
 (0)