[Git][ghc/ghc][wip/nr/wasm-translation-prototypes] cleaned up translator
Norman Ramsey (@nrnrnr)
gitlab at gitlab.haskell.org
Thu Oct 6 21:05:05 UTC 2022
Norman Ramsey pushed to branch wip/nr/wasm-translation-prototypes at Glasgow Haskell Compiler / GHC
Commits:
f8e96ae5 by Norman Ramsey at 2022-10-06T17:04:49-04:00
cleaned up translator
- - - - -
1 changed file:
- compiler/GHC/Wasm/Tx.hs
Changes:
=====================================
compiler/GHC/Wasm/Tx.hs
=====================================
@@ -7,7 +7,7 @@
module GHC.Wasm.Tx
( tx
, CG(..)
- , WasmExpr(..)
+ , WasmExpr
)
where
@@ -19,41 +19,77 @@ import Data.Type.Equality
import qualified GHC.Cmm.Type as CT
import GHC.Cmm.Expr
import GHC.Utils.Panic
+import GHC.Utils.Panic.Plain (assert)
import GHC.Wasm.IR
----------------------------------------------------------------
+---
+--- Overview
+---
+----------------------------------------------------------------
+--
+-- This module translates Cmm expressions to Wasm instructions while
+-- meeting the following goals:
+-- * Keep the code compact and readable
+-- * Use GADTs to track the stack types of the Wasm code
+-- * Check Cmm types only when necessary to prove type correctness
+-- of the generated code or when debugging GHC
+--
-newtype WasmExpr bool t =
- WasmExpr (forall pre . WasmIR bool pre (t : pre))
-
-apply1 :: (forall stack . WasmIR bool (t : stack) (t' : stack))
- -> WasmExpr bool t
- -> WasmExpr bool t'
-apply1 operator (WasmExpr code) = WasmExpr (code <> operator)
-apply2 :: (forall stack . WasmIR bool (t2 : t1 : stack) (t : stack))
- -> WasmExpr bool t1
- -> WasmExpr bool t2
- -> WasmExpr bool t
-apply2 operator (WasmExpr code1) (WasmExpr code2) =
- WasmExpr (code1 <> code2 <> operator)
----------------------------------------------------------------
+-- code-generation monad
+
+-- This class is a placeholder that expresses the only
+-- property used in the prototype: the platform Boolean
+-- type is discoverable.
class Monad (codegen bool) => CG bool codegen where
--- platformWordSize :: m Int
--- asType :: WasmTypeTag t -> m () -- check that type is consistent
--- -- with platform word size
--- asInt :: WasmTypeTag t -> m () -- insist on the platofrm integer type
booleanWasmTypeTag :: codegen bool (WasmTypeTag bool)
+----------------------------------------------------------------
+
+-- Each Cmm expression is translated into a "WebAssembly expression of
+-- type t." This is Wasm code that can push a value of type `t` onto
+-- *any* evaluation stack.
+
+type WasmExpr bool t = (forall stack . WasmIR bool stack (t : stack))
+
+-- At translation time, the target type `t` is not known.
+-- It can be defined by a tag, but we wish to avoid the bookkeeping
+-- associated with packing a tag and a translation into existentially
+-- quantified pair. Instead, the translator uses continuation-passing
+-- style (CPS) to pass a tag and a translation to its continuation.
+-- This technique is recommended by Richard Eisenberg, Stitch: The
+-- Sound Type-Indexed Type Checker (Functional Pearl), Haskell
+-- Symposium 2020 (https://doi.org/10.1145/3406088.3409015).
tx :: CG bool codegen
=> CmmExpr
- -> (forall t . WasmTypeTag t -> WasmExpr bool t -> codegen bool r)
- -> codegen bool r
- -- combines translation with some type checking
+ -> (forall t . WasmTypeTag t -> WasmExpr bool t -> codegen bool a)
+ -> codegen bool a
+ -- type `a` is the answer type of the continuation
+
+-- The translation is organized as follows:
+--
+-- * The main translation function `tx` dispatches on the form of a
+-- Cmm expression.
+--
+-- * For every different type of Cmm operator, `tx` calls a
+-- different auxiliary function: `wasmUnary`, `wasmBinary`,
+-- `wasmCompare`, and so on.
+--
+-- (Since every different type of Cmm operator generates
+-- intermediate Wasm code of different types, it seems sensible
+-- that each type of operator might require a Haskell translation
+-- function of a different type. But it's a bit irksome.)
+--
+-- * Each auxiliary function calls back into `tx` to translate
+-- operands, if any, then composes the resulting code.
+--
+-- All functions are CPS.
tx expr k =
case expr of
@@ -70,6 +106,10 @@ tx expr k =
_ -> panic "unimplemented"
+------ Types of all the translation functions
+
+-- | Cmm integer and floating-point literals (with zero operands)
+
wasmNullaryInt, wasmNullaryFloat ::
CG bool codegen
=> CT.Width
@@ -77,6 +117,8 @@ wasmNullaryInt, wasmNullaryFloat ::
-> (forall t . WasmTypeTag t -> WasmExpr bool t -> codegen bool r)
-> codegen bool r
+-- | Cmm unary operators of type `t -> t`
+
wasmUnary :: CG bool codegen
=> CT.Width
-> [CmmExpr]
@@ -84,6 +126,8 @@ wasmUnary :: CG bool codegen
-> (forall t . WasmTypeTag t -> WasmExpr bool t -> codegen bool r)
-> codegen bool r
+-- | Cmm binary operators of type `t -> t -> t`
+
wasmBinary ::
CG bool codegen
=> CT.Width
@@ -93,6 +137,8 @@ wasmBinary ::
-> codegen bool r
+-- | Cmm binary operators of type `t -> t -> bool`
+
wasmCompare ::
forall bool codegen r . CG bool codegen
=> CT.Width
@@ -101,29 +147,29 @@ wasmCompare ::
-> (WasmTypeTag bool -> WasmExpr bool bool -> codegen bool r)
-> codegen bool r
-----------------------------------------------------------------
+---------- Implementations of the translation functions
wasmNullaryInt w operator k =
- withIntWidthTag w $ \tag -> k tag (WasmExpr $ operator tag)
+ withIntWidthTag w $ \tag -> k tag (operator tag)
wasmNullaryFloat w operator k =
- withFloatWidthTag w $ \tag -> k tag (WasmExpr $ operator tag)
+ withFloatWidthTag w $ \tag -> k tag (operator tag)
wasmUnary w [e] operator k =
- tx e $ \tag code -> checkTagWidth tag w $ k tag (apply1 (operator tag) code)
+ tx e $ \tag code -> assert (tag `hasWidth` w) $ k tag (code <> operator tag)
wasmUnary _ _ _ _ = panic "wrong number of operands to unary operator in Cmm"
wasmBinary w es operator k =
binaryCPS es $ \tag code1 code2 ->
- checkTagWidth tag w $ -- optional check
- k tag (apply2 (operator tag) code1 code2)
+ assert (tag `hasWidth` w) $
+ k tag (code1 <> code2 <> operator tag)
wasmCompare w es operator k =
binaryCPS es $ \tag code1 code2 -> do
bool <- booleanWasmTypeTag
- checkTagWidth bool w $
- k bool (apply2 (operator tag) code1 code2)
+ assert (bool `hasWidth` w) $
+ k bool (code1 <> code2 <> operator tag)
binaryCPS
:: forall bool codegen a . CG bool codegen
@@ -145,12 +191,12 @@ binaryCPS _ _ = panic "wrong number of operands to binary operator in Cmm"
----------------------------------------------------------------
-checkTagWidth :: WasmTypeTag t -> CT.Width -> a -> a
-checkTagWidth TagI32 CT.W32 a = a
-checkTagWidth TagF32 CT.W32 a = a
-checkTagWidth TagI64 CT.W64 a = a
-checkTagWidth TagF64 CT.W64 a = a
-checkTagWidth _ _ _ = panic "ill-typed Cmm (width mismatch)"
+hasWidth :: WasmTypeTag t -> CT.Width -> Bool
+hasWidth TagI32 CT.W32 = True
+hasWidth TagF32 CT.W32 = True
+hasWidth TagI64 CT.W64 = True
+hasWidth TagF64 CT.W64 = True
+hasWidth _ _ = False
withIntWidthTag :: CT.Width -> (forall t . WasmTypeTag t -> a) -> a
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/f8e96ae56bddd0d22c9fb671b0f03d123cccc233
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/f8e96ae56bddd0d22c9fb671b0f03d123cccc233
You're receiving this email because of your account on gitlab.haskell.org.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-commits/attachments/20221006/278be9d6/attachment-0001.html>
More information about the ghc-commits
mailing list