{-# LANGUAGE CPP #-}
{-# LANGUAGE RecordWildCards #-}
{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
module GHC.Runtime.Interpreter.Wasm (spawnWasmInterp) where
import GHC.Prelude
import GHC.Runtime.Interpreter.Types
#if !defined(mingw32_HOST_OS)
import Control.Concurrent.MVar
import Data.Maybe
import GHC.Data.FastString
import qualified GHC.Data.ShortText as ST
import GHC.Platform
import GHC.Unit
import GHCi.Message
import System.Directory
import System.Environment.Blank
import System.IO
import qualified System.Posix.IO as Posix
import System.Process
#else
import GHC.Utils.Panic
#endif
spawnWasmInterp :: WasmInterpConfig -> IO (ExtInterpInstance ())
#if !defined(mingw32_HOST_OS)
spawnWasmInterp WasmInterpConfig {..} = do
let Just ghci_unit_id =
lookupPackageName
wasmInterpUnitState
(PackageName $ fsLit "ghci")
ghci_unit_info = unsafeLookupUnitId wasmInterpUnitState ghci_unit_id
ghci_so_dirs = map ST.unpack $ unitLibraryDynDirs ghci_unit_info
[ghci_lib_name] = map ST.unpack $ unitLibraries ghci_unit_info
ghci_so_name = ghci_lib_name ++ wasmInterpHsSoSuffix
ghci_so_file = platformHsSOName wasmInterpTargetPlatform ghci_so_name
Just ghci_so_path <- findFile ghci_so_dirs ghci_so_file
(rfd1, wfd1) <- Posix.createPipe
(rfd2, wfd2) <- Posix.createPipe
Posix.setFdOption rfd1 Posix.CloseOnExec True
Posix.setFdOption wfd2 Posix.CloseOnExec True
ghc_env <- getEnvironment
let dyld_env =
[("GHCI_BROWSER", "1") | wasmInterpBrowser]
++ [("GHCI_BROWSER_HOST", wasmInterpBrowserHost), ("GHCI_BROWSER_PORT", show wasmInterpBrowserPort)]
++ [("GHCI_BROWSER_REDIRECT_WASI_CONSOLE", "1") | wasmInterpBrowserRedirectWasiConsole]
++ [("GHCI_BROWSER_PUPPETEER_LAUNCH_OPTS", f) | f <- maybeToList wasmInterpBrowserPuppeteerLaunchOpts]
++ [("GHCI_BROWSER_PLAYWRIGHT_BROWSER_TYPE", f) | f <- maybeToList wasmInterpBrowserPlaywrightBrowserType]
++ [("GHCI_BROWSER_PLAYWRIGHT_LAUNCH_OPTS", f) | f <- maybeToList wasmInterpBrowserPlaywrightLaunchOpts]
++ ghc_env
(_, _, _, ph) <-
createProcess
( proc wasmInterpDyLD $
[wasmInterpLibDir, ghci_so_path, show wfd1, show rfd2]
++ wasmInterpOpts
++ ["+RTS", "-H64m", "-RTS"]
) { env = Just dyld_env }
Posix.closeFd wfd1
Posix.closeFd rfd2
rh <- Posix.fdToHandle rfd1
wh <- Posix.fdToHandle wfd2
hSetBuffering wh NoBuffering
hSetBuffering rh NoBuffering
interpPipe <- mkPipeFromHandles rh wh
pending_frees <- newMVar []
lock <- newMVar ()
pure
$ ExtInterpInstance
{ instProcess =
InterpProcess
{ interpHandle = ph,
interpPipe,
interpLock = lock
},
instPendingFrees = pending_frees,
instExtra = ()
}
#else
spawnWasmInterp :: WasmInterpConfig -> IO (ExtInterpInstance ())
spawnWasmInterp WasmInterpConfig
_ = String -> IO (ExtInterpInstance ())
forall a. HasCallStack => String -> a
sorry String
"Wasm iserv doesn't work on Win32 host yet"
#endif