wasmedge-hs-0.17.1.0: src/WasmEdge/Configure.hs
{- |
Module : WasmEdge.Configure
Description : WasmEdge configuration context
Copyright : (c) 2026 Tushar Adhatrao
License : MIT
Stability : stable
The 'Configure' context controls which WASM proposals are enabled,
how the compiler behaves, and which built-in host modules are registered.
Example:
@
import WasmEdge.Configure
import WasmEdge.Types
main :: IO ()
main = withConfigure $ \cfg -> do
addProposal cfg SIMD
addProposal cfg Threads
setMaxMemoryPage cfg 65536
setRunMode cfg RunModeAOT
-- pass cfg to VM or Executor...
@
-}
module WasmEdge.Configure
( -- * Configure context
Configure
, createConfigure
, deleteConfigure
, withConfigure
-- * Proposals
, addProposal
, removeProposal
, hasProposal
, setWasmStandard
-- * Host registrations
, addHostRegistration
, removeHostRegistration
, hasHostRegistration
-- * Memory limits
, setMaxMemoryPage
, getMaxMemoryPage
-- * Run mode (0.18+)
, setRunMode
, getRunMode
-- * Interpreter options
, setForceInterpreter
, isForceInterpreter
-- * Compiler options
, CompilerOptions (..)
, defaultCompilerOptions
, setCompilerOptions
, getCompilerOptions
-- * Statistics options
, StatisticsOptions (..)
, defaultStatisticsOptions
, setStatisticsOptions
, getStatisticsOptions
-- * Internal / borrowed pointers
, unsafeConfigurePtr
, borrowConfigure
) where
import Control.Exception (bracket)
import Data.Word (Word32)
import Foreign.C (CBool (..))
import Foreign.Ptr
import WasmEdge.Internal.FFI.Configure
import WasmEdge.Internal.Ownership (OwnedCtx, finalizeOwned, mkOwned, withOwned)
import WasmEdge.Internal.Types (ConfigureTag)
import WasmEdge.Types
-- ---------------------------------------------------------------------------
-- Configure newtype
-- ---------------------------------------------------------------------------
{- | Opaque WasmEdge configuration context.
Create with 'createConfigure' or use 'withConfigure' for scoped use.
-}
newtype Configure = Configure (OwnedCtx ConfigureTag)
-- ---------------------------------------------------------------------------
-- Lifecycle
-- ---------------------------------------------------------------------------
{- | Create a new 'Configure' with default settings.
The caller is responsible for calling 'deleteConfigure' or using 'withConfigure'.
-}
createConfigure :: IO Configure
createConfigure = do
ptr <- c_ConfigureCreate
Configure <$> mkOwned (\p -> c_ConfigureDelete `appFunPtr` p) ptr
{- | Explicitly delete a 'Configure' context.
After this call, the 'Configure' must not be used.
-}
deleteConfigure :: Configure -> IO ()
deleteConfigure (Configure owned) = finalizeOwned owned
{- | Scoped 'Configure' context.
@withConfigure action@ creates a 'Configure', passes it to @action@,
and ensures it is deleted when @action@ completes (even on exception).
-}
withConfigure :: (Configure -> IO a) -> IO a
withConfigure = bracket createConfigure deleteConfigure
-- ---------------------------------------------------------------------------
-- Proposals
-- ---------------------------------------------------------------------------
-- | Add a 'Proposal' to the configuration.
addProposal :: Configure -> Proposal -> IO ()
addProposal (Configure owned) p =
withOwned owned $ \ptr -> c_ConfigureAddProposal ptr (proposalToC p)
-- | Remove a 'Proposal' from the configuration.
removeProposal :: Configure -> Proposal -> IO ()
removeProposal (Configure owned) p =
withOwned owned $ \ptr -> c_ConfigureRemoveProposal ptr (proposalToC p)
-- | Check whether a 'Proposal' is currently enabled.
hasProposal :: Configure -> Proposal -> IO Bool
hasProposal (Configure owned) p =
withOwned owned $ \ptr -> do
CBool b <- c_ConfigureHasProposal ptr (proposalToC p)
pure (b /= 0)
-- | Set all proposals to match a standard preset.
setWasmStandard :: Configure -> WasmStandard -> IO ()
setWasmStandard (Configure owned) std =
withOwned owned $ \ptr -> c_ConfigureSetWASMStandard ptr (wasmStdToC std)
-- ---------------------------------------------------------------------------
-- Host registrations
-- ---------------------------------------------------------------------------
-- | Enable a built-in host module (e.g., WASI).
addHostRegistration :: Configure -> HostRegistration -> IO ()
addHostRegistration (Configure owned) hr =
withOwned owned $ \ptr -> c_ConfigureAddHostRegistration ptr (hrToC hr)
-- | Disable a built-in host module.
removeHostRegistration :: Configure -> HostRegistration -> IO ()
removeHostRegistration (Configure owned) hr =
withOwned owned $ \ptr -> c_ConfigureRemoveHostRegistration ptr (hrToC hr)
-- | Check whether a host module is registered.
hasHostRegistration :: Configure -> HostRegistration -> IO Bool
hasHostRegistration (Configure owned) hr =
withOwned owned $ \ptr -> do
CBool b <- c_ConfigureHasHostRegistration ptr (hrToC hr)
pure (b /= 0)
-- ---------------------------------------------------------------------------
-- Memory limits
-- ---------------------------------------------------------------------------
-- | Set the maximum number of memory pages (default: 65536 = 4 GiB).
setMaxMemoryPage :: Configure -> Word32 -> IO ()
setMaxMemoryPage (Configure owned) n =
withOwned owned $ \ptr -> c_ConfigureSetMaxMemoryPage ptr n
-- | Get the current maximum memory page count.
getMaxMemoryPage :: Configure -> IO Word32
getMaxMemoryPage (Configure owned) =
withOwned owned c_ConfigureGetMaxMemoryPage
-- ---------------------------------------------------------------------------
-- Run mode (0.18+)
-- ---------------------------------------------------------------------------
-- | Set the execution run mode.
setRunMode :: Configure -> RunMode -> IO ()
setRunMode (Configure owned) mode =
withOwned owned $ \ptr -> c_ConfigureSetRunningMode ptr (runModeToC mode)
-- | Get the current run mode.
getRunMode :: Configure -> IO RunMode
getRunMode (Configure owned) =
withOwned owned $ \ptr -> do
n <- c_ConfigureGetRunningMode ptr
pure $ case n of
0 -> RunModeInterpreter
1 -> RunModeAOT
2 -> RunModeLazyJIT
_ -> RunModeInterpreter
-- ---------------------------------------------------------------------------
-- Force interpreter
-- ---------------------------------------------------------------------------
setForceInterpreter :: Configure -> Bool -> IO ()
setForceInterpreter (Configure owned) b =
withOwned owned $ \ptr -> c_ConfigureSetForceInterpreter ptr (CBool (if b then 1 else 0))
isForceInterpreter :: Configure -> IO Bool
isForceInterpreter (Configure owned) =
withOwned owned $ \ptr -> do
CBool b <- c_ConfigureIsForceInterpreter ptr
pure (b /= 0)
-- ---------------------------------------------------------------------------
-- Compiler options
-- ---------------------------------------------------------------------------
-- | AOT compiler options bundle.
data CompilerOptions = CompilerOptions
{ compOptLevel :: !OptimizationLevel
, compOutputFormat :: !OutputFormat
, compDumpIR :: !Bool
, compGenericBinary :: !Bool
, compInterruptible :: !Bool
}
deriving stock (Show, Eq)
defaultCompilerOptions :: CompilerOptions
defaultCompilerOptions =
CompilerOptions
{ compOptLevel = OptO3
, compOutputFormat = OutputNativeSharedLibrary
, compDumpIR = False
, compGenericBinary = False
, compInterruptible = False
}
setCompilerOptions :: Configure -> CompilerOptions -> IO ()
setCompilerOptions (Configure owned) opts =
withOwned owned $ \ptr -> do
c_ConfigureCompilerSetOptimizationLevel ptr (fromIntegral (fromEnum (compOptLevel opts)))
c_ConfigureCompilerSetOutputFormat ptr (fromIntegral (fromEnum (compOutputFormat opts)))
c_ConfigureCompilerSetDumpIR ptr (boolC (compDumpIR opts))
c_ConfigureCompilerSetGenericBinary ptr (boolC (compGenericBinary opts))
c_ConfigureCompilerSetInterruptible ptr (boolC (compInterruptible opts))
getCompilerOptions :: Configure -> IO CompilerOptions
getCompilerOptions (Configure owned) =
withOwned owned $ \ptr -> do
ol <- c_ConfigureCompilerGetOptimizationLevel ptr
fmt <- c_ConfigureCompilerGetOutputFormat ptr
di <- c_ConfigureCompilerIsDumpIR ptr
gb <- c_ConfigureCompilerIsGenericBinary ptr
ir <- c_ConfigureCompilerIsInterruptible ptr
pure
CompilerOptions
{ compOptLevel = toEnum (fromIntegral ol)
, compOutputFormat = toEnum (fromIntegral fmt)
, compDumpIR = fromCBool di
, compGenericBinary = fromCBool gb
, compInterruptible = fromCBool ir
}
-- ---------------------------------------------------------------------------
-- Statistics options
-- ---------------------------------------------------------------------------
data StatisticsOptions = StatisticsOptions
{ statInstructionCounting :: !Bool
, statCostMeasuring :: !Bool
, statTimeMeasuring :: !Bool
}
deriving stock (Show, Eq)
defaultStatisticsOptions :: StatisticsOptions
defaultStatisticsOptions = StatisticsOptions False False False
setStatisticsOptions :: Configure -> StatisticsOptions -> IO ()
setStatisticsOptions (Configure owned) opts =
withOwned owned $ \ptr -> do
c_ConfigureStatisticsSetInstructionCounting ptr (boolC (statInstructionCounting opts))
c_ConfigureStatisticsSetCostMeasuring ptr (boolC (statCostMeasuring opts))
c_ConfigureStatisticsSetTimeMeasuring ptr (boolC (statTimeMeasuring opts))
getStatisticsOptions :: Configure -> IO StatisticsOptions
getStatisticsOptions (Configure owned) =
withOwned owned $ \ptr -> do
ic <- c_ConfigureStatisticsIsInstructionCounting ptr
cm <- c_ConfigureStatisticsIsCostMeasuring ptr
tm <- c_ConfigureStatisticsIsTimeMeasuring ptr
pure
StatisticsOptions
{ statInstructionCounting = fromCBool ic
, statCostMeasuring = fromCBool cm
, statTimeMeasuring = fromCBool tm
}
-- ---------------------------------------------------------------------------
-- Internal helpers
-- ---------------------------------------------------------------------------
-- Enum conversions (kept internal)
proposalToC :: Proposal -> Word32
proposalToC = fromIntegral . fromEnum
wasmStdToC :: WasmStandard -> Word32
wasmStdToC = fromIntegral . fromEnum
hrToC :: HostRegistration -> Word32
hrToC = fromIntegral . fromEnum
runModeToC :: RunMode -> Word32
runModeToC = fromIntegral . fromEnum
boolC :: Bool -> CBool
boolC True = CBool 1
boolC False = CBool 0
fromCBool :: CBool -> Bool
fromCBool (CBool 0) = False
fromCBool _ = True
-- | Extract the underlying pointer for passing to other contexts (unsafe).
unsafeConfigurePtr :: Configure -> IO (Ptr ConfigureTag)
unsafeConfigurePtr (Configure o) = withOwned o pure
-- | Create a borrowed 'Configure' context from an existing pointer.
borrowConfigure :: Ptr ConfigureTag -> IO Configure
borrowConfigure p = Configure <$> mkOwned (\_ -> pure ()) p
-- Helper to apply a FunPtr
appFunPtr :: FunPtr (Ptr a -> IO ()) -> Ptr a -> IO ()
appFunPtr fp p = do
let f = mkDeleter fp
f p
foreign import ccall "dynamic"
mkDeleter :: FunPtr (Ptr a -> IO ()) -> Ptr a -> IO ()