Skip to content

Commit ebd270c

Browse files
Apply Clash specific modifications to src-bin-9.12
1 parent 236e0bb commit ebd270c

File tree

7 files changed

+316
-75
lines changed

7 files changed

+316
-75
lines changed

clash-ghc/src-bin-9.12/Clash/GHCi/Leak.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
{-# LANGUAGE RecordWildCards, LambdaCase #-}
2-
module GHCi.Leak
2+
module Clash.GHCi.Leak
33
( LeakIndicators
44
, getLeakIndicators
55
, checkLeakIndicators
66
) where
77

8+
import Clash.GHCi.Util
89
import Control.Monad
910
import Data.Bits
1011
import Foreign.Ptr (ptrToIntPtr, intPtrToPtr)
1112
import GHC
1213
import GHC.Ptr (Ptr (..))
13-
import GHCi.Util
1414
import GHC.Driver.Env
1515
import GHC.Driver.Ppr
1616
import GHC.Utils.Outputable

clash-ghc/src-bin-9.12/Clash/GHCi/UI.hs

Lines changed: 176 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,20 @@
2222
--
2323
-----------------------------------------------------------------------------
2424

25-
module GHCi.UI (
25+
module Clash.GHCi.UI (
2626
interactiveUI,
2727
GhciSettings(..),
2828
defaultGhciSettings,
2929
ghciCommands,
30-
ghciWelcomeMsg
30+
ghciWelcomeMsg,
31+
makeHDL
3132
) where
3233

3334
-- GHCi
34-
import qualified GHCi.UI.Monad as GhciMonad ( args, runStmt, runDecls' )
35-
import GHCi.UI.Monad hiding ( args, runStmt )
36-
import GHCi.UI.Info
37-
import GHCi.UI.Exception
35+
import qualified Clash.GHCi.UI.Monad as GhciMonad ( args, runStmt, runDecls' )
36+
import Clash.GHCi.UI.Monad hiding ( args, runStmt )
37+
import Clash.GHCi.UI.Info
38+
import Clash.GHCi.UI.Exception
3839
import GHC.Runtime.Debugger
3940
import GHC.Runtime.Eval (mkTopLevEnv)
4041

@@ -96,7 +97,6 @@ import GHC.Utils.Logger
9697

9798
-- Other random utilities
9899
import GHC.Types.Basic hiding ( isTopLevel )
99-
import GHC.Settings.Config
100100
import GHC.Data.Graph.Directed
101101
import GHC.Utils.Encoding
102102
import GHC.Data.FastString
@@ -170,9 +170,27 @@ import GHC.IO.Exception ( IOErrorType(InvalidArgument) )
170170
import GHC.IO.Handle ( hFlushAll )
171171
import GHC.TopHandler ( topHandler )
172172

173-
import GHCi.Leak
173+
import Clash.GHCi.Leak
174174
import qualified GHC.Unit.Module.Graph as GHC
175175

176+
-- clash additions
177+
import Clash.Backend (Backend(initBackend, hdlKind, primDirs))
178+
import Clash.Backend.SystemVerilog (SystemVerilogState)
179+
import Clash.Backend.VHDL (VHDLState)
180+
import Clash.Backend.Verilog (VerilogState)
181+
import qualified Clash.Driver
182+
import Clash.Driver.Bool (fromGhcOverridingBool)
183+
import Clash.Driver.Types (ClashOpts(..), ClashEnv(..), ClashDesign(..))
184+
import Clash.GHC.Evaluator
185+
import Clash.GHC.GenerateBindings
186+
import Clash.GHC.NetlistTypes
187+
import Clash.GHC.PartialEval
188+
import Clash.GHCi.Common
189+
import Clash.Util (clashLibVersion, reportTimeDiff)
190+
import Data.Proxy
191+
import qualified Data.Time.Clock as Clock
192+
import qualified Paths_clash_ghc
193+
176194
-----------------------------------------------------------------------------
177195

178196
data GhciSettings = GhciSettings {
@@ -183,22 +201,23 @@ data GhciSettings = GhciSettings {
183201
defPromptCont :: PromptFunction
184202
}
185203

186-
defaultGhciSettings :: GhciSettings
187-
defaultGhciSettings =
204+
defaultGhciSettings :: IORef ClashOpts -> GhciSettings
205+
defaultGhciSettings opts =
188206
GhciSettings {
189-
availableCommands = ghciCommands,
207+
availableCommands = ghciCommands opts,
190208
shortHelpText = defShortHelpText,
191209
defPrompt = default_prompt,
192210
defPromptCont = default_prompt_cont,
193211
fullHelpText = defFullHelpText
194212
}
195213

196214
ghciWelcomeMsg :: String
197-
ghciWelcomeMsg = "GHCi, version " ++ cProjectVersion ++
198-
": https://www.haskell.org/ghc/ :? for help"
215+
ghciWelcomeMsg = "Clashi, version " ++ Data.Version.showVersion Paths_clash_ghc.version ++
216+
" (using clash-lib, version " ++ Data.Version.showVersion clashLibVersion ++
217+
"):\nhttps://clash-lang.org/ :? for help"
199218

200-
ghciCommands :: [Command]
201-
ghciCommands = map mkCmd [
219+
ghciCommands :: IORef ClashOpts -> [Command]
220+
ghciCommands opts = map mkCmd [
202221
-- Hugs users are accustomed to :e, so make sure it doesn't overlap
203222
("?", keepGoing help, noCompletion),
204223
("add", keepGoingPaths addModule, completeFilename),
@@ -252,6 +271,9 @@ ghciCommands = map mkCmd [
252271
("undef", keepGoing undefineMacro, completeMacro),
253272
("unset", keepGoing unsetOptions, completeSetOptions),
254273
("where", keepGoing whereCmd, noCompletion),
274+
("vhdl", keepGoingPaths (makeVHDL opts), completeHomeModuleOrFile),
275+
("verilog", keepGoingPaths (makeVerilog opts), completeHomeModuleOrFile),
276+
("systemverilog",keepGoingPaths (makeSystemVerilog opts), completeHomeModuleOrFile),
255277
("instances", keepGoing' instancesCmd, completeExpression)
256278
] ++ map mkCmdHidden [ -- hidden commands
257279
("all-types", keepGoing' allTypesCmd),
@@ -384,6 +406,12 @@ defFullHelpText =
384406
" :undef <cmd> undefine user-defined command :<cmd>\n" ++
385407
" ::<cmd> run the builtin command\n" ++
386408
" :!<command> run the shell command <command>\n" ++
409+
" :vhdl synthesize currently loaded module to vhdl\n" ++
410+
" :vhdl [<module>] synthesize specified modules/files to vhdl\n" ++
411+
" :verilog synthesize currently loaded module to verilog\n" ++
412+
" :verilog [<module>] synthesize specified modules/files to verilog\n" ++
413+
" :systemverilog synthesize currently loaded module to systemverilog\n" ++
414+
" :systemverilog [<module>] synthesize specified modules/files to systemverilog\n" ++
387415
"\n" ++
388416
" -- Commands for debugging:\n" ++
389417
"\n" ++
@@ -483,8 +511,8 @@ default_progname = "<interactive>"
483511
default_stop = ""
484512

485513
default_prompt, default_prompt_cont :: PromptFunction
486-
default_prompt = generatePromptFunctionFromString "ghci> "
487-
default_prompt_cont = generatePromptFunctionFromString "ghci| "
514+
default_prompt = generatePromptFunctionFromString "clashi> "
515+
default_prompt_cont = generatePromptFunctionFromString "clashi| "
488516

489517
default_args :: [String]
490518
default_args = []
@@ -649,31 +677,32 @@ ghciLogAction lastErrLocations old_log_action
649677
getAppDataFile :: XdgDirectory -> FilePath -> IO (Maybe FilePath)
650678
getAppDataFile xdgDir file = do
651679
xdgAppDir <-
652-
tryIO (getXdgDirectory xdgDir "ghc") >>= \case
680+
tryIO (getXdgDirectory xdgDir "clash") >>= \case
653681
Left _ -> pure Nothing
654682
Right dir -> flip catchIO (const $ pure Nothing) $ do
655683
createDirectoryIfMissing False dir
656684
pure $ Just dir
657685
appDir <-
658-
tryIO (getAppUserDataDirectory "ghc") >>= \case
686+
tryIO (getAppUserDataDirectory "clash") >>= \case
659687
Right dir ->
660688
doesDirectoryExist dir >>= \case
661689
True -> pure $ Just dir
662690
False -> pure xdgAppDir
663691
Left _ -> pure xdgAppDir
664692
pure $ appDir >>= \dir -> Just $ dir </> file
665693

694+
666695
runGHCi :: [(FilePath, Maybe UnitId, Maybe Phase)] -> Maybe [String] -> GHCi ()
667696
runGHCi paths maybe_exprs = do
668697
dflags <- getDynFlags
669698
let
670699
ignore_dot_ghci = gopt Opt_IgnoreDotGhci dflags
671700

672-
appDataCfg = liftIO $ getAppDataFile XdgConfig "ghci.conf"
701+
appDataCfg = liftIO $ getAppDataFile XdgConfig "clashi.conf"
673702

674703
homeCfg = do
675704
liftIO $ tryIO (getEnv "HOME") >>= \case
676-
Right home -> pure $ Just $ home </> ".ghci"
705+
Right home -> pure $ Just $ home </> ".clashi"
677706
_ -> pure Nothing
678707

679708
canonicalizePath' :: FilePath -> IO (Maybe FilePath)
@@ -698,7 +727,7 @@ runGHCi paths maybe_exprs = do
698727
-- Also, let the user silence the message with -v0
699728
-- (the default verbosity in GHCi is 1).
700729
when (isNothing maybe_exprs && verbosity dflags > 0) $
701-
liftIO $ putStrLn ("Loaded GHCi configuration from " ++ file)
730+
liftIO $ putStrLn ("Loaded Clashi configuration from " ++ file)
702731

703732
--
704733

@@ -713,7 +742,7 @@ runGHCi paths maybe_exprs = do
713742
liftIO . fmap (nub . catMaybes) $ mapM canonicalizePath' checkedPaths
714743

715744
localCfg <- do
716-
let path = ".ghci"
745+
let path = ".clashi"
717746
ok <- liftIO $ checkFileAndDirPerms path
718747
if ok then liftIO $ canonicalizePath' path else pure Nothing
719748

@@ -766,10 +795,21 @@ runGHCi paths maybe_exprs = do
766795
case maybe_exprs of
767796
Nothing ->
768797
do
798+
-- Set different defaulting rules (See #280)
799+
runGHCiExpressions
800+
["default ((), [], Prelude.Integer, Prelude.Int, Prelude.Double, Prelude.String)"]
801+
769802
-- enter the interactive loop
770803
runGHCiInput $ runCommands $ nextInputLine show_prompt is_tty
771804
Just exprs -> do
772805
-- just evaluate the expression we were given
806+
runGHCiExpressions exprs
807+
808+
-- and finally, exit
809+
liftIO $ when (verbosity dflags > 0) $ putStrLn "Leaving Clashi."
810+
811+
runGHCiExpressions :: [String] -> GHCi ()
812+
runGHCiExpressions exprs = do
773813
enqueueCommands exprs
774814
let hdle e = do st <- getGHCiState
775815
-- flush the interpreter's stdout/stderr on exit (#3890)
@@ -787,9 +827,6 @@ runGHCi paths maybe_exprs = do
787827
(return Nothing)
788828
return ()
789829

790-
-- and finally, exit
791-
liftIO $ when (verbosity dflags > 0) $ putStrLn "Leaving GHCi."
792-
793830
runGHCiInput :: InputT GHCi a -> GHCi a
794831
runGHCiInput f = do
795832
dflags <- getDynFlags
@@ -798,8 +835,8 @@ runGHCiInput f = do
798835
currentDirectory <- liftIO getCurrentDirectory
799836

800837
histFile <- case (ghciHistory, localGhciHistory) of
801-
(True, True) -> pure $ Just $ currentDirectory </> ".ghci_history"
802-
(True, _) -> liftIO $ getAppDataFile XdgData "ghci_history"
838+
(True, True) -> pure $ Just $ currentDirectory </> ".clashi_history"
839+
(True, _) -> liftIO $ getAppDataFile XdgData "clashi_history"
803840
_ -> pure Nothing
804841

805842
runInputT
@@ -2346,6 +2383,115 @@ runExceptGhciMonad act = handleSourceError printGhciException $
23462383
exceptT :: Applicative m => Either e a -> ExceptT e m a
23472384
exceptT = ExceptT . pure
23482385

2386+
makeHDL'
2387+
:: forall backend
2388+
. Backend backend
2389+
=> Proxy backend
2390+
-> IORef ClashOpts
2391+
-> [FilePath]
2392+
-> InputT GHCi ()
2393+
makeHDL' backend opts lst = go =<< case lst of
2394+
srcs@(_:_) -> return srcs
2395+
[] -> do
2396+
modGraph <- GHC.getModuleGraph
2397+
let sortedGraph =
2398+
-- TODO: this might break backpack
2399+
filterToposortToModules $
2400+
GHC.topSortModuleGraph False modGraph Nothing
2401+
return $ case (reverse sortedGraph) of
2402+
((AcyclicSCC top) : _) -> maybeToList $ (GHC.ml_hs_file . GHC.ms_location) top
2403+
_ -> []
2404+
where
2405+
go srcs = do
2406+
dflags <- GHC.getSessionDynFlags
2407+
goX dflags srcs `MC.finally` recover dflags
2408+
2409+
goX dflags srcs = do
2410+
-- Issue #439 step 1
2411+
(dflagsX,_,_) <- parseDynamicFlagsCmdLine dflags
2412+
[ noLoc "-fobject-code" -- For #439
2413+
, noLoc "-fforce-recomp" -- Actually compile to object-code
2414+
, noLoc "-keep-tmp-files" -- To prevent linker errors from
2415+
-- multiple calls to :hdl command
2416+
]
2417+
_ <- GHC.setSessionDynFlags dflagsX
2418+
reloadModule ""
2419+
-- Issue #439 step 2
2420+
-- Unload any object files
2421+
-- This fixes: https://github.com/clash-lang/clash-compiler/issues/439#issuecomment-522015868
2422+
env <- GHC.getSession
2423+
liftIO (Loader.unload (hscInterp env) env [])
2424+
-- Finally generate the HDL
2425+
makeHDL backend (return ()) opts srcs
2426+
2427+
recover dflags = do
2428+
_ <- GHC.setSessionDynFlags dflags
2429+
reloadModule ""
2430+
2431+
makeHDL
2432+
:: forall backend m
2433+
. (GHC.GhcMonad m, Backend backend)
2434+
=> Proxy backend
2435+
-> Ghc ()
2436+
-> IORef ClashOpts
2437+
-> [FilePath]
2438+
-> m ()
2439+
makeHDL Proxy startAction optsRef srcs = do
2440+
dflags <- GHC.getSessionDynFlags
2441+
liftIO $ do startTime <- Clock.getCurrentTime
2442+
opts0 <- readIORef optsRef
2443+
let opts1 = opts0 { opt_color = fromGhcOverridingBool (useColor dflags) }
2444+
let iw = opt_intWidth opts1
2445+
hdl = hdlKind backend
2446+
-- determine whether `-outputdir` was used
2447+
outputDir = do odir <- objectDir dflags
2448+
hidir <- hiDir dflags
2449+
sdir <- stubDir dflags
2450+
ddir <- dumpDir dflags
2451+
if all (== odir) [hidir,sdir,ddir]
2452+
then Just odir
2453+
else Nothing
2454+
idirs = importPaths dflags
2455+
opts2 = opts1 { opt_hdlDir = maybe outputDir Just (opt_hdlDir opts1)
2456+
, opt_importPaths = idirs}
2457+
backend = initBackend @backend opts2
2458+
2459+
checkMonoLocalBinds dflags
2460+
checkImportDirs opts0 idirs
2461+
2462+
primDirs_ <- primDirs backend
2463+
2464+
forM_ srcs $ \src -> do
2465+
-- Generate bindings:
2466+
let dbs = reverse [p | PackageDB (PkgDbPath p) <- packageDBFlags dflags]
2467+
(clashEnv, clashDesign) <- generateBindings opts2 startAction primDirs_ idirs dbs hdl src (Just dflags)
2468+
2469+
let getMain = getMainTopEntity src clashDesign
2470+
mainTopEntity <- traverse getMain (GHC.mainFunIs dflags)
2471+
prepTime <- startTime `deepseq` designBindings clashDesign `deepseq` envTyConMap clashEnv `deepseq` Clock.getCurrentTime
2472+
let prepStartDiff = reportTimeDiff prepTime startTime
2473+
putStrLn $ "GHC+Clash: Loading modules cumulatively took " ++ prepStartDiff
2474+
2475+
-- Generate HDL:
2476+
Clash.Driver.generateHDL
2477+
clashEnv
2478+
clashDesign
2479+
(Just backend)
2480+
(ghcTypeToHWType iw)
2481+
ghcEvaluator
2482+
evaluator
2483+
mainTopEntity
2484+
startTime
2485+
2486+
makeVHDL :: IORef ClashOpts -> [FilePath] -> InputT GHCi ()
2487+
makeVHDL = makeHDL' (Proxy @VHDLState)
2488+
2489+
makeVerilog :: IORef ClashOpts -> [FilePath] -> InputT GHCi ()
2490+
makeVerilog = makeHDL' (Proxy @VerilogState)
2491+
2492+
makeSystemVerilog :: IORef ClashOpts -> [FilePath] -> InputT GHCi ()
2493+
makeSystemVerilog = makeHDL' (Proxy @SystemVerilogState)
2494+
23492495
-----------------------------------------------------------------------------
23502496
-- | @:type@ command. See also Note [TcRnExprMode] in GHC.Tc.Module.
23512497

@@ -2885,7 +3031,6 @@ setGHCContextFromGHCiState = do
28853031
getImplicitPreludeImports :: GhciMonad m
28863032
=> [InteractiveImport] -> m [InteractiveImport]
28873033
getImplicitPreludeImports iidecls = do
2888-
dflags <- GHC.getInteractiveDynFlags
28893034
-- allow :seti to override -XNoImplicitPrelude
28903035
st <- getGHCiState
28913036

@@ -2894,7 +3039,7 @@ getImplicitPreludeImports iidecls = do
28943039
-- of the same module. This means that you can override the prelude import
28953040
-- with "import Prelude hiding (map)", for example.
28963041
let prel_iidecls =
2897-
if xopt LangExt.ImplicitPrelude dflags && not (any isIIModule iidecls)
3042+
if not (any isIIModule iidecls)
28983043
then [ IIDecl imp
28993044
| imp <- prelude_imports st
29003045
, not (any (sameImpModule imp) iidecls) ]
@@ -2924,7 +3069,7 @@ iiModuleName (IIModule m) = m
29243069
iiModuleName (IIDecl d) = unLoc (ideclName d)
29253070

29263071
preludeModuleName :: ModuleName
2927-
preludeModuleName = GHC.mkModuleName "Prelude"
3072+
preludeModuleName = GHC.mkModuleName "Clash.Prelude"
29283073

29293074
sameImpModule :: ImportDecl GhcPs -> InteractiveImport -> Bool
29303075
sameImpModule _ (IIModule _) = False -- we only care about imports here

clash-ghc/src-bin-9.12/Clash/GHCi/UI/Exception.hs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
{-# LANGUAGE TypeFamilies #-}
33
{-# LANGUAGE UndecidableInstances #-}
44
{-# LANGUAGE LambdaCase #-}
5-
module GHCi.UI.Exception(printGhciException, GHCiMessage(..)) where
5+
{-# LANGUAGE NoImplicitPrelude #-}
6+
module Clash.GHCi.UI.Exception(printGhciException, GHCiMessage(..)) where
67

78
import GHC.Prelude
89

0 commit comments

Comments
 (0)