1
1
mirror of https://github.com/tweag/asterius.git synced 2024-09-19 21:07:55 +03:00

Finish work for #34 (+8 squashed commit)

This commit is contained in:
Shao Cheng 2018-10-23 19:29:28 +08:00
parent 900e09a6d0
commit 9c7500e6ba
19 changed files with 625 additions and 780 deletions

View File

@ -65,123 +65,116 @@ async function newAsteriusInstance(req) {
);
return p0;
},
__asterius_memory_trap_trigger: (p_lo, p_hi) =>
console.error(
"[ERROR] Uninitialized memory trapped at 0x" +
__asterius_newI64(p_lo, p_hi)
.toString(16)
.padStart(8, "0")
),
__asterius_load_i64: (p_lo, p_hi, v_lo, v_hi) =>
__asterius_load_i64: (p_lo, p_hi, o, v_lo, v_hi) =>
console.log(
"[INFO] Loading i64 at 0x" +
__asterius_newI64(p_lo, p_hi)
.toString(16)
.padStart(8, "0") +
", value: 0x" +
"+" + o + ", value: 0x" +
__asterius_newI64(v_lo, v_hi)
.toString(16)
.padStart(8, "0")
),
__asterius_store_i64: (p_lo, p_hi, v_lo, v_hi) =>
__asterius_store_i64: (p_lo, p_hi, o, v_lo, v_hi) =>
console.log(
"[INFO] Storing i64 at 0x" +
__asterius_newI64(p_lo, p_hi)
.toString(16)
.padStart(8, "0") +
", value: 0x" +
"+" + o + ", value: 0x" +
__asterius_newI64(v_lo, v_hi)
.toString(16)
.padStart(8, "0")
),
__asterius_load_i8: (p_lo, p_hi, v) =>
__asterius_load_i8: (p_lo, p_hi, o, v) =>
console.log(
"[INFO] Loading i8 at 0x" +
__asterius_newI64(p_lo, p_hi)
.toString(16)
.padStart(8, "0") +
", value: " +
"+" + o + ", value: " +
v
),
__asterius_store_i8: (p_lo, p_hi, v) =>
__asterius_store_i8: (p_lo, p_hi, o, v) =>
console.log(
"[INFO] Storing i8 at 0x" +
__asterius_newI64(p_lo, p_hi)
.toString(16)
.padStart(8, "0") +
", value: " +
"+" + o + ", value: " +
v
),
__asterius_load_i16: (p_lo, p_hi, v) =>
__asterius_load_i16: (p_lo, p_hi, o, v) =>
console.log(
"[INFO] Loading i16 at 0x" +
__asterius_newI64(p_lo, p_hi)
.toString(16)
.padStart(8, "0") +
", value: " +
"+" + o + ", value: " +
v
),
__asterius_store_i16: (p_lo, p_hi, v) =>
__asterius_store_i16: (p_lo, p_hi, o, v) =>
console.log(
"[INFO] Storing i16 at 0x" +
__asterius_newI64(p_lo, p_hi)
.toString(16)
.padStart(8, "0") +
", value: " +
"+" + o + ", value: " +
v
),
__asterius_load_i32: (p_lo, p_hi, v) =>
__asterius_load_i32: (p_lo, p_hi, o, v) =>
console.log(
"[INFO] Loading i32 at 0x" +
__asterius_newI64(p_lo, p_hi)
.toString(16)
.padStart(8, "0") +
", value: " +
"+" + o + ", value: " +
v
),
__asterius_store_i32: (p_lo, p_hi, v) =>
__asterius_store_i32: (p_lo, p_hi, o, v) =>
console.log(
"[INFO] Storing i32 at 0x" +
__asterius_newI64(p_lo, p_hi)
.toString(16)
.padStart(8, "0") +
", value: " +
"+" + o + ", value: " +
v
),
__asterius_load_f32: (p_lo, p_hi, v) =>
__asterius_load_f32: (p_lo, p_hi, o, v) =>
console.log(
"[INFO] Loading f32 at 0x" +
__asterius_newI64(p_lo, p_hi)
.toString(16)
.padStart(8, "0") +
", value: " +
"+" + o + ", value: " +
v
),
__asterius_store_f32: (p_lo, p_hi, v) =>
__asterius_store_f32: (p_lo, p_hi, o, v) =>
console.log(
"[INFO] Storing f32 at 0x" +
__asterius_newI64(p_lo, p_hi)
.toString(16)
.padStart(8, "0") +
", value: " +
"+" + o + ", value: " +
v
),
__asterius_load_f64: (p_lo, p_hi, v) =>
__asterius_load_f64: (p_lo, p_hi, o, v) =>
console.log(
"[INFO] Loading f64 at 0x" +
__asterius_newI64(p_lo, p_hi)
.toString(16)
.padStart(8, "0") +
", value: " +
"+" + o + ", value: " +
v
),
__asterius_store_f64: (p_lo, p_hi, v) =>
__asterius_store_f64: (p_lo, p_hi, o, v) =>
console.log(
"[INFO] Storing f64 at 0x" +
__asterius_newI64(p_lo, p_hi)
.toString(16)
.padStart(8, "0") +
", value: " +
"+" + o + ", value: " +
v
),
__asterius_traceCmm: f =>

File diff suppressed because it is too large Load Diff

View File

@ -129,7 +129,7 @@ marshalCmmStatic st =
GHC.CmmLabel clbl -> UnresolvedStatic <$> marshalCLabel clbl
GHC.CmmLabelOff clbl o -> do
sym <- marshalCLabel clbl
pure $ UnresolvedOffStatic sym o
pure $ SymbolStatic sym o
_ -> throwError $ UnsupportedCmmLit $ showSBS lit
GHC.CmmUninitialised s -> pure $ Uninitialized s
GHC.CmmString s -> pure $ Serialized $ SBS.pack s <> "\0"
@ -187,10 +187,16 @@ marshalCmmLit lit =
(ConstF64 $ fromRational x, F64)
GHC.CmmLabel clbl -> do
sym <- marshalCLabel clbl
pure (Unresolved {unresolvedSymbol = sym}, I64)
pure
( Symbol
{unresolvedSymbol = sym, symbolOffset = 0, resolvedSymbol = Nothing}
, I64)
GHC.CmmLabelOff clbl o -> do
sym <- marshalCLabel clbl
pure (UnresolvedOff {unresolvedSymbol = sym, offset' = o}, I64)
pure
( Symbol
{unresolvedSymbol = sym, symbolOffset = o, resolvedSymbol = Nothing}
, I64)
_ -> throwError $ UnsupportedCmmLit $ showSBS lit
marshalCmmLoad :: GHC.CmmExpr -> GHC.CmmType -> CodeGen (Expression, ValueType)
@ -240,11 +246,11 @@ marshalCmmReg r =
( case gr_k of
GCEnter1 ->
emitErrorMessage
I64
[I64]
"GetGlobal instruction: attempting to read GCEnter1"
GCFun ->
emitErrorMessage
I64
[I64]
"GetGlobal instruction: attempting to read GCFun"
_ -> UnresolvedGetGlobal {unresolvedGlobalReg = gr_k}
, unresolvedGlobalRegType gr_k)
@ -565,7 +571,7 @@ marshalCmmUnMathPrimCall op vt r x = do
CallImport
{ target' = "__asterius_" <> op <> "_" <> showSBS vt
, operands = [xe]
, valueType = vt
, callImportReturnTypes = [vt]
}
}
]
@ -588,7 +594,7 @@ marshalCmmBinMathPrimCall op vt r x y = do
CallImport
{ target' = "__asterius_" <> op <> "_" <> showSBS vt
, operands = [xe, ye]
, valueType = vt
, callImportReturnTypes = [vt]
}
}
]
@ -737,20 +743,21 @@ marshalCmmUnsafeCall ::
marshalCmmUnsafeCall p@(GHC.CmmLit (GHC.CmmLabel clbl)) f rs xs = do
sym <- marshalCLabel clbl
if entityName sym == "barf"
then pure [emitErrorMessage None "barf() is invoked"]
then pure [emitErrorMessage [] "barf() is invoked"]
else do
xes <-
for xs $ \x -> do
(xe, _) <- marshalCmmExpr x
pure xe
case rs of
[] -> pure [Call {target = sym, operands = xes, valueType = None}]
[] -> pure [Call {target = sym, operands = xes, callReturnTypes = []}]
[r] -> do
(lr, vt) <- marshalCmmLocalReg r
pure
[ UnresolvedSetLocal
{ unresolvedLocalReg = lr
, value = Call {target = sym, operands = xes, valueType = vt}
, value =
Call {target = sym, operands = xes, callReturnTypes = [vt]}
}
]
_ ->
@ -817,7 +824,7 @@ marshalCmmBlockBranch instr =
case instr of
GHC.CmmBranch lbl -> do
k <- marshalLabel lbl
pure ([], Nothing, [AddBranch {to = k, condition = Null, code = Null}])
pure ([], Nothing, [AddBranch {to = k, addBranchCondition = Nothing}])
GHC.CmmCondBranch {..} -> do
c <- marshalAndCastCmmExpr cml_pred I32
kf <- marshalLabel cml_false
@ -825,8 +832,8 @@ marshalCmmBlockBranch instr =
pure
( []
, Nothing
, [AddBranch {to = kt, condition = c, code = Null} | kt /= kf] <>
[AddBranch {to = kf, condition = Null, code = Null}])
, [AddBranch {to = kt, addBranchCondition = Just c} | kt /= kf] <>
[AddBranch {to = kf, addBranchCondition = Nothing}])
GHC.CmmSwitch cml_arg st -> do
a <- marshalAndCastCmmExpr cml_arg I64
brs <-
@ -852,11 +859,11 @@ marshalCmmBlockBranch instr =
, operand1 = ConstI64 $ fromIntegral l
}
}
, [ AddBranchForSwitch {to = dest, indexes = tags, code = Null}
, [ AddBranchForSwitch {to = dest, indexes = tags}
| (dest, tags) <- M.toList $ M.fromListWith (<>) brs
, dest /= dest_def
] <>
[AddBranch {to = dest_def, condition = Null, code = Null}])
[AddBranch {to = dest_def, addBranchCondition = Nothing}])
GHC.CmmCall {..} -> do
t <- marshalAndCastCmmExpr cml_target I64
pure ([SetLocal {index = 2, value = t}], Nothing, [])
@ -893,7 +900,7 @@ marshalCmmBlock inner_nodes exit_node = do
case es of
[] -> Nop
[e] -> e
_ -> Block {name = "", bodys = es, valueType = None}
_ -> Block {name = "", bodys = es, blockReturnTypes = []}
marshalCmmProc :: GHC.CmmGraph -> CodeGen AsteriusFunction
marshalCmmProc GHC.CmmGraph {g_graph = GHC.GMany _ body _, ..} = do
@ -910,7 +917,7 @@ marshalCmmProc GHC.CmmGraph {g_graph = GHC.GMany _ body _, ..} = do
AddBlock
{ code =
emitErrorMessage
None
[]
"__asterius_unreachable block is entered"
}
, addBranches = []
@ -936,7 +943,7 @@ marshalCmmProc GHC.CmmGraph {g_graph = GHC.GMany _ body _, ..} = do
]
pure
AsteriusFunction
{ functionType = FunctionType {returnType = I64, paramTypes = []}
{ functionType = FunctionType {paramTypes = [], returnTypes = [I64]}
, body =
Block
{ name = ""
@ -949,7 +956,7 @@ marshalCmmProc GHC.CmmGraph {g_graph = GHC.GMany _ body _, ..} = do
}
, GetLocal {index = 2, valueType = I64}
]
, valueType = I64
, blockReturnTypes = [I64]
}
}

View File

@ -11,7 +11,7 @@ module Asterius.EDSL
, LVal
, getLVal
, putLVal
, setReturnType
, setReturnTypes
, mutParam
, mutLocal
, param
@ -102,7 +102,6 @@ module Asterius.EDSL
import Asterius.Internals
import Asterius.Types
import Asterius.TypesConv
import Control.Monad.Fail
import Control.Monad.State.Strict
import qualified Data.ByteString.Short as SBS
@ -118,7 +117,7 @@ fromDList :: DList a -> [a]
fromDList = ($ []) . appEndo
data EDSLState = EDSLState
{ retType :: ValueType
{ retTypes :: [ValueType]
, paramBuf :: DList ValueType
, paramNum, localNum, labelNum :: Int
, exprBuf :: DList Expression
@ -127,7 +126,7 @@ data EDSLState = EDSLState
initialEDSLState :: EDSLState
initialEDSLState =
EDSLState
{ retType = None
{ retTypes = []
, paramBuf = mempty
, paramNum = 0
, localNum = 0
@ -152,19 +151,19 @@ emit :: Expression -> EDSL ()
emit e =
EDSL $ modify' $ \s@EDSLState {..} -> s {exprBuf = exprBuf `dListSnoc` e}
bundleExpressions :: ValueType -> [Expression] -> Expression
bundleExpressions vt el =
bundleExpressions :: [ValueType] -> [Expression] -> Expression
bundleExpressions vts el =
case el of
[] -> Nop
[e] -> e
_ -> Block {name = mempty, bodys = el, valueType = vt}
_ -> Block {name = mempty, bodys = el, blockReturnTypes = vts}
runEDSL :: ValueType -> EDSL () -> AsteriusFunction
runEDSL vt (EDSL m) =
runEDSL :: [ValueType] -> EDSL () -> AsteriusFunction
runEDSL vts (EDSL m) =
AsteriusFunction
{ functionType =
FunctionType {returnType = retType, paramTypes = fromDList paramBuf}
, body = bundleExpressions vt $ fromDList exprBuf
FunctionType {paramTypes = fromDList paramBuf, returnTypes = retTypes}
, body = bundleExpressions vts $ fromDList exprBuf
}
where
EDSLState {..} = execState m initialEDSLState
@ -174,8 +173,8 @@ data LVal = LVal
, putLVal :: Expression -> EDSL ()
}
setReturnType :: ValueType -> EDSL ()
setReturnType vt = EDSL $ modify' $ \s -> s {retType = vt}
setReturnTypes :: [ValueType] -> EDSL ()
setReturnTypes vts = EDSL $ modify' $ \s -> s {retTypes = vts}
mutParam, mutLocal :: ValueType -> EDSL LVal
mutParam vt =
@ -237,18 +236,24 @@ pointer :: ValueType -> BinaryenIndex -> Expression -> Int -> LVal
pointer vt b bp o =
LVal
{ getLVal =
Load {signed = False, bytes = b, offset = 0, valueType = vt, ptr = p}
Load
{ signed = False
, bytes = b
, offset = fromIntegral o
, valueType = vt
, ptr = wrapInt64 bp
}
, putLVal =
\v ->
emit $
Store {bytes = b, offset = 0, ptr = p, value = v, valueType = vt}
Store
{ bytes = b
, offset = fromIntegral o
, ptr = wrapInt64 bp
, value = v
, valueType = vt
}
}
where
p =
wrapInt64 $
case o of
0 -> bp
_ -> bp `addInt64` constI64 o
pointerI64, pointerI32, pointerI16, pointerI8, pointerF64, pointerF32 ::
Expression -> Int -> LVal
@ -293,35 +298,38 @@ storeF64 bp o = putLVal $ pointerF64 bp o
storeF32 bp o = putLVal $ pointerF32 bp o
call :: AsteriusEntitySymbol -> [Expression] -> EDSL ()
call f xs = emit Call {target = f, operands = xs, valueType = None}
call f xs = emit Call {target = f, operands = xs, callReturnTypes = []}
call' :: AsteriusEntitySymbol -> [Expression] -> ValueType -> EDSL Expression
call' f xs vt = do
lr <- mutLocal vt
putLVal lr Call {target = f, operands = xs, valueType = vt}
putLVal lr Call {target = f, operands = xs, callReturnTypes = [vt]}
pure $ getLVal lr
callImport :: SBS.ShortByteString -> [Expression] -> EDSL ()
callImport f xs = emit CallImport {target' = f, operands = xs, valueType = None}
callImport f xs =
emit CallImport {target' = f, operands = xs, callImportReturnTypes = []}
callImport' ::
SBS.ShortByteString -> [Expression] -> ValueType -> EDSL Expression
callImport' f xs vt = do
lr <- mutLocal vt
putLVal lr CallImport {target' = f, operands = xs, valueType = vt}
putLVal
lr
CallImport {target' = f, operands = xs, callImportReturnTypes = [vt]}
pure $ getLVal lr
callIndirect' :: Expression -> [Expression] -> FunctionType -> EDSL Expression
callIndirect' f xs ft = do
lr <- mutLocal (returnType ft)
callIndirect' f xs ft@FunctionType {returnTypes = [rt]} = do
lr <- mutLocal rt
putLVal
lr
CallIndirect
{ indirectTarget = wrapInt64 f
, operands = xs
, typeName = generateWasmFunctionTypeName ft
}
{indirectTarget = wrapInt64 f, operands = xs, functionType = ft}
pure $ getLVal lr
callIndirect' _ _ ft =
Control.Monad.Fail.fail $
"callIndirect': unsupported function type: " <> show ft
newtype Label = Label
{ unLabel :: SBS.ShortByteString
@ -340,61 +348,61 @@ newScope m = do
m
EDSL $ state $ \s@EDSLState {..} -> (exprBuf, s {exprBuf = orig_buf})
block', loop' :: ValueType -> (Label -> EDSL ()) -> EDSL ()
block' vt cont = do
block', loop' :: [ValueType] -> (Label -> EDSL ()) -> EDSL ()
block' vts cont = do
lbl <- newLabel
es <- newScope $ cont lbl
emit Block {name = unLabel lbl, bodys = fromDList es, valueType = vt}
emit Block {name = unLabel lbl, bodys = fromDList es, blockReturnTypes = vts}
blockWithLabel :: ValueType -> Label -> EDSL () -> EDSL ()
blockWithLabel vt lbl m = do
blockWithLabel :: [ValueType] -> Label -> EDSL () -> EDSL ()
blockWithLabel vts lbl m = do
es <- newScope m
emit Block {name = unLabel lbl, bodys = fromDList es, valueType = vt}
emit Block {name = unLabel lbl, bodys = fromDList es, blockReturnTypes = vts}
loop' vt cont = do
loop' vts cont = do
lbl <- newLabel
es <- newScope $ cont lbl
emit Loop {name = unLabel lbl, body = bundleExpressions vt $ fromDList es}
emit Loop {name = unLabel lbl, body = bundleExpressions vts $ fromDList es}
if' :: ValueType -> Expression -> EDSL () -> EDSL () -> EDSL ()
if' vt cond t f = do
if' :: [ValueType] -> Expression -> EDSL () -> EDSL () -> EDSL ()
if' vts cond t f = do
t_es <- newScope t
f_es <- newScope f
emit
If
{ condition = cond
, ifTrue = bundleExpressions vt $ fromDList t_es
, ifFalse = bundleExpressions vt $ fromDList f_es
, ifTrue = bundleExpressions vts $ fromDList t_es
, ifFalse = Just $ bundleExpressions vts $ fromDList f_es
}
break' :: Label -> Expression -> EDSL ()
break' (Label lbl) cond = emit Break {name = lbl, condition = cond}
break' :: Label -> Maybe Expression -> EDSL ()
break' (Label lbl) cond = emit Break {name = lbl, breakCondition = cond}
whileLoop :: ValueType -> Expression -> EDSL () -> EDSL ()
whileLoop vt cond body =
loop' vt $ \lbl -> if' vt cond (body *> break' lbl Null) mempty
whileLoop :: [ValueType] -> Expression -> EDSL () -> EDSL ()
whileLoop vts cond body =
loop' vts $ \lbl -> if' vts cond (body *> break' lbl Nothing) mempty
switchI64 :: Expression -> (EDSL () -> ([(Int, EDSL ())], EDSL ())) -> EDSL ()
switchI64 cond make_clauses =
block' None $ \switch_lbl ->
let exit_switch = break' switch_lbl Null
block' [] $ \switch_lbl ->
let exit_switch = break' switch_lbl Nothing
(clauses, def_clause) = make_clauses exit_switch
switch_block = do
switch_def_lbl <- newLabel
blockWithLabel None switch_def_lbl $ do
blockWithLabel [] switch_def_lbl $ do
clause_seq <-
for (reverse clauses) $ \(clause_i, clause_m) -> do
clause_lbl <- newLabel
pure (clause_i, clause_lbl, clause_m)
foldr
(\(_, clause_lbl, clause_m) tot_m -> do
blockWithLabel None clause_lbl tot_m
blockWithLabel [] clause_lbl tot_m
clause_m)
(foldr
(\(clause_i, clause_lbl, _) br_m -> do
break' clause_lbl $ cond `eqInt64` constI64 clause_i
break' clause_lbl $ Just $ cond `eqInt64` constI64 clause_i
br_m)
(break' switch_def_lbl Null)
(break' switch_def_lbl Nothing)
clause_seq)
clause_seq
def_clause
@ -418,7 +426,7 @@ convertUInt64ToFloat64 = Unary ConvertUInt64ToFloat64
truncUFloat64ToInt64 = Unary TruncUFloat64ToInt64
growMemory x = Host {hostOp = GrowMemory, name = "", operands = [x]}
growMemory x = Host {hostOp = GrowMemory, operands = [x]}
roundupBytesToWords n = (n `addInt64` constI64 7) `divUInt64` constI64 8
@ -465,7 +473,8 @@ andInt32 = Binary AndInt32
orInt32 = Binary OrInt32
symbol :: AsteriusEntitySymbol -> Expression
symbol = Unresolved
symbol sym =
Symbol {unresolvedSymbol = sym, symbolOffset = 0, resolvedSymbol = Nothing}
constI32, constI64 :: Int -> Expression
constI32 = ConstI32 . fromIntegral

View File

@ -153,11 +153,12 @@ marshalToFFIValueType (GHC.unLoc -> t) =
| GHC.occNameString tv == "JSRef" -> pure FFI_JSREF
_ -> empty
marshalToFFIResultType ::
(GHC.HasOccName (GHC.IdP p)) => GHC.LHsType p -> Maybe (Maybe FFIValueType)
marshalToFFIResultType (GHC.unLoc -> GHC.HsParTy _ t) = marshalToFFIResultType t
marshalToFFIResultType (GHC.unLoc -> GHC.HsTupleTy _ _ []) = pure Nothing
marshalToFFIResultType t = Just <$> marshalToFFIValueType t
marshalToFFIResultTypes ::
(GHC.HasOccName (GHC.IdP p)) => GHC.LHsType p -> Maybe [FFIValueType]
marshalToFFIResultTypes (GHC.unLoc -> GHC.HsParTy _ t) =
marshalToFFIResultTypes t
marshalToFFIResultTypes (GHC.unLoc -> GHC.HsTupleTy _ _ []) = pure []
marshalToFFIResultTypes t = (: []) <$> marshalToFFIValueType t
marshalToFFIFunctionType ::
(GHC.HasOccName (GHC.IdP p)) => GHC.LHsType p -> Maybe FFIFunctionType
@ -171,14 +172,15 @@ marshalToFFIFunctionType (GHC.unLoc -> ty) =
pure ft {ffiParamTypes = vt : ffiParamTypes ft}
GHC.HsAppTy _ (GHC.unLoc -> (GHC.HsTyVar _ _ (GHC.occName . GHC.unLoc -> io))) t
| io == GHC.occName GHC.ioTyConName -> do
r <- marshalToFFIResultType t
r <- marshalToFFIResultTypes t
pure $
FFIFunctionType
{ffiParamTypes = [], ffiResultType = r, ffiInIO = True}
{ffiParamTypes = [], ffiResultTypes = r, ffiInIO = True}
_ -> do
r <- marshalToFFIResultType (GHC.noLoc ty)
r <- marshalToFFIResultTypes (GHC.noLoc ty)
pure
FFIFunctionType {ffiParamTypes = [], ffiResultType = r, ffiInIO = False}
FFIFunctionType
{ffiParamTypes = [], ffiResultTypes = r, ffiInIO = False}
rewriteJSRef :: (Monad m, Data a) => a -> m a
rewriteJSRef t =
@ -191,32 +193,30 @@ rewriteJSRef t =
_ -> pure t
_ -> gmapM rewriteJSRef t
recoverWasmImportValueType :: Maybe FFIValueType -> ValueType
recoverWasmImportValueType :: FFIValueType -> ValueType
recoverWasmImportValueType vt =
case vt of
Just FFI_VAL {..} -> ffiJSValueType
Just FFI_JSREF -> I32
Nothing -> None
FFI_VAL {..} -> ffiJSValueType
FFI_JSREF -> I32
recoverWasmWrapperValueType :: Maybe FFIValueType -> ValueType
recoverWasmWrapperValueType :: FFIValueType -> ValueType
recoverWasmWrapperValueType vt =
case vt of
Just FFI_VAL {..} -> ffiWasmValueType
Just FFI_JSREF -> I64
Nothing -> None
FFI_VAL {..} -> ffiWasmValueType
FFI_JSREF -> I64
recoverWasmImportFunctionType :: FFIFunctionType -> FunctionType
recoverWasmImportFunctionType FFIFunctionType {..} =
FunctionType
{ returnType = recoverWasmImportValueType ffiResultType
, paramTypes = [recoverWasmImportValueType $ Just t | t <- ffiParamTypes]
{ paramTypes = [recoverWasmImportValueType t | t <- ffiParamTypes]
, returnTypes = map recoverWasmImportValueType ffiResultTypes
}
recoverWasmWrapperFunctionType :: FFIFunctionType -> FunctionType
recoverWasmWrapperFunctionType FFIFunctionType {..} =
FunctionType
{ returnType = recoverWasmWrapperValueType ffiResultType
, paramTypes = [recoverWasmWrapperValueType $ Just t | t <- ffiParamTypes]
{ paramTypes = [recoverWasmWrapperValueType t | t <- ffiParamTypes]
, returnTypes = map recoverWasmWrapperValueType ffiResultTypes
}
recoverWasmImportFunctionName :: AsteriusModuleSymbol -> Int -> String
@ -385,11 +385,11 @@ addFFIProcessor c = do
, generateFFIWrapperModule $ ffi_states ! mod_sym))
generateImplicitCastExpression ::
Bool -> ValueType -> ValueType -> Expression -> Expression
generateImplicitCastExpression signed src_t dest_t src_expr =
case (src_t, dest_t) of
(I64, I32) -> Unary {unaryOp = WrapInt64, operand0 = src_expr}
(I32, I64) ->
Bool -> [ValueType] -> [ValueType] -> Expression -> Expression
generateImplicitCastExpression signed src_ts dest_ts src_expr =
case (src_ts, dest_ts) of
([I64], [I32]) -> Unary {unaryOp = WrapInt64, operand0 = src_expr}
([I32], [I64]) ->
Unary
{ unaryOp =
if signed
@ -398,10 +398,11 @@ generateImplicitCastExpression signed src_t dest_t src_expr =
, operand0 = src_expr
}
_
| src_t == dest_t -> src_expr
| src_ts == dest_ts -> src_expr
| otherwise ->
error $
"Unsupported implicit cast from " <> show src_t <> " to " <> show dest_t
"Unsupported implicit cast from " <> show src_ts <> " to " <>
show dest_ts
generateFFIImportWrapperFunction ::
AsteriusModuleSymbol -> Int -> FFIImportDecl -> AsteriusFunction
@ -410,11 +411,11 @@ generateFFIImportWrapperFunction mod_sym k FFIImportDecl {..} =
{ functionType = recoverWasmWrapperFunctionType ffiFunctionType
, body =
generateImplicitCastExpression
(case ffiResultType ffiFunctionType of
Just FFI_VAL {..} -> signed
(case ffiResultTypes ffiFunctionType of
[FFI_VAL {..}] -> signed
_ -> False)
(returnType import_func_type)
(returnType wrapper_func_type) $
(returnTypes import_func_type)
(returnTypes wrapper_func_type) $
CallImport
{ target' = fromString $ recoverWasmImportFunctionName mod_sym k
, operands =
@ -422,8 +423,8 @@ generateFFIImportWrapperFunction mod_sym k FFIImportDecl {..} =
(case param_t of
FFI_VAL {..} -> signed
_ -> False)
wrapper_param_t
import_param_t
[wrapper_param_t]
[import_param_t]
GetLocal {index = i, valueType = wrapper_param_t}
| (i, param_t, wrapper_param_t, import_param_t) <-
zip4
@ -432,7 +433,7 @@ generateFFIImportWrapperFunction mod_sym k FFIImportDecl {..} =
(paramTypes wrapper_func_type)
(paramTypes import_func_type)
]
, valueType = returnType import_func_type
, callImportReturnTypes = returnTypes import_func_type
}
}
where
@ -453,7 +454,7 @@ generateFFIExportFunction FFIExportDecl {..} =
Call
{ target = "allocate"
, operands = [cap, ConstI64 1]
, valueType = I64
, callReturnTypes = [I64]
}
}
, Call
@ -484,29 +485,33 @@ generateFFIExportFunction FFIExportDecl {..} =
, GetLocal
{ index = ffi_param_i
, valueType =
recoverWasmWrapperValueType $
Just ffi_param_t
recoverWasmWrapperValueType
ffi_param_t
}
]
, valueType = I64
, callReturnTypes = [I64]
}
]
, valueType = I64
, callReturnTypes = [I64]
})
Unresolved {unresolvedSymbol = ffiExportClosure}
Symbol
{ unresolvedSymbol = ffiExportClosure
, symbolOffset = 0
, resolvedSymbol = Nothing
}
(zip [0 ..] $ ffiParamTypes ffiFunctionType)
, UnresolvedGetLocal {unresolvedLocalReg = ret}
]
, valueType = None
, callReturnTypes = []
}
, Call
{ target = "rts_checkSchedStatus"
, operands = [cap]
, valueType = None
, callReturnTypes = []
}
] <>
case ffiResultType ffiFunctionType of
Just ffi_result_t ->
case ffiResultTypes ffiFunctionType of
[ffi_result_t] ->
[ Call
{ target =
AsteriusEntitySymbol
@ -526,17 +531,22 @@ generateFFIExportFunction FFIExportDecl {..} =
}
}
]
, valueType =
recoverWasmWrapperValueType $ Just ffi_result_t
, callReturnTypes =
[recoverWasmWrapperValueType ffi_result_t]
}
]
_ -> []
, valueType =
recoverWasmWrapperValueType $ ffiResultType ffiFunctionType
, blockReturnTypes =
map recoverWasmWrapperValueType $ ffiResultTypes ffiFunctionType
}
}
where
cap = Unresolved {unresolvedSymbol = "MainCapability"}
cap =
Symbol
{ unresolvedSymbol = "MainCapability"
, symbolOffset = 0
, resolvedSymbol = Nothing
}
ret = UniqueLocalReg 0 I64
generateFFIWrapperModule :: FFIMarshalState -> AsteriusModule
@ -569,9 +579,9 @@ generateFFIWrapperModule mod_ffi_state@FFIMarshalState {..} =
| (k, f) <- export_funcs
]
generateFFIFunctionImports :: FFIMarshalState -> [AsteriusFunctionImport]
generateFFIFunctionImports :: FFIMarshalState -> [FunctionImport]
generateFFIFunctionImports FFIMarshalState {..} =
[ AsteriusFunctionImport
[ FunctionImport
{ internalName = fn
, externalModuleName = "jsffi"
, externalBaseName = fn
@ -587,8 +597,8 @@ generateFFILambda FFIImportDecl {ffiFunctionType = FFIFunctionType {..}, ..} =
"((" <>
mconcat (intersperse "," ["_" <> intDec i | i <- [1 .. length ffiParamTypes]]) <>
")=>" <>
(case ffiResultType of
Just FFI_JSREF -> "__asterius_jsffi.newJSRef("
(case ffiResultTypes of
[FFI_JSREF] -> "__asterius_jsffi.newJSRef("
_ -> "(") <>
mconcat
[ case chunk of

View File

@ -1,6 +1,7 @@
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# OPTIONS_GHC -Wno-overflowed-literals #-}
module Asterius.Marshal
( MarshalError(..)
@ -10,6 +11,7 @@ module Asterius.Marshal
import Asterius.Internals
import Asterius.Types
import Asterius.TypesConv
import Bindings.Binaryen.Raw
import Control.Exception
import qualified Data.ByteString as BS
@ -17,6 +19,7 @@ import qualified Data.ByteString.Short as SBS
import qualified Data.ByteString.Unsafe as BS
import Data.Foldable
import qualified Data.Map.Strict as M
import qualified Data.Set as Set
import Data.Traversable
import Foreign
import Foreign.C
@ -38,12 +41,20 @@ marshalBool flag =
marshalValueType :: ValueType -> BinaryenType
marshalValueType t =
case t of
None -> c_BinaryenTypeNone
I32 -> c_BinaryenTypeInt32
I64 -> c_BinaryenTypeInt64
F32 -> c_BinaryenTypeFloat32
F64 -> c_BinaryenTypeFloat64
marshalReturnTypes :: [ValueType] -> IO BinaryenType
marshalReturnTypes vts =
case vts of
[] -> pure c_BinaryenTypeNone
[vt] -> pure $ marshalValueType vt
_ ->
fail $
"binaryen doesn't support multi-value yet: failed to marshal " <> show vts
marshalUnaryOp :: UnaryOp -> BinaryenOp
marshalUnaryOp op =
case op of
@ -189,8 +200,9 @@ marshalFunctionType ::
-> IO BinaryenFunctionTypeRef
marshalFunctionType pool m k FunctionType {..} = do
(pts, ptl) <- marshalV pool $ map marshalValueType paramTypes
rts <- marshalReturnTypes returnTypes
np <- marshalSBS pool k
c_BinaryenAddFunctionType m np (marshalValueType returnType) pts ptl
c_BinaryenAddFunctionType m np rts pts ptl
marshalExpression ::
Pool -> BinaryenModuleRef -> Expression -> IO BinaryenExpressionRef
@ -200,18 +212,19 @@ marshalExpression pool m e =
bs <- forM bodys $ marshalExpression pool m
(bsp, bl) <- marshalV pool bs
np <- marshalSBS pool name
c_BinaryenBlock m np bsp bl (marshalValueType valueType)
rts <- marshalReturnTypes blockReturnTypes
c_BinaryenBlock m np bsp bl rts
If {..} -> do
c <- marshalExpression pool m condition
t <- marshalExpression pool m ifTrue
f <- marshalExpression pool m ifFalse
f <- marshalMaybeExpression pool m ifFalse
c_BinaryenIf m c t f
Loop {..} -> do
b <- marshalExpression pool m body
np <- marshalSBS pool name
c_BinaryenLoop m np b
Break {..} -> do
c <- marshalExpression pool m condition
c <- marshalMaybeExpression pool m breakCondition
np <- marshalSBS pool name
c_BinaryenBreak m np c nullPtr
Switch {..} -> do
@ -224,17 +237,19 @@ marshalExpression pool m e =
os <- forM operands $ marshalExpression pool m
(ops, osl) <- marshalV pool os
tp <- marshalSBS pool (entityName target)
c_BinaryenCall m tp ops osl (marshalValueType valueType)
rts <- marshalReturnTypes callReturnTypes
c_BinaryenCall m tp ops osl rts
CallImport {..} -> do
os <- forM operands $ marshalExpression pool m
(ops, osl) <- marshalV pool os
tp <- marshalSBS pool target'
c_BinaryenCall m tp ops osl (marshalValueType valueType)
rts <- marshalReturnTypes callImportReturnTypes
c_BinaryenCall m tp ops osl rts
CallIndirect {..} -> do
t <- marshalExpression pool m indirectTarget
os <- forM operands $ marshalExpression pool m
(ops, osl) <- marshalV pool os
tp <- marshalSBS pool typeName
tp <- marshalSBS pool $ showSBS functionType
c_BinaryenCallIndirect m t ops osl tp
GetLocal {..} -> c_BinaryenGetLocal m index $ marshalValueType valueType
SetLocal {..} -> do
@ -268,14 +283,21 @@ marshalExpression pool m e =
Host {..} -> do
xs <- forM operands $ marshalExpression pool m
(es, en) <- marshalV pool xs
np <- marshalSBS pool name
c_BinaryenHost m (marshalHostOp hostOp) np es en
c_BinaryenHost m (marshalHostOp hostOp) nullPtr es en
Nop -> c_BinaryenNop m
Unreachable -> c_BinaryenUnreachable m
CFG {..} -> relooperRun pool m graph
Null -> pure nullPtr
Symbol {resolvedSymbol = Just x, ..} ->
c_BinaryenConstInt64 m (x + fromIntegral symbolOffset)
_ -> throwIO $ UnsupportedExpression e
marshalMaybeExpression ::
Pool -> BinaryenModuleRef -> Maybe Expression -> IO BinaryenExpressionRef
marshalMaybeExpression pool m x =
case x of
Just e -> marshalExpression pool m e
_ -> pure nullPtr
marshalFunction ::
Pool
-> BinaryenModuleRef
@ -332,7 +354,7 @@ marshalMemory pool m Memory {..} = do
c_BinaryenSetMemory
m
initialPages
maximumPages
(-1)
enp
cp
ofs
@ -341,17 +363,18 @@ marshalMemory pool m Memory {..} = do
0
marshalModule :: Pool -> Module -> IO BinaryenModuleRef
marshalModule pool Module {..} = do
marshalModule pool hs_mod@Module {..} = do
let fts = generateWasmFunctionTypeSet hs_mod
m <- c_BinaryenModuleCreate
ftps <-
fmap M.fromList $
for (M.toList functionTypeMap) $ \(k, ft) -> do
ftp <- marshalFunctionType pool m k ft
pure (k, ftp)
for (Set.toList fts) $ \ft -> do
ftp <- marshalFunctionType pool m (showSBS ft) ft
pure (ft, ftp)
for_ (M.toList functionMap') $ \(k, f@Function {..}) ->
marshalFunction pool m k (ftps ! functionTypeName) f
marshalFunction pool m k (ftps ! functionType) f
forM_ functionImports $ \fi@FunctionImport {..} ->
marshalFunctionImport pool m (ftps ! functionTypeName) fi
marshalFunctionImport pool m (ftps ! functionType) fi
forM_ functionExports $ marshalFunctionExport pool m
marshalFunctionTable pool m functionTable
marshalMemory pool m memory
@ -383,13 +406,11 @@ relooperAddBranch ::
relooperAddBranch pool m bm k ab =
case ab of
AddBranch {..} -> do
_cond <- marshalExpression pool m condition
_code <- marshalExpression pool m code
c_RelooperAddBranch (bm ! k) (bm ! to) _cond _code
_cond <- marshalMaybeExpression pool m addBranchCondition
c_RelooperAddBranch (bm ! k) (bm ! to) _cond nullPtr
AddBranchForSwitch {..} -> do
c <- marshalExpression pool m code
(idp, idn) <- marshalV pool indexes
c_RelooperAddBranchForSwitch (bm ! k) (bm ! to) idp idn c
c_RelooperAddBranchForSwitch (bm ! k) (bm ! to) idp idn nullPtr
relooperRun ::
Pool -> BinaryenModuleRef -> RelooperRun -> IO BinaryenExpressionRef

View File

@ -45,8 +45,8 @@ addMemoryTrapDeep t =
(F32, 4) -> "__asterius_Load_F32"
(F64, 8) -> "__asterius_Load_F64"
_ -> error $ "Unsupported instruction: " <> show t
, operands = [new_i64_ptr]
, valueType = valueType
, operands = [new_i64_ptr, ConstI32 $ fromIntegral offset]
, callReturnTypes = [valueType]
}
Store {ptr = Unary {unaryOp = WrapInt64, operand0 = i64_ptr}, ..} -> do
new_i64_ptr <- addMemoryTrapDeep i64_ptr
@ -62,22 +62,23 @@ addMemoryTrapDeep t =
(F32, 4) -> "__asterius_Store_F32"
(F64, 8) -> "__asterius_Store_F64"
_ -> error $ "Unsupported instruction: " <> show t
, operands = [new_i64_ptr, new_value]
, valueType = None
, operands =
[new_i64_ptr, ConstI32 $ fromIntegral offset, new_value]
, callReturnTypes = []
}
Host {hostOp = CurrentMemory} ->
pure
CallImport
{ target' = "__asterius_current_memory"
, operands = [t]
, valueType = I32
, callImportReturnTypes = [I32]
}
Host {hostOp = GrowMemory, ..} ->
pure
CallImport
{ target' = "__asterius_grow_memory"
, operands = [t, head operands]
, valueType = I32
, callImportReturnTypes = [I32]
}
_ -> go
_ -> go

View File

@ -12,12 +12,14 @@ import Asterius.Internals
import qualified Asterius.Internals.DList as DList
import Asterius.TypeInfer
import Asterius.Types
import Asterius.TypesConv
import Control.Exception
import Control.Monad.Except
import qualified Data.ByteString.Short as SBS
import Data.Coerce
import Data.List
import qualified Data.Map.Strict as Map
import qualified Data.Set as Set
import Data.Traversable
import Data.Word
import qualified Language.WebAssembly.WireFormat as Wasm
@ -33,51 +35,46 @@ data MarshalError
instance Exception MarshalError
data ModuleSymbolTable = ModuleSymbolTable
{ functionTypeSymbols :: Map.Map SBS.ShortByteString Wasm.FunctionTypeIndex
{ functionTypeSymbols :: Map.Map FunctionType Wasm.FunctionTypeIndex
, functionSymbols :: Map.Map SBS.ShortByteString Wasm.FunctionIndex
}
makeModuleSymbolTable ::
MonadError MarshalError m => Module -> m ModuleSymbolTable
makeModuleSymbolTable Module {..} = do
makeModuleSymbolTable m@Module {..} = do
let _has_dup l = length l /= length (nub l)
_func_import_syms =
[internalName | FunctionImport {..} <- functionImports]
_func_syms = Map.keys functionMap'
_func_conflict_syms = _func_import_syms `intersect` _func_syms
_func_types = generateWasmFunctionTypeSet m
if _has_dup _func_import_syms
then throwError DuplicateFunctionImport
else pure
ModuleSymbolTable
{ functionTypeSymbols =
Map.fromDistinctAscList $
zip (Map.keys functionTypeMap) (coerce [0 :: Word32 ..])
zip (Set.toList _func_types) (coerce [0 :: Word32 ..])
, functionSymbols =
Map.fromList $
zip (_func_import_syms <> _func_syms) (coerce [0 :: Word32 ..])
}
makeResultType :: ValueType -> [Wasm.ValueType]
makeResultType vt =
makeValueType :: ValueType -> Wasm.ValueType
makeValueType vt =
case vt of
None -> []
I32 -> [Wasm.I32]
I64 -> [Wasm.I64]
F32 -> [Wasm.F32]
F64 -> [Wasm.F64]
I32 -> Wasm.I32
I64 -> Wasm.I64
F32 -> Wasm.F32
F64 -> Wasm.F64
makeTypeSection :: MonadError MarshalError m => Module -> m Wasm.Section
makeTypeSection Module {..} = do
makeTypeSection ::
MonadError MarshalError m => Module -> ModuleSymbolTable -> m Wasm.Section
makeTypeSection Module {..} ModuleSymbolTable {..} = do
_func_types <-
for (Map.elems functionTypeMap) $ \FunctionType {..} -> do
_param_types <-
for paramTypes $ \case
None -> throwError InvalidParameterType
I32 -> pure Wasm.I32
I64 -> pure Wasm.I64
F32 -> pure Wasm.F32
F64 -> pure Wasm.F64
let _result_type = makeResultType returnType
for (Map.keys functionTypeSymbols) $ \FunctionType {..} -> do
let _param_types = map makeValueType paramTypes
_result_type = map makeValueType returnTypes
pure
Wasm.FunctionType
{parameterTypes = _param_types, resultTypes = _result_type}
@ -93,7 +90,7 @@ makeImportSection Module {..} ModuleSymbolTable {..} =
{ moduleName = coerce externalModuleName
, importName = coerce externalBaseName
, importDescription =
Wasm.ImportFunction $ functionTypeSymbols ! functionTypeName
Wasm.ImportFunction $ functionTypeSymbols ! functionType
}
| FunctionImport {..} <- functionImports
]
@ -105,7 +102,7 @@ makeFunctionSection Module {..} ModuleSymbolTable {..} =
pure
Wasm.FunctionSection
{ functionTypeIndices =
[ functionTypeSymbols ! functionTypeName
[ functionTypeSymbols ! functionType
| Function {..} <- Map.elems functionMap'
]
}
@ -143,9 +140,7 @@ makeMemorySection Module {..} =
Wasm.MemoryType
{ memoryLimits =
Wasm.Limits
{ minLimit = initialPages
, maxLimit = Just maximumPages
}
{minLimit = initialPages, maxLimit = Nothing}
}
}
]
@ -244,8 +239,7 @@ makeLocalContext Module {..} Function {..} =
(arity, emptyLocalContext) $
sort $ zip varTypes [arity ..]
where
arity =
fromIntegral $ length $ paramTypes (functionTypeMap ! functionTypeName)
arity = fromIntegral $ length $ paramTypes functionType
lookupLocalContext :: LocalContext -> BinaryenIndex -> Wasm.LocalIndex
lookupLocalContext LocalContext {..} i =
@ -276,7 +270,7 @@ makeInstructions _module_symtable@ModuleSymbolTable {..} _de_bruijn_ctx _local_c
pure $
DList.singleton
Wasm.Block
{ blockResultType = makeResultType valueType
{ blockResultType = map makeValueType blockReturnTypes
, blockInstructions = DList.toList $ mconcat bs
}
If {..} -> do
@ -287,12 +281,16 @@ makeInstructions _module_symtable@ModuleSymbolTable {..} _de_bruijn_ctx _local_c
makeInstructions _module_symtable _new_de_bruijn_ctx _local_ctx ifTrue
f <-
DList.toList <$>
makeInstructions _module_symtable _new_de_bruijn_ctx _local_ctx ifFalse
makeInstructionsMaybe
_module_symtable
_new_de_bruijn_ctx
_local_ctx
ifFalse
pure $
c <>
DList.singleton
Wasm.If
{ ifResultType = makeResultType $ infer ifTrue
{ ifResultType = map makeValueType $ infer ifTrue
, thenInstructions = t
, elseInstructions =
case f of
@ -307,16 +305,11 @@ makeInstructions _module_symtable@ModuleSymbolTable {..} _de_bruijn_ctx _local_c
Wasm.Loop {loopResultType = [], loopInstructions = DList.toList b}
Break {..} -> do
let _lbl = extractLabel _de_bruijn_ctx name
case condition of
Null -> pure $ DList.singleton Wasm.Branch {branchLabel = _lbl}
_ -> do
c <-
makeInstructions
_module_symtable
_de_bruijn_ctx
_local_ctx
condition
case breakCondition of
Just cond -> do
c <- makeInstructions _module_symtable _de_bruijn_ctx _local_ctx cond
pure $ c <> DList.singleton Wasm.BranchIf {branchIfLabel = _lbl}
_ -> pure $ DList.singleton Wasm.Branch {branchLabel = _lbl}
Switch {..} -> do
c <- makeInstructions _module_symtable _de_bruijn_ctx _local_ctx condition
pure $
@ -356,7 +349,7 @@ makeInstructions _module_symtable@ModuleSymbolTable {..} _de_bruijn_ctx _local_c
mconcat xs <> f <>
DList.singleton
Wasm.CallIndirect
{callIndirectFuctionTypeIndex = functionTypeSymbols ! typeName}
{callIndirectFuctionTypeIndex = functionTypeSymbols ! functionType}
GetLocal {..} ->
pure $
DList.singleton
@ -563,22 +556,37 @@ makeInstructions _module_symtable@ModuleSymbolTable {..} _de_bruijn_ctx _local_c
pure $ mconcat xs <> op
Nop -> pure $ DList.singleton Wasm.Nop
Unreachable -> pure $ DList.singleton Wasm.Unreachable
Null -> pure mempty
Symbol {resolvedSymbol = Just x, ..} ->
pure $
DList.singleton
Wasm.I64Const {i64ConstValue = x + fromIntegral symbolOffset}
_ -> throwError $ UnsupportedExpression expr
makeInstructionsMaybe ::
MonadError MarshalError m
=> ModuleSymbolTable
-> DeBruijnContext
-> LocalContext
-> Maybe Expression
-> m (DList.DList Wasm.Instruction)
makeInstructionsMaybe _module_symtable _de_bruijn_ctx _local_ctx m_expr =
case m_expr of
Just expr ->
makeInstructions _module_symtable _de_bruijn_ctx _local_ctx expr
_ -> pure mempty
makeCodeSection ::
MonadError MarshalError m => Module -> ModuleSymbolTable -> m Wasm.Section
makeCodeSection _mod@Module {..} _module_symtable =
fmap Wasm.CodeSection $
for (Map.elems functionMap') $ \_func@Function {..} -> do
let _local_ctx@LocalContext {..} = makeLocalContext _mod _func
_locals <-
for (Map.toList localCount) $ \case
(None, _) -> throwError InvalidLocalType
(I32, c) -> pure (Wasm.I32, c)
(I64, c) -> pure (Wasm.I64, c)
(F32, c) -> pure (Wasm.F32, c)
(F64, c) -> pure (Wasm.F64, c)
_locals =
flip map (Map.toList localCount) $ \case
(I32, c) -> (Wasm.I32, c)
(I64, c) -> (Wasm.I64, c)
(F32, c) -> (Wasm.F32, c)
(F64, c) -> (Wasm.F64, c)
_body <-
makeInstructions _module_symtable emptyDeBruijnContext _local_ctx body
pure
@ -614,7 +622,7 @@ makeDataSection Module {..} _module_symtable =
makeModule :: MonadError MarshalError m => Module -> m Wasm.Module
makeModule m = do
_module_symtable <- makeModuleSymbolTable m
_type_sec <- makeTypeSection m
_type_sec <- makeTypeSection m _module_symtable
_import_sec <- makeImportSection m _module_symtable
_func_sec <- makeFunctionSection m _module_symtable
_table_sec <- makeTableSection m

View File

@ -37,24 +37,27 @@ relooper RelooperRun {..} = result_expr
M.foldlWithKey'
(\(tot_expr, residule_exprs) lbl RelooperBlock {..} ->
( Block
{name = lbl, bodys = tot_expr : residule_exprs, valueType = None}
{ name = lbl
, bodys = tot_expr : residule_exprs
, blockReturnTypes = []
}
, case addBlock of
AddBlock {..} ->
code :
(case addBranches of
[] -> [Break {name = exit_lbl, condition = Null}]
[] -> [Break {name = exit_lbl, breakCondition = Nothing}]
branches ->
foldr
(\AddBranch {condition, to} e ->
(\AddBranch {addBranchCondition = Just cond, to} e ->
If
{ condition = condition
{ condition = cond
, ifTrue = set_block_lbl to
, ifFalse = e
, ifFalse = Just e
})
(set_block_lbl $ to def_branch)
(init branches) :
[Break {name = loop_lbl, condition = Null}]
where def_branch@AddBranch {condition = Null, code = Null} =
[Break {name = loop_lbl, breakCondition = Nothing}]
where def_branch@AddBranch {addBranchCondition = Nothing} =
last branches)
AddBlockWithSwitch {..} ->
[code, SetLocal {index = 1, value = condition}] <>
@ -73,13 +76,13 @@ relooper RelooperRun {..} = result_expr
| tag <- indexes
]
, ifTrue = set_block_lbl to
, ifFalse = e
, ifFalse = Just e
})
(set_block_lbl $ to def_branch)
(init branches) :
[Break {name = loop_lbl, condition = Null}])
[Break {name = loop_lbl, breakCondition = Nothing}])
where branches = addBranches
def_branch@AddBranch {condition = Null, code = Null} =
def_branch@AddBranch {addBranchCondition = Nothing} =
last branches))
(initial_expr, [])
blockMap
@ -94,11 +97,11 @@ relooper RelooperRun {..} = result_expr
Block
{ name = ""
, bodys = blocks_expr : last_block_residule_exprs
, valueType = None
, blockReturnTypes = []
}
}
]
, valueType = None
, blockReturnTypes = []
}
relooperDeep :: (Monad m, Data a) => a -> m a

View File

@ -113,10 +113,10 @@ resolveGlobalRegs x =
UnresolvedGetGlobal {..}
| unresolvedGlobalReg == BaseReg ->
pure
Binary
{ binaryOp = AddInt64
, operand0 = Unresolved {unresolvedSymbol = "MainCapability"}
, operand1 = ConstI64 $ fromIntegral offset_Capability_r
Symbol
{ unresolvedSymbol = "MainCapability"
, symbolOffset = offset_Capability_r
, resolvedSymbol = Nothing
}
| otherwise ->
pure
@ -131,7 +131,7 @@ resolveGlobalRegs x =
| unresolvedGlobalReg == BaseReg ->
pure $
emitErrorMessage
None
[]
"SetGlobal instruction: attempting to assign to BaseReg"
| otherwise -> do
new_value <- resolveGlobalRegs value
@ -150,12 +150,10 @@ resolveGlobalRegs x =
Unary
{ unaryOp = WrapInt64
, operand0 =
Binary
{ binaryOp = AddInt64
, operand0 = Unresolved {unresolvedSymbol = "MainCapability"}
, operand1 =
ConstI64 $
fromIntegral $ offset_Capability_r + globalRegOffset gr
Symbol
{ unresolvedSymbol = "MainCapability"
, symbolOffset = offset_Capability_r + globalRegOffset gr
, resolvedSymbol = Nothing
}
}
go = gmapM resolveGlobalRegs x
@ -294,9 +292,11 @@ mergeSymbols debug AsteriusStore {..} root_syms export_funcs = do
, AsteriusFunction
{ functionType =
FunctionType
{returnType = I64, paramTypes = []}
{ paramTypes = []
, returnTypes = [I64]
}
, body =
emitErrorMessage I64 $
emitErrorMessage [I64] $
entityName i_staging_sym <>
" failed: it was marked as broken by code generator, with error message: " <>
showSBS
@ -361,7 +361,6 @@ makeMemory debug AsteriusModule {..} last_o sym_map =
{ initialPages =
fromIntegral $
roundup (fromIntegral last_o) mblock_size `div` wasmPageSize
, maximumPages = 65535
, exportName = "mem"
, dataSegments =
if debug
@ -413,9 +412,8 @@ resolveEntitySymbols sym_table = f
case eqTypeRep (typeOf t) (typeRep :: TypeRep Expression) of
Just HRefl ->
case t of
Unresolved {..} -> pure $ ConstI64 $ subst unresolvedSymbol
UnresolvedOff {..} ->
pure $ ConstI64 $ subst unresolvedSymbol + fromIntegral offset'
Symbol {..} ->
pure t {resolvedSymbol = Just $ subst unresolvedSymbol}
_ -> go
_ ->
case eqTypeRep (typeOf t) (typeRep :: TypeRep AsteriusStatic) of
@ -423,26 +421,17 @@ resolveEntitySymbols sym_table = f
case t of
UnresolvedStatic unresolvedSymbol ->
pure $ Serialized (encodeStorable (subst unresolvedSymbol))
UnresolvedOffStatic unresolvedSymbol offset' ->
SymbolStatic unresolvedSymbol symbolOffset ->
pure $
Serialized
(encodeStorable
(subst unresolvedSymbol + fromIntegral offset'))
(subst unresolvedSymbol + fromIntegral symbolOffset))
_ -> pure t
_ -> go
where
go = gmapM f t
subst = (sym_table !)
resolveFunctionImport :: AsteriusFunctionImport -> FunctionImport
resolveFunctionImport AsteriusFunctionImport {..} =
FunctionImport
{ internalName = internalName
, externalModuleName = externalModuleName
, externalBaseName = externalBaseName
, functionTypeName = generateWasmFunctionTypeName functionType
}
collectErrorMessages :: Data a => a -> S.Set ErrorMessage
collectErrorMessages = collect proxy#
@ -467,11 +456,11 @@ rewriteEmitErrorMessage x = do
[ CallImport
{ target' = "__asterius_errorI32"
, operands = [ConstI32 $ msg_lookup errorMessage]
, valueType = None
, callImportReturnTypes = []
}
, Unreachable
]
, valueType = valueType
, blockReturnTypes = phantomReturnTypes
}
_ -> go
_ -> go
@ -495,8 +484,7 @@ resolveAsteriusModule debug bundled_ffi_state export_funcs m_globals_resolved =
resolve_syms = resolveEntitySymbols (func_sym_map <> ss_sym_map)
m_globals_syms_resolved <- resolve_syms m_globals_resolved
let func_imports =
rtsAsteriusFunctionImports debug <>
generateFFIFunctionImports bundled_ffi_state
rtsFunctionImports debug <> generateFFIFunctionImports bundled_ffi_state
new_function_map <-
fmap M.fromList $
for (M.toList $ functionMap m_globals_syms_resolved) $ \(func_sym, AsteriusFunction {..}) -> do
@ -504,7 +492,7 @@ resolveAsteriusModule debug bundled_ffi_state export_funcs m_globals_resolved =
resolveLocalRegs (length $ paramTypes functionType) body
let func =
Function
{ functionTypeName = generateWasmFunctionTypeName functionType
{ functionType = functionType
, varTypes = local_types
, body = body_locals_resolved
}
@ -517,18 +505,8 @@ resolveAsteriusModule debug bundled_ffi_state export_funcs m_globals_resolved =
(new_mod, err_msgs) <-
rewriteEmitErrorMessage
Module
{ functionTypeMap =
M.fromList
[ (generateWasmFunctionTypeName ft, ft)
| ft <-
[functionType | AsteriusFunctionImport {..} <- func_imports] <>
[ functionType
| AsteriusFunction {..} <-
M.elems $ functionMap m_globals_syms_resolved
]
]
, functionMap' = new_function_map
, functionImports = [resolveFunctionImport imp | imp <- func_imports]
{ functionMap' = new_function_map
, functionImports = func_imports
, functionExports =
rtsAsteriusFunctionExports debug <>
[ FunctionExport

View File

@ -40,7 +40,7 @@ addTracingModule func_sym_map func_sym func_type func
new_body <- f body
pure
Function
{ functionTypeName = functionTypeName
{ functionType = functionType
, varTypes = varTypes
, body =
Block
@ -49,11 +49,11 @@ addTracingModule func_sym_map func_sym func_type func
[ CallImport
{ target' = "__asterius_traceCmm"
, operands = [func_idx]
, valueType = None
, callImportReturnTypes = []
}
, new_body
]
, valueType = infer new_body
, blockReturnTypes = infer new_body
}
}
_ ->
@ -83,11 +83,11 @@ addTracingModule func_sym_map func_sym func_type func
[ func_idx
, lbl_to_idx lbl
]
, valueType = None
, callImportReturnTypes = []
}
, new_code
]
, valueType = infer new_code
, blockReturnTypes = infer new_code
}
}
})
@ -109,11 +109,11 @@ addTracingModule func_sym_map func_sym func_type func
[ func_idx
, lbl_to_idx lbl
]
, valueType = None
, callImportReturnTypes = []
}
, new_code
]
, valueType = infer new_code
, blockReturnTypes = infer new_code
}
, condition = condition
}
@ -137,10 +137,10 @@ addTracingModule func_sym_map func_sym func_type func
[func_idx, ConstI32 $ fromIntegral index] <>
cutI64
GetLocal {index = index, valueType = I64}
, valueType = None
, callImportReturnTypes = []
}
]
, valueType = None
, blockReturnTypes = []
}
where params = paramTypes func_type
param_num = length params

View File

@ -6,47 +6,45 @@ module Asterius.TypeInfer
import Asterius.Types
infer :: Expression -> ValueType
infer :: Expression -> [ValueType]
infer expr =
case expr of
Block {..} -> valueType
Block {..} -> blockReturnTypes
If {..} -> infer ifTrue
Loop {} -> None
Break {} -> None
Switch {} -> None
Call {..} -> valueType
CallImport {..} -> valueType
CallIndirect {} -> I64
GetLocal {..} -> valueType
SetLocal {..} -> None
Load {..} -> valueType
Store {} -> None
ConstI32 {} -> I32
ConstI64 {} -> I64
ConstF32 {} -> F32
ConstF64 {} -> F64
Unary {unaryOp = WrapInt64} -> I32
Unary {unaryOp = ExtendUInt32} -> I64
Host {..} -> I32
Nop -> None
Unreachable -> None
CFG {} -> None
Unresolved {} -> I64
UnresolvedOff {} -> I64
Loop {} -> []
Break {} -> []
Switch {} -> []
Call {..} -> callReturnTypes
CallImport {..} -> callImportReturnTypes
CallIndirect {} -> [I64]
GetLocal {..} -> [valueType]
SetLocal {..} -> []
Load {..} -> [valueType]
Store {} -> []
ConstI32 {} -> [I32]
ConstI64 {} -> [I64]
ConstF32 {} -> [F32]
ConstF64 {} -> [F64]
Unary {unaryOp = WrapInt64} -> [I32]
Unary {unaryOp = ExtendUInt32} -> [I64]
Host {..} -> [I32]
Nop -> []
Unreachable -> []
CFG {} -> []
Symbol {} -> [I64]
UnresolvedGetLocal {..} ->
case unresolvedLocalReg of
UniqueLocalReg _ vt -> vt
QuotRemI32X -> I32
QuotRemI32Y -> I32
QuotRemI64X -> I64
QuotRemI64Y -> I64
UnresolvedSetLocal {} -> None
UniqueLocalReg _ vt -> [vt]
QuotRemI32X -> [I32]
QuotRemI32Y -> [I32]
QuotRemI64X -> [I64]
QuotRemI64Y -> [I64]
UnresolvedSetLocal {} -> []
UnresolvedGetGlobal {..} ->
case unresolvedGlobalReg of
FloatReg {} -> F32
DoubleReg {} -> F64
_ -> I64
UnresolvedSetGlobal {..} -> None
EmitErrorMessage {..} -> valueType
Null -> None
FloatReg {} -> [F32]
DoubleReg {} -> [F64]
_ -> [I64]
UnresolvedSetGlobal {..} -> []
EmitErrorMessage {..} -> phantomReturnTypes
_ -> error $ "Asterius.TypeInfer.infer: " <> show expr

View File

@ -3,11 +3,7 @@
{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE OverloadedLists #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE StrictData #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Asterius.Types
( BinaryenIndex
@ -15,7 +11,6 @@ module Asterius.Types
, AsteriusStatic(..)
, AsteriusStatics(..)
, AsteriusFunction(..)
, AsteriusFunctionImport(..)
, AsteriusModule(..)
, AsteriusModuleSymbol(..)
, AsteriusEntitySymbol(..)
@ -80,8 +75,8 @@ instance Exception AsteriusCodeGenError
data AsteriusStatic
= UnresolvedStatic AsteriusEntitySymbol
| UnresolvedOffStatic AsteriusEntitySymbol
Int
| SymbolStatic AsteriusEntitySymbol
Int
| Uninitialized Int
| Serialized SBS.ShortByteString
deriving (Eq, Ord, Show, Generic, Data)
@ -101,13 +96,6 @@ data AsteriusFunction = AsteriusFunction
instance Binary AsteriusFunction
data AsteriusFunctionImport = AsteriusFunctionImport
{ internalName, externalModuleName, externalBaseName :: SBS.ShortByteString
, functionType :: FunctionType
} deriving (Eq, Show, Generic, Data)
instance Binary AsteriusFunctionImport
data AsteriusModule = AsteriusModule
{ staticsMap :: M.Map AsteriusEntitySymbol AsteriusStatics
, staticsErrorMap :: M.Map AsteriusEntitySymbol AsteriusCodeGenError
@ -201,8 +189,7 @@ deriving newtype instance Show ErrorMessage
instance Binary ErrorMessage
data ValueType
= None
| I32
= I32
| I64
| F32
| F64
@ -211,8 +198,7 @@ data ValueType
instance Binary ValueType
data FunctionType = FunctionType
{ returnType :: ValueType
, paramTypes :: [ValueType]
{ paramTypes, returnTypes :: [ValueType]
} deriving (Eq, Ord, Show, Generic, Data)
instance Binary FunctionType
@ -360,24 +346,25 @@ instance Binary HostOp
data Expression
= Block { name :: SBS.ShortByteString
, bodys :: [Expression]
, valueType :: ValueType }
| If { condition, ifTrue, ifFalse :: Expression }
, blockReturnTypes :: [ValueType] }
| If { condition, ifTrue :: Expression
, ifFalse :: Maybe Expression }
| Loop { name :: SBS.ShortByteString
, body :: Expression }
| Break { name :: SBS.ShortByteString
, condition :: Expression }
, breakCondition :: Maybe Expression }
| Switch { names :: [SBS.ShortByteString]
, defaultName :: SBS.ShortByteString
, condition :: Expression }
| Call { target :: AsteriusEntitySymbol
, operands :: [Expression]
, valueType :: ValueType }
, callReturnTypes :: [ValueType] }
| CallImport { target' :: SBS.ShortByteString
, operands :: [Expression]
, valueType :: ValueType }
, callImportReturnTypes :: [ValueType] }
| CallIndirect { indirectTarget :: Expression
, operands :: [Expression]
, typeName :: SBS.ShortByteString }
, functionType :: FunctionType }
| GetLocal { index :: BinaryenIndex
, valueType :: ValueType }
| SetLocal { index :: BinaryenIndex
@ -398,14 +385,13 @@ data Expression
| Binary { binaryOp :: BinaryOp
, operand0, operand1 :: Expression }
| Host { hostOp :: HostOp
, name :: SBS.ShortByteString
, operands :: [Expression] }
| Nop
| Unreachable
| CFG { graph :: RelooperRun }
| Unresolved { unresolvedSymbol :: AsteriusEntitySymbol }
| UnresolvedOff { unresolvedSymbol :: AsteriusEntitySymbol
, offset' :: Int }
| Symbol { unresolvedSymbol :: AsteriusEntitySymbol
, symbolOffset :: Int
, resolvedSymbol :: Maybe Int64 }
| UnresolvedGetLocal { unresolvedLocalReg :: UnresolvedLocalReg }
| UnresolvedSetLocal { unresolvedLocalReg :: UnresolvedLocalReg
, value :: Expression }
@ -413,14 +399,13 @@ data Expression
| UnresolvedSetGlobal { unresolvedGlobalReg :: UnresolvedGlobalReg
, value :: Expression }
| EmitErrorMessage { errorMessage :: ErrorMessage
, valueType :: ValueType }
| Null
, phantomReturnTypes :: [ValueType] }
deriving (Eq, Show, Generic, Data)
instance Binary Expression
data Function = Function
{ functionTypeName :: SBS.ShortByteString
{ functionType :: FunctionType
, varTypes :: [ValueType]
, body :: Expression
} deriving (Eq, Show, Generic, Data)
@ -428,7 +413,8 @@ data Function = Function
instance Binary Function
data FunctionImport = FunctionImport
{ internalName, externalModuleName, externalBaseName, functionTypeName :: SBS.ShortByteString
{ internalName, externalModuleName, externalBaseName :: SBS.ShortByteString
, functionType :: FunctionType
} deriving (Eq, Show, Data, Generic)
instance Binary FunctionImport
@ -453,7 +439,7 @@ data DataSegment = DataSegment
instance Binary DataSegment
data Memory = Memory
{ initialPages, maximumPages :: BinaryenIndex
{ initialPages :: BinaryenIndex
, exportName :: SBS.ShortByteString
, dataSegments :: [DataSegment]
} deriving (Eq, Show, Data, Generic)
@ -461,8 +447,7 @@ data Memory = Memory
instance Binary Memory
data Module = Module
{ functionTypeMap :: M.Map SBS.ShortByteString FunctionType
, functionMap' :: M.Map SBS.ShortByteString Function
{ functionMap' :: M.Map SBS.ShortByteString Function
, functionImports :: [FunctionImport]
, functionExports :: [FunctionExport]
, functionTable :: FunctionTable
@ -480,10 +465,9 @@ instance Binary RelooperAddBlock
data RelooperAddBranch
= AddBranch { to :: SBS.ShortByteString
, condition, code :: Expression }
, addBranchCondition :: Maybe Expression }
| AddBranchForSwitch { to :: SBS.ShortByteString
, indexes :: [BinaryenIndex]
, code :: Expression }
, indexes :: [BinaryenIndex] }
deriving (Eq, Show, Generic, Data)
instance Binary RelooperAddBranch
@ -520,8 +504,7 @@ data FFIValueType
instance Binary FFIValueType
data FFIFunctionType = FFIFunctionType
{ ffiParamTypes :: [FFIValueType]
, ffiResultType :: Maybe FFIValueType
{ ffiParamTypes, ffiResultTypes :: [FFIValueType]
, ffiInIO :: Bool
} deriving (Eq, Show, Generic, Data)

View File

@ -5,7 +5,7 @@
module Asterius.TypesConv
( marshalToModuleSymbol
, zEncodeModuleSymbol
, generateWasmFunctionTypeName
, generateWasmFunctionTypeSet
, asmPpr
, asmPrint
) where
@ -15,12 +15,14 @@ import Asterius.Types
import qualified Data.ByteString.Char8 as CBS
import qualified Data.ByteString.Short as SBS
import Data.List
import qualified Data.Map.Strict as Map
import qualified Data.Set as Set
import qualified GhcPlugins as GHC
import Prelude hiding (IO)
import qualified Pretty as GHC
import System.IO (IOMode(WriteMode), withFile)
{-# INLINEABLE marshalToModuleSymbol #-}
{-# INLINE marshalToModuleSymbol #-}
marshalToModuleSymbol :: GHC.Module -> AsteriusModuleSymbol
marshalToModuleSymbol (GHC.Module u m) =
AsteriusModuleSymbol
@ -30,7 +32,7 @@ marshalToModuleSymbol (GHC.Module u m) =
CBS.splitWith (== '.') $ GHC.fs_bs $ GHC.moduleNameFS m
}
{-# INLINEABLE zEncodeModuleSymbol #-}
{-# INLINE zEncodeModuleSymbol #-}
zEncodeModuleSymbol :: AsteriusModuleSymbol -> String
zEncodeModuleSymbol AsteriusModuleSymbol {..} =
GHC.zString $
@ -39,18 +41,17 @@ zEncodeModuleSymbol AsteriusModuleSymbol {..} =
SBS.fromShort unitId <> "_" <>
CBS.intercalate "." [SBS.fromShort mod_chunk | mod_chunk <- moduleName]
{-# INLINEABLE generateWasmFunctionTypeName #-}
generateWasmFunctionTypeName :: FunctionType -> SBS.ShortByteString
generateWasmFunctionTypeName FunctionType {..} =
showSBS returnType <> "(" <>
mconcat (intersperse "," [showSBS t | t <- paramTypes]) <>
")"
{-# INLINE generateWasmFunctionTypeSet #-}
generateWasmFunctionTypeSet :: Module -> Set.Set FunctionType
generateWasmFunctionTypeSet Module {..} =
Set.fromList [functionType | FunctionImport {..} <- functionImports] <>
Set.fromList [functionType | Function {..} <- Map.elems functionMap']
{-# INLINEABLE asmPpr #-}
{-# INLINE asmPpr #-}
asmPpr :: GHC.Outputable a => GHC.DynFlags -> a -> String
asmPpr dflags = GHC.showSDoc dflags . GHC.pprCode GHC.AsmStyle . GHC.ppr
{-# INLINEABLE asmPrint #-}
{-# INLINE asmPrint #-}
asmPrint :: GHC.Outputable a => GHC.DynFlags -> FilePath -> a -> IO ()
asmPrint dflags p a =
withFile p WriteMode $ \h ->

View File

@ -24,7 +24,7 @@ patchWritePtrArrayOp t =
new_bodys <- w bodys
pure t {bodys = new_bodys}
where w :: Monad m => [Expression] -> m [Expression]
w (e0@Store {value = Unresolved {unresolvedSymbol = "stg_MUT_ARR_PTRS_DIRTY_info"}}:Store {bytes = 1}:es) = do
w (e0@Store {value = Symbol {unresolvedSymbol = "stg_MUT_ARR_PTRS_DIRTY_info"}}:Store {bytes = 1}:es) = do
new_es <- w es
pure $ e0 : new_es
w (e0:e1:es) = do
@ -56,7 +56,7 @@ maskUnknownCCallTargets export_funcs = f
| not $ has_call_target target ->
pure $
emitErrorMessage
valueType
callReturnTypes
(entityName target <>
" failed: unimplemented stub function entered")
| target == "createIOThread" ->

View File

@ -11,28 +11,25 @@ import Foreign
import qualified Language.WebAssembly.WireFormat as Wasm
main :: IO ()
main
-- c_BinaryenSetAPITracing 1
= do
main = do
c_BinaryenSetOptimizeLevel 0
c_BinaryenSetShrinkLevel 0
m <-
withPool $ \pool ->
marshalModule pool $
Module
{ functionTypeMap = [("func_type", FunctionType I32 [])]
, functionMap' =
{ functionMap' =
[ ( "func"
, Function "func_type" [I32, I64, I64, I32] $
, Function (FunctionType [] [I32]) [I32, I64, I64, I32] $
Block
mempty
[Block mempty [Block mempty [GetLocal 3 I32] I32] I32]
I32)
[Block mempty [Block mempty [GetLocal 3 I32] [I32]] [I32]]
[I32])
]
, functionImports = []
, functionExports = []
, functionTable = FunctionTable []
, memory = Memory 1 1 mempty mempty
, memory = Memory 1 mempty mempty
}
c_BinaryenModuleValidate m >>= print
buf <- LBS.fromStrict <$> serializeModule m

View File

@ -1,3 +1,4 @@
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE RecordWildCards #-}
import Asterius.Internals
@ -41,14 +42,14 @@ shrinkExpression =
pure expr {bodys = _new_bodys}
If {..} -> do
_new_ifTrue <- shrinkExpression ifTrue
_new_ifFalse <- shrinkExpression ifFalse
_new_ifFalse <- shrinkMaybeExpression ifFalse
pure expr {ifTrue = _new_ifTrue, ifFalse = _new_ifFalse}
Loop {..} -> do
_new_body <- shrinkExpression body
pure Loop {name = name, body = _new_body}
Break {..} -> do
_new_condition <- shrinkExpression condition
pure Break {name = name, condition = _new_condition}
_new_condition <- shrinkMaybeExpression breakCondition
pure Break {name = name, breakCondition = _new_condition}
Switch {..} -> do
_new_condition <- shrinkExpression condition
pure
@ -90,6 +91,12 @@ shrinkExpression =
pure expr {operands = _new_operands}
_ -> mempty
shrinkMaybeExpression :: Shrink (Maybe Expression)
shrinkMaybeExpression =
preserve Nothing $ \case
Just expr -> Just <$> shrinkExpression expr
_ -> mempty
shrinkModule' :: Shrink Module
shrinkModule' m@Module {..} = _shrink_funcs {-_shrink_memory <> _shrink_exports <>-}
where
@ -121,7 +128,7 @@ shrinkModule' m@Module {..} = _shrink_funcs {-_shrink_memory <> _shrink_exports
Map.insert
_func_to_shrink_key
Function
{ functionTypeName = functionTypeName
{ functionType = functionType
, varTypes = varTypes
, body = Unreachable
}
@ -138,7 +145,7 @@ shrinkModule' m@Module {..} = _shrink_funcs {-_shrink_memory <> _shrink_exports
Map.insert
_func_to_shrink_key
Function
{ functionTypeName = functionTypeName
{ functionType = functionType
, varTypes = varTypes
, body = _shrink_expr
}

View File

@ -31,7 +31,6 @@ module Language.WebAssembly.WireFormat
, Global(..)
, ExportDescription(..)
, Export(..)
, Start(..)
, Element(..)
, Locals(..)
, Function(..)
@ -1103,16 +1102,6 @@ putExport Export {..} = do
putName exportName
putExportDescription exportDescription
newtype Start = Start
{ startFunctionIndex :: FunctionIndex
} deriving (Eq, Generic, Ord, Show)
getStart :: Get Start
getStart = coerce getFunctionIndex
putStart :: Start -> Put
putStart = coerce putFunctionIndex
data Element = Element
{ tableIndex :: TableIndex
, tableOffset :: Expression
@ -1333,7 +1322,7 @@ data Section
| MemorySection { memories :: [Memory] }
| GlobalSection { globals :: [Global] }
| ExportSection { exports :: [Export] }
| StartSection { start :: Start }
| StartSection { startFunctionIndex :: FunctionIndex }
| ElementSection { elements :: [Element] }
| CodeSection { functions' :: [Function] }
| DataSection { dataSegments :: [DataSegment] }
@ -1400,7 +1389,7 @@ getSection = do
5 -> getCheckedRegion (MemorySection <$> getVec getMemory)
6 -> getCheckedRegion (GlobalSection <$> getVec getGlobal)
7 -> getCheckedRegion (ExportSection <$> getVec getExport)
8 -> getCheckedRegion (StartSection <$> getStart)
8 -> getCheckedRegion (StartSection <$> getFunctionIndex)
9 -> getCheckedRegion (ElementSection <$> getVec getElement)
10 ->
getCheckedRegion (CodeSection <$> getVec (getCheckedRegion getFunction))
@ -1465,7 +1454,7 @@ putSection sec =
putWithLength $ putVec putExport exports
StartSection {..} -> do
putWord8 8
putWithLength $ putStart start
putWithLength $ putFunctionIndex startFunctionIndex
ElementSection {..} -> do
putWord8 9
putWithLength $ putVec putElement elements
@ -1560,16 +1549,16 @@ getVS64 :: Get Int64
getVS64 = getVSN 64
getF32 :: Get Float
getF32 = getFloatle
getF32 = getFloathost
putF32 :: Float -> Put
putF32 = putFloatle
putF32 = putFloathost
getF64 :: Get Double
getF64 = getDoublele
getF64 = getDoublehost
putF64 :: Double -> Put
putF64 = putDoublele
putF64 = putDoublehost
getVec :: Get a -> Get [a]
getVec g = do

View File

@ -408,13 +408,6 @@ instance Arbitrary Export where
arbitrary = genExport
shrink = genericShrink
genStart :: Gen Start
genStart = coerce genFunctionIndex
instance Arbitrary Start where
arbitrary = genStart
shrink = genericShrink
genElement :: Gen Element
genElement =
Element <$> genTableIndex <*> genExpression <*> listOf genFunctionIndex
@ -545,7 +538,7 @@ genSection =
, MemorySection <$> listOf genMemory
, GlobalSection <$> listOf genGlobal
, ExportSection <$> listOf genExport
, StartSection <$> genStart
, StartSection <$> genFunctionIndex
, ElementSection <$> listOf genElement
, CodeSection <$> listOf genFunction
, DataSection <$> listOf genDataSegment