{-# LANGUAGE DataKinds #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE Strict #-} {-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-} module GHC.CmmToAsm.Wasm (ncgWasm) where import Data.ByteString.Builder import Data.ByteString.Lazy.Char8 (unpack) import Data.Maybe import Data.Semigroup import GHC.Cmm import GHC.Cmm.ContFlowOpt import GHC.Cmm.GenericOpt import GHC.CmmToAsm.Config import GHC.CmmToAsm.Wasm.Asm import GHC.CmmToAsm.Wasm.FromCmm import GHC.CmmToAsm.Wasm.Types import GHC.StgToCmm.CgUtils (CgStream) import GHC.Data.Stream (StreamS (..), runStream, liftIO) import GHC.Driver.DynFlags import GHC.Platform import GHC.Prelude import GHC.Settings import GHC.Types.Unique.DSM import GHC.Unit import GHC.Utils.Logger import GHC.Utils.Outputable (text) import System.IO ncgWasm :: NCGConfig -> Logger -> Platform -> ToolSettings -> ModLocation -> Handle -> CgStream RawCmmGroup a -> UniqDSMT IO a ncgWasm ncg_config logger platform ts loc h cmms = do (r, s) <- streamCmmGroups ncg_config platform cmms outputWasm $ "# " <> string7 (fromJust $ ml_hs_file loc) <> "\n\n" -- See Note [WasmTailCall] let cfg = (defaultWasmAsmConfig s) { pic = ncgPIC ncg_config, tailcall = doTailCall ts } outputWasm $ execWasmAsmM cfg $ asmTellEverything TagI32 s pure r where outputWasm builder = liftIO $ do putDumpFileMaybe logger Opt_D_dump_asm "Asm Code" FormatASM (text . unpack $ toLazyByteString builder) hPutBuilder h builder streamCmmGroups :: NCGConfig -> Platform -> CgStream RawCmmGroup a -> UniqDSMT IO (a, WasmCodeGenState 'I32) streamCmmGroups ncg_config platform cmms = withDUS $ \us -> do (r,s) <- go (initialWasmCodeGenState platform us) $ runStream cmms return ((r,s), wasmDUniqSupply s) where go s (Done r) = pure (r, s) go s (Effect m) = do (a, us') <- runUDSMT (wasmDUniqSupply s) m go s{wasmDUniqSupply = us'} a go s (Yield decls k) = go (wasmExecM (onCmmGroup $ map opt decls) s) k where -- Run the generic cmm optimizations like other NCGs, followed -- by a late control-flow optimization pass that does shrink -- the CFG block count in some cases. opt decl = case decl of CmmData {} -> decl CmmProc {} -> CmmProc info lbl live $ cmmCfgOpts False graph where (CmmProc info lbl live graph, _) = cmmToCmm ncg_config decl doTailCall :: ToolSettings -> Bool doTailCall ts = Option "-mtail-call" `elem` as_args where (_, as_args) = toolSettings_pgm_a ts