    -- | C code generator.  This module can convert a correct ImpCode
    -- program to an equivalent C program.  This C program is expected to
    -- be converted to WebAssembly, so we also produce the intended
    -- JavaScript wrapper.
    module Futhark.CodeGen.Backends.MulticoreWASM
      ( compileProg,
        runServer,
        libraryExports,
        GC.CParts (..),
        GC.asLibrary,
        GC.asExecutable,
        GC.asServer,
      )
    where

    import Data.Maybe
    import Data.Text qualified as T
    import Futhark.CodeGen.Backends.GenericC qualified as GC
    import Futhark.CodeGen.Backends.GenericWASM
    import Futhark.CodeGen.Backends.MulticoreC qualified as MC
    import Futhark.CodeGen.Backends.MulticoreC.Boilerplate (generateBoilerplate)
    import Futhark.CodeGen.ImpCode.Multicore qualified as Imp
    import Futhark.CodeGen.ImpGen.Multicore qualified as ImpGen
    import Futhark.IR.MCMem
    import Futhark.MonadFreshNames

    -- | Compile Futhark program to wasm-multicore program (some assembly
    -- required).
    --
    -- The triple that is returned consists of
    --
    -- * Generated C code (to be passed to Emscripten).
    --
    -- * JavaScript wrapper code that presents a nicer interface to the
    --   Emscripten-produced code (this should be put in a @.class.js@
    --   file by itself).
    --
    -- * Options that should be passed to @emcc@.
    compileProg ::
      (MonadFreshNames m) =>
      T.Text ->
      Prog MCMem ->
      m (ImpGen.Warnings, (GC.CParts, T.Text, [String]))
    compileProg :: forall (m :: * -> *).
    MonadFreshNames m =>
    Text -> Prog MCMem -> m (Warnings, (CParts, Text, [String]))
    compileProg Text
    version Prog MCMem
    prog = do
      (Warnings
    ws, Definitions Multicore
    prog') <- Prog MCMem -> m (Warnings, Definitions Multicore)
    forall (m :: * -> *).
    MonadFreshNames m =>
    Prog MCMem -> m (Warnings, Definitions Multicore)
    ImpGen.compileProg Prog MCMem
    prog

      CParts
    prog'' <-
        Text
    -> Text
    -> ParamMap
    -> Operations Multicore ()
    -> CompilerM Multicore () ()
    -> Text
    -> (Space, [Space])
    -> [Option]
    -> Definitions Multicore
    -> m CParts
    forall (m :: * -> *) op.
    MonadFreshNames m =>
    Text
    -> Text
    -> ParamMap
    -> Operations op ()
    -> CompilerM op () ()
    -> Text
    -> (Space, [Space])
    -> [Option]
    -> Definitions op
    -> m CParts
    GC.compileProg
          Text
    "wasm_multicore"
          Text
    version
          ParamMap
    forall a. Monoid a => a
    mempty
          Operations Multicore ()
    forall s. Operations Multicore s
    MC.operations
          CompilerM Multicore () ()
    forall op s. CompilerM op s ()
    generateBoilerplate
          Text
    ""
          (Space
    DefaultSpace, [Space
    DefaultSpace])
          [Option]
    MC.cliOptions
          Definitions Multicore
    prog'

      (Warnings, (CParts, Text, [String]))
    -> m (Warnings, (CParts, Text, [String]))
    forall a. a -> m a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure
        ( Warnings
    ws,
          ( CParts
    prog'',
            [JSEntryPoint] -> Text
    javascriptWrapper (Definitions Multicore -> [JSEntryPoint]
    fRepMyRep Definitions Multicore
    prog'),
            String
    "_futhark_context_config_set_num_threads" String -> [String] -> [String]
    forall a. a -> [a] -> [a]
    : [JSEntryPoint] -> [String]
    emccExportNames (Definitions Multicore -> [JSEntryPoint]
    fRepMyRep Definitions Multicore
    prog')
          )
        )

    fRepMyRep :: Imp.Definitions Imp.Multicore -> [JSEntryPoint]
    fRepMyRep :: Definitions Multicore -> [JSEntryPoint]
    fRepMyRep Definitions Multicore
    prog =
      let Imp.Functions [(Name, Function Multicore)]
    fs = Definitions Multicore -> Functions Multicore
    forall a. Definitions a -> Functions a
    Imp.defFuns Definitions Multicore
    prog
          function :: FunctionT a -> Maybe JSEntryPoint
    function (Imp.Function Maybe EntryPoint
    entry [Param]
    _ [Param]
    _ Code a
    _) = do
            Imp.EntryPoint Name
    n [(Uniqueness, ExternalValue)]
    res [((Name, Uniqueness), ExternalValue)]
    args <- Maybe EntryPoint
    entry
            JSEntryPoint -> Maybe JSEntryPoint
    forall a. a -> Maybe a
    Just (JSEntryPoint -> Maybe JSEntryPoint)
    -> JSEntryPoint -> Maybe JSEntryPoint
    forall a b. (a -> b) -> a -> b
    $
              JSEntryPoint
                { name :: String
    name = Name -> String
    nameToString Name
    n,
                  parameters :: [String]
    parameters = (((Name, Uniqueness), ExternalValue) -> String)
    -> [((Name, Uniqueness), ExternalValue)] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map (ExternalValue -> String
    extToString (ExternalValue -> String)
    -> (((Name, Uniqueness), ExternalValue) -> ExternalValue)
    -> ((Name, Uniqueness), ExternalValue)
    -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ((Name, Uniqueness), ExternalValue) -> ExternalValue
    forall a b. (a, b) -> b
    snd) [((Name, Uniqueness), ExternalValue)]
    args,
                  ret :: [String]
    ret = ((Uniqueness, ExternalValue) -> String)
    -> [(Uniqueness, ExternalValue)] -> [String]
    forall a b. (a -> b) -> [a] -> [b]
    map (ExternalValue -> String
    extToString (ExternalValue -> String)
    -> ((Uniqueness, ExternalValue) -> ExternalValue)
    -> (Uniqueness, ExternalValue)
    -> String
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Uniqueness, ExternalValue) -> ExternalValue
    forall a b. (a, b) -> b
    snd) [(Uniqueness, ExternalValue)]
    res
                }
       in ((Name, Function Multicore) -> Maybe JSEntryPoint)
    -> [(Name, Function Multicore)] -> [JSEntryPoint]
    forall a b. (a -> Maybe b) -> [a] -> [b]
    mapMaybe (Function Multicore -> Maybe JSEntryPoint
    forall {a}. FunctionT a -> Maybe JSEntryPoint
    function (Function Multicore -> Maybe JSEntryPoint)
    -> ((Name, Function Multicore) -> Function Multicore)
    -> (Name, Function Multicore)
    -> Maybe JSEntryPoint
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Name, Function Multicore) -> Function Multicore
    forall a b. (a, b) -> b
    snd) [(Name, Function Multicore)]
    fs