    {-# LANGUAGE DataKinds #-}
    {-# LANGUAGE FlexibleContexts #-}
    {-# LANGUAGE GADTs #-}
    {-# LANGUAGE MultiWayIf #-}
    {-# LANGUAGE OverloadedStrings #-}
    {-# LANGUAGE RankNTypes #-}
    {-# LANGUAGE RecordWildCards #-}
    {-# LANGUAGE ScopedTypeVariables #-}
    {-# LANGUAGE Strict #-}
    {-# LANGUAGE TupleSections #-}
    {-# LANGUAGE TypeFamilies #-}
    {-# LANGUAGE UnboxedTuples #-}
    {-# LANGUAGE UndecidableInstances #-}
    {-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}

    {-# HLINT ignore "Use camelCase" #-}
    module GHC.CmmToAsm.Wasm.FromCmm
      ( alignmentFromWordType,
        globalInfoFromCmmGlobalReg,
        supportedCmmGlobalRegs,
        onCmmGroup,
      )
    where

    import Control.Monad
    import qualified Data.ByteString as BS
    import Data.Foldable
    import Data.Functor
    import qualified GHC.Data.Word64Set as WS
    import Data.Semigroup
    import Data.String
    import Data.Traversable
    import Data.Type.Equality
    import GHC.Cmm
    import GHC.Cmm.BlockId
    import GHC.Cmm.CLabel
    import GHC.Cmm.Dataflow.Block
    import GHC.Cmm.Dataflow.Label
    import GHC.Cmm.InitFini
    import GHC.CmmToAsm.Wasm.Types
    import GHC.CmmToAsm.Wasm.Utils
    import GHC.Float
    import GHC.Platform
    import GHC.Prelude
    import GHC.StgToCmm.CgUtils
    import GHC.Types.Basic
    import GHC.Types.ForeignCall
    import GHC.Types.Unique
    import GHC.Types.Unique.FM
    import GHC.Types.Unique.Map
    import GHC.Types.Unique.Supply
    import GHC.Utils.Outputable hiding ((<>))
    import GHC.Utils.Panic
    import GHC.Wasm.ControlFlow.FromCmm

    -- | Calculate the wasm representation type from a 'CmmType'. This is
    -- a lossy conversion, and sometimes we need to pass the original
    -- 'CmmType' or at least its 'Width' around, so to properly add
    -- subword truncation or extension logic.
    someWasmTypeFromCmmType :: CmmType -> SomeWasmType
    someWasmTypeFromCmmType :: CmmType -> SomeWasmType
    someWasmTypeFromCmmType CmmType
    t
      | CmmType -> Bool
    isWord32 CmmType
    t = WasmTypeTag 'I32 -> SomeWasmType
    forall (t :: WasmType). WasmTypeTag t -> SomeWasmType
    SomeWasmType WasmTypeTag 'I32
    TagI32
      | CmmType -> Bool
    isWord64 CmmType
    t = WasmTypeTag 'I64 -> SomeWasmType
    forall (t :: WasmType). WasmTypeTag t -> SomeWasmType
    SomeWasmType WasmTypeTag 'I64
    TagI64
      | CmmType
    t CmmType -> CmmType -> Bool
    `cmmEqType` CmmType
    b16 = WasmTypeTag 'I32 -> SomeWasmType
    forall (t :: WasmType). WasmTypeTag t -> SomeWasmType
    SomeWasmType WasmTypeTag 'I32
    TagI32
      | CmmType
    t CmmType -> CmmType -> Bool
    `cmmEqType` CmmType
    b8 = WasmTypeTag 'I32 -> SomeWasmType
    forall (t :: WasmType). WasmTypeTag t -> SomeWasmType
    SomeWasmType WasmTypeTag 'I32
    TagI32
      | CmmType -> Bool
    isFloat64 CmmType
    t = WasmTypeTag 'F64 -> SomeWasmType
    forall (t :: WasmType). WasmTypeTag t -> SomeWasmType
    SomeWasmType WasmTypeTag 'F64
    TagF64
      | CmmType -> Bool
    isFloat32 CmmType
    t = WasmTypeTag 'F32 -> SomeWasmType
    forall (t :: WasmType). WasmTypeTag t -> SomeWasmType
    SomeWasmType WasmTypeTag 'F32
    TagF32
      | Bool
    otherwise =
          String -> SomeWasmType
    forall a. HasCallStack => String -> a
    panic (String -> SomeWasmType) -> String -> SomeWasmType
    forall a b. (a -> b) -> a -> b
    $
            String
    "someWasmTypeFromCmmType: unsupported CmmType "
              String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> SDocContext -> SDoc -> String
    showSDocOneLine SDocContext
    defaultSDocContext (CmmType -> SDoc
    forall a. Outputable a => a -> SDoc
    ppr CmmType
    t)

    -- | Calculate the optional memory narrowing of a 'CmmLoad' or
    -- 'CmmStore'.
    wasmMemoryNarrowing :: WasmTypeTag t -> CmmType -> Maybe Int
    wasmMemoryNarrowing :: forall (t :: WasmType). WasmTypeTag t -> CmmType -> Maybe Int
    wasmMemoryNarrowing WasmTypeTag t
    ty CmmType
    ty_cmm = case (# WasmTypeTag t
    ty, CmmType -> Width
    typeWidth CmmType
    ty_cmm #) of
      (# WasmTypeTag t
    TagI32, Width
    W8 #) -> Int -> Maybe Int
    forall a. a -> Maybe a
    Just Int
    8
      (# WasmTypeTag t
    TagI32, Width
    W16 #) -> Int -> Maybe Int
    forall a. a -> Maybe a
    Just Int
    16
      (# WasmTypeTag t
    TagI32, Width
    W32 #) -> Maybe Int
    forall a. Maybe a
    Nothing
      (# WasmTypeTag t
    TagI64, Width
    W8 #) -> Int -> Maybe Int
    forall a. a -> Maybe a
    Just Int
    8
      (# WasmTypeTag t
    TagI64, Width
    W16 #) -> Int -> Maybe Int
    forall a. a -> Maybe a
    Just Int
    16
      (# WasmTypeTag t
    TagI64, Width
    W32 #) -> Int -> Maybe Int
    forall a. a -> Maybe a
    Just Int
    32
      (# WasmTypeTag t
    TagI64, Width
    W64 #) -> Maybe Int
    forall a. Maybe a
    Nothing
      (# WasmTypeTag t
    TagF32, Width
    W32 #) -> Maybe Int
    forall a. Maybe a
    Nothing
      (# WasmTypeTag t
    TagF64, Width
    W64 #) -> Maybe Int
    forall a. Maybe a
    Nothing
      (# WasmTypeTag t, Width #)
    _ -> String -> Maybe Int
    forall a. HasCallStack => String -> a
    panic String
    "wasmMemoryNarrowing: unreachable"

    -- | Despite this is used by the WebAssembly native codegen, we use
    -- 'pprCLabel' instead of 'pprAsmLabel' when emitting the textual
    -- symbol name. Either one would work, but 'pprCLabel' makes the
    -- output assembly code looks closer to the unregisterised codegen
    -- output, which can be handy when using the unregisterised codegen as
    -- a source of truth when debugging the native codegen.
    symNameFromCLabel :: CLabel -> SymName
    symNameFromCLabel :: CLabel -> SymName
    symNameFromCLabel CLabel
    lbl =
      String -> SymName
    forall a. IsString a => String -> a
    fromString (String -> SymName) -> String -> SymName
    forall a b. (a -> b) -> a -> b
    $
        SDocContext -> SDoc -> String
    showSDocOneLine SDocContext
    defaultSDocContext {sdocStyle = PprCode} (SDoc -> String) -> SDoc -> String
    forall a b. (a -> b) -> a -> b
    $
          Platform -> CLabel -> SDoc
    forall doc. IsLine doc => Platform -> CLabel -> doc
    pprCLabel Platform
    genericPlatform CLabel
    lbl

    -- | Calculate a symbol's visibility.
    symVisibilityFromCLabel :: CLabel -> SymVisibility
    symVisibilityFromCLabel :: CLabel -> SymVisibility
    symVisibilityFromCLabel CLabel
    lbl
      | CLabel -> Bool
    externallyVisibleCLabel CLabel
    lbl = SymVisibility
    SymDefault
      | Bool
    otherwise = SymVisibility
    SymStatic

    -- | Calculate a symbol's kind, see haddock docs of 'SymKind' for more
    -- explanation.
    symKindFromCLabel :: CLabel -> SymKind
    symKindFromCLabel :: CLabel -> SymKind
    symKindFromCLabel CLabel
    lbl
      | CLabel -> Bool
    isCFunctionLabel CLabel
    lbl = SymKind
    SymFunc
      | Bool
    otherwise = SymKind
    SymData

    -- | Calculate a data section's kind, see haddock docs of
    -- 'DataSectionKind' for more explanation.
    dataSectionKindFromCmmSection :: Section -> DataSectionKind
    dataSectionKindFromCmmSection :: Section -> DataSectionKind
    dataSectionKindFromCmmSection Section
    s = case Section -> SectionProtection
    sectionProtection Section
    s of
      SectionProtection
    ReadWriteSection -> DataSectionKind
    SectionData
      SectionProtection
    _ -> DataSectionKind
    SectionROData

    -- | Calculate the natural alignment size given the platform word
    -- type.
    alignmentFromWordType :: WasmTypeTag w -> Alignment
    alignmentFromWordType :: forall (w :: WasmType). WasmTypeTag w -> Alignment
    alignmentFromWordType WasmTypeTag w
    TagI32 = Int -> Alignment
    mkAlignment Int
    4
    alignmentFromWordType WasmTypeTag w
    TagI64 = Int -> Alignment
    mkAlignment Int
    8
    alignmentFromWordType WasmTypeTag w
    _ = String -> Alignment
    forall a. HasCallStack => String -> a
    panic String
    "alignmentFromWordType: unreachable"

    -- | Calculate a data section's alignment. As a conservative
    -- optimization, a data section with a single CmmString/CmmFileEmbed
    -- has no alignment requirement, otherwise we always align to the word
    -- size to satisfy pointer tagging requirements and avoid unaligned
    -- loads/stores.
    alignmentFromCmmSection :: WasmTypeTag w -> [DataSectionContent] -> Alignment
    alignmentFromCmmSection :: forall (w :: WasmType).
    WasmTypeTag w -> [DataSectionContent] -> Alignment
    alignmentFromCmmSection WasmTypeTag w
    _ [DataASCII {}] = Int -> Alignment
    mkAlignment Int
    1
    alignmentFromCmmSection WasmTypeTag w
    _ [DataIncBin {}] = Int -> Alignment
    mkAlignment Int
    1
    alignmentFromCmmSection WasmTypeTag w
    t [DataSectionContent]
    _ = WasmTypeTag w -> Alignment
    forall (w :: WasmType). WasmTypeTag w -> Alignment
    alignmentFromWordType WasmTypeTag w
    t

    -- | Lower a 'CmmStatic'.
    lower_CmmStatic :: CmmStatic -> WasmCodeGenM w DataSectionContent
    lower_CmmStatic :: forall (w :: WasmType).
    CmmStatic -> WasmCodeGenM w DataSectionContent
    lower_CmmStatic CmmStatic
    s = case CmmStatic
    s of
      CmmStaticLit (CmmInt Integer
    i Width
    W8) -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (DataSectionContent -> WasmCodeGenM w DataSectionContent)
    -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall a b. (a -> b) -> a -> b
    $ Word8 -> DataSectionContent
    DataI8 (Word8 -> DataSectionContent) -> Word8 -> DataSectionContent
    forall a b. (a -> b) -> a -> b
    $ Integer -> Word8
    forall a. Num a => Integer -> a
    fromInteger (Integer -> Word8) -> Integer -> Word8
    forall a b. (a -> b) -> a -> b
    $ Width -> Integer -> Integer
    narrowU Width
    W8 Integer
    i
      CmmStaticLit (CmmInt Integer
    i Width
    W16) -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (DataSectionContent -> WasmCodeGenM w DataSectionContent)
    -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall a b. (a -> b) -> a -> b
    $ Word16 -> DataSectionContent
    DataI16 (Word16 -> DataSectionContent) -> Word16 -> DataSectionContent
    forall a b. (a -> b) -> a -> b
    $ Integer -> Word16
    forall a. Num a => Integer -> a
    fromInteger (Integer -> Word16) -> Integer -> Word16
    forall a b. (a -> b) -> a -> b
    $ Width -> Integer -> Integer
    narrowU Width
    W16 Integer
    i
      CmmStaticLit (CmmInt Integer
    i Width
    W32) -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (DataSectionContent -> WasmCodeGenM w DataSectionContent)
    -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall a b. (a -> b) -> a -> b
    $ Word32 -> DataSectionContent
    DataI32 (Word32 -> DataSectionContent) -> Word32 -> DataSectionContent
    forall a b. (a -> b) -> a -> b
    $ Integer -> Word32
    forall a. Num a => Integer -> a
    fromInteger (Integer -> Word32) -> Integer -> Word32
    forall a b. (a -> b) -> a -> b
    $ Width -> Integer -> Integer
    narrowU Width
    W32 Integer
    i
      CmmStaticLit (CmmInt Integer
    i Width
    W64) -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (DataSectionContent -> WasmCodeGenM w DataSectionContent)
    -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall a b. (a -> b) -> a -> b
    $ Word64 -> DataSectionContent
    DataI64 (Word64 -> DataSectionContent) -> Word64 -> DataSectionContent
    forall a b. (a -> b) -> a -> b
    $ Integer -> Word64
    forall a. Num a => Integer -> a
    fromInteger (Integer -> Word64) -> Integer -> Word64
    forall a b. (a -> b) -> a -> b
    $ Width -> Integer -> Integer
    narrowU Width
    W64 Integer
    i
      CmmStaticLit (CmmFloat Rational
    f Width
    W32) -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (DataSectionContent -> WasmCodeGenM w DataSectionContent)
    -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall a b. (a -> b) -> a -> b
    $ Float -> DataSectionContent
    DataF32 (Float -> DataSectionContent) -> Float -> DataSectionContent
    forall a b. (a -> b) -> a -> b
    $ Rational -> Float
    forall a. Fractional a => Rational -> a
    fromRational Rational
    f
      CmmStaticLit (CmmFloat Rational
    d Width
    W64) -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (DataSectionContent -> WasmCodeGenM w DataSectionContent)
    -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall a b. (a -> b) -> a -> b
    $ Double -> DataSectionContent
    DataF64 (Double -> DataSectionContent) -> Double -> DataSectionContent
    forall a b. (a -> b) -> a -> b
    $ Rational -> Double
    forall a. Fractional a => Rational -> a
    fromRational Rational
    d
      CmmStaticLit (CmmLabel CLabel
    lbl) ->
        CLabel -> WasmCodeGenM w ()
    forall (w :: WasmType). CLabel -> WasmCodeGenM w ()
    onAnySym CLabel
    lbl
          WasmCodeGenM w ()
    -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall (f :: * -> *) a b. Functor f => f a -> b -> f b
    $> SymName -> Int -> DataSectionContent
    DataSym
            (CLabel -> SymName
    symNameFromCLabel CLabel
    lbl)
            Int
    0
      CmmStaticLit (CmmLabelOff CLabel
    lbl Int
    o) ->
        CLabel -> WasmCodeGenM w ()
    forall (w :: WasmType). CLabel -> WasmCodeGenM w ()
    onAnySym CLabel
    lbl
          WasmCodeGenM w ()
    -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall (f :: * -> *) a b. Functor f => f a -> b -> f b
    $> SymName -> Int -> DataSectionContent
    DataSym
            (CLabel -> SymName
    symNameFromCLabel CLabel
    lbl)
            Int
    o
      CmmUninitialised Int
    i -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (DataSectionContent -> WasmCodeGenM w DataSectionContent)
    -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall a b. (a -> b) -> a -> b
    $ Int -> DataSectionContent
    DataSkip Int
    i
      CmmString ByteString
    b -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (DataSectionContent -> WasmCodeGenM w DataSectionContent)
    -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall a b. (a -> b) -> a -> b
    $ ByteString -> DataSectionContent
    DataASCII ByteString
    b
      CmmFileEmbed String
    f Int
    l -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (DataSectionContent -> WasmCodeGenM w DataSectionContent)
    -> DataSectionContent -> WasmCodeGenM w DataSectionContent
    forall a b. (a -> b) -> a -> b
    $ String -> Int -> DataSectionContent
    DataIncBin String
    f Int
    l
      CmmStatic
    _ -> String -> WasmCodeGenM w DataSectionContent
    forall a. HasCallStack => String -> a
    panic String
    "lower_CmmStatic: unreachable"

    {-
    Note [Register mapping on WebAssembly]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    Unlike typical ISAs, WebAssembly doesn't expose a fixed set of
    registers. For now, we map each Cmm LocalReg to a wasm local, and each
    Cmm GlobalReg to a wasm global. The wasm globals are defined in
    rts/wasm/Wasm.S, and must be kept in sync with
    'globalInfoFromCmmGlobalReg' and 'supportedCmmGlobalRegs' here.

    There are some other Cmm GlobalRegs which are still represented by
    StgRegTable fields instead of wasm globals (e.g. HpAlloc). It's cheap
    to add wasm globals, but other parts of rts logic only work with the
    StgRegTable fields, so we also need to instrument StgRun/StgReturn to
    sync the wasm globals with the StgRegTable. It's not really worth the
    trouble.

    -}
    globalInfoFromCmmGlobalReg :: WasmTypeTag w -> GlobalReg -> Maybe GlobalInfo
    globalInfoFromCmmGlobalReg :: forall (w :: WasmType).
    WasmTypeTag w -> GlobalReg -> Maybe GlobalInfo
    globalInfoFromCmmGlobalReg WasmTypeTag w
    t GlobalReg
    reg = case GlobalReg
    reg of
      VanillaReg Int
    i
        | Int
    i Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    1 Bool -> Bool -> Bool
    && Int
    i Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    10 -> GlobalInfo -> Maybe GlobalInfo
    forall a. a -> Maybe a
    Just (String -> SymName
    forall a. IsString a => String -> a
    fromString (String -> SymName) -> String -> SymName
    forall a b. (a -> b) -> a -> b
    $ String
    "__R" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> Int -> String
    forall a. Show a => a -> String
    show Int
    i, SomeWasmType
    ty_word)
      FloatReg Int
    i
        | Int
    i Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    1 Bool -> Bool -> Bool
    && Int
    i Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    6 ->
            GlobalInfo -> Maybe GlobalInfo
    forall a. a -> Maybe a
    Just (String -> SymName
    forall a. IsString a => String -> a
    fromString (String -> SymName) -> String -> SymName
    forall a b. (a -> b) -> a -> b
    $ String
    "__F" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> Int -> String
    forall a. Show a => a -> String
    show Int
    i, WasmTypeTag 'F32 -> SomeWasmType
    forall (t :: WasmType). WasmTypeTag t -> SomeWasmType
    SomeWasmType WasmTypeTag 'F32
    TagF32)
      DoubleReg Int
    i
        | Int
    i Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    1 Bool -> Bool -> Bool
    && Int
    i Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Int
    6 ->
            GlobalInfo -> Maybe GlobalInfo
    forall a. a -> Maybe a
    Just (String -> SymName
    forall a. IsString a => String -> a
    fromString (String -> SymName) -> String -> SymName
    forall a b. (a -> b) -> a -> b
    $ String
    "__D" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> Int -> String
    forall a. Show a => a -> String
    show Int
    i, WasmTypeTag 'F64 -> SomeWasmType
    forall (t :: WasmType). WasmTypeTag t -> SomeWasmType
    SomeWasmType WasmTypeTag 'F64
    TagF64)
      LongReg Int
    i
        | Int
    i Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    == Int
    1 -> GlobalInfo -> Maybe GlobalInfo
    forall a. a -> Maybe a
    Just (String -> SymName
    forall a. IsString a => String -> a
    fromString (String -> SymName) -> String -> SymName
    forall a b. (a -> b) -> a -> b
    $ String
    "__L" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> Int -> String
    forall a. Show a => a -> String
    show Int
    i, WasmTypeTag 'I64 -> SomeWasmType
    forall (t :: WasmType). WasmTypeTag t -> SomeWasmType
    SomeWasmType WasmTypeTag 'I64
    TagI64)
      GlobalReg
    Sp -> GlobalInfo -> Maybe GlobalInfo
    forall a. a -> Maybe a
    Just (SymName
    "__Sp", SomeWasmType
    ty_word)
      GlobalReg
    SpLim -> GlobalInfo -> Maybe GlobalInfo
    forall a. a -> Maybe a
    Just (SymName
    "__SpLim", SomeWasmType
    ty_word)
      GlobalReg
    Hp -> GlobalInfo -> Maybe GlobalInfo
    forall a. a -> Maybe a
    Just (SymName
    "__Hp", SomeWasmType
    ty_word)
      GlobalReg
    HpLim -> GlobalInfo -> Maybe GlobalInfo
    forall a. a -> Maybe a
    Just (SymName
    "__HpLim", SomeWasmType
    ty_word)
      GlobalReg
    _ -> Maybe GlobalInfo
    forall a. Maybe a
    Nothing
      where
        ty_word :: SomeWasmType
    ty_word = WasmTypeTag w -> SomeWasmType
    forall (t :: WasmType). WasmTypeTag t -> SomeWasmType
    SomeWasmType WasmTypeTag w
    t

    supportedCmmGlobalRegs :: [GlobalReg]
    supportedCmmGlobalRegs :: [GlobalReg]
    supportedCmmGlobalRegs =
      [Int -> GlobalReg
    VanillaReg Int
    i | Int
    i <- [Int
    1 .. Int
    10]]
        [GlobalReg] -> [GlobalReg] -> [GlobalReg]
    forall a. Semigroup a => a -> a -> a
    <> [Int -> GlobalReg
    FloatReg Int
    i | Int
    i <- [Int
    1 .. Int
    6]]
        [GlobalReg] -> [GlobalReg] -> [GlobalReg]
    forall a. Semigroup a => a -> a -> a
    <> [Int -> GlobalReg
    DoubleReg Int
    i | Int
    i <- [Int
    1 .. Int
    6]]
        [GlobalReg] -> [GlobalReg] -> [GlobalReg]
    forall a. Semigroup a => a -> a -> a
    <> [Int -> GlobalReg
    LongReg Int
    i | Int
    i <- [Int
    1 .. Int
    1]]
        [GlobalReg] -> [GlobalReg] -> [GlobalReg]
    forall a. Semigroup a => a -> a -> a
    <> [GlobalReg
    Sp, GlobalReg
    SpLim, GlobalReg
    Hp, GlobalReg
    HpLim]

    -- | Truncate a subword.
    truncSubword :: Width -> WasmTypeTag t -> WasmExpr w t -> WasmExpr w t
    truncSubword :: forall (t :: WasmType) (w :: WasmType).
    Width -> WasmTypeTag t -> WasmExpr w t -> WasmExpr w t
    truncSubword Width
    W8 WasmTypeTag t
    ty (WasmExpr forall (pre :: [WasmType]). WasmInstr w pre (t : pre)
    instr) =
      (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    forall (w :: WasmType) (t :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    WasmExpr ((forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
     -> WasmExpr w t)
    -> (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    forall a b. (a -> b) -> a -> b
    $ WasmInstr w pre (t : pre)
    forall (pre :: [WasmType]). WasmInstr w pre (t : pre)
    instr WasmInstr w pre (t : pre)
    -> WasmInstr w (t : pre) (t : t : pre)
    -> WasmInstr w pre (t : t : pre)
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmTypeTag t -> Integer -> WasmInstr w (t : pre) (t : t : pre)
    forall (t :: WasmType) (a :: WasmType) (b :: [WasmType]).
    WasmTypeTag t -> Integer -> WasmInstr a b (t : b)
    WasmConst WasmTypeTag t
    ty Integer
    0xFF WasmInstr w pre (t : t : pre)
    -> WasmInstr w (t : t : pre) (t : pre) -> WasmInstr w pre (t : pre)
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    WasmTypeTag t -> WasmInstr a (t : t : pre) (t : pre)
    WasmAnd WasmTypeTag t
    ty
    truncSubword Width
    W16 WasmTypeTag t
    ty (WasmExpr forall (pre :: [WasmType]). WasmInstr w pre (t : pre)
    instr) =
      (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    forall (w :: WasmType) (t :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    WasmExpr ((forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
     -> WasmExpr w t)
    -> (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    forall a b. (a -> b) -> a -> b
    $ WasmInstr w pre (t : pre)
    forall (pre :: [WasmType]). WasmInstr w pre (t : pre)
    instr WasmInstr w pre (t : pre)
    -> WasmInstr w (t : pre) (t : t : pre)
    -> WasmInstr w pre (t : t : pre)
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmTypeTag t -> Integer -> WasmInstr w (t : pre) (t : t : pre)
    forall (t :: WasmType) (a :: WasmType) (b :: [WasmType]).
    WasmTypeTag t -> Integer -> WasmInstr a b (t : b)
    WasmConst WasmTypeTag t
    ty Integer
    0xFFFF WasmInstr w pre (t : t : pre)
    -> WasmInstr w (t : t : pre) (t : pre) -> WasmInstr w pre (t : pre)
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    WasmTypeTag t -> WasmInstr a (t : t : pre) (t : pre)
    WasmAnd WasmTypeTag t
    ty
    truncSubword Width
    _ WasmTypeTag t
    _ WasmExpr w t
    expr = WasmExpr w t
    expr

    -- | Sign-extend a subword.
    extendSubword :: Width -> WasmTypeTag t -> WasmExpr w t -> WasmExpr w t
    extendSubword :: forall (t :: WasmType) (w :: WasmType).
    Width -> WasmTypeTag t -> WasmExpr w t -> WasmExpr w t
    extendSubword Width
    W8 WasmTypeTag t
    TagI32 (WasmExpr forall (pre :: [WasmType]). WasmInstr w pre (t : pre)
    instr) =
      (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    forall (w :: WasmType) (t :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    WasmExpr ((forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
     -> WasmExpr w t)
    -> (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    forall a b. (a -> b) -> a -> b
    $ WasmInstr w pre (t : pre)
    forall (pre :: [WasmType]). WasmInstr w pre (t : pre)
    instr WasmInstr w pre (t : pre)
    -> WasmInstr w (t : pre) (t : pre) -> WasmInstr w pre (t : pre)
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmInstr w (t : pre) (t : pre)
    WasmInstr w ('I32 : pre) ('I32 : pre)
    forall (a :: WasmType) (pre :: [WasmType]).
    WasmInstr a ('I32 : pre) ('I32 : pre)
    WasmI32Extend8S
    extendSubword Width
    W16 WasmTypeTag t
    TagI32 (WasmExpr forall (pre :: [WasmType]). WasmInstr w pre (t : pre)
    instr) =
      (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    forall (w :: WasmType) (t :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    WasmExpr ((forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
     -> WasmExpr w t)
    -> (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    forall a b. (a -> b) -> a -> b
    $ WasmInstr w pre (t : pre)
    forall (pre :: [WasmType]). WasmInstr w pre (t : pre)
    instr WasmInstr w pre (t : pre)
    -> WasmInstr w (t : pre) (t : pre) -> WasmInstr w pre (t : pre)
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmInstr w (t : pre) (t : pre)
    WasmInstr w ('I32 : pre) ('I32 : pre)
    forall (a :: WasmType) (pre :: [WasmType]).
    WasmInstr a ('I32 : pre) ('I32 : pre)
    WasmI32Extend16S
    extendSubword Width
    W8 WasmTypeTag t
    TagI64 (WasmExpr forall (pre :: [WasmType]). WasmInstr w pre (t : pre)
    instr) =
      (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    forall (w :: WasmType) (t :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    WasmExpr ((forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
     -> WasmExpr w t)
    -> (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    forall a b. (a -> b) -> a -> b
    $ WasmInstr w pre (t : pre)
    forall (pre :: [WasmType]). WasmInstr w pre (t : pre)
    instr WasmInstr w pre (t : pre)
    -> WasmInstr w (t : pre) (t : pre) -> WasmInstr w pre (t : pre)
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmInstr w (t : pre) (t : pre)
    WasmInstr w ('I64 : pre) ('I64 : pre)
    forall (a :: WasmType) (pre :: [WasmType]).
    WasmInstr a ('I64 : pre) ('I64 : pre)
    WasmI64Extend8S
    extendSubword Width
    W16 WasmTypeTag t
    TagI64 (WasmExpr forall (pre :: [WasmType]). WasmInstr w pre (t : pre)
    instr) =
      (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    forall (w :: WasmType) (t :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    WasmExpr ((forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
     -> WasmExpr w t)
    -> (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    forall a b. (a -> b) -> a -> b
    $ WasmInstr w pre (t : pre)
    forall (pre :: [WasmType]). WasmInstr w pre (t : pre)
    instr WasmInstr w pre (t : pre)
    -> WasmInstr w (t : pre) (t : pre) -> WasmInstr w pre (t : pre)
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmInstr w (t : pre) (t : pre)
    WasmInstr w ('I64 : pre) ('I64 : pre)
    forall (a :: WasmType) (pre :: [WasmType]).
    WasmInstr a ('I64 : pre) ('I64 : pre)
    WasmI64Extend16S
    extendSubword Width
    W32 WasmTypeTag t
    TagI64 (WasmExpr forall (pre :: [WasmType]). WasmInstr w pre (t : pre)
    instr) =
      (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    forall (w :: WasmType) (t :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    WasmExpr ((forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
     -> WasmExpr w t)
    -> (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    forall a b. (a -> b) -> a -> b
    $ WasmInstr w pre (t : pre)
    forall (pre :: [WasmType]). WasmInstr w pre (t : pre)
    instr WasmInstr w pre (t : pre)
    -> WasmInstr w (t : pre) (t : pre) -> WasmInstr w pre (t : pre)
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmInstr w (t : pre) (t : pre)
    WasmInstr w ('I64 : pre) ('I64 : pre)
    forall (a :: WasmType) (pre :: [WasmType]).
    WasmInstr a ('I64 : pre) ('I64 : pre)
    WasmI64Extend32S
    extendSubword Width
    _ WasmTypeTag t
    _ WasmExpr w t
    expr = WasmExpr w t
    expr

    -- | Lower an unary homogeneous operation.
    lower_MO_Un_Homo ::
      ( forall pre t.
        WasmTypeTag t ->
        WasmInstr
          w
          (t : pre)
          (t : pre)
      ) ->
      CLabel ->
      CmmType ->
      [CmmExpr] ->
      WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Un_Homo :: forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Un_Homo forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : pre) (t : pre)
    op CLabel
    lbl CmmType
    t0 [CmmExpr
    x] = case CmmType -> SomeWasmType
    someWasmTypeFromCmmType CmmType
    t0 of
      SomeWasmType WasmTypeTag t
    ty -> do
        WasmExpr x_instr <- CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag t
    ty CmmExpr
    x
        pure $
          SomeWasmExpr ty $
            WasmExpr $
              x_instr `WasmConcat` op ty
    lower_MO_Un_Homo forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : pre) (t : pre)
    _ CLabel
    _ CmmType
    _ [CmmExpr]
    _ = String -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_MO_Un_Homo: unreachable"

    -- | Lower a binary homogeneous operation. Homogeneous: result type is
    -- the same with operand types.
    lower_MO_Bin_Homo ::
      ( forall pre t.
        WasmTypeTag t ->
        WasmInstr
          w
          (t : t : pre)
          (t : pre)
      ) ->
      CLabel ->
      CmmType ->
      [CmmExpr] ->
      WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo :: forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    op CLabel
    lbl CmmType
    t0 [CmmExpr
    x, CmmExpr
    y] = case CmmType -> SomeWasmType
    someWasmTypeFromCmmType CmmType
    t0 of
      SomeWasmType WasmTypeTag t
    ty -> do
        WasmExpr x_instr <- CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag t
    ty CmmExpr
    x
        WasmExpr y_instr <- lower_CmmExpr_Typed lbl ty y
        pure $
          SomeWasmExpr ty $
            WasmExpr $
              x_instr `WasmConcat` y_instr `WasmConcat` op ty
    lower_MO_Bin_Homo forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    _ CLabel
    _ CmmType
    _ [CmmExpr]
    _ = String -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_MO_Bin_Homo: unreachable"

    -- | Lower a binary homogeneous operation, and truncate the result if
    -- it's a subword.
    lower_MO_Bin_Homo_Trunc ::
      (forall pre t. WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)) ->
      CLabel ->
      Width ->
      [CmmExpr] ->
      WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo_Trunc :: forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo_Trunc forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    op CLabel
    lbl Width
    w0 [CmmExpr
    x, CmmExpr
    y] =
      case CmmType -> SomeWasmType
    someWasmTypeFromCmmType (Width -> CmmType
    cmmBits Width
    w0) of
        SomeWasmType WasmTypeTag t
    ty -> do
          WasmExpr x_instr <- CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag t
    ty CmmExpr
    x
          WasmExpr y_instr <- lower_CmmExpr_Typed lbl ty y
          pure $
            SomeWasmExpr ty $
              truncSubword w0 ty $
                WasmExpr $
                  x_instr `WasmConcat` y_instr `WasmConcat` op ty
    lower_MO_Bin_Homo_Trunc forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    _ CLabel
    _ Width
    _ [CmmExpr]
    _ = String -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_MO_Bin_Homo_Trunc: unreachable"

    -- | Lower a binary homogeneous operation, first sign extending the
    -- operands, then truncating the result.
    lower_MO_Bin_Homo_Ext_Trunc ::
      (forall pre t. WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)) ->
      CLabel ->
      Width ->
      [CmmExpr] ->
      WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo_Ext_Trunc :: forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo_Ext_Trunc forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    op CLabel
    lbl Width
    w0 [CmmExpr
    x, CmmExpr
    y] =
      case CmmType -> SomeWasmType
    someWasmTypeFromCmmType (Width -> CmmType
    cmmBits Width
    w0) of
        SomeWasmType WasmTypeTag t
    ty -> do
          WasmExpr x_instr <-
            Width -> WasmTypeTag t -> WasmExpr w t -> WasmExpr w t
    forall (t :: WasmType) (w :: WasmType).
    Width -> WasmTypeTag t -> WasmExpr w t -> WasmExpr w t
    extendSubword Width
    w0 WasmTypeTag t
    ty (WasmExpr w t -> WasmExpr w t)
    -> WasmCodeGenM w (WasmExpr w t) -> WasmCodeGenM w (WasmExpr w t)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag t
    ty CmmExpr
    x
          WasmExpr y_instr <-
            extendSubword w0 ty <$> lower_CmmExpr_Typed lbl ty y
          pure $
            SomeWasmExpr ty $
              truncSubword w0 ty $
                WasmExpr $
                  x_instr `WasmConcat` y_instr `WasmConcat` op ty
    lower_MO_Bin_Homo_Ext_Trunc forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    _ CLabel
    _ Width
    _ [CmmExpr]
    _ =
      String -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_MO_Bin_Homo_Ext_Trunc: unreachable"

    -- | Lower a relational binary operation, first sign extending the
    -- operands. Relational: result type is a boolean (word type).
    lower_MO_Bin_Rel_Ext ::
      (forall pre t. WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)) ->
      CLabel ->
      Width ->
      [CmmExpr] ->
      WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel_Ext :: forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel_Ext forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    op CLabel
    lbl Width
    w0 [CmmExpr
    x, CmmExpr
    y] =
      case CmmType -> SomeWasmType
    someWasmTypeFromCmmType (Width -> CmmType
    cmmBits Width
    w0) of
        SomeWasmType WasmTypeTag t
    ty -> do
          WasmExpr x_instr <-
            Width -> WasmTypeTag t -> WasmExpr w t -> WasmExpr w t
    forall (t :: WasmType) (w :: WasmType).
    Width -> WasmTypeTag t -> WasmExpr w t -> WasmExpr w t
    extendSubword Width
    w0 WasmTypeTag t
    ty (WasmExpr w t -> WasmExpr w t)
    -> WasmCodeGenM w (WasmExpr w t) -> WasmCodeGenM w (WasmExpr w t)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag t
    ty CmmExpr
    x
          WasmExpr y_instr <-
            extendSubword w0 ty <$> lower_CmmExpr_Typed lbl ty y
          ty_word <- wasmWordTypeM
          pure $
            SomeWasmExpr ty_word $
              WasmExpr $
                x_instr `WasmConcat` y_instr `WasmConcat` op ty
    lower_MO_Bin_Rel_Ext forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    _ CLabel
    _ Width
    _ [CmmExpr]
    _ = String -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_MO_Bin_Rel_Ext: unreachable"

    -- | Lower a relational binary operation.
    lower_MO_Bin_Rel ::
      ( forall pre t.
        WasmTypeTag t ->
        WasmInstr
          w
          (t : t : pre)
          (w : pre)
      ) ->
      CLabel ->
      CmmType ->
      [CmmExpr] ->
      WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel :: forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    op CLabel
    lbl CmmType
    t0 [CmmExpr
    x, CmmExpr
    y] = case CmmType -> SomeWasmType
    someWasmTypeFromCmmType CmmType
    t0 of
      SomeWasmType WasmTypeTag t
    ty -> do
        WasmExpr x_instr <- CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag t
    ty CmmExpr
    x
        WasmExpr y_instr <- lower_CmmExpr_Typed lbl ty y
        ty_word <- wasmWordTypeM
        pure $
          SomeWasmExpr ty_word $
            WasmExpr $
              x_instr `WasmConcat` y_instr `WasmConcat` op ty
    lower_MO_Bin_Rel forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    _ CLabel
    _ CmmType
    _ [CmmExpr]
    _ = String -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_MO_Bin_Rel: unreachable"

    -- | Cast a shiftL/shiftR RHS to the same type as LHS. Because we may
    -- have a 64-bit LHS and 32-bit RHS, but wasm shift operators are
    -- homogeneous.
    shiftRHSCast ::
      CLabel ->
      WasmTypeTag t ->
      CmmExpr ->
      WasmCodeGenM
        w
        (WasmExpr w t)
    shiftRHSCast :: forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    shiftRHSCast CLabel
    lbl WasmTypeTag t
    t1 CmmExpr
    x = do
      SomeWasmExpr t0 (WasmExpr x_instr) <- CLabel -> CmmExpr -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel -> CmmExpr -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmExpr CLabel
    lbl CmmExpr
    x
      if
          | Just Refl <- t0 `testEquality` t1 -> pure $ WasmExpr x_instr
          | TagI32 <- t0,
            TagI64 <- t1 ->
              pure $ WasmExpr $ x_instr `WasmConcat` WasmI64ExtendI32 Unsigned
          | otherwise -> panic "shiftRHSCast: unreachable"

    -- | Lower a 'MO_Shl' operation, truncating the result.
    lower_MO_Shl ::
      CLabel ->
      Width ->
      [CmmExpr] ->
      WasmCodeGenM
        w
        (SomeWasmExpr w)
    lower_MO_Shl :: forall (w :: WasmType).
    CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Shl CLabel
    lbl Width
    w0 [CmmExpr
    x, CmmExpr
    y] = case CmmType -> SomeWasmType
    someWasmTypeFromCmmType (Width -> CmmType
    cmmBits Width
    w0) of
      SomeWasmType WasmTypeTag t
    ty -> do
        WasmExpr x_instr <- CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag t
    ty CmmExpr
    x
        WasmExpr y_instr <- shiftRHSCast lbl ty y
        pure $
          SomeWasmExpr ty $
            truncSubword w0 ty $
              WasmExpr $
                x_instr `WasmConcat` y_instr `WasmConcat` WasmShl ty
    lower_MO_Shl CLabel
    _ Width
    _ [CmmExpr]
    _ = String -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_MO_Shl: unreachable"

    -- | Lower a 'MO_U_Shr' operation.
    lower_MO_U_Shr ::
      CLabel ->
      Width ->
      [CmmExpr] ->
      WasmCodeGenM
        w
        (SomeWasmExpr w)
    lower_MO_U_Shr :: forall (w :: WasmType).
    CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_U_Shr CLabel
    lbl Width
    w0 [CmmExpr
    x, CmmExpr
    y] = case CmmType -> SomeWasmType
    someWasmTypeFromCmmType (Width -> CmmType
    cmmBits Width
    w0) of
      SomeWasmType WasmTypeTag t
    ty -> do
        WasmExpr x_instr <- CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag t
    ty CmmExpr
    x
        WasmExpr y_instr <- shiftRHSCast lbl ty y
        pure $
          SomeWasmExpr ty $
            WasmExpr $
              x_instr `WasmConcat` y_instr `WasmConcat` WasmShr Unsigned ty
    lower_MO_U_Shr CLabel
    _ Width
    _ [CmmExpr]
    _ = String -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_MO_U_Shr: unreachable"

    -- | Lower a 'MO_S_Shr' operation, first sign-extending the LHS, then
    -- truncating the result.
    lower_MO_S_Shr ::
      CLabel ->
      Width ->
      [CmmExpr] ->
      WasmCodeGenM
        w
        (SomeWasmExpr w)
    lower_MO_S_Shr :: forall (w :: WasmType).
    CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_S_Shr CLabel
    lbl Width
    w0 [CmmExpr
    x, CmmExpr
    y] = case CmmType -> SomeWasmType
    someWasmTypeFromCmmType (Width -> CmmType
    cmmBits Width
    w0) of
      SomeWasmType WasmTypeTag t
    ty -> do
        WasmExpr x_instr <- Width -> WasmTypeTag t -> WasmExpr w t -> WasmExpr w t
    forall (t :: WasmType) (w :: WasmType).
    Width -> WasmTypeTag t -> WasmExpr w t -> WasmExpr w t
    extendSubword Width
    w0 WasmTypeTag t
    ty (WasmExpr w t -> WasmExpr w t)
    -> WasmCodeGenM w (WasmExpr w t) -> WasmCodeGenM w (WasmExpr w t)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag t
    ty CmmExpr
    x
        WasmExpr y_instr <- shiftRHSCast lbl ty y
        pure $
          SomeWasmExpr ty $
            truncSubword w0 ty $
              WasmExpr $
                x_instr `WasmConcat` y_instr `WasmConcat` WasmShr Signed ty
    lower_MO_S_Shr CLabel
    _ Width
    _ [CmmExpr]
    _ = String -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_MO_S_Shr: unreachable"

    -- | Lower a 'MO_MulMayOflo' operation. It's translated to a ccall to
    -- @hs_mulIntMayOflo@ function in @ghc-prim/cbits/mulIntMayOflo@,
    -- otherwise it's quite non-trivial to implement as inline assembly.
    lower_MO_MulMayOflo ::
      CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_MulMayOflo :: forall (w :: WasmType).
    CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_MulMayOflo CLabel
    lbl Width
    w0 [CmmExpr
    x, CmmExpr
    y] = case CmmType -> SomeWasmType
    someWasmTypeFromCmmType CmmType
    ty_cmm of
      SomeWasmType WasmTypeTag t
    ty -> do
        WasmExpr x_instr <- CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag t
    ty CmmExpr
    x
        WasmExpr y_instr <- lower_CmmExpr_Typed lbl ty y
        onFuncSym "hs_mulIntMayOflo" [ty_cmm, ty_cmm] [ty_cmm]
        pure $
          SomeWasmExpr ty $
            WasmExpr $
              x_instr
                `WasmConcat` y_instr
                `WasmConcat` WasmCCall "hs_mulIntMayOflo"
      where
        ty_cmm :: CmmType
    ty_cmm = Width -> CmmType
    cmmBits Width
    w0
    lower_MO_MulMayOflo CLabel
    _ Width
    _ [CmmExpr]
    _ = String -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_MO_MulMayOflo: unreachable"

    -- | Lower an unary conversion operation.
    lower_MO_Un_Conv ::
      ( forall pre t0 t1.
        WasmTypeTag t0 ->
        WasmTypeTag t1 ->
        WasmInstr w (t0 : pre) (t1 : pre)
      ) ->
      CLabel ->
      CmmType ->
      CmmType ->
      [CmmExpr] ->
      WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Un_Conv :: forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t0 :: WasmType) (t1 :: WasmType).
     WasmTypeTag t0
     -> WasmTypeTag t1 -> WasmInstr w (t0 : pre) (t1 : pre))
    -> CLabel
    -> CmmType
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Un_Conv forall (pre :: [WasmType]) (t0 :: WasmType) (t1 :: WasmType).
    WasmTypeTag t0
    -> WasmTypeTag t1 -> WasmInstr w (t0 : pre) (t1 : pre)
    op CLabel
    lbl CmmType
    t0 CmmType
    t1 [CmmExpr
    x] =
      case (# CmmType -> SomeWasmType
    someWasmTypeFromCmmType CmmType
    t0, CmmType -> SomeWasmType
    someWasmTypeFromCmmType CmmType
    t1 #) of
        (# SomeWasmType WasmTypeTag t
    ty0, SomeWasmType WasmTypeTag t
    ty1 #) -> do
          WasmExpr x_instr <- CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag t
    ty0 CmmExpr
    x
          pure $ SomeWasmExpr ty1 $ WasmExpr $ x_instr `WasmConcat` op ty0 ty1
    lower_MO_Un_Conv forall (pre :: [WasmType]) (t0 :: WasmType) (t1 :: WasmType).
    WasmTypeTag t0
    -> WasmTypeTag t1 -> WasmInstr w (t0 : pre) (t1 : pre)
    _ CLabel
    _ CmmType
    _ CmmType
    _ [CmmExpr]
    _ = String -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_MO_Un_Conv: unreachable"

    -- | Lower a 'MO_SS_Conv' operation.
    lower_MO_SS_Conv ::
      CLabel ->
      Width ->
      Width ->
      [CmmExpr] ->
      WasmCodeGenM
        w
        (SomeWasmExpr w)
    lower_MO_SS_Conv :: forall (w :: WasmType).
    CLabel
    -> Width -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_SS_Conv CLabel
    lbl Width
    w0 Width
    w1 [CmmExpr
    x]
      | Width
    w0 Width -> Width -> Bool
    forall a. Eq a => a -> a -> Bool
    == Width
    w1 = CLabel -> CmmExpr -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel -> CmmExpr -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmExpr CLabel
    lbl CmmExpr
    x
    lower_MO_SS_Conv CLabel
    lbl Width
    w0 Width
    w1 [CmmLoad CmmExpr
    ptr CmmType
    _ AlignmentSpec
    align]
      | Width
    w0 Width -> Width -> Bool
    forall a. Ord a => a -> a -> Bool
    < Width
    w1,
        Width
    w1 Width -> Width -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Width
    W32 = do
          (WasmExpr ptr_instr, o) <- CLabel -> CmmExpr -> WasmCodeGenM w (WasmExpr w w, Int)
    forall (w :: WasmType).
    CLabel -> CmmExpr -> WasmCodeGenM w (WasmExpr w w, Int)
    lower_CmmExpr_Ptr CLabel
    lbl CmmExpr
    ptr
          pure $
            SomeWasmExpr TagI32 $
              truncSubword w1 TagI32 $
                WasmExpr $
                  ptr_instr
                    `WasmConcat` WasmLoad
                      TagI32
                      (wasmMemoryNarrowing TagI32 (cmmBits w0))
                      Signed
                      o
                      align
      | Width
    w0 Width -> Width -> Bool
    forall a. Ord a => a -> a -> Bool
    > Width
    w1 =
          WasmTypeTag 'I32 -> WasmExpr w 'I32 -> SomeWasmExpr w
    forall (t :: WasmType) (w :: WasmType).
    WasmTypeTag t -> WasmExpr w t -> SomeWasmExpr w
    SomeWasmExpr WasmTypeTag 'I32
    TagI32
            (WasmExpr w 'I32 -> SomeWasmExpr w)
    -> WasmCodeGenM w (WasmExpr w 'I32)
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CLabel
    -> CmmExpr
    -> WasmTypeTag 'I32
    -> CmmType
    -> AlignmentSpec
    -> WasmCodeGenM w (WasmExpr w 'I32)
    forall (t :: WasmType) (w :: WasmType).
    CLabel
    -> CmmExpr
    -> WasmTypeTag t
    -> CmmType
    -> AlignmentSpec
    -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmLoad_Typed
              CLabel
    lbl
              CmmExpr
    ptr
              WasmTypeTag 'I32
    TagI32
              (Width -> CmmType
    cmmBits Width
    w1)
              AlignmentSpec
    align
    lower_MO_SS_Conv CLabel
    lbl Width
    w0 Width
    W64 [CmmLoad CmmExpr
    ptr CmmType
    _ AlignmentSpec
    align] = do
      (WasmExpr ptr_instr, o) <- CLabel -> CmmExpr -> WasmCodeGenM w (WasmExpr w w, Int)
    forall (w :: WasmType).
    CLabel -> CmmExpr -> WasmCodeGenM w (WasmExpr w w, Int)
    lower_CmmExpr_Ptr CLabel
    lbl CmmExpr
    ptr
      pure $
        SomeWasmExpr TagI64 $
          WasmExpr $
            ptr_instr
              `WasmConcat` WasmLoad
                TagI64
                (wasmMemoryNarrowing TagI64 (cmmBits w0))
                Signed
                o
                align
    lower_MO_SS_Conv CLabel
    lbl Width
    w0 Width
    w1 [CmmExpr
    x]
      | Width
    w0 Width -> Width -> Bool
    forall a. Ord a => a -> a -> Bool
    < Width
    w1,
        Width
    w1 Width -> Width -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Width
    W32 = do
          x_expr <- CLabel
    -> WasmTypeTag 'I32 -> CmmExpr -> WasmCodeGenM w (WasmExpr w 'I32)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag 'I32
    TagI32 CmmExpr
    x
          pure $
            SomeWasmExpr TagI32 $
              truncSubword w1 TagI32 $
                extendSubword w0 TagI32 x_expr
      | Width
    W32 Width -> Width -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Width
    w0,
        Width
    w0 Width -> Width -> Bool
    forall a. Ord a => a -> a -> Bool
    > Width
    w1 = do
          x_expr <- CLabel
    -> WasmTypeTag 'I32 -> CmmExpr -> WasmCodeGenM w (WasmExpr w 'I32)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag 'I32
    TagI32 CmmExpr
    x
          pure $ SomeWasmExpr TagI32 $ truncSubword w1 TagI32 x_expr
    lower_MO_SS_Conv CLabel
    lbl Width
    W32 Width
    W64 [CmmExpr
    x] = do
      WasmExpr x_instr <- CLabel
    -> WasmTypeTag 'I32 -> CmmExpr -> WasmCodeGenM w (WasmExpr w 'I32)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag 'I32
    TagI32 CmmExpr
    x
      pure $
        SomeWasmExpr TagI64 $
          WasmExpr $
            x_instr `WasmConcat` WasmI64ExtendI32 Signed
    lower_MO_SS_Conv CLabel
    lbl Width
    w0 Width
    W64 [CmmExpr
    x] = do
      WasmExpr x_instr <- CLabel
    -> WasmTypeTag 'I32 -> CmmExpr -> WasmCodeGenM w (WasmExpr w 'I32)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag 'I32
    TagI32 CmmExpr
    x
      pure $
        SomeWasmExpr TagI64 $
          extendSubword w0 TagI64 $
            WasmExpr $
              x_instr `WasmConcat` WasmI64ExtendI32 Unsigned
    lower_MO_SS_Conv CLabel
    lbl Width
    W64 Width
    w1 [CmmExpr
    x] = do
      WasmExpr x_instr <- CLabel
    -> WasmTypeTag 'I64 -> CmmExpr -> WasmCodeGenM w (WasmExpr w 'I64)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag 'I64
    TagI64 CmmExpr
    x
      pure $
        SomeWasmExpr TagI32 $
          truncSubword w1 TagI32 $
            WasmExpr $
              x_instr `WasmConcat` WasmI32WrapI64
    lower_MO_SS_Conv CLabel
    _ Width
    _ Width
    _ [CmmExpr]
    _ = String -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_MO_SS_Conv: unreachable"

    -- | Lower a 'MO_UU_Conv' operation.
    lower_MO_UU_Conv ::
      CLabel ->
      Width ->
      Width ->
      [CmmExpr] ->
      WasmCodeGenM
        w
        (SomeWasmExpr w)
    lower_MO_UU_Conv :: forall (w :: WasmType).
    CLabel
    -> Width -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_UU_Conv CLabel
    lbl Width
    w0 Width
    w1 [CmmLoad CmmExpr
    ptr CmmType
    _ AlignmentSpec
    align] =
      case CmmType -> SomeWasmType
    someWasmTypeFromCmmType (Width -> CmmType
    cmmBits Width
    w1) of
        SomeWasmType WasmTypeTag t
    ty ->
          WasmTypeTag t -> WasmExpr w t -> SomeWasmExpr w
    forall (t :: WasmType) (w :: WasmType).
    WasmTypeTag t -> WasmExpr w t -> SomeWasmExpr w
    SomeWasmExpr WasmTypeTag t
    ty
            (WasmExpr w t -> SomeWasmExpr w)
    -> WasmCodeGenM w (WasmExpr w t) -> WasmCodeGenM w (SomeWasmExpr w)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CLabel
    -> CmmExpr
    -> WasmTypeTag t
    -> CmmType
    -> AlignmentSpec
    -> WasmCodeGenM w (WasmExpr w t)
    forall (t :: WasmType) (w :: WasmType).
    CLabel
    -> CmmExpr
    -> WasmTypeTag t
    -> CmmType
    -> AlignmentSpec
    -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmLoad_Typed
              CLabel
    lbl
              CmmExpr
    ptr
              WasmTypeTag t
    ty
              (Width -> CmmType
    cmmBits (Width -> Width -> Width
    forall a. Ord a => a -> a -> a
    min Width
    w0 Width
    w1))
              AlignmentSpec
    align
    lower_MO_UU_Conv CLabel
    lbl Width
    w0 Width
    w1 [CmmExpr
    x]
      | Width
    w0 Width -> Width -> Bool
    forall a. Eq a => a -> a -> Bool
    == Width
    w1 = CLabel -> CmmExpr -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel -> CmmExpr -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmExpr CLabel
    lbl CmmExpr
    x
      | Width
    w0 Width -> Width -> Bool
    forall a. Ord a => a -> a -> Bool
    < Width
    w1, Width
    w1 Width -> Width -> Bool
    forall a. Ord a => a -> a -> Bool
    <= Width
    W32 = CLabel -> CmmExpr -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel -> CmmExpr -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmExpr CLabel
    lbl CmmExpr
    x
      | Width
    W32 Width -> Width -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Width
    w0,
        Width
    w0 Width -> Width -> Bool
    forall a. Ord a => a -> a -> Bool
    > Width
    w1 = do
          x_expr <- CLabel
    -> WasmTypeTag 'I32 -> CmmExpr -> WasmCodeGenM w (WasmExpr w 'I32)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag 'I32
    TagI32 CmmExpr
    x
          pure $ SomeWasmExpr TagI32 $ truncSubword w1 TagI32 x_expr
    lower_MO_UU_Conv CLabel
    lbl Width
    _ Width
    W64 [CmmExpr
    x] = do
      WasmExpr x_instr <- CLabel
    -> WasmTypeTag 'I32 -> CmmExpr -> WasmCodeGenM w (WasmExpr w 'I32)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag 'I32
    TagI32 CmmExpr
    x
      pure $
        SomeWasmExpr TagI64 $
          WasmExpr $
            x_instr `WasmConcat` WasmI64ExtendI32 Unsigned
    lower_MO_UU_Conv CLabel
    lbl Width
    W64 Width
    w1 [CmmExpr
    x] = do
      WasmExpr x_instr <- CLabel
    -> WasmTypeTag 'I64 -> CmmExpr -> WasmCodeGenM w (WasmExpr w 'I64)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag 'I64
    TagI64 CmmExpr
    x
      pure $
        SomeWasmExpr TagI32 $
          truncSubword w1 TagI32 $
            WasmExpr $
              x_instr `WasmConcat` WasmI32WrapI64
    lower_MO_UU_Conv CLabel
    _ Width
    _ Width
    _ [CmmExpr]
    _ = String -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_MO_UU_Conv: unreachable"

    -- | Lower a 'MO_FF_Conv' operation.
    lower_MO_FF_Conv ::
      CLabel ->
      Width ->
      Width ->
      [CmmExpr] ->
      WasmCodeGenM
        w
        (SomeWasmExpr w)
    lower_MO_FF_Conv :: forall (w :: WasmType).
    CLabel
    -> Width -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_FF_Conv CLabel
    lbl Width
    W32 Width
    W64 [CmmExpr
    x] = do
      WasmExpr x_instr <- CLabel
    -> WasmTypeTag 'F32 -> CmmExpr -> WasmCodeGenM w (WasmExpr w 'F32)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag 'F32
    TagF32 CmmExpr
    x
      pure $
        SomeWasmExpr TagF64 $
          WasmExpr $
            x_instr `WasmConcat` WasmF64PromoteF32
    lower_MO_FF_Conv CLabel
    lbl Width
    W64 Width
    W32 [CmmExpr
    x] = do
      WasmExpr x_instr <- CLabel
    -> WasmTypeTag 'F64 -> CmmExpr -> WasmCodeGenM w (WasmExpr w 'F64)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag 'F64
    TagF64 CmmExpr
    x
      pure $
        SomeWasmExpr TagF32 $
          WasmExpr $
            x_instr `WasmConcat` WasmF32DemoteF64
    lower_MO_FF_Conv CLabel
    _ Width
    _ Width
    _ [CmmExpr]
    _ = String -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_MO_FF_Conv: unreachable"

    -- | Lower a 'CmmMachOp'.
    lower_CmmMachOp ::
      CLabel ->
      MachOp ->
      [CmmExpr] ->
      WasmCodeGenM
        w
        (SomeWasmExpr w)
    lower_CmmMachOp :: forall (w :: WasmType).
    CLabel -> MachOp -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmMachOp CLabel
    lbl (MO_RelaxedRead Width
    w0) [CmmExpr
    x] = CLabel -> CmmExpr -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel -> CmmExpr -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmExpr CLabel
    lbl (CmmExpr -> CmmType -> AlignmentSpec -> CmmExpr
    CmmLoad CmmExpr
    x (Width -> CmmType
    cmmBits Width
    w0) AlignmentSpec
    NaturallyAligned)
    lower_CmmMachOp CLabel
    lbl (MO_Add Width
    w0) [CmmExpr]
    xs = (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo_Trunc WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    WasmTypeTag t -> WasmInstr a (t : t : pre) (t : pre)
    WasmAdd CLabel
    lbl Width
    w0 [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_Sub Width
    w0) [CmmExpr]
    xs = (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo_Trunc WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    WasmTypeTag t -> WasmInstr a (t : t : pre) (t : pre)
    WasmSub CLabel
    lbl Width
    w0 [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_Eq Width
    w0) [CmmExpr]
    xs = (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    WasmTypeTag t -> WasmInstr a (t : t : pre) (a : pre)
    WasmEq CLabel
    lbl (Width -> CmmType
    cmmBits Width
    w0) [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_Ne Width
    w0) [CmmExpr]
    xs = (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    WasmTypeTag t -> WasmInstr a (t : t : pre) (a : pre)
    WasmNe CLabel
    lbl (Width -> CmmType
    cmmBits Width
    w0) [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_Mul Width
    w0) [CmmExpr]
    xs = (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo_Trunc WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    WasmTypeTag t -> WasmInstr a (t : t : pre) (t : pre)
    WasmMul CLabel
    lbl Width
    w0 [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_S_MulMayOflo Width
    w0) [CmmExpr]
    xs = CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_MulMayOflo CLabel
    lbl Width
    w0 [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_S_Quot Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo_Ext_Trunc
        (Signage -> WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    Signage -> WasmTypeTag t -> WasmInstr a (t : t : pre) (t : pre)
    WasmDiv Signage
    Signed)
        CLabel
    lbl
        Width
    w0
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_S_Rem Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo_Ext_Trunc
        (Signage -> WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    Signage -> WasmTypeTag t -> WasmInstr a (t : t : pre) (t : pre)
    WasmRem Signage
    Signed)
        CLabel
    lbl
        Width
    w0
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_S_Neg Width
    w0) [CmmExpr
    x] =
      CLabel -> MachOp -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel -> MachOp -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmMachOp
        CLabel
    lbl
        (Width -> MachOp
    MO_Sub Width
    w0)
        [CmmLit -> CmmExpr
    CmmLit (CmmLit -> CmmExpr) -> CmmLit -> CmmExpr
    forall a b. (a -> b) -> a -> b
    $ Integer -> Width -> CmmLit
    CmmInt Integer
    0 Width
    w0, CmmExpr
    x]
    lower_CmmMachOp CLabel
    lbl (MO_U_Quot Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo
        (Signage -> WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    Signage -> WasmTypeTag t -> WasmInstr a (t : t : pre) (t : pre)
    WasmDiv Signage
    Unsigned)
        CLabel
    lbl
        (Width -> CmmType
    cmmBits Width
    w0)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_U_Rem Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo
        (Signage -> WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    Signage -> WasmTypeTag t -> WasmInstr a (t : t : pre) (t : pre)
    WasmRem Signage
    Unsigned)
        CLabel
    lbl
        (Width -> CmmType
    cmmBits Width
    w0)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_S_Ge Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel_Ext
        (Signage -> WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    Signage -> WasmTypeTag t -> WasmInstr a (t : t : pre) (a : pre)
    WasmGe Signage
    Signed)
        CLabel
    lbl
        Width
    w0
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_S_Le Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel_Ext
        (Signage -> WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    Signage -> WasmTypeTag t -> WasmInstr a (t : t : pre) (a : pre)
    WasmLe Signage
    Signed)
        CLabel
    lbl
        Width
    w0
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_S_Gt Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel_Ext
        (Signage -> WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    Signage -> WasmTypeTag t -> WasmInstr a (t : t : pre) (a : pre)
    WasmGt Signage
    Signed)
        CLabel
    lbl
        Width
    w0
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_S_Lt Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel_Ext
        (Signage -> WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    Signage -> WasmTypeTag t -> WasmInstr a (t : t : pre) (a : pre)
    WasmLt Signage
    Signed)
        CLabel
    lbl
        Width
    w0
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_U_Ge Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel
        (Signage -> WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    Signage -> WasmTypeTag t -> WasmInstr a (t : t : pre) (a : pre)
    WasmGe Signage
    Unsigned)
        CLabel
    lbl
        (Width -> CmmType
    cmmBits Width
    w0)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_U_Le Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel
        (Signage -> WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    Signage -> WasmTypeTag t -> WasmInstr a (t : t : pre) (a : pre)
    WasmLe Signage
    Unsigned)
        CLabel
    lbl
        (Width -> CmmType
    cmmBits Width
    w0)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_U_Gt Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel
        (Signage -> WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    Signage -> WasmTypeTag t -> WasmInstr a (t : t : pre) (a : pre)
    WasmGt Signage
    Unsigned)
        CLabel
    lbl
        (Width -> CmmType
    cmmBits Width
    w0)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_U_Lt Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel
        (Signage -> WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    Signage -> WasmTypeTag t -> WasmInstr a (t : t : pre) (a : pre)
    WasmLt Signage
    Unsigned)
        CLabel
    lbl
        (Width -> CmmType
    cmmBits Width
    w0)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_F_Add Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo
        WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    WasmTypeTag t -> WasmInstr a (t : t : pre) (t : pre)
    WasmAdd
        CLabel
    lbl
        (Width -> CmmType
    cmmFloat Width
    w0)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_F_Sub Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo
        WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    WasmTypeTag t -> WasmInstr a (t : t : pre) (t : pre)
    WasmSub
        CLabel
    lbl
        (Width -> CmmType
    cmmFloat Width
    w0)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_F_Neg Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Un_Homo
        WasmTypeTag t -> WasmInstr w (t : pre) (t : pre)
    forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : pre) (t : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    WasmTypeTag t -> WasmInstr a (t : pre) (t : pre)
    WasmNeg
        CLabel
    lbl
        (Width -> CmmType
    cmmFloat Width
    w0)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_F_Mul Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo
        WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    WasmTypeTag t -> WasmInstr a (t : t : pre) (t : pre)
    WasmMul
        CLabel
    lbl
        (Width -> CmmType
    cmmFloat Width
    w0)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_F_Quot Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo
        (Signage -> WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    Signage -> WasmTypeTag t -> WasmInstr a (t : t : pre) (t : pre)
    WasmDiv Signage
    Signed)
        CLabel
    lbl
        (Width -> CmmType
    cmmFloat Width
    w0)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_F_Eq Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel
        WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    WasmTypeTag t -> WasmInstr a (t : t : pre) (a : pre)
    WasmEq
        CLabel
    lbl
        (Width -> CmmType
    cmmFloat Width
    w0)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_F_Ne Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel
        WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    WasmTypeTag t -> WasmInstr a (t : t : pre) (a : pre)
    WasmNe
        CLabel
    lbl
        (Width -> CmmType
    cmmFloat Width
    w0)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_F_Ge Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel
        (Signage -> WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    Signage -> WasmTypeTag t -> WasmInstr a (t : t : pre) (a : pre)
    WasmGe Signage
    Signed)
        CLabel
    lbl
        (Width -> CmmType
    cmmFloat Width
    w0)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_F_Le Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel
        (Signage -> WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    Signage -> WasmTypeTag t -> WasmInstr a (t : t : pre) (a : pre)
    WasmLe Signage
    Signed)
        CLabel
    lbl
        (Width -> CmmType
    cmmFloat Width
    w0)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_F_Gt Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel
        (Signage -> WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    Signage -> WasmTypeTag t -> WasmInstr a (t : t : pre) (a : pre)
    WasmGt Signage
    Signed)
        CLabel
    lbl
        (Width -> CmmType
    cmmFloat Width
    w0)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_F_Lt Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Rel
        (Signage -> WasmTypeTag t -> WasmInstr w (t : t : pre) (w : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    Signage -> WasmTypeTag t -> WasmInstr a (t : t : pre) (a : pre)
    WasmLt Signage
    Signed)
        CLabel
    lbl
        (Width -> CmmType
    cmmFloat Width
    w0)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_And Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo
        WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    WasmTypeTag t -> WasmInstr a (t : t : pre) (t : pre)
    WasmAnd
        CLabel
    lbl
        (Width -> CmmType
    cmmBits Width
    w0)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_Or Width
    w0) [CmmExpr]
    xs = (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    WasmTypeTag t -> WasmInstr a (t : t : pre) (t : pre)
    WasmOr CLabel
    lbl (Width -> CmmType
    cmmBits Width
    w0) [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_Xor Width
    w0) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t :: WasmType).
     WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre))
    -> CLabel
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Bin_Homo
        WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (pre :: [WasmType]) (t :: WasmType).
    WasmTypeTag t -> WasmInstr w (t : t : pre) (t : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    WasmTypeTag t -> WasmInstr a (t : t : pre) (t : pre)
    WasmXor
        CLabel
    lbl
        (Width -> CmmType
    cmmBits Width
    w0)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_Not Width
    w0) [CmmExpr
    x] =
      CLabel -> MachOp -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel -> MachOp -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmMachOp
        CLabel
    lbl
        (Width -> MachOp
    MO_Xor Width
    w0)
        [CmmExpr
    x, CmmLit -> CmmExpr
    CmmLit (CmmLit -> CmmExpr) -> CmmLit -> CmmExpr
    forall a b. (a -> b) -> a -> b
    $ Integer -> Width -> CmmLit
    CmmInt (Width -> Integer
    widthMax Width
    w0) Width
    w0]
    lower_CmmMachOp CLabel
    lbl (MO_Shl Width
    w0) [CmmExpr]
    xs = CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Shl CLabel
    lbl Width
    w0 [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_U_Shr Width
    w0) [CmmExpr]
    xs = CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_U_Shr CLabel
    lbl Width
    w0 [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_S_Shr Width
    w0) [CmmExpr]
    xs = CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_S_Shr CLabel
    lbl Width
    w0 [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_SF_Conv Width
    w0 Width
    w1) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t0 :: WasmType) (t1 :: WasmType).
     WasmTypeTag t0
     -> WasmTypeTag t1 -> WasmInstr w (t0 : pre) (t1 : pre))
    -> CLabel
    -> CmmType
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t0 :: WasmType) (t1 :: WasmType).
     WasmTypeTag t0
     -> WasmTypeTag t1 -> WasmInstr w (t0 : pre) (t1 : pre))
    -> CLabel
    -> CmmType
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Un_Conv
        (Signage
    -> WasmTypeTag t0
    -> WasmTypeTag t1
    -> WasmInstr w (t0 : pre) (t1 : pre)
    forall (t0 :: WasmType) (t1 :: WasmType) (a :: WasmType)
           (pre :: [WasmType]).
    Signage
    -> WasmTypeTag t0
    -> WasmTypeTag t1
    -> WasmInstr a (t0 : pre) (t1 : pre)
    WasmConvert Signage
    Signed)
        CLabel
    lbl
        (Width -> CmmType
    cmmBits Width
    w0)
        (Width -> CmmType
    cmmFloat Width
    w1)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_FS_Conv Width
    w0 Width
    w1) [CmmExpr]
    xs =
      (forall (pre :: [WasmType]) (t0 :: WasmType) (t1 :: WasmType).
     WasmTypeTag t0
     -> WasmTypeTag t1 -> WasmInstr w (t0 : pre) (t1 : pre))
    -> CLabel
    -> CmmType
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    (forall (pre :: [WasmType]) (t0 :: WasmType) (t1 :: WasmType).
     WasmTypeTag t0
     -> WasmTypeTag t1 -> WasmInstr w (t0 : pre) (t1 : pre))
    -> CLabel
    -> CmmType
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_Un_Conv
        (Signage
    -> WasmTypeTag t0
    -> WasmTypeTag t1
    -> WasmInstr w (t0 : pre) (t1 : pre)
    forall (t0 :: WasmType) (t1 :: WasmType) (a :: WasmType)
           (pre :: [WasmType]).
    Signage
    -> WasmTypeTag t0
    -> WasmTypeTag t1
    -> WasmInstr a (t0 : pre) (t1 : pre)
    WasmTruncSat Signage
    Signed)
        CLabel
    lbl
        (Width -> CmmType
    cmmFloat Width
    w0)
        (Width -> CmmType
    cmmBits Width
    w1)
        [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_SS_Conv Width
    w0 Width
    w1) [CmmExpr]
    xs = CLabel
    -> Width -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel
    -> Width -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_SS_Conv CLabel
    lbl Width
    w0 Width
    w1 [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_UU_Conv Width
    w0 Width
    w1) [CmmExpr]
    xs = CLabel
    -> Width -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel
    -> Width -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_UU_Conv CLabel
    lbl Width
    w0 Width
    w1 [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_XX_Conv Width
    w0 Width
    w1) [CmmExpr]
    xs = CLabel
    -> Width -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel
    -> Width -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_UU_Conv CLabel
    lbl Width
    w0 Width
    w1 [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    lbl (MO_FF_Conv Width
    w0 Width
    w1) [CmmExpr]
    xs = CLabel
    -> Width -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel
    -> Width -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_MO_FF_Conv CLabel
    lbl Width
    w0 Width
    w1 [CmmExpr]
    xs
    lower_CmmMachOp CLabel
    _ MachOp
    mop [CmmExpr]
    _ =
      String -> SDoc -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. HasCallStack => String -> SDoc -> a
    pprPanic String
    "lower_CmmMachOp: unreachable" (SDoc -> WasmCodeGenM w (SomeWasmExpr w))
    -> SDoc -> WasmCodeGenM w (SomeWasmExpr w)
    forall a b. (a -> b) -> a -> b
    $
        [SDoc] -> SDoc
    forall doc. IsDoc doc => [doc] -> doc
    vcat [ String -> SDoc
    forall doc. IsLine doc => String -> doc
    text String
    "offending MachOp:" SDoc -> SDoc -> SDoc
    forall doc. IsLine doc => doc -> doc -> doc
    <+> MachOp -> SDoc
    pprMachOp MachOp
    mop ]

    -- | Lower a 'CmmLit'. Note that we don't emit 'f32.const' or
    -- 'f64.const' for the time being, and instead emit their relative bit
    -- pattern as int literals, then use an reinterpret cast. This is
    -- simpler than dealing with textual representation of floating point
    -- values.
    lower_CmmLit :: CmmLit -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmLit :: forall (w :: WasmType). CmmLit -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmLit CmmLit
    lit = do
      ty_word <- WasmCodeGenM w (WasmTypeTag w)
    forall (w :: WasmType). WasmCodeGenM w (WasmTypeTag w)
    wasmWordTypeM
      case lit of
        CmmInt Integer
    i Width
    w -> case CmmType -> SomeWasmType
    someWasmTypeFromCmmType (Width -> CmmType
    cmmBits Width
    w) of
          SomeWasmType WasmTypeTag t
    ty ->
            SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w))
    -> SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w)
    forall a b. (a -> b) -> a -> b
    $
              WasmTypeTag t -> WasmExpr w t -> SomeWasmExpr w
    forall (t :: WasmType) (w :: WasmType).
    WasmTypeTag t -> WasmExpr w t -> SomeWasmExpr w
    SomeWasmExpr WasmTypeTag t
    ty (WasmExpr w t -> SomeWasmExpr w) -> WasmExpr w t -> SomeWasmExpr w
    forall a b. (a -> b) -> a -> b
    $
                (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    forall (w :: WasmType) (t :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    WasmExpr ((forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
     -> WasmExpr w t)
    -> (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    forall a b. (a -> b) -> a -> b
    $
                  WasmTypeTag t -> Integer -> WasmInstr w pre (t : pre)
    forall (t :: WasmType) (a :: WasmType) (b :: [WasmType]).
    WasmTypeTag t -> Integer -> WasmInstr a b (t : b)
    WasmConst WasmTypeTag t
    ty (Integer -> WasmInstr w pre (t : pre))
    -> Integer -> WasmInstr w pre (t : pre)
    forall a b. (a -> b) -> a -> b
    $
                    Width -> Integer -> Integer
    narrowU Width
    w Integer
    i
        CmmFloat Rational
    f Width
    W32 ->
          SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w))
    -> SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w)
    forall a b. (a -> b) -> a -> b
    $
            WasmTypeTag 'F32 -> WasmExpr w 'F32 -> SomeWasmExpr w
    forall (t :: WasmType) (w :: WasmType).
    WasmTypeTag t -> WasmExpr w t -> SomeWasmExpr w
    SomeWasmExpr WasmTypeTag 'F32
    TagF32 (WasmExpr w 'F32 -> SomeWasmExpr w)
    -> WasmExpr w 'F32 -> SomeWasmExpr w
    forall a b. (a -> b) -> a -> b
    $
              (forall (pre :: [WasmType]). WasmInstr w pre ('F32 : pre))
    -> WasmExpr w 'F32
    forall (w :: WasmType) (t :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    WasmExpr ((forall (pre :: [WasmType]). WasmInstr w pre ('F32 : pre))
     -> WasmExpr w 'F32)
    -> (forall (pre :: [WasmType]). WasmInstr w pre ('F32 : pre))
    -> WasmExpr w 'F32
    forall a b. (a -> b) -> a -> b
    $
                WasmTypeTag 'I32 -> Integer -> WasmInstr w pre ('I32 : pre)
    forall (t :: WasmType) (a :: WasmType) (b :: [WasmType]).
    WasmTypeTag t -> Integer -> WasmInstr a b (t : b)
    WasmConst
                  WasmTypeTag 'I32
    TagI32
                  (Word32 -> Integer
    forall a. Integral a => a -> Integer
    toInteger (Word32 -> Integer) -> Word32 -> Integer
    forall a b. (a -> b) -> a -> b
    $ Float -> Word32
    castFloatToWord32 (Float -> Word32) -> Float -> Word32
    forall a b. (a -> b) -> a -> b
    $ Rational -> Float
    forall a. Fractional a => Rational -> a
    fromRational Rational
    f)
                  WasmInstr w pre ('I32 : pre)
    -> WasmInstr w ('I32 : pre) ('F32 : pre)
    -> WasmInstr w pre ('F32 : pre)
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmTypeTag 'I32
    -> WasmTypeTag 'F32 -> WasmInstr w ('I32 : pre) ('F32 : pre)
    forall (t0 :: WasmType) (t1 :: WasmType) (a :: WasmType)
           (pre :: [WasmType]).
    WasmTypeTag t0
    -> WasmTypeTag t1 -> WasmInstr a (t0 : pre) (t1 : pre)
    WasmReinterpret WasmTypeTag 'I32
    TagI32 WasmTypeTag 'F32
    TagF32
        CmmFloat Rational
    f Width
    W64 ->
          SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w))
    -> SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w)
    forall a b. (a -> b) -> a -> b
    $
            WasmTypeTag 'F64 -> WasmExpr w 'F64 -> SomeWasmExpr w
    forall (t :: WasmType) (w :: WasmType).
    WasmTypeTag t -> WasmExpr w t -> SomeWasmExpr w
    SomeWasmExpr WasmTypeTag 'F64
    TagF64 (WasmExpr w 'F64 -> SomeWasmExpr w)
    -> WasmExpr w 'F64 -> SomeWasmExpr w
    forall a b. (a -> b) -> a -> b
    $
              (forall (pre :: [WasmType]). WasmInstr w pre ('F64 : pre))
    -> WasmExpr w 'F64
    forall (w :: WasmType) (t :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    WasmExpr ((forall (pre :: [WasmType]). WasmInstr w pre ('F64 : pre))
     -> WasmExpr w 'F64)
    -> (forall (pre :: [WasmType]). WasmInstr w pre ('F64 : pre))
    -> WasmExpr w 'F64
    forall a b. (a -> b) -> a -> b
    $
                WasmTypeTag 'I64 -> Integer -> WasmInstr w pre ('I64 : pre)
    forall (t :: WasmType) (a :: WasmType) (b :: [WasmType]).
    WasmTypeTag t -> Integer -> WasmInstr a b (t : b)
    WasmConst
                  WasmTypeTag 'I64
    TagI64
                  (Word64 -> Integer
    forall a. Integral a => a -> Integer
    toInteger (Word64 -> Integer) -> Word64 -> Integer
    forall a b. (a -> b) -> a -> b
    $ Double -> Word64
    castDoubleToWord64 (Double -> Word64) -> Double -> Word64
    forall a b. (a -> b) -> a -> b
    $ Rational -> Double
    forall a. Fractional a => Rational -> a
    fromRational Rational
    f)
                  WasmInstr w pre ('I64 : pre)
    -> WasmInstr w ('I64 : pre) ('F64 : pre)
    -> WasmInstr w pre ('F64 : pre)
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmTypeTag 'I64
    -> WasmTypeTag 'F64 -> WasmInstr w ('I64 : pre) ('F64 : pre)
    forall (t0 :: WasmType) (t1 :: WasmType) (a :: WasmType)
           (pre :: [WasmType]).
    WasmTypeTag t0
    -> WasmTypeTag t1 -> WasmInstr a (t0 : pre) (t1 : pre)
    WasmReinterpret WasmTypeTag 'I64
    TagI64 WasmTypeTag 'F64
    TagF64
        CmmLabel CLabel
    lbl' -> do
          CLabel -> WasmCodeGenM w ()
    forall (w :: WasmType). CLabel -> WasmCodeGenM w ()
    onAnySym CLabel
    lbl'
          let sym :: SymName
    sym = CLabel -> SymName
    symNameFromCLabel CLabel
    lbl'
          SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w))
    -> SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w)
    forall a b. (a -> b) -> a -> b
    $ WasmTypeTag w -> WasmExpr w w -> SomeWasmExpr w
    forall (t :: WasmType) (w :: WasmType).
    WasmTypeTag t -> WasmExpr w t -> SomeWasmExpr w
    SomeWasmExpr WasmTypeTag w
    ty_word (WasmExpr w w -> SomeWasmExpr w) -> WasmExpr w w -> SomeWasmExpr w
    forall a b. (a -> b) -> a -> b
    $ (forall (pre :: [WasmType]). WasmInstr w pre (w : pre))
    -> WasmExpr w w
    forall (w :: WasmType) (t :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    WasmExpr ((forall (pre :: [WasmType]). WasmInstr w pre (w : pre))
     -> WasmExpr w w)
    -> (forall (pre :: [WasmType]). WasmInstr w pre (w : pre))
    -> WasmExpr w w
    forall a b. (a -> b) -> a -> b
    $ SymName -> WasmInstr w pre (w : pre)
    forall (a :: WasmType) (b :: [WasmType]).
    SymName -> WasmInstr a b (a : b)
    WasmSymConst SymName
    sym
        CmmLabelOff CLabel
    lbl' Int
    o -> do
          CLabel -> WasmCodeGenM w ()
    forall (w :: WasmType). CLabel -> WasmCodeGenM w ()
    onAnySym CLabel
    lbl'
          let sym :: SymName
    sym = CLabel -> SymName
    symNameFromCLabel CLabel
    lbl'
          SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w))
    -> SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w)
    forall a b. (a -> b) -> a -> b
    $
            WasmTypeTag w -> WasmExpr w w -> SomeWasmExpr w
    forall (t :: WasmType) (w :: WasmType).
    WasmTypeTag t -> WasmExpr w t -> SomeWasmExpr w
    SomeWasmExpr WasmTypeTag w
    ty_word (WasmExpr w w -> SomeWasmExpr w) -> WasmExpr w w -> SomeWasmExpr w
    forall a b. (a -> b) -> a -> b
    $
              (forall (pre :: [WasmType]). WasmInstr w pre (w : pre))
    -> WasmExpr w w
    forall (w :: WasmType) (t :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    WasmExpr ((forall (pre :: [WasmType]). WasmInstr w pre (w : pre))
     -> WasmExpr w w)
    -> (forall (pre :: [WasmType]). WasmInstr w pre (w : pre))
    -> WasmExpr w w
    forall a b. (a -> b) -> a -> b
    $
                SymName -> WasmInstr w pre (w : pre)
    forall (a :: WasmType) (b :: [WasmType]).
    SymName -> WasmInstr a b (a : b)
    WasmSymConst SymName
    sym
                  WasmInstr w pre (w : pre)
    -> WasmInstr w (w : pre) (w : w : pre)
    -> WasmInstr w pre (w : w : pre)
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmTypeTag w -> Integer -> WasmInstr w (w : pre) (w : w : pre)
    forall (t :: WasmType) (a :: WasmType) (b :: [WasmType]).
    WasmTypeTag t -> Integer -> WasmInstr a b (t : b)
    WasmConst WasmTypeTag w
    ty_word (Int -> Integer
    forall a. Integral a => a -> Integer
    toInteger Int
    o)
                  WasmInstr w pre (w : w : pre)
    -> WasmInstr w (w : w : pre) (w : pre) -> WasmInstr w pre (w : pre)
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmTypeTag w -> WasmInstr w (w : w : pre) (w : pre)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    WasmTypeTag t -> WasmInstr a (t : t : pre) (t : pre)
    WasmAdd WasmTypeTag w
    ty_word
        CmmBlock BlockId
    bid -> CmmLit -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType). CmmLit -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmLit (CmmLit -> WasmCodeGenM w (SomeWasmExpr w))
    -> CmmLit -> WasmCodeGenM w (SomeWasmExpr w)
    forall a b. (a -> b) -> a -> b
    $ CLabel -> CmmLit
    CmmLabel (CLabel -> CmmLit) -> CLabel -> CmmLit
    forall a b. (a -> b) -> a -> b
    $ BlockId -> CLabel
    infoTblLbl BlockId
    bid
        CmmLit
    _ -> String -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_CmmLit: unreachable"

    --  | Lower a 'CmmReg'. Some of the logic here wouldn't be needed if
    --  we have run 'fixStgRegisters' on the wasm NCG's input Cmm, but we
    --  haven't run it yet for certain reasons.
    lower_CmmReg :: CLabel -> CmmReg -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmReg :: forall (w :: WasmType).
    CLabel -> CmmReg -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmReg CLabel
    _ (CmmLocal LocalReg
    reg) = do
      (reg_i, SomeWasmType ty) <- LocalReg -> WasmCodeGenM w (Int, SomeWasmType)
    forall (w :: WasmType).
    LocalReg -> WasmCodeGenM w (Int, SomeWasmType)
    onCmmLocalReg LocalReg
    reg
      pure $ SomeWasmExpr ty $ WasmExpr $ WasmLocalGet ty reg_i
    lower_CmmReg CLabel
    lbl (CmmGlobal (GlobalRegUse GlobalReg
    greg CmmType
    reg_use_ty)) = do
      ty_word <- WasmCodeGenM w (WasmTypeTag w)
    forall (w :: WasmType). WasmCodeGenM w (WasmTypeTag w)
    wasmWordTypeM
      ty_word_cmm <- wasmWordCmmTypeM
      case greg of
        GlobalReg
    EagerBlackholeInfo ->
          SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w))
    -> SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w)
    forall a b. (a -> b) -> a -> b
    $
            WasmTypeTag w -> WasmExpr w w -> SomeWasmExpr w
    forall (t :: WasmType) (w :: WasmType).
    WasmTypeTag t -> WasmExpr w t -> SomeWasmExpr w
    SomeWasmExpr WasmTypeTag w
    ty_word (WasmExpr w w -> SomeWasmExpr w) -> WasmExpr w w -> SomeWasmExpr w
    forall a b. (a -> b) -> a -> b
    $
              (forall (pre :: [WasmType]). WasmInstr w pre (w : pre))
    -> WasmExpr w w
    forall (w :: WasmType) (t :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    WasmExpr ((forall (pre :: [WasmType]). WasmInstr w pre (w : pre))
     -> WasmExpr w w)
    -> (forall (pre :: [WasmType]). WasmInstr w pre (w : pre))
    -> WasmExpr w w
    forall a b. (a -> b) -> a -> b
    $
                SymName -> WasmInstr w pre (w : pre)
    forall (a :: WasmType) (b :: [WasmType]).
    SymName -> WasmInstr a b (a : b)
    WasmSymConst SymName
    "__stg_EAGER_BLACKHOLE_info"
        GlobalReg
    GCEnter1 -> do
          SymName -> [CmmType] -> [CmmType] -> WasmCodeGenM w ()
    forall (w :: WasmType).
    SymName -> [CmmType] -> [CmmType] -> WasmCodeGenM w ()
    onFuncSym SymName
    "__stg_gc_enter_1" [] [CmmType
    ty_word_cmm]
          SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w))
    -> SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w)
    forall a b. (a -> b) -> a -> b
    $ WasmTypeTag w -> WasmExpr w w -> SomeWasmExpr w
    forall (t :: WasmType) (w :: WasmType).
    WasmTypeTag t -> WasmExpr w t -> SomeWasmExpr w
    SomeWasmExpr WasmTypeTag w
    ty_word (WasmExpr w w -> SomeWasmExpr w) -> WasmExpr w w -> SomeWasmExpr w
    forall a b. (a -> b) -> a -> b
    $ (forall (pre :: [WasmType]). WasmInstr w pre (w : pre))
    -> WasmExpr w w
    forall (w :: WasmType) (t :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    WasmExpr ((forall (pre :: [WasmType]). WasmInstr w pre (w : pre))
     -> WasmExpr w w)
    -> (forall (pre :: [WasmType]). WasmInstr w pre (w : pre))
    -> WasmExpr w w
    forall a b. (a -> b) -> a -> b
    $ SymName -> WasmInstr w pre (w : pre)
    forall (a :: WasmType) (b :: [WasmType]).
    SymName -> WasmInstr a b (a : b)
    WasmSymConst SymName
    "__stg_gc_enter_1"
        GlobalReg
    GCFun -> do
          SymName -> [CmmType] -> [CmmType] -> WasmCodeGenM w ()
    forall (w :: WasmType).
    SymName -> [CmmType] -> [CmmType] -> WasmCodeGenM w ()
    onFuncSym SymName
    "__stg_gc_fun" [] [CmmType
    ty_word_cmm]
          SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w))
    -> SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w)
    forall a b. (a -> b) -> a -> b
    $ WasmTypeTag w -> WasmExpr w w -> SomeWasmExpr w
    forall (t :: WasmType) (w :: WasmType).
    WasmTypeTag t -> WasmExpr w t -> SomeWasmExpr w
    SomeWasmExpr WasmTypeTag w
    ty_word (WasmExpr w w -> SomeWasmExpr w) -> WasmExpr w w -> SomeWasmExpr w
    forall a b. (a -> b) -> a -> b
    $ (forall (pre :: [WasmType]). WasmInstr w pre (w : pre))
    -> WasmExpr w w
    forall (w :: WasmType) (t :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    WasmExpr ((forall (pre :: [WasmType]). WasmInstr w pre (w : pre))
     -> WasmExpr w w)
    -> (forall (pre :: [WasmType]). WasmInstr w pre (w : pre))
    -> WasmExpr w w
    forall a b. (a -> b) -> a -> b
    $ SymName -> WasmInstr w pre (w : pre)
    forall (a :: WasmType) (b :: [WasmType]).
    SymName -> WasmInstr a b (a : b)
    WasmSymConst SymName
    "__stg_gc_fun"
        GlobalReg
    BaseReg -> do
          platform <- WasmCodeGenM w Platform
    forall (w :: WasmType). WasmCodeGenM w Platform
    wasmPlatformM
          lower_CmmExpr lbl $ regTableOffset platform 0
        GlobalReg
    _other
          | Just (SymName
    sym_global, SomeWasmType WasmTypeTag t
    ty) <-
              WasmTypeTag w -> GlobalReg -> Maybe GlobalInfo
    forall (w :: WasmType).
    WasmTypeTag w -> GlobalReg -> Maybe GlobalInfo
    globalInfoFromCmmGlobalReg WasmTypeTag w
    ty_word GlobalReg
    greg ->
              SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w))
    -> SomeWasmExpr w -> WasmCodeGenM w (SomeWasmExpr w)
    forall a b. (a -> b) -> a -> b
    $ WasmTypeTag t -> WasmExpr w t -> SomeWasmExpr w
    forall (t :: WasmType) (w :: WasmType).
    WasmTypeTag t -> WasmExpr w t -> SomeWasmExpr w
    SomeWasmExpr WasmTypeTag t
    ty (WasmExpr w t -> SomeWasmExpr w) -> WasmExpr w t -> SomeWasmExpr w
    forall a b. (a -> b) -> a -> b
    $ (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    forall (w :: WasmType) (t :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    WasmExpr ((forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
     -> WasmExpr w t)
    -> (forall (pre :: [WasmType]). WasmInstr w pre (t : pre))
    -> WasmExpr w t
    forall a b. (a -> b) -> a -> b
    $ WasmTypeTag t -> SymName -> WasmInstr w pre (t : pre)
    forall (t :: WasmType) (a :: WasmType) (b :: [WasmType]).
    WasmTypeTag t -> SymName -> WasmInstr a b (t : b)
    WasmGlobalGet WasmTypeTag t
    ty SymName
    sym_global
          | Bool
    otherwise -> do
              platform <- WasmCodeGenM w Platform
    forall (w :: WasmType). WasmCodeGenM w Platform
    wasmPlatformM
              case someWasmTypeFromCmmType reg_use_ty of
                SomeWasmType WasmTypeTag t
    ty -> do
                  (WasmExpr ptr_instr, o) <-
                    CLabel -> CmmExpr -> WasmCodeGenM w (WasmExpr w w, Int)
    forall (w :: WasmType).
    CLabel -> CmmExpr -> WasmCodeGenM w (WasmExpr w w, Int)
    lower_CmmExpr_Ptr CLabel
    lbl (CmmExpr -> WasmCodeGenM w (WasmExpr w w, Int))
    -> CmmExpr -> WasmCodeGenM w (WasmExpr w w, Int)
    forall a b. (a -> b) -> a -> b
    $
                      Platform -> GlobalReg -> CmmExpr
    get_GlobalReg_addr Platform
    platform GlobalReg
    greg
                  pure $
                    SomeWasmExpr ty $
                      WasmExpr $
                        ptr_instr
                          `WasmConcat` WasmLoad
                            ty
                            Nothing
                            Unsigned
                            o
                            NaturallyAligned

    -- | Lower a 'CmmRegOff'.
    lower_CmmRegOff :: CLabel -> CmmReg -> Int -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmRegOff :: forall (w :: WasmType).
    CLabel -> CmmReg -> Int -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmRegOff CLabel
    lbl CmmReg
    reg Int
    0 = CLabel -> CmmReg -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel -> CmmReg -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmReg CLabel
    lbl CmmReg
    reg
    lower_CmmRegOff CLabel
    lbl CmmReg
    reg Int
    o = do
      SomeWasmExpr ty (WasmExpr reg_instr) <- CLabel -> CmmReg -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel -> CmmReg -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmReg CLabel
    lbl CmmReg
    reg
      pure $
        SomeWasmExpr ty $
          WasmExpr $
            reg_instr
              `WasmConcat` WasmConst
                ty
                (toInteger o)
              `WasmConcat` WasmAdd ty

    -- | Lower a 'CmmLoad', passing in the expected wasm representation
    -- type, and also the Cmm type (which contains width info needed for
    -- memory narrowing).
    --
    -- The Cmm type system doesn't track signedness, so all 'CmmLoad's are
    -- unsigned loads. However, as an optimization, we do emit signed
    -- loads when a 'CmmLoad' result is immediately used as a 'MO_SS_Conv'
    -- operand.
    lower_CmmLoad_Typed ::
      CLabel ->
      CmmExpr ->
      WasmTypeTag t ->
      CmmType ->
      AlignmentSpec ->
      WasmCodeGenM w (WasmExpr w t)
    lower_CmmLoad_Typed :: forall (t :: WasmType) (w :: WasmType).
    CLabel
    -> CmmExpr
    -> WasmTypeTag t
    -> CmmType
    -> AlignmentSpec
    -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmLoad_Typed CLabel
    lbl CmmExpr
    ptr_expr WasmTypeTag t
    ty CmmType
    ty_cmm AlignmentSpec
    align = do
      (WasmExpr ptr_instr, o) <- CLabel -> CmmExpr -> WasmCodeGenM w (WasmExpr w w, Int)
    forall (w :: WasmType).
    CLabel -> CmmExpr -> WasmCodeGenM w (WasmExpr w w, Int)
    lower_CmmExpr_Ptr CLabel
    lbl CmmExpr
    ptr_expr
      pure $
        WasmExpr $
          ptr_instr
            `WasmConcat` WasmLoad
              ty
              (wasmMemoryNarrowing ty ty_cmm)
              Unsigned
              o
              align

    -- | Lower a 'CmmLoad'.
    lower_CmmLoad ::
      CLabel ->
      CmmExpr ->
      CmmType ->
      AlignmentSpec ->
      WasmCodeGenM
        w
        (SomeWasmExpr w)
    lower_CmmLoad :: forall (w :: WasmType).
    CLabel
    -> CmmExpr
    -> CmmType
    -> AlignmentSpec
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmLoad CLabel
    lbl CmmExpr
    ptr_expr CmmType
    ty_cmm AlignmentSpec
    align = case CmmType -> SomeWasmType
    someWasmTypeFromCmmType CmmType
    ty_cmm of
      SomeWasmType WasmTypeTag t
    ty ->
        WasmTypeTag t -> WasmExpr w t -> SomeWasmExpr w
    forall (t :: WasmType) (w :: WasmType).
    WasmTypeTag t -> WasmExpr w t -> SomeWasmExpr w
    SomeWasmExpr WasmTypeTag t
    ty (WasmExpr w t -> SomeWasmExpr w)
    -> WasmCodeGenM w (WasmExpr w t) -> WasmCodeGenM w (SomeWasmExpr w)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CLabel
    -> CmmExpr
    -> WasmTypeTag t
    -> CmmType
    -> AlignmentSpec
    -> WasmCodeGenM w (WasmExpr w t)
    forall (t :: WasmType) (w :: WasmType).
    CLabel
    -> CmmExpr
    -> WasmTypeTag t
    -> CmmType
    -> AlignmentSpec
    -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmLoad_Typed CLabel
    lbl CmmExpr
    ptr_expr WasmTypeTag t
    ty CmmType
    ty_cmm AlignmentSpec
    align

    -- | Lower a 'CmmExpr'.
    lower_CmmExpr :: CLabel -> CmmExpr -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmExpr :: forall (w :: WasmType).
    CLabel -> CmmExpr -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmExpr CLabel
    lbl CmmExpr
    expr = case CmmExpr
    expr of
      CmmLit CmmLit
    lit -> CmmLit -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType). CmmLit -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmLit CmmLit
    lit
      CmmLoad CmmExpr
    ptr_expr CmmType
    ty_cmm AlignmentSpec
    align -> CLabel
    -> CmmExpr
    -> CmmType
    -> AlignmentSpec
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel
    -> CmmExpr
    -> CmmType
    -> AlignmentSpec
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmLoad CLabel
    lbl CmmExpr
    ptr_expr CmmType
    ty_cmm AlignmentSpec
    align
      CmmReg CmmReg
    reg -> CLabel -> CmmReg -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel -> CmmReg -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmReg CLabel
    lbl CmmReg
    reg
      CmmRegOff CmmReg
    reg Int
    o -> CLabel -> CmmReg -> Int -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel -> CmmReg -> Int -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmRegOff CLabel
    lbl CmmReg
    reg Int
    o
      CmmMachOp MachOp
    op [CmmExpr]
    xs -> CLabel -> MachOp -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel -> MachOp -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmMachOp CLabel
    lbl MachOp
    op [CmmExpr]
    xs
      CmmExpr
    _ -> String -> WasmCodeGenM w (SomeWasmExpr w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_CmmExpr: unreachable"

    -- | Lower a 'CmmExpr', passing in the expected wasm representation
    -- type.
    lower_CmmExpr_Typed ::
      CLabel ->
      WasmTypeTag t ->
      CmmExpr ->
      WasmCodeGenM
        w
        (WasmExpr w t)
    lower_CmmExpr_Typed :: forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag t
    ty CmmExpr
    expr = do
      SomeWasmExpr ty' r <- CLabel -> CmmExpr -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel -> CmmExpr -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmExpr CLabel
    lbl CmmExpr
    expr
      if
          | Just Refl <- ty' `testEquality` ty -> pure r
          | otherwise -> panic "lower_CmmExpr_Typed: unreachable"

    -- | Lower a 'CmmExpr' as a pointer, returning the pair of base
    -- pointer and non-negative offset.
    lower_CmmExpr_Ptr :: CLabel -> CmmExpr -> WasmCodeGenM w (WasmExpr w w, Int)
    lower_CmmExpr_Ptr :: forall (w :: WasmType).
    CLabel -> CmmExpr -> WasmCodeGenM w (WasmExpr w w, Int)
    lower_CmmExpr_Ptr CLabel
    lbl CmmExpr
    ptr = do
      ty_word <- WasmCodeGenM w (WasmTypeTag w)
    forall (w :: WasmType). WasmCodeGenM w (WasmTypeTag w)
    wasmWordTypeM
      case ptr of
        CmmLit (CmmLabelOff CLabel
    lbl Int
    o)
          | Int
    o Int -> Int -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Int
    0 -> do
              instrs <-
                CLabel -> WasmTypeTag w -> CmmExpr -> WasmCodeGenM w (WasmExpr w w)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed
                  CLabel
    lbl
                  WasmTypeTag w
    ty_word
                  (CmmLit -> CmmExpr
    CmmLit (CmmLit -> CmmExpr) -> CmmLit -> CmmExpr
    forall a b. (a -> b) -> a -> b
    $ CLabel -> CmmLit
    CmmLabel CLabel
    lbl)
              pure (instrs, o)
        CmmMachOp (MO_Add Width
    _) [CmmExpr
    base, CmmLit (CmmInt Integer
    o Width
    _)]
          | Integer
    o Integer -> Integer -> Bool
    forall a. Ord a => a -> a -> Bool
    >= Integer
    0 -> do
              instrs <- CLabel -> WasmTypeTag w -> CmmExpr -> WasmCodeGenM w (WasmExpr w w)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag w
    ty_word CmmExpr
    base
              pure (instrs, fromInteger o)
        CmmExpr
    _ -> do
          instrs <- CLabel -> WasmTypeTag w -> CmmExpr -> WasmCodeGenM w (WasmExpr w w)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag w
    ty_word CmmExpr
    ptr
          pure (instrs, 0)

    -- | Push a series of values onto the wasm value stack, returning the
    -- result stack type.
    type family
      WasmPushes (ts :: [WasmType]) (pre :: [WasmType]) ::
        [WasmType]
      where
      WasmPushes '[] pre = pre
      WasmPushes (t : ts) pre = WasmPushes ts (t : pre)

    -- | Push the arguments onto the wasm value stack before a ccall.
    data SomeWasmPreCCall w where
      SomeWasmPreCCall ::
        TypeList ts ->
        (forall pre. WasmInstr w pre (WasmPushes ts pre)) ->
        SomeWasmPreCCall w

    -- | Pop the results into locals after a ccall.
    data SomeWasmPostCCall w where
      SomeWasmPostCCall ::
        TypeList ts ->
        (forall post. WasmInstr w (WasmPushes ts post) post) ->
        SomeWasmPostCCall w

    -- | Lower an unary homogeneous 'CallishMachOp' to a ccall.
    lower_CMO_Un_Homo ::
      CLabel ->
      SymName ->
      [CmmFormal] ->
      [CmmActual] ->
      WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo :: forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    op [LocalReg
    reg] [CmmExpr
    x] = do
      (ri, SomeWasmType ty) <- LocalReg -> WasmCodeGenM w (Int, SomeWasmType)
    forall (w :: WasmType).
    LocalReg -> WasmCodeGenM w (Int, SomeWasmType)
    onCmmLocalReg LocalReg
    reg
      WasmExpr x_instr <- lower_CmmExpr_Typed lbl ty x
      let ty_cmm = LocalReg -> CmmType
    localRegType LocalReg
    reg
      onFuncSym op [ty_cmm] [ty_cmm]
      pure $
        WasmStatements $
          x_instr `WasmConcat` WasmCCall op `WasmConcat` WasmLocalSet ty ri
    lower_CMO_Un_Homo CLabel
    _ SymName
    _ [LocalReg]
    _ [CmmExpr]
    _ = String -> WasmCodeGenM w (WasmStatements w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_CMO_Un_Homo: unreachable"

    -- | Lower a binary homogeneous 'CallishMachOp' to a ccall.
    lower_CMO_Bin_Homo ::
      CLabel ->
      SymName ->
      [CmmFormal] ->
      [CmmActual] ->
      WasmCodeGenM w (WasmStatements w)
    lower_CMO_Bin_Homo :: forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Bin_Homo CLabel
    lbl SymName
    op [LocalReg
    reg] [CmmExpr
    x, CmmExpr
    y] = do
      (ri, SomeWasmType ty) <- LocalReg -> WasmCodeGenM w (Int, SomeWasmType)
    forall (w :: WasmType).
    LocalReg -> WasmCodeGenM w (Int, SomeWasmType)
    onCmmLocalReg LocalReg
    reg
      WasmExpr x_instr <- lower_CmmExpr_Typed lbl ty x
      WasmExpr y_instr <- lower_CmmExpr_Typed lbl ty y
      let ty_cmm = LocalReg -> CmmType
    localRegType LocalReg
    reg
      onFuncSym op [ty_cmm, ty_cmm] [ty_cmm]
      pure $
        WasmStatements $
          x_instr
            `WasmConcat` y_instr
            `WasmConcat` WasmCCall op
            `WasmConcat` WasmLocalSet ty ri
    lower_CMO_Bin_Homo CLabel
    _ SymName
    _ [LocalReg]
    _ [CmmExpr]
    _ = String -> WasmCodeGenM w (WasmStatements w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_CMO_Bin_Homo: unreachable"

    -- | Lower a 'MO_UF_Conv' operation.
    lower_MO_UF_Conv ::
      CLabel ->
      Width ->
      [CmmFormal] ->
      [CmmActual] ->
      WasmCodeGenM w (WasmStatements w)
    lower_MO_UF_Conv :: forall (w :: WasmType).
    CLabel
    -> Width
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_MO_UF_Conv CLabel
    lbl Width
    W32 [LocalReg
    reg] [CmmExpr
    x] = do
      ri <- WasmTypeTag 'F32 -> LocalReg -> WasmCodeGenM w Int
    forall (t :: WasmType) (w :: WasmType).
    WasmTypeTag t -> LocalReg -> WasmCodeGenM w Int
    onCmmLocalReg_Typed WasmTypeTag 'F32
    TagF32 LocalReg
    reg
      SomeWasmExpr ty0 (WasmExpr x_instr) <- lower_CmmExpr lbl x
      pure $
        WasmStatements $
          x_instr
            `WasmConcat` WasmConvert Unsigned ty0 TagF32
            `WasmConcat` WasmLocalSet TagF32 ri
    lower_MO_UF_Conv CLabel
    lbl Width
    W64 [LocalReg
    reg] [CmmExpr
    x] = do
      ri <- WasmTypeTag 'F64 -> LocalReg -> WasmCodeGenM w Int
    forall (t :: WasmType) (w :: WasmType).
    WasmTypeTag t -> LocalReg -> WasmCodeGenM w Int
    onCmmLocalReg_Typed WasmTypeTag 'F64
    TagF64 LocalReg
    reg
      SomeWasmExpr ty0 (WasmExpr x_instr) <- lower_CmmExpr lbl x
      pure $
        WasmStatements $
          x_instr
            `WasmConcat` WasmConvert Unsigned ty0 TagF64
            `WasmConcat` WasmLocalSet TagF64 ri
    lower_MO_UF_Conv CLabel
    _ Width
    _ [LocalReg]
    _ [CmmExpr]
    _ = String -> WasmCodeGenM w (WasmStatements w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_MO_UF_Conv: unreachable"

    -- | Lower a 'MO_Cmpxchg' operation to inline assembly. Currently we
    -- target wasm without atomics and threads, so it's just lowered to
    -- regular memory loads and stores.
    lower_MO_Cmpxchg ::
      CLabel ->
      Width ->
      [CmmFormal] ->
      [CmmActual] ->
      WasmCodeGenM w (WasmStatements w)
    lower_MO_Cmpxchg :: forall (w :: WasmType).
    CLabel
    -> Width
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_MO_Cmpxchg CLabel
    lbl Width
    w0 [LocalReg
    reg] [CmmExpr
    ptr, CmmExpr
    expected, CmmExpr
    new] =
      case CmmType -> SomeWasmType
    someWasmTypeFromCmmType CmmType
    ty_cmm of
        SomeWasmType WasmTypeTag t
    ty -> do
          reg_i <- WasmTypeTag t -> LocalReg -> WasmCodeGenM w Int
    forall (t :: WasmType) (w :: WasmType).
    WasmTypeTag t -> LocalReg -> WasmCodeGenM w Int
    onCmmLocalReg_Typed WasmTypeTag t
    ty LocalReg
    reg
          let narrowing = WasmTypeTag t -> CmmType -> Maybe Int
    forall (t :: WasmType). WasmTypeTag t -> CmmType -> Maybe Int
    wasmMemoryNarrowing WasmTypeTag t
    ty CmmType
    ty_cmm
          (WasmExpr ptr_instr, o) <- lower_CmmExpr_Ptr lbl ptr
          WasmExpr expected_instr <- lower_CmmExpr_Typed lbl ty expected
          WasmExpr new_instr <- lower_CmmExpr_Typed lbl ty new
          pure $
            WasmStatements $
              ptr_instr
                `WasmConcat` WasmLoad ty narrowing Unsigned o NaturallyAligned
                `WasmConcat` WasmLocalTee ty reg_i
                `WasmConcat` expected_instr
                `WasmConcat` WasmEq ty
                `WasmConcat` WasmCond
                  ( ptr_instr
                      `WasmConcat` new_instr
                      `WasmConcat` WasmStore ty narrowing o NaturallyAligned
                  )
      where
        ty_cmm :: CmmType
    ty_cmm = Width -> CmmType
    cmmBits Width
    w0
    lower_MO_Cmpxchg CLabel
    _ Width
    _ [LocalReg]
    _ [CmmExpr]
    _ = String -> WasmCodeGenM w (WasmStatements w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_MO_Cmpxchg: unreachable"

    -- | Lower a 'CallishMachOp'.
    lower_CallishMachOp ::
      CLabel ->
      CallishMachOp ->
      [CmmFormal] ->
      [CmmActual] ->
      WasmCodeGenM w (WasmStatements w)
    lower_CallishMachOp :: forall (w :: WasmType).
    CLabel
    -> CallishMachOp
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F64_Pwr [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Bin_Homo CLabel
    lbl SymName
    "pow" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F64_Sin [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "sin" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F64_Cos [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "cos" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F64_Tan [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "tan" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F64_Sinh [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "sinh" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F64_Cosh [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "cosh" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F64_Tanh [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "tanh" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F64_Asin [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "asin" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F64_Acos [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "acos" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F64_Atan [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "atan" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F64_Asinh [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "asinh" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F64_Acosh [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "acosh" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F64_Atanh [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "atanh" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F64_Log [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "log" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F64_Log1P [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "log1p" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F64_Exp [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "exp" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F64_ExpM1 [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "expm1" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F64_Fabs [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "fabs" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F64_Sqrt [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "sqrt" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F32_Pwr [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Bin_Homo CLabel
    lbl SymName
    "powf" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F32_Sin [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "sinf" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F32_Cos [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "cosf" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F32_Tan [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "tanf" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F32_Sinh [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "sinhf" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F32_Cosh [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "coshf" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F32_Tanh [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "tanhf" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F32_Asin [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "asinf" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F32_Acos [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "acosf" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F32_Atan [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "atanf" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F32_Asinh [LocalReg]
    rs [CmmExpr]
    xs =
      CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "asinhf" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F32_Acosh [LocalReg]
    rs [CmmExpr]
    xs =
      CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "acoshf" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F32_Atanh [LocalReg]
    rs [CmmExpr]
    xs =
      CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "atanhf" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F32_Log [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "logf" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F32_Log1P [LocalReg]
    rs [CmmExpr]
    xs =
      CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "log1pf" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F32_Exp [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "expf" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F32_ExpM1 [LocalReg]
    rs [CmmExpr]
    xs =
      CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "expm1f" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F32_Fabs [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "fabsf" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_F32_Sqrt [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> SymName
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CMO_Un_Homo CLabel
    lbl SymName
    "sqrtf" [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl (MO_UF_Conv Width
    w0) [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> Width
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> Width
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_MO_UF_Conv CLabel
    lbl Width
    w0 [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    _ CallishMachOp
    MO_AcquireFence [LocalReg]
    _ [CmmExpr]
    _ = WasmStatements w -> WasmCodeGenM w (WasmStatements w)
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (WasmStatements w -> WasmCodeGenM w (WasmStatements w))
    -> WasmStatements w -> WasmCodeGenM w (WasmStatements w)
    forall a b. (a -> b) -> a -> b
    $ (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    forall (w :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    WasmStatements WasmInstr w pre pre
    forall (pre :: [WasmType]). WasmInstr w pre pre
    forall (a :: WasmType) (b :: [WasmType]). WasmInstr a b b
    WasmNop
    lower_CallishMachOp CLabel
    _ CallishMachOp
    MO_ReleaseFence [LocalReg]
    _ [CmmExpr]
    _ = WasmStatements w -> WasmCodeGenM w (WasmStatements w)
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (WasmStatements w -> WasmCodeGenM w (WasmStatements w))
    -> WasmStatements w -> WasmCodeGenM w (WasmStatements w)
    forall a b. (a -> b) -> a -> b
    $ (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    forall (w :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    WasmStatements WasmInstr w pre pre
    forall (pre :: [WasmType]). WasmInstr w pre pre
    forall (a :: WasmType) (b :: [WasmType]). WasmInstr a b b
    WasmNop
    lower_CallishMachOp CLabel
    _ CallishMachOp
    MO_SeqCstFence [LocalReg]
    _ [CmmExpr]
    _ = WasmStatements w -> WasmCodeGenM w (WasmStatements w)
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (WasmStatements w -> WasmCodeGenM w (WasmStatements w))
    -> WasmStatements w -> WasmCodeGenM w (WasmStatements w)
    forall a b. (a -> b) -> a -> b
    $ (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    forall (w :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    WasmStatements WasmInstr w pre pre
    forall (pre :: [WasmType]). WasmInstr w pre pre
    forall (a :: WasmType) (b :: [WasmType]). WasmInstr a b b
    WasmNop
    lower_CallishMachOp CLabel
    _ CallishMachOp
    MO_Touch [LocalReg]
    _ [CmmExpr]
    _ = WasmStatements w -> WasmCodeGenM w (WasmStatements w)
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (WasmStatements w -> WasmCodeGenM w (WasmStatements w))
    -> WasmStatements w -> WasmCodeGenM w (WasmStatements w)
    forall a b. (a -> b) -> a -> b
    $ (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    forall (w :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    WasmStatements WasmInstr w pre pre
    forall (pre :: [WasmType]). WasmInstr w pre pre
    forall (a :: WasmType) (b :: [WasmType]). WasmInstr a b b
    WasmNop
    lower_CallishMachOp CLabel
    _ (MO_Prefetch_Data {}) [LocalReg]
    _ [CmmExpr]
    _ = WasmStatements w -> WasmCodeGenM w (WasmStatements w)
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (WasmStatements w -> WasmCodeGenM w (WasmStatements w))
    -> WasmStatements w -> WasmCodeGenM w (WasmStatements w)
    forall a b. (a -> b) -> a -> b
    $ (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    forall (w :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    WasmStatements WasmInstr w pre pre
    forall (pre :: [WasmType]). WasmInstr w pre pre
    forall (a :: WasmType) (b :: [WasmType]). WasmInstr a b b
    WasmNop
    lower_CallishMachOp CLabel
    lbl (MO_Memcpy {}) [] [CmmExpr]
    xs = do
      ty_word_cmm <- WasmCodeGenM w CmmType
    forall (w :: WasmType). WasmCodeGenM w CmmType
    wasmWordCmmTypeM
      lower_CmmUnsafeForeignCall_Drop lbl "memcpy" ty_word_cmm xs
    lower_CallishMachOp CLabel
    lbl (MO_Memset {}) [] [CmmExpr]
    xs = do
      ty_word_cmm <- WasmCodeGenM w CmmType
    forall (w :: WasmType). WasmCodeGenM w CmmType
    wasmWordCmmTypeM
      lower_CmmUnsafeForeignCall_Drop lbl "memset" ty_word_cmm xs
    lower_CallishMachOp CLabel
    lbl (MO_Memmove {}) [] [CmmExpr]
    xs = do
      ty_word_cmm <- WasmCodeGenM w CmmType
    forall (w :: WasmType). WasmCodeGenM w CmmType
    wasmWordCmmTypeM
      lower_CmmUnsafeForeignCall_Drop lbl "memmove" ty_word_cmm xs
    lower_CallishMachOp CLabel
    lbl (MO_Memcmp {}) [LocalReg]
    rs [CmmExpr]
    xs =
      CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmUnsafeForeignCall
        CLabel
    lbl
        (SymName -> Either SymName CmmExpr
    forall a b. a -> Either a b
    Left SymName
    "memcmp")
        Maybe ([ForeignHint], [ForeignHint])
    forall a. Maybe a
    Nothing
        CmmReturnInfo
    CmmMayReturn
        [LocalReg]
    rs
        [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl (MO_PopCnt Width
    w0) [LocalReg]
    rs [CmmExpr]
    xs =
      CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmUnsafeForeignCall
        CLabel
    lbl
        (SymName -> Either SymName CmmExpr
    forall a b. a -> Either a b
    Left (SymName -> Either SymName CmmExpr)
    -> SymName -> Either SymName CmmExpr
    forall a b. (a -> b) -> a -> b
    $ String -> SymName
    forall a. IsString a => String -> a
    fromString (String -> SymName) -> String -> SymName
    forall a b. (a -> b) -> a -> b
    $ String
    "hs_popcnt" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> Int -> String
    forall a. Show a => a -> String
    show (Width -> Int
    widthInBits Width
    w0))
        Maybe ([ForeignHint], [ForeignHint])
    forall a. Maybe a
    Nothing
        CmmReturnInfo
    CmmMayReturn
        [LocalReg]
    rs
        [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl (MO_Pdep Width
    w0) [LocalReg]
    rs [CmmExpr]
    xs =
      CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmUnsafeForeignCall
        CLabel
    lbl
        (SymName -> Either SymName CmmExpr
    forall a b. a -> Either a b
    Left (SymName -> Either SymName CmmExpr)
    -> SymName -> Either SymName CmmExpr
    forall a b. (a -> b) -> a -> b
    $ String -> SymName
    forall a. IsString a => String -> a
    fromString (String -> SymName) -> String -> SymName
    forall a b. (a -> b) -> a -> b
    $ String
    "hs_pdep" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> Int -> String
    forall a. Show a => a -> String
    show (Width -> Int
    widthInBits Width
    w0))
        Maybe ([ForeignHint], [ForeignHint])
    forall a. Maybe a
    Nothing
        CmmReturnInfo
    CmmMayReturn
        [LocalReg]
    rs
        [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl (MO_Pext Width
    w0) [LocalReg]
    rs [CmmExpr]
    xs =
      CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmUnsafeForeignCall
        CLabel
    lbl
        (SymName -> Either SymName CmmExpr
    forall a b. a -> Either a b
    Left (SymName -> Either SymName CmmExpr)
    -> SymName -> Either SymName CmmExpr
    forall a b. (a -> b) -> a -> b
    $ String -> SymName
    forall a. IsString a => String -> a
    fromString (String -> SymName) -> String -> SymName
    forall a b. (a -> b) -> a -> b
    $ String
    "hs_pext" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> Int -> String
    forall a. Show a => a -> String
    show (Width -> Int
    widthInBits Width
    w0))
        Maybe ([ForeignHint], [ForeignHint])
    forall a. Maybe a
    Nothing
        CmmReturnInfo
    CmmMayReturn
        [LocalReg]
    rs
        [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl (MO_Clz Width
    w0) [LocalReg]
    rs [CmmExpr]
    xs =
      CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmUnsafeForeignCall
        CLabel
    lbl
        (SymName -> Either SymName CmmExpr
    forall a b. a -> Either a b
    Left (SymName -> Either SymName CmmExpr)
    -> SymName -> Either SymName CmmExpr
    forall a b. (a -> b) -> a -> b
    $ String -> SymName
    forall a. IsString a => String -> a
    fromString (String -> SymName) -> String -> SymName
    forall a b. (a -> b) -> a -> b
    $ String
    "hs_clz" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> Int -> String
    forall a. Show a => a -> String
    show (Width -> Int
    widthInBits Width
    w0))
        Maybe ([ForeignHint], [ForeignHint])
    forall a. Maybe a
    Nothing
        CmmReturnInfo
    CmmMayReturn
        [LocalReg]
    rs
        [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl (MO_Ctz Width
    w0) [LocalReg]
    rs [CmmExpr]
    xs =
      CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmUnsafeForeignCall
        CLabel
    lbl
        (SymName -> Either SymName CmmExpr
    forall a b. a -> Either a b
    Left (SymName -> Either SymName CmmExpr)
    -> SymName -> Either SymName CmmExpr
    forall a b. (a -> b) -> a -> b
    $ String -> SymName
    forall a. IsString a => String -> a
    fromString (String -> SymName) -> String -> SymName
    forall a b. (a -> b) -> a -> b
    $ String
    "hs_ctz" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> Int -> String
    forall a. Show a => a -> String
    show (Width -> Int
    widthInBits Width
    w0))
        Maybe ([ForeignHint], [ForeignHint])
    forall a. Maybe a
    Nothing
        CmmReturnInfo
    CmmMayReturn
        [LocalReg]
    rs
        [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl (MO_BSwap Width
    w0) [LocalReg]
    rs [CmmExpr]
    xs =
      CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmUnsafeForeignCall
        CLabel
    lbl
        (SymName -> Either SymName CmmExpr
    forall a b. a -> Either a b
    Left (SymName -> Either SymName CmmExpr)
    -> SymName -> Either SymName CmmExpr
    forall a b. (a -> b) -> a -> b
    $ String -> SymName
    forall a. IsString a => String -> a
    fromString (String -> SymName) -> String -> SymName
    forall a b. (a -> b) -> a -> b
    $ String
    "hs_bswap" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> Int -> String
    forall a. Show a => a -> String
    show (Width -> Int
    widthInBits Width
    w0))
        Maybe ([ForeignHint], [ForeignHint])
    forall a. Maybe a
    Nothing
        CmmReturnInfo
    CmmMayReturn
        [LocalReg]
    rs
        [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl (MO_BRev Width
    w0) [LocalReg]
    rs [CmmExpr]
    xs =
      CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmUnsafeForeignCall
        CLabel
    lbl
        (SymName -> Either SymName CmmExpr
    forall a b. a -> Either a b
    Left (SymName -> Either SymName CmmExpr)
    -> SymName -> Either SymName CmmExpr
    forall a b. (a -> b) -> a -> b
    $ String -> SymName
    forall a. IsString a => String -> a
    fromString (String -> SymName) -> String -> SymName
    forall a b. (a -> b) -> a -> b
    $ String
    "hs_bitrev" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> Int -> String
    forall a. Show a => a -> String
    show (Width -> Int
    widthInBits Width
    w0))
        Maybe ([ForeignHint], [ForeignHint])
    forall a. Maybe a
    Nothing
        CmmReturnInfo
    CmmMayReturn
        [LocalReg]
    rs
        [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl (MO_AtomicRMW Width
    w0 AtomicMachOp
    op) [LocalReg]
    rs [CmmExpr]
    xs =
      CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmUnsafeForeignCall
        CLabel
    lbl
        ( SymName -> Either SymName CmmExpr
    forall a b. a -> Either a b
    Left (SymName -> Either SymName CmmExpr)
    -> SymName -> Either SymName CmmExpr
    forall a b. (a -> b) -> a -> b
    $
            String -> SymName
    forall a. IsString a => String -> a
    fromString (String -> SymName) -> String -> SymName
    forall a b. (a -> b) -> a -> b
    $
              ( case AtomicMachOp
    op of
                  AtomicMachOp
    AMO_Add -> String
    "hs_atomic_add"
                  AtomicMachOp
    AMO_Sub -> String
    "hs_atomic_sub"
                  AtomicMachOp
    AMO_And -> String
    "hs_atomic_and"
                  AtomicMachOp
    AMO_Nand -> String
    "hs_atomic_nand"
                  AtomicMachOp
    AMO_Or -> String
    "hs_atomic_or"
                  AtomicMachOp
    AMO_Xor -> String
    "hs_atomic_xor"
              )
                String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> Int -> String
    forall a. Show a => a -> String
    show (Width -> Int
    widthInBits Width
    w0)
        )
        Maybe ([ForeignHint], [ForeignHint])
    forall a. Maybe a
    Nothing
        CmmReturnInfo
    CmmMayReturn
        [LocalReg]
    rs
        [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl (MO_AtomicRead Width
    w0 MemoryOrdering
    _) [LocalReg
    reg] [CmmExpr
    ptr] = do
      SomeWasmExpr ty (WasmExpr ret_instr) <-
        CLabel
    -> CmmExpr
    -> CmmType
    -> AlignmentSpec
    -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel
    -> CmmExpr
    -> CmmType
    -> AlignmentSpec
    -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmLoad
          CLabel
    lbl
          CmmExpr
    ptr
          (Width -> CmmType
    cmmBits Width
    w0)
          AlignmentSpec
    NaturallyAligned
      ri <- onCmmLocalReg_Typed ty reg
      pure $ WasmStatements $ ret_instr `WasmConcat` WasmLocalSet ty ri
    lower_CallishMachOp CLabel
    lbl (MO_AtomicWrite Width
    _ MemoryOrdering
    _) [] [CmmExpr
    ptr, CmmExpr
    val] =
      CLabel
    -> CmmExpr
    -> CmmExpr
    -> AlignmentSpec
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> CmmExpr
    -> CmmExpr
    -> AlignmentSpec
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmStore CLabel
    lbl CmmExpr
    ptr CmmExpr
    val AlignmentSpec
    NaturallyAligned
    lower_CallishMachOp CLabel
    lbl (MO_Cmpxchg Width
    w0) [LocalReg]
    rs [CmmExpr]
    xs = CLabel
    -> Width
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> Width
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_MO_Cmpxchg CLabel
    lbl Width
    w0 [LocalReg]
    rs [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl (MO_Xchg Width
    w0) [LocalReg]
    rs [CmmExpr]
    xs =
      CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmUnsafeForeignCall
        CLabel
    lbl
        (SymName -> Either SymName CmmExpr
    forall a b. a -> Either a b
    Left (SymName -> Either SymName CmmExpr)
    -> SymName -> Either SymName CmmExpr
    forall a b. (a -> b) -> a -> b
    $ String -> SymName
    forall a. IsString a => String -> a
    fromString (String -> SymName) -> String -> SymName
    forall a b. (a -> b) -> a -> b
    $ String
    "hs_xchg" String -> String -> String
    forall a. Semigroup a => a -> a -> a
    <> Int -> String
    forall a. Show a => a -> String
    show (Width -> Int
    widthInBits Width
    w0))
        Maybe ([ForeignHint], [ForeignHint])
    forall a. Maybe a
    Nothing
        CmmReturnInfo
    CmmMayReturn
        [LocalReg]
    rs
        [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_SuspendThread [LocalReg]
    rs [CmmExpr]
    xs =
      CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmUnsafeForeignCall
        CLabel
    lbl
        (SymName -> Either SymName CmmExpr
    forall a b. a -> Either a b
    Left SymName
    "suspendThread")
        Maybe ([ForeignHint], [ForeignHint])
    forall a. Maybe a
    Nothing
        CmmReturnInfo
    CmmMayReturn
        [LocalReg]
    rs
        [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    MO_ResumeThread [LocalReg]
    rs [CmmExpr]
    xs =
      CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmUnsafeForeignCall
        CLabel
    lbl
        (SymName -> Either SymName CmmExpr
    forall a b. a -> Either a b
    Left SymName
    "resumeThread")
        Maybe ([ForeignHint], [ForeignHint])
    forall a. Maybe a
    Nothing
        CmmReturnInfo
    CmmMayReturn
        [LocalReg]
    rs
        [CmmExpr]
    xs
    lower_CallishMachOp CLabel
    _ CallishMachOp
    _ [LocalReg]
    _ [CmmExpr]
    _ = String -> WasmCodeGenM w (WasmStatements w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_CallishMachOp: unreachable"

    -- | Lower a ccall, but drop the result by assigning it to an unused
    -- local. This is only used for lowering 'MO_Memcpy' and such, where
    -- the libc functions do have a return value, but the corresponding
    -- 'CallishMachOp' does not expect one.
    lower_CmmUnsafeForeignCall_Drop ::
      CLabel ->
      SymName ->
      CmmType ->
      [CmmActual] ->
      WasmCodeGenM w (WasmStatements w)
    lower_CmmUnsafeForeignCall_Drop :: forall (w :: WasmType).
    CLabel
    -> SymName
    -> CmmType
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmUnsafeForeignCall_Drop CLabel
    lbl SymName
    sym_callee CmmType
    ret_cmm_ty [CmmExpr]
    arg_exprs = do
      ret_uniq <- WasmCodeGenM w Unique
    forall (m :: * -> *). MonadUnique m => m Unique
    getUniqueM
      let ret_local = Unique -> CmmType -> LocalReg
    LocalReg Unique
    ret_uniq CmmType
    ret_cmm_ty
      lower_CmmUnsafeForeignCall
        lbl
        (Left sym_callee)
        Nothing
        CmmMayReturn
        [ret_local]
        arg_exprs

    -- | Lower a 'CmmUnsafeForeignCall'. The target is 'Either' a symbol,
    -- which translates to a direct @call@, or an expression, which
    -- translates to a @call_indirect@. The callee function signature is
    -- inferred from the passed in arguments here.
    lower_CmmUnsafeForeignCall ::
      CLabel ->
      (Either SymName CmmExpr) ->
      Maybe
        ([ForeignHint], [ForeignHint]) ->
      CmmReturnInfo ->
      [CmmFormal] ->
      [CmmActual] ->
      WasmCodeGenM w (WasmStatements w)
    lower_CmmUnsafeForeignCall :: forall (w :: WasmType).
    CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmUnsafeForeignCall CLabel
    lbl Either SymName CmmExpr
    target Maybe ([ForeignHint], [ForeignHint])
    mb_hints CmmReturnInfo
    ret_info [LocalReg]
    ret_locals [CmmExpr]
    arg_exprs = do
      platform <- WasmCodeGenM w Platform
    forall (w :: WasmType). WasmCodeGenM w Platform
    wasmPlatformM
      SomeWasmPreCCall arg_tys args_instr <-
        foldrM
          ( \(CmmExpr
    arg_expr, ForeignHint
    arg_hint) (SomeWasmPreCCall TypeList ts
    acc_tys forall (pre :: [WasmType]). WasmInstr w pre (WasmPushes ts pre)
    acc_instr) -> do
              SomeWasmExpr arg_ty arg_wasm_expr <- CLabel -> CmmExpr -> WasmCodeGenM w (SomeWasmExpr w)
    forall (w :: WasmType).
    CLabel -> CmmExpr -> WasmCodeGenM w (SomeWasmExpr w)
    lower_CmmExpr CLabel
    lbl CmmExpr
    arg_expr
              let WasmExpr arg_instr = case arg_hint of
                    ForeignHint
    SignedHint ->
                      Width -> WasmTypeTag t -> WasmExpr w t -> WasmExpr w t
    forall (t :: WasmType) (w :: WasmType).
    Width -> WasmTypeTag t -> WasmExpr w t -> WasmExpr w t
    extendSubword
                        (Platform -> CmmExpr -> Width
    cmmExprWidth Platform
    platform CmmExpr
    arg_expr)
                        WasmTypeTag t
    arg_ty
                        WasmExpr w t
    arg_wasm_expr
                    ForeignHint
    _ -> WasmExpr w t
    arg_wasm_expr
              pure $
                SomeWasmPreCCall (arg_ty `TypeListCons` acc_tys) $
                  arg_instr `WasmConcat` acc_instr
          )
          (SomeWasmPreCCall TypeListNil WasmNop)
          arg_exprs_hints
      SomeWasmPostCCall ret_tys ret_instr <-
        foldrM
          ( \(LocalReg
    reg, ForeignHint
    ret_hint) (SomeWasmPostCCall TypeList ts
    acc_tys forall (post :: [WasmType]). WasmInstr w (WasmPushes ts post) post
    acc_instr) -> do
              (reg_i, SomeWasmType reg_ty) <- LocalReg -> WasmCodeGenM w (Int, SomeWasmType)
    forall (w :: WasmType).
    LocalReg -> WasmCodeGenM w (Int, SomeWasmType)
    onCmmLocalReg LocalReg
    reg
              pure $
                SomeWasmPostCCall (reg_ty `TypeListCons` acc_tys) $
                  case (# ret_hint, cmmRegWidth $ CmmLocal reg #) of
                    (# ForeignHint
    SignedHint, Width
    W8 #) ->
                      WasmInstr w (WasmPushes ts (t : post)) (t : post)
    forall (post :: [WasmType]). WasmInstr w (WasmPushes ts post) post
    acc_instr
                        WasmInstr w (WasmPushes ts (t : post)) (t : post)
    -> WasmInstr w (t : post) (t : t : post)
    -> WasmInstr w (WasmPushes ts (t : post)) (t : t : post)
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmTypeTag t -> Integer -> WasmInstr w (t : post) (t : t : post)
    forall (t :: WasmType) (a :: WasmType) (b :: [WasmType]).
    WasmTypeTag t -> Integer -> WasmInstr a b (t : b)
    WasmConst WasmTypeTag t
    reg_ty Integer
    0xFF
                        WasmInstr w (WasmPushes ts (t : post)) (t : t : post)
    -> WasmInstr w (t : t : post) (t : post)
    -> WasmInstr w (WasmPushes ts (t : post)) (t : post)
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmTypeTag t -> WasmInstr w (t : t : post) (t : post)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    WasmTypeTag t -> WasmInstr a (t : t : pre) (t : pre)
    WasmAnd WasmTypeTag t
    reg_ty
                        WasmInstr w (WasmPushes ts (t : post)) (t : post)
    -> WasmInstr w (t : post) post
    -> WasmInstr w (WasmPushes ts (t : post)) post
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmTypeTag t -> Int -> WasmInstr w (t : post) post
    forall (t :: WasmType) (a :: WasmType) (c :: [WasmType]).
    WasmTypeTag t -> Int -> WasmInstr a (t : c) c
    WasmLocalSet WasmTypeTag t
    reg_ty Int
    reg_i
                    (# ForeignHint
    SignedHint, Width
    W16 #) ->
                      WasmInstr w (WasmPushes ts (t : post)) (t : post)
    forall (post :: [WasmType]). WasmInstr w (WasmPushes ts post) post
    acc_instr
                        WasmInstr w (WasmPushes ts (t : post)) (t : post)
    -> WasmInstr w (t : post) (t : t : post)
    -> WasmInstr w (WasmPushes ts (t : post)) (t : t : post)
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmTypeTag t -> Integer -> WasmInstr w (t : post) (t : t : post)
    forall (t :: WasmType) (a :: WasmType) (b :: [WasmType]).
    WasmTypeTag t -> Integer -> WasmInstr a b (t : b)
    WasmConst WasmTypeTag t
    reg_ty Integer
    0xFFFF
                        WasmInstr w (WasmPushes ts (t : post)) (t : t : post)
    -> WasmInstr w (t : t : post) (t : post)
    -> WasmInstr w (WasmPushes ts (t : post)) (t : post)
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmTypeTag t -> WasmInstr w (t : t : post) (t : post)
    forall (t :: WasmType) (a :: WasmType) (pre :: [WasmType]).
    WasmTypeTag t -> WasmInstr a (t : t : pre) (t : pre)
    WasmAnd WasmTypeTag t
    reg_ty
                        WasmInstr w (WasmPushes ts (t : post)) (t : post)
    -> WasmInstr w (t : post) post
    -> WasmInstr w (WasmPushes ts (t : post)) post
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmTypeTag t -> Int -> WasmInstr w (t : post) post
    forall (t :: WasmType) (a :: WasmType) (c :: [WasmType]).
    WasmTypeTag t -> Int -> WasmInstr a (t : c) c
    WasmLocalSet WasmTypeTag t
    reg_ty Int
    reg_i
                    (# ForeignHint, Width #)
    _ -> WasmInstr w (WasmPushes ts (t : post)) (t : post)
    forall (post :: [WasmType]). WasmInstr w (WasmPushes ts post) post
    acc_instr WasmInstr w (WasmPushes ts (t : post)) (t : post)
    -> WasmInstr w (t : post) post
    -> WasmInstr w (WasmPushes ts (t : post)) post
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmTypeTag t -> Int -> WasmInstr w (t : post) post
    forall (t :: WasmType) (a :: WasmType) (c :: [WasmType]).
    WasmTypeTag t -> Int -> WasmInstr a (t : c) c
    WasmLocalSet WasmTypeTag t
    reg_ty Int
    reg_i
          )
          (SomeWasmPostCCall TypeListNil WasmNop)
          ret_locals_hints
      case target of
        Left SymName
    sym_callee -> do
          platform <- WasmCodeGenM w Platform
    forall (w :: WasmType). WasmCodeGenM w Platform
    wasmPlatformM
          let arg_cmm_tys = (CmmExpr -> CmmType) -> [CmmExpr] -> [CmmType]
    forall a b. (a -> b) -> [a] -> [b]
    map (Platform -> CmmExpr -> CmmType
    cmmExprType Platform
    platform) [CmmExpr]
    arg_exprs
              ret_cmm_tys = (LocalReg -> CmmType) -> [LocalReg] -> [CmmType]
    forall a b. (a -> b) -> [a] -> [b]
    map LocalReg -> CmmType
    localRegType [LocalReg]
    ret_locals
          onFuncSym sym_callee arg_cmm_tys ret_cmm_tys
          pure $
            WasmStatements $
              args_instr
                `WasmConcat` WasmCCall sym_callee
                `WasmConcat` ( case ret_info of
                                 CmmReturnInfo
    CmmMayReturn -> WasmInstr w (WasmPushes ts pre) pre
    forall (post :: [WasmType]). WasmInstr w (WasmPushes ts post) post
    ret_instr
                                 CmmReturnInfo
    CmmNeverReturns -> WasmInstr w (WasmPushes ts pre) pre
    forall (a :: WasmType) (b :: [WasmType]) (c :: [WasmType]).
    WasmInstr a b c
    WasmUnreachable
                             )
        Right CmmExpr
    fptr_callee -> do
          (WasmExpr instr_callee, _) <- CLabel -> CmmExpr -> WasmCodeGenM w (WasmExpr w w, Int)
    forall (w :: WasmType).
    CLabel -> CmmExpr -> WasmCodeGenM w (WasmExpr w w, Int)
    lower_CmmExpr_Ptr CLabel
    lbl CmmExpr
    fptr_callee
          pure $
            WasmStatements $
              args_instr
                `WasmConcat` instr_callee
                `WasmConcat` WasmCCallIndirect arg_tys ret_tys
                `WasmConcat` ( case ret_info of
                                 CmmReturnInfo
    CmmMayReturn -> WasmInstr w (WasmPushes ts pre) pre
    forall (post :: [WasmType]). WasmInstr w (WasmPushes ts post) post
    ret_instr
                                 CmmReturnInfo
    CmmNeverReturns -> WasmInstr w (WasmPushes ts pre) pre
    forall (a :: WasmType) (b :: [WasmType]) (c :: [WasmType]).
    WasmInstr a b c
    WasmUnreachable
                             )
      where
        (# [(CmmExpr, ForeignHint)]
    arg_exprs_hints, [(LocalReg, ForeignHint)]
    ret_locals_hints #) = case Maybe ([ForeignHint], [ForeignHint])
    mb_hints of
          Just ([ForeignHint]
    arg_hints, [ForeignHint]
    ret_hints) ->
            (# [CmmExpr] -> [ForeignHint] -> [(CmmExpr, ForeignHint)]
    forall a b. [a] -> [b] -> [(a, b)]
    zip [CmmExpr]
    arg_exprs [ForeignHint]
    arg_hints, [LocalReg] -> [ForeignHint] -> [(LocalReg, ForeignHint)]
    forall a b. [a] -> [b] -> [(a, b)]
    zip [LocalReg]
    ret_locals [ForeignHint]
    ret_hints #)
          Maybe ([ForeignHint], [ForeignHint])
    _ -> (# (CmmExpr -> (CmmExpr, ForeignHint))
    -> [CmmExpr] -> [(CmmExpr, ForeignHint)]
    forall a b. (a -> b) -> [a] -> [b]
    map (,ForeignHint
    NoHint) [CmmExpr]
    arg_exprs, (LocalReg -> (LocalReg, ForeignHint))
    -> [LocalReg] -> [(LocalReg, ForeignHint)]
    forall a b. (a -> b) -> [a] -> [b]
    map (,ForeignHint
    NoHint) [LocalReg]
    ret_locals #)

    -- | Lower a 'CmmStore'.
    lower_CmmStore ::
      CLabel ->
      CmmExpr ->
      CmmExpr ->
      AlignmentSpec ->
      WasmCodeGenM
        w
        (WasmStatements w)
    lower_CmmStore :: forall (w :: WasmType).
    CLabel
    -> CmmExpr
    -> CmmExpr
    -> AlignmentSpec
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmStore CLabel
    lbl CmmExpr
    ptr CmmExpr
    val AlignmentSpec
    align = do
      platform <- WasmCodeGenM w Platform
    forall (w :: WasmType). WasmCodeGenM w Platform
    wasmPlatformM
      (WasmExpr ptr_instr, o) <- lower_CmmExpr_Ptr lbl ptr
      let ty_cmm = Platform -> CmmExpr -> CmmType
    cmmExprType Platform
    platform CmmExpr
    val
      SomeWasmExpr ty (WasmExpr val_instr) <- lower_CmmExpr lbl val
      pure $
        WasmStatements $
          ptr_instr
            `WasmConcat` val_instr
            `WasmConcat` WasmStore ty (wasmMemoryNarrowing ty ty_cmm) o align

    -- | Lower a single Cmm action.
    lower_CmmAction :: CLabel -> CmmNode O O -> WasmCodeGenM w (WasmStatements w)
    lower_CmmAction :: forall (w :: WasmType).
    CLabel -> CmmNode O O -> WasmCodeGenM w (WasmStatements w)
    lower_CmmAction CLabel
    lbl CmmNode O O
    act = do
      ty_word <- WasmCodeGenM w (WasmTypeTag w)
    forall (w :: WasmType). WasmCodeGenM w (WasmTypeTag w)
    wasmWordTypeM
      platform <- wasmPlatformM
      case act of
        CmmComment {} -> WasmStatements w -> WasmCodeGenM w (WasmStatements w)
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (WasmStatements w -> WasmCodeGenM w (WasmStatements w))
    -> WasmStatements w -> WasmCodeGenM w (WasmStatements w)
    forall a b. (a -> b) -> a -> b
    $ (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    forall (w :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    WasmStatements WasmInstr w pre pre
    forall (pre :: [WasmType]). WasmInstr w pre pre
    forall (a :: WasmType) (b :: [WasmType]). WasmInstr a b b
    WasmNop
        CmmTick {} -> WasmStatements w -> WasmCodeGenM w (WasmStatements w)
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (WasmStatements w -> WasmCodeGenM w (WasmStatements w))
    -> WasmStatements w -> WasmCodeGenM w (WasmStatements w)
    forall a b. (a -> b) -> a -> b
    $ (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    forall (w :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    WasmStatements WasmInstr w pre pre
    forall (pre :: [WasmType]). WasmInstr w pre pre
    forall (a :: WasmType) (b :: [WasmType]). WasmInstr a b b
    WasmNop
        CmmUnwind {} -> WasmStatements w -> WasmCodeGenM w (WasmStatements w)
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (WasmStatements w -> WasmCodeGenM w (WasmStatements w))
    -> WasmStatements w -> WasmCodeGenM w (WasmStatements w)
    forall a b. (a -> b) -> a -> b
    $ (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    forall (w :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    WasmStatements WasmInstr w pre pre
    forall (pre :: [WasmType]). WasmInstr w pre pre
    forall (a :: WasmType) (b :: [WasmType]). WasmInstr a b b
    WasmNop
        CmmAssign (CmmLocal LocalReg
    reg) CmmExpr
    e -> do
          (i, SomeWasmType ty_reg) <- LocalReg -> WasmCodeGenM w (Int, SomeWasmType)
    forall (w :: WasmType).
    LocalReg -> WasmCodeGenM w (Int, SomeWasmType)
    onCmmLocalReg LocalReg
    reg
          WasmExpr instrs <- lower_CmmExpr_Typed lbl ty_reg e
          pure $ WasmStatements $ instrs `WasmConcat` WasmLocalSet ty_reg i
        CmmAssign (CmmGlobal (GlobalRegUse GlobalReg
    reg CmmType
    _)) CmmExpr
    e
          | GlobalReg
    BaseReg <- GlobalReg
    reg -> WasmStatements w -> WasmCodeGenM w (WasmStatements w)
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (WasmStatements w -> WasmCodeGenM w (WasmStatements w))
    -> WasmStatements w -> WasmCodeGenM w (WasmStatements w)
    forall a b. (a -> b) -> a -> b
    $ (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    forall (w :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    WasmStatements WasmInstr w pre pre
    forall (pre :: [WasmType]). WasmInstr w pre pre
    forall (a :: WasmType) (b :: [WasmType]). WasmInstr a b b
    WasmNop
          | Just (SymName
    sym_global, SomeWasmType WasmTypeTag t
    ty_reg) <-
              WasmTypeTag w -> GlobalReg -> Maybe GlobalInfo
    forall (w :: WasmType).
    WasmTypeTag w -> GlobalReg -> Maybe GlobalInfo
    globalInfoFromCmmGlobalReg WasmTypeTag w
    ty_word GlobalReg
    reg -> do
              WasmExpr instrs <- CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag t
    ty_reg CmmExpr
    e
              pure $
                WasmStatements $
                  instrs `WasmConcat` WasmGlobalSet ty_reg sym_global
          | Bool
    otherwise -> do
              (WasmExpr ptr_instr, o) <-
                CLabel -> CmmExpr -> WasmCodeGenM w (WasmExpr w w, Int)
    forall (w :: WasmType).
    CLabel -> CmmExpr -> WasmCodeGenM w (WasmExpr w w, Int)
    lower_CmmExpr_Ptr CLabel
    lbl (CmmExpr -> WasmCodeGenM w (WasmExpr w w, Int))
    -> CmmExpr -> WasmCodeGenM w (WasmExpr w w, Int)
    forall a b. (a -> b) -> a -> b
    $ Platform -> GlobalReg -> CmmExpr
    get_GlobalReg_addr Platform
    platform GlobalReg
    reg
              SomeWasmExpr ty_e (WasmExpr instrs) <- lower_CmmExpr lbl e
              pure $
                WasmStatements $
                  ptr_instr
                    `WasmConcat` instrs
                    `WasmConcat` WasmStore ty_e Nothing o NaturallyAligned
        CmmStore CmmExpr
    ptr CmmExpr
    val AlignmentSpec
    align -> CLabel
    -> CmmExpr
    -> CmmExpr
    -> AlignmentSpec
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> CmmExpr
    -> CmmExpr
    -> AlignmentSpec
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmStore CLabel
    lbl CmmExpr
    ptr CmmExpr
    val AlignmentSpec
    align
        CmmUnsafeForeignCall
          ( ForeignTarget
              (CmmLit (CmmLabel CLabel
    lbl_callee))
              (ForeignConvention CCallConv
    conv [ForeignHint]
    arg_hints [ForeignHint]
    ret_hints CmmReturnInfo
    ret_info)
            )
          [LocalReg]
    ret_locals
          [CmmExpr]
    arg_exprs
            | CCallConv
    conv CCallConv -> [CCallConv] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [CCallConv
    CCallConv, CCallConv
    CApiConv] ->
                CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmUnsafeForeignCall
                  CLabel
    lbl
                  (SymName -> Either SymName CmmExpr
    forall a b. a -> Either a b
    Left (SymName -> Either SymName CmmExpr)
    -> SymName -> Either SymName CmmExpr
    forall a b. (a -> b) -> a -> b
    $ CLabel -> SymName
    symNameFromCLabel CLabel
    lbl_callee)
                  (([ForeignHint], [ForeignHint])
    -> Maybe ([ForeignHint], [ForeignHint])
    forall a. a -> Maybe a
    Just ([ForeignHint]
    arg_hints, [ForeignHint]
    ret_hints))
                  CmmReturnInfo
    ret_info
                  [LocalReg]
    ret_locals
                  [CmmExpr]
    arg_exprs
        CmmUnsafeForeignCall
          (ForeignTarget CmmExpr
    target_expr (ForeignConvention CCallConv
    conv [ForeignHint]
    arg_hints [ForeignHint]
    ret_hints CmmReturnInfo
    ret_info))
          [LocalReg]
    ret_locals
          [CmmExpr]
    arg_exprs
            | CCallConv
    conv CCallConv -> [CCallConv] -> Bool
    forall a. Eq a => a -> [a] -> Bool
    forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
    `elem` [CCallConv
    CCallConv, CCallConv
    CApiConv] ->
                CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> Either SymName CmmExpr
    -> Maybe ([ForeignHint], [ForeignHint])
    -> CmmReturnInfo
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmUnsafeForeignCall
                  CLabel
    lbl
                  (CmmExpr -> Either SymName CmmExpr
    forall a b. b -> Either a b
    Right CmmExpr
    target_expr)
                  (([ForeignHint], [ForeignHint])
    -> Maybe ([ForeignHint], [ForeignHint])
    forall a. a -> Maybe a
    Just ([ForeignHint]
    arg_hints, [ForeignHint]
    ret_hints))
                  CmmReturnInfo
    ret_info
                  [LocalReg]
    ret_locals
                  [CmmExpr]
    arg_exprs
        CmmUnsafeForeignCall (PrimTarget CallishMachOp
    op) [LocalReg]
    ret_locals [CmmExpr]
    arg_exprs ->
          CLabel
    -> CallishMachOp
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel
    -> CallishMachOp
    -> [LocalReg]
    -> [CmmExpr]
    -> WasmCodeGenM w (WasmStatements w)
    lower_CallishMachOp CLabel
    lbl CallishMachOp
    op [LocalReg]
    ret_locals [CmmExpr]
    arg_exprs
        CmmNode O O
    _ -> String -> WasmCodeGenM w (WasmStatements w)
    forall a. HasCallStack => String -> a
    panic String
    "lower_CmmAction: unreachable"

    -- | Lower a block of Cmm actions.
    lower_CmmActions ::
      CLabel ->
      Label ->
      Block CmmNode O O ->
      WasmCodeGenM
        w
        (WasmStatements w)
    lower_CmmActions :: forall (w :: WasmType).
    CLabel
    -> BlockId
    -> Block CmmNode O O
    -> WasmCodeGenM w (WasmStatements w)
    lower_CmmActions CLabel
    lbl BlockId
    _ Block CmmNode O O
    blk =
      (WasmStatements w
     -> CmmNode O O -> WasmCodeGenM w (WasmStatements w))
    -> WasmStatements w
    -> [CmmNode O O]
    -> WasmCodeGenM w (WasmStatements w)
    forall (t :: * -> *) (m :: * -> *) b a.
    (Foldable t, Monad m) =>
    (b -> a -> m b) -> b -> t a -> m b
    foldlM
        ( \(WasmStatements forall (pre :: [WasmType]). WasmInstr w pre pre
    acc) CmmNode O O
    act ->
            (\(WasmStatements forall (pre :: [WasmType]). WasmInstr w pre pre
    stmts) -> (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    forall (w :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    WasmStatements ((forall (pre :: [WasmType]). WasmInstr w pre pre)
     -> WasmStatements w)
    -> (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    forall a b. (a -> b) -> a -> b
    $ WasmInstr w pre pre
    forall (pre :: [WasmType]). WasmInstr w pre pre
    acc WasmInstr w pre pre -> WasmInstr w pre pre -> WasmInstr w pre pre
    forall (a :: WasmType) (b :: [WasmType]) (mid :: [WasmType])
           (c :: [WasmType]).
    WasmInstr a b mid -> WasmInstr a mid c -> WasmInstr a b c
    `WasmConcat` WasmInstr w pre pre
    forall (pre :: [WasmType]). WasmInstr w pre pre
    stmts)
              (WasmStatements w -> WasmStatements w)
    -> WasmCodeGenM w (WasmStatements w)
    -> WasmCodeGenM w (WasmStatements w)
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> CLabel -> CmmNode O O -> WasmCodeGenM w (WasmStatements w)
    forall (w :: WasmType).
    CLabel -> CmmNode O O -> WasmCodeGenM w (WasmStatements w)
    lower_CmmAction CLabel
    lbl CmmNode O O
    act
        )
        ((forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    forall (w :: WasmType).
    (forall (pre :: [WasmType]). WasmInstr w pre pre)
    -> WasmStatements w
    WasmStatements WasmInstr w pre pre
    forall (pre :: [WasmType]). WasmInstr w pre pre
    forall (a :: WasmType) (b :: [WasmType]). WasmInstr a b b
    WasmNop)
        [CmmNode O O]
    acts
      where
        acts :: [CmmNode O O]
    acts = Block CmmNode O O -> [CmmNode O O]
    forall (n :: Extensibility -> Extensibility -> *).
    Block n O O -> [n O O]
    blockToList Block CmmNode O O
    blk

    -- | Lower a 'CmmGraph'.
    lower_CmmGraph :: CLabel -> CmmGraph -> WasmCodeGenM w (FuncBody w)
    lower_CmmGraph :: forall (w :: WasmType).
    CLabel -> CmmGraph -> WasmCodeGenM w (FuncBody w)
    lower_CmmGraph CLabel
    lbl CmmGraph
    g = do
      ty_word <- WasmCodeGenM w (WasmTypeTag w)
    forall (w :: WasmType). WasmCodeGenM w (WasmTypeTag w)
    wasmWordTypeM
      platform <- wasmPlatformM
      us <- getUniqueSupplyM
      body <-
        structuredControl
          platform
          us
          (\BlockId
    _ -> CLabel -> WasmTypeTag w -> CmmExpr -> WasmCodeGenM w (WasmExpr w w)
    forall (t :: WasmType) (w :: WasmType).
    CLabel -> WasmTypeTag t -> CmmExpr -> WasmCodeGenM w (WasmExpr w t)
    lower_CmmExpr_Typed CLabel
    lbl WasmTypeTag w
    ty_word)
          (lower_CmmActions lbl)
          g
      locals <- wasmStateM $ \WasmCodeGenState w
    s ->
        (#
          ((Int, SomeWasmType) -> SomeWasmType)
    -> [(Int, SomeWasmType)] -> [SomeWasmType]
    forall a b. (a -> b) -> [a] -> [b]
    map (Int, SomeWasmType) -> SomeWasmType
    forall a b. (a, b) -> b
    snd ([(Int, SomeWasmType)] -> [SomeWasmType])
    -> [(Int, SomeWasmType)] -> [SomeWasmType]
    forall a b. (a -> b) -> a -> b
    $ UniqFM LocalReg (Int, SomeWasmType) -> [(Int, SomeWasmType)]
    forall {k1} k2 (k0 :: k1) a.
    Ord k2 =>
    UniqFM k0 (k2, a) -> [(k2, a)]
    detEltsUFM (UniqFM LocalReg (Int, SomeWasmType) -> [(Int, SomeWasmType)])
    -> UniqFM LocalReg (Int, SomeWasmType) -> [(Int, SomeWasmType)]
    forall a b. (a -> b) -> a -> b
    $ WasmCodeGenState w -> UniqFM LocalReg (Int, SomeWasmType)
    forall (w :: WasmType).
    WasmCodeGenState w -> UniqFM LocalReg (Int, SomeWasmType)
    localRegs WasmCodeGenState w
    s,
          WasmCodeGenState w
    s {localRegs = emptyUFM, localRegsCount = 0}
        #)
      pure FuncBody {funcLocals = locals, funcBody = wasmControlCast $ body}

    -- | Invoked once for each 'CLabel' which indexes a 'CmmData' or
    -- 'CmmProc'.
    onTopSym :: CLabel -> WasmCodeGenM w ()
    onTopSym :: forall (w :: WasmType). CLabel -> WasmCodeGenM w ()
    onTopSym CLabel
    lbl = case SymVisibility
    sym_vis of
      SymVisibility
    SymDefault -> (WasmCodeGenState w -> WasmCodeGenState w) -> WasmCodeGenM w ()
    forall (w :: WasmType).
    (WasmCodeGenState w -> WasmCodeGenState w) -> WasmCodeGenM w ()
    wasmModifyM ((WasmCodeGenState w -> WasmCodeGenState w) -> WasmCodeGenM w ())
    -> (WasmCodeGenState w -> WasmCodeGenState w) -> WasmCodeGenM w ()
    forall a b. (a -> b) -> a -> b
    $ \WasmCodeGenState w
    s ->
        WasmCodeGenState w
    s
          { defaultSyms =
              WS.insert
                (getKey $ getUnique sym)
                $ defaultSyms s
          }
      SymVisibility
    _ -> () -> WasmCodeGenM w ()
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ()
      where
        sym :: SymName
    sym = CLabel -> SymName
    symNameFromCLabel CLabel
    lbl

        sym_vis :: SymVisibility
    sym_vis = CLabel -> SymVisibility
    symVisibilityFromCLabel CLabel
    lbl

    -- | Invoked for each function 'CLabel' with known type (e.g. a
    -- 'CmmProc', or callee of 'CmmUnsafeForeignCall').
    onFuncSym :: SymName -> [CmmType] -> [CmmType] -> WasmCodeGenM w ()
    onFuncSym :: forall (w :: WasmType).
    SymName -> [CmmType] -> [CmmType] -> WasmCodeGenM w ()
    onFuncSym SymName
    sym [CmmType]
    arg_tys [CmmType]
    ret_tys = (WasmCodeGenState w -> WasmCodeGenState w) -> WasmCodeGenM w ()
    forall (w :: WasmType).
    (WasmCodeGenState w -> WasmCodeGenState w) -> WasmCodeGenM w ()
    wasmModifyM ((WasmCodeGenState w -> WasmCodeGenState w) -> WasmCodeGenM w ())
    -> (WasmCodeGenState w -> WasmCodeGenState w) -> WasmCodeGenM w ()
    forall a b. (a -> b) -> a -> b
    $
      \s :: WasmCodeGenState w
    s@WasmCodeGenState {Int
    [SymName]
    Word64Set
    UniqFM LocalReg (Int, SomeWasmType)
    UniqSupply
    SymMap ([SomeWasmType], [SomeWasmType])
    SymMap (FuncBody w)
    SymMap DataSection
    Platform
    localRegs :: forall (w :: WasmType).
    WasmCodeGenState w -> UniqFM LocalReg (Int, SomeWasmType)
    localRegsCount :: forall (w :: WasmType). WasmCodeGenState w -> Int
    defaultSyms :: forall (w :: WasmType). WasmCodeGenState w -> Word64Set
    wasmPlatform :: Platform
    defaultSyms :: Word64Set
    funcTypes :: SymMap ([SomeWasmType], [SomeWasmType])
    funcBodies :: SymMap (FuncBody w)
    dataSections :: SymMap DataSection
    ctors :: [SymName]
    localRegs :: UniqFM LocalReg (Int, SomeWasmType)
    localRegsCount :: Int
    wasmUniqSupply :: UniqSupply
    wasmUniqSupply :: forall (w :: WasmType). WasmCodeGenState w -> UniqSupply
    ctors :: forall (w :: WasmType). WasmCodeGenState w -> [SymName]
    dataSections :: forall (w :: WasmType). WasmCodeGenState w -> SymMap DataSection
    funcBodies :: forall (w :: WasmType). WasmCodeGenState w -> SymMap (FuncBody w)
    funcTypes :: forall (w :: WasmType).
    WasmCodeGenState w -> SymMap ([SomeWasmType], [SomeWasmType])
    wasmPlatform :: forall (w :: WasmType). WasmCodeGenState w -> Platform
    ..} ->
        WasmCodeGenState w
    s
          { funcTypes =
              addToUniqMap
                funcTypes
                sym
                ( map someWasmTypeFromCmmType arg_tys,
                  map someWasmTypeFromCmmType ret_tys
                )
          }

    -- | Invoked for all other 'CLabel's along the way, e.g. in
    -- 'CmmStatic's or 'CmmExpr's.
    onAnySym :: CLabel -> WasmCodeGenM w ()
    onAnySym :: forall (w :: WasmType). CLabel -> WasmCodeGenM w ()
    onAnySym CLabel
    lbl = case SymKind
    sym_kind of
      SymKind
    SymFunc -> do
        ty_word <- WasmCodeGenM w (WasmTypeTag w)
    forall (w :: WasmType). WasmCodeGenM w (WasmTypeTag w)
    wasmWordTypeM
        wasmModifyM $ \s :: WasmCodeGenState w
    s@WasmCodeGenState {Int
    [SymName]
    Word64Set
    UniqFM LocalReg (Int, SomeWasmType)
    UniqSupply
    SymMap ([SomeWasmType], [SomeWasmType])
    SymMap (FuncBody w)
    SymMap DataSection
    Platform
    localRegs :: forall (w :: WasmType).
    WasmCodeGenState w -> UniqFM LocalReg (Int, SomeWasmType)
    localRegsCount :: forall (w :: WasmType). WasmCodeGenState w -> Int
    defaultSyms :: forall (w :: WasmType). WasmCodeGenState w -> Word64Set
    wasmUniqSupply :: forall (w :: WasmType). WasmCodeGenState w -> UniqSupply
    ctors :: forall (w :: WasmType). WasmCodeGenState w -> [SymName]
    dataSections :: forall (w :: WasmType). WasmCodeGenState w -> SymMap DataSection
    funcBodies :: forall (w :: WasmType). WasmCodeGenState w -> SymMap (FuncBody w)
    funcTypes :: forall (w :: WasmType).
    WasmCodeGenState w -> SymMap ([SomeWasmType], [SomeWasmType])
    wasmPlatform :: forall (w :: WasmType). WasmCodeGenState w -> Platform
    wasmPlatform :: Platform
    defaultSyms :: Word64Set
    funcTypes :: SymMap ([SomeWasmType], [SomeWasmType])
    funcBodies :: SymMap (FuncBody w)
    dataSections :: SymMap DataSection
    ctors :: [SymName]
    localRegs :: UniqFM LocalReg (Int, SomeWasmType)
    localRegsCount :: Int
    wasmUniqSupply :: UniqSupply
    ..} ->
          WasmCodeGenState w
    s {funcTypes = addToUniqMap_C const funcTypes sym ([], [SomeWasmType ty_word])}
      SymKind
    _ -> () -> WasmCodeGenM w ()
    forall a. a -> WasmCodeGenM w a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ()
      where
        sym :: SymName
    sym = CLabel -> SymName
    symNameFromCLabel CLabel
    lbl

        sym_kind :: SymKind
    sym_kind = CLabel -> SymKind
    symKindFromCLabel CLabel
    lbl

    -- | Invoked for each 'LocalReg', returning its wasm local id and
    -- representation type.
    onCmmLocalReg :: LocalReg -> WasmCodeGenM w LocalInfo
    onCmmLocalReg :: forall (w :: WasmType).
    LocalReg -> WasmCodeGenM w (Int, SomeWasmType)
    onCmmLocalReg LocalReg
    reg = (WasmCodeGenState w
     -> (# (Int, SomeWasmType), WasmCodeGenState w #))
    -> WasmCodeGenM w (Int, SomeWasmType)
    forall (w :: WasmType) a.
    (WasmCodeGenState w -> (# a, WasmCodeGenState w #))
    -> WasmCodeGenM w a
    wasmStateM ((WasmCodeGenState w
      -> (# (Int, SomeWasmType), WasmCodeGenState w #))
     -> WasmCodeGenM w (Int, SomeWasmType))
    -> (WasmCodeGenState w
        -> (# (Int, SomeWasmType), WasmCodeGenState w #))
    -> WasmCodeGenM w (Int, SomeWasmType)
    forall a b. (a -> b) -> a -> b
    $ \s :: WasmCodeGenState w
    s@WasmCodeGenState {Int
    [SymName]
    Word64Set
    UniqFM LocalReg (Int, SomeWasmType)
    UniqSupply
    SymMap ([SomeWasmType], [SomeWasmType])
    SymMap (FuncBody w)
    SymMap DataSection
    Platform
    localRegs :: forall (w :: WasmType).
    WasmCodeGenState w -> UniqFM LocalReg (Int, SomeWasmType)
    localRegsCount :: forall (w :: WasmType). WasmCodeGenState w -> Int
    defaultSyms :: forall (w :: WasmType). WasmCodeGenState w -> Word64Set
    wasmUniqSupply :: forall (w :: WasmType). WasmCodeGenState w -> UniqSupply
    ctors :: forall (w :: WasmType). WasmCodeGenState w -> [SymName]
    dataSections :: forall (w :: WasmType). WasmCodeGenState w -> SymMap DataSection
    funcBodies :: forall (w :: WasmType). WasmCodeGenState w -> SymMap (FuncBody w)
    funcTypes :: forall (w :: WasmType).
    WasmCodeGenState w -> SymMap ([SomeWasmType], [SomeWasmType])
    wasmPlatform :: forall (w :: WasmType). WasmCodeGenState w -> Platform
    wasmPlatform :: Platform
    defaultSyms :: Word64Set
    funcTypes :: SymMap ([SomeWasmType], [SomeWasmType])
    funcBodies :: SymMap (FuncBody w)
    dataSections :: SymMap DataSection
    ctors :: [SymName]
    localRegs :: UniqFM LocalReg (Int, SomeWasmType)
    localRegsCount :: Int
    wasmUniqSupply :: UniqSupply
    ..} ->
      let reg_info :: (Int, SomeWasmType)
    reg_info =
            (Int
    localRegsCount, CmmType -> SomeWasmType
    someWasmTypeFromCmmType (CmmType -> SomeWasmType) -> CmmType -> SomeWasmType
    forall a b. (a -> b) -> a -> b
    $ LocalReg -> CmmType
    localRegType LocalReg
    reg)
       in case (LocalReg
     -> (Int, SomeWasmType)
     -> (Int, SomeWasmType)
     -> (Int, SomeWasmType))
    -> LocalReg
    -> (Int, SomeWasmType)
    -> UniqFM LocalReg (Int, SomeWasmType)
    -> (Maybe (Int, SomeWasmType), UniqFM LocalReg (Int, SomeWasmType))
    forall key elt.
    Uniquable key =>
    (key -> elt -> elt -> elt)
    -> key -> elt -> UniqFM key elt -> (Maybe elt, UniqFM key elt)
    addToUFM_L (\LocalReg
    _ (Int, SomeWasmType)
    i (Int, SomeWasmType)
    _ -> (Int, SomeWasmType)
    i) LocalReg
    reg (Int, SomeWasmType)
    reg_info UniqFM LocalReg (Int, SomeWasmType)
    localRegs of
            (Just (Int, SomeWasmType)
    i, UniqFM LocalReg (Int, SomeWasmType)
    _) -> (# (Int, SomeWasmType)
    i, WasmCodeGenState w
    s #)
            (Maybe (Int, SomeWasmType)
    _, UniqFM LocalReg (Int, SomeWasmType)
    localRegs') ->
              (#
                (Int, SomeWasmType)
    reg_info,
                WasmCodeGenState w
    s
                  { localRegs = localRegs',
                    localRegsCount =
                      localRegsCount + 1
                  }
              #)

    -- | Invoked for each 'LocalReg' with expected representation type,
    -- only returning its wasm local id.
    onCmmLocalReg_Typed :: WasmTypeTag t -> LocalReg -> WasmCodeGenM w Int
    onCmmLocalReg_Typed :: forall (t :: WasmType) (w :: WasmType).
    WasmTypeTag t -> LocalReg -> WasmCodeGenM w Int
    onCmmLocalReg_Typed WasmTypeTag t
    ty LocalReg
    reg = do
      (i, SomeWasmType ty') <- LocalReg -> WasmCodeGenM w (Int, SomeWasmType)
    forall (w :: WasmType).
    LocalReg -> WasmCodeGenM w (Int, SomeWasmType)
    onCmmLocalReg LocalReg
    reg
      if
          | Just Refl <- ty' `testEquality` ty -> pure i
          | otherwise -> panic "onCmmLocalReg_Typed: unreachable"

    -- | Invoked for dtors. We don't bother to implement dtors yet;
    -- there's no native @.fini_array@ support for wasm, and the way
    -- @clang@ handles dtors is generating a ctor that calls @atexit()@
    -- for dtors. Which makes some sense, but we don't need to do the same
    -- thing yet.
    onFini :: [SymName] -> WasmCodeGenM w ()
    onFini :: forall (w :: WasmType). [SymName] -> WasmCodeGenM w ()
    onFini [SymName]
    syms = do
      let n_finis :: Int
    n_finis = [SymName] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [SymName]
    syms
      Bool -> WasmCodeGenM w () -> WasmCodeGenM w ()
    forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
    when (Int
    n_finis Int -> Int -> Bool
    forall a. Eq a => a -> a -> Bool
    /= Int
    0) (WasmCodeGenM w () -> WasmCodeGenM w ())
    -> WasmCodeGenM w () -> WasmCodeGenM w ()
    forall a b. (a -> b) -> a -> b
    $ String -> WasmCodeGenM w ()
    forall a. HasCallStack => String -> a
    panic String
    "dtors unsupported by wasm32 NCG"

    -- | Invoked for ctors and dtors.
    onCmmInitFini :: InitOrFini -> [CLabel] -> WasmCodeGenM w ()
    onCmmInitFini :: forall (w :: WasmType). InitOrFini -> [CLabel] -> WasmCodeGenM w ()
    onCmmInitFini InitOrFini
    iof [CLabel]
    lbls = do
      [CLabel] -> (CLabel -> WasmCodeGenM w ()) -> WasmCodeGenM w ()
    forall (t :: * -> *) (f :: * -> *) a b.
    (Foldable t, Applicative f) =>
    t a -> (a -> f b) -> f ()
    for_ [CLabel]
    lbls ((CLabel -> WasmCodeGenM w ()) -> WasmCodeGenM w ())
    -> (CLabel -> WasmCodeGenM w ()) -> WasmCodeGenM w ()
    forall a b. (a -> b) -> a -> b
    $ \CLabel
    lbl -> SymName -> [CmmType] -> [CmmType] -> WasmCodeGenM w ()
    forall (w :: WasmType).
    SymName -> [CmmType] -> [CmmType] -> WasmCodeGenM w ()
    onFuncSym (CLabel -> SymName
    symNameFromCLabel CLabel
    lbl) [] []
      case InitOrFini
    iof of
        InitOrFini
    IsInitArray -> (WasmCodeGenState w -> WasmCodeGenState w) -> WasmCodeGenM w ()
    forall (w :: WasmType).
    (WasmCodeGenState w -> WasmCodeGenState w) -> WasmCodeGenM w ()
    wasmModifyM ((WasmCodeGenState w -> WasmCodeGenState w) -> WasmCodeGenM w ())
    -> (WasmCodeGenState w -> WasmCodeGenState w) -> WasmCodeGenM w ()
    forall a b. (a -> b) -> a -> b
    $ \WasmCodeGenState w
    s -> WasmCodeGenState w
    s {ctors = syms <> ctors s}
        InitOrFini
    IsFiniArray -> [SymName] -> WasmCodeGenM w ()
    forall (w :: WasmType). [SymName] -> WasmCodeGenM w ()
    onFini [SymName]
    syms
      where
        syms :: [SymName]
    syms = (CLabel -> SymName) -> [CLabel] -> [SymName]
    forall a b. (a -> b) -> [a] -> [b]
    map CLabel -> SymName
    symNameFromCLabel [CLabel]
    lbls

    -- | Invoked for each data section.
    onCmmData :: CLabel -> Section -> [CmmStatic] -> WasmCodeGenM w ()
    onCmmData :: forall (w :: WasmType).
    CLabel -> Section -> [CmmStatic] -> WasmCodeGenM w ()
    onCmmData CLabel
    lbl Section
    s [CmmStatic]
    statics = do
      ty_word <- WasmCodeGenM w (WasmTypeTag w)
    forall (w :: WasmType). WasmCodeGenM w (WasmTypeTag w)
    wasmWordTypeM
      onTopSym lbl
      cs <- for statics lower_CmmStatic
      let sym = CLabel -> SymName
    symNameFromCLabel CLabel
    lbl
          sec =
            DataSection
              { dataSectionKind :: DataSectionKind
    dataSectionKind =
                  Section -> DataSectionKind
    dataSectionKindFromCmmSection Section
    s,
                dataSectionAlignment :: Alignment
    dataSectionAlignment =
                  WasmTypeTag w -> [DataSectionContent] -> Alignment
    forall (w :: WasmType).
    WasmTypeTag w -> [DataSectionContent] -> Alignment
    alignmentFromCmmSection WasmTypeTag w
    ty_word [DataSectionContent]
    cs,
                dataSectionContents :: [DataSectionContent]
    dataSectionContents =
                  case [DataSectionContent]
    cs of
                    [DataASCII ByteString
    buf] -> [ByteString -> DataSectionContent
    DataASCII (ByteString -> DataSectionContent)
    -> ByteString -> DataSectionContent
    forall a b. (a -> b) -> a -> b
    $ ByteString
    buf ByteString -> Word8 -> ByteString
    `BS.snoc` Word8
    0]
                    [DataIncBin String
    p Int
    l] -> [String -> Int -> DataSectionContent
    DataIncBin String
    p Int
    l, Word8 -> DataSectionContent
    DataI8 Word8
    0]
                    [DataSectionContent]
    _ -> [DataSectionContent]
    cs
              }
      wasmModifyM $ \WasmCodeGenState w
    s ->
        WasmCodeGenState w
    s
          { dataSections =
              addToUniqMap (dataSections s) sym sec
          }

    -- | Invoked for each 'CmmProc'.
    onCmmProc :: CLabel -> CmmGraph -> WasmCodeGenM w ()
    onCmmProc :: forall (w :: WasmType). CLabel -> CmmGraph -> WasmCodeGenM w ()
    onCmmProc CLabel
    lbl CmmGraph
    g = do
      ty_word <- WasmCodeGenM w CmmType
    forall (w :: WasmType). WasmCodeGenM w CmmType
    wasmWordCmmTypeM
      onTopSym lbl
      onFuncSym sym [] [ty_word]
      body <- lower_CmmGraph lbl g
      wasmModifyM $ \WasmCodeGenState w
    s -> WasmCodeGenState w
    s {funcBodies = addToUniqMap (funcBodies s) sym body}
      where
        sym :: SymName
    sym = CLabel -> SymName
    symNameFromCLabel CLabel
    lbl

    -- | Invoked for each 'RawCmmDecl'.
    onCmmDecl :: RawCmmDecl -> WasmCodeGenM w ()
    onCmmDecl :: forall (w :: WasmType). RawCmmDecl -> WasmCodeGenM w ()
    onCmmDecl RawCmmDecl
    decl
      | Just (InitOrFini
    iof, [CLabel]
    lbls) <- RawCmmDecl -> Maybe (InitOrFini, [CLabel])
    isInitOrFiniArray RawCmmDecl
    decl = InitOrFini -> [CLabel] -> WasmCodeGenM w ()
    forall (w :: WasmType). InitOrFini -> [CLabel] -> WasmCodeGenM w ()
    onCmmInitFini InitOrFini
    iof [CLabel]
    lbls
    onCmmDecl (CmmData Section
    s (CmmStaticsRaw CLabel
    lbl [CmmStatic]
    statics)) = CLabel -> Section -> [CmmStatic] -> WasmCodeGenM w ()
    forall (w :: WasmType).
    CLabel -> Section -> [CmmStatic] -> WasmCodeGenM w ()
    onCmmData CLabel
    lbl Section
    s [CmmStatic]
    statics
    onCmmDecl (CmmProc LabelMap (GenCmmStatics 'True)
    _ CLabel
    lbl [GlobalReg]
    _ CmmGraph
    g) = CLabel -> CmmGraph -> WasmCodeGenM w ()
    forall (w :: WasmType). CLabel -> CmmGraph -> WasmCodeGenM w ()
    onCmmProc CLabel
    lbl CmmGraph
    g

    -- | Invoked for each 'RawCmmGroup'.
    onCmmGroup :: RawCmmGroup -> WasmCodeGenM w ()
    onCmmGroup :: forall (w :: WasmType). RawCmmGroup -> WasmCodeGenM w ()
    onCmmGroup RawCmmGroup
    cmms = (WasmCodeGenState w -> (# (), WasmCodeGenState w #))
    -> WasmCodeGenM w ()
    forall (w :: WasmType) a.
    (WasmCodeGenState w -> (# a, WasmCodeGenState w #))
    -> WasmCodeGenM w a
    wasmStateM ((WasmCodeGenState w -> (# (), WasmCodeGenState w #))
     -> WasmCodeGenM w ())
    -> (WasmCodeGenState w -> (# (), WasmCodeGenState w #))
    -> WasmCodeGenM w ()
    forall a b. (a -> b) -> a -> b
    $ \WasmCodeGenState w
    s0 ->
      (# (), (WasmCodeGenState w -> RawCmmDecl -> WasmCodeGenState w)
    -> WasmCodeGenState w -> RawCmmGroup -> WasmCodeGenState w
    forall b a. (b -> a -> b) -> b -> [a] -> b
    forall (t :: * -> *) b a.
    Foldable t =>
    (b -> a -> b) -> b -> t a -> b
    foldl' (\WasmCodeGenState w
    s RawCmmDecl
    cmm -> WasmCodeGenM w () -> WasmCodeGenState w -> WasmCodeGenState w
    forall (w :: WasmType) a.
    WasmCodeGenM w a -> WasmCodeGenState w -> WasmCodeGenState w
    wasmExecM (RawCmmDecl -> WasmCodeGenM w ()
    forall (w :: WasmType). RawCmmDecl -> WasmCodeGenM w ()
    onCmmDecl RawCmmDecl
    cmm) WasmCodeGenState w
    s) WasmCodeGenState w
    s0 RawCmmGroup
    cmms #)