-----------------------------------------------------------------------------
--- $Id: DriverPhases.hs,v 1.25 2003/06/04 15:47:59 simonmar Exp $
+-- $Id: DriverPhases.hs,v 1.38 2005/05/17 11:01:59 simonmar Exp $
--
-- GHC Driver
--
--
-----------------------------------------------------------------------------
-#include "../includes/config.h"
-
module DriverPhases (
+ HscSource(..), isHsBoot, hscSourceString,
Phase(..),
- happensBefore,
+ happensBefore, eqPhase, anyHsc, isStopLn,
startPhase, -- :: String -> Phase
phaseInputExt, -- :: Phase -> String
- haskellish_file, haskellish_suffix,
- haskellish_src_file, haskellish_src_suffix,
- objish_file, objish_suffix,
- cish_file, cish_suffix,
- isExtCore_file, extcoreish_suffix,
- isSourceFile -- :: FilePath -> Bool
+ isHaskellishSuffix,
+ isHaskellSrcSuffix,
+ isObjectSuffix,
+ isCishSuffix,
+ isExtCoreSuffix,
+ isDynLibSuffix,
+ isHaskellUserSrcSuffix,
+ isSourceSuffix,
+
+ isHaskellishFilename,
+ isHaskellSrcFilename,
+ isObjectFilename,
+ isCishFilename,
+ isExtCoreFilename,
+ isDynLibFilename,
+ isHaskellUserSrcFilename,
+ isSourceFilename -- :: FilePath -> Bool
) where
-import DriverUtil
+import Util ( suffixOf )
+import Panic ( panic )
-----------------------------------------------------------------------------
-- Phases
linker | other | - | a.out
-}
+data HscSource
+ = HsSrcFile | HsBootFile | ExtCoreFile
+ deriving( Eq, Ord, Show )
+ -- Ord needed for the finite maps we build in CompManager
+
+
+hscSourceString :: HscSource -> String
+hscSourceString HsSrcFile = ""
+hscSourceString HsBootFile = "[boot]"
+hscSourceString ExtCoreFile = "[ext core]"
+
+isHsBoot :: HscSource -> Bool
+isHsBoot HsBootFile = True
+isHsBoot other = False
+
data Phase
- = Unlit
- | Cpp
- | HsPp
- | Hsc
+ = Unlit HscSource
+ | Cpp HscSource
+ | HsPp HscSource
+ | Hsc HscSource
| Cc
| HCc -- Haskellised C (as opposed to vanilla C) compilation
| Mangle -- assembly mangling, now done by a separate script.
| SplitMangle -- after mangler if splitting
| SplitAs
| As
- | Ln
-#ifdef ILX
- | Ilx2Il
- | Ilasm
-#endif
+ | CmmCpp -- pre-process Cmm source
+ | Cmm -- parse & compile Cmm code
+
+ -- The final phase is a pseudo-phase that tells the pipeline to stop.
+ -- There is no runPhase case for it.
+ | StopLn -- Stop, but linking will follow, so generate .o file
deriving (Eq, Show)
+anyHsc :: Phase
+anyHsc = Hsc (panic "anyHsc")
+
+isStopLn :: Phase -> Bool
+isStopLn StopLn = True
+isStopLn other = False
+
+eqPhase :: Phase -> Phase -> Bool
+-- Equality of constructors, ignoring the HscSource field
+-- NB: the HscSource field can be 'bot'; see anyHsc above
+eqPhase (Unlit _) (Unlit _) = True
+eqPhase (Cpp _) (Cpp _) = True
+eqPhase (HsPp _) (HsPp _) = True
+eqPhase (Hsc _) (Hsc _) = True
+eqPhase Cc Cc = True
+eqPhase HCc HCc = True
+eqPhase Mangle Mangle = True
+eqPhase SplitMangle SplitMangle = True
+eqPhase SplitAs SplitAs = True
+eqPhase As As = True
+eqPhase CmmCpp CmmCpp = True
+eqPhase Cmm Cmm = True
+eqPhase StopLn StopLn = True
+eqPhase _ _ = False
+
-- Partial ordering on phases: we want to know which phases will occur before
-- which others. This is used for sanity checking, to ensure that the
-- pipeline will stop at some point (see DriverPipeline.runPipeline).
-x `happensBefore` y
- | x `elem` haskell_pipe = y `elem` tail (dropWhile (/= x) haskell_pipe)
- | x `elem` c_pipe = y `elem` tail (dropWhile (/= x) c_pipe)
- | otherwise = False
+StopLn `happensBefore` y = False
+x `happensBefore` y = after_x `eqPhase` y || after_x `happensBefore` y
+ where
+ after_x = nextPhase x
-haskell_pipe = [Unlit,Cpp,HsPp,Hsc,HCc,Mangle,As,Ln]
-c_pipe = [Cc,As,Ln]
+nextPhase :: Phase -> Phase
+-- A conservative approximation the next phase, used in happensBefore
+nextPhase (Unlit sf) = Cpp sf
+nextPhase (Cpp sf) = HsPp sf
+nextPhase (HsPp sf) = Hsc sf
+nextPhase (Hsc sf) = HCc
+nextPhase HCc = Mangle
+nextPhase Mangle = SplitMangle
+nextPhase SplitMangle = As
+nextPhase As = SplitAs
+nextPhase SplitAs = StopLn
+nextPhase Cc = As
+nextPhase CmmCpp = Cmm
+nextPhase Cmm = HCc
+nextPhase StopLn = panic "nextPhase: nothing after StopLn"
-- the first compilation phase for a given file is determined
-- by its suffix.
-startPhase "lhs" = Unlit
-startPhase "hs" = Cpp
-startPhase "hscpp" = HsPp
-startPhase "hspp" = Hsc
-startPhase "hcr" = Hsc
-startPhase "hc" = HCc
-startPhase "c" = Cc
-startPhase "cpp" = Cc
-startPhase "C" = Cc
-startPhase "cc" = Cc
-startPhase "cxx" = Cc
-startPhase "raw_s" = Mangle
-startPhase "s" = As
-startPhase "S" = As
-startPhase "o" = Ln
-startPhase _ = Ln -- all unknown file types
-
--- the output suffix for a given phase is uniquely determined by
--- the input requirements of the next phase.
-phaseInputExt Unlit = "lhs"
-phaseInputExt Cpp = "lpp" -- intermediate only
-phaseInputExt HsPp = "hscpp"
-phaseInputExt Hsc = "hspp"
-phaseInputExt HCc = "hc"
-phaseInputExt Cc = "c"
-phaseInputExt Mangle = "raw_s"
-phaseInputExt SplitMangle = "split_s" -- not really generated
-phaseInputExt As = "s"
-phaseInputExt SplitAs = "split_s" -- not really generated
-phaseInputExt Ln = "o"
+startPhase "lhs" = Unlit HsSrcFile
+startPhase "lhs-boot" = Unlit HsBootFile
+startPhase "hs" = Cpp HsSrcFile
+startPhase "hs-boot" = Cpp HsBootFile
+startPhase "hscpp" = HsPp HsSrcFile
+startPhase "hspp" = Hsc HsSrcFile
+startPhase "hcr" = Hsc ExtCoreFile
+startPhase "hc" = HCc
+startPhase "c" = Cc
+startPhase "cpp" = Cc
+startPhase "C" = Cc
+startPhase "cc" = Cc
+startPhase "cxx" = Cc
+startPhase "raw_s" = Mangle
+startPhase "s" = As
+startPhase "S" = As
+startPhase "o" = StopLn
+startPhase "cmm" = CmmCpp
+startPhase "cmmcpp" = Cmm
+startPhase _ = StopLn -- all unknown file types
+
+-- This is used to determine the extension for the output from the
+-- current phase (if it generates a new file). The extension depends
+-- on the next phase in the pipeline.
+phaseInputExt (Unlit HsSrcFile) = "lhs"
+phaseInputExt (Unlit HsBootFile) = "lhs-boot"
+phaseInputExt (Unlit ExtCoreFile) = "lhcr"
+phaseInputExt (Cpp _) = "lpp" -- intermediate only
+phaseInputExt (HsPp _) = "hscpp" -- intermediate only
+phaseInputExt (Hsc _) = "hspp" -- intermediate only
+ -- NB: as things stand, phaseInputExt (Hsc x) must not evaluate x
+ -- because runPipeline uses the StopBefore phase to pick the
+ -- output filename. That could be fixed, but watch out.
+phaseInputExt HCc = "hc"
+phaseInputExt Cc = "c"
+phaseInputExt Mangle = "raw_s"
+phaseInputExt SplitMangle = "split_s" -- not really generated
+phaseInputExt As = "s"
+phaseInputExt SplitAs = "split_s" -- not really generated
+phaseInputExt CmmCpp = "cmm"
+phaseInputExt Cmm = "cmmcpp"
+phaseInputExt StopLn = "o"
#ifdef ILX
-phaseInputExt Ilx2Il = "ilx"
-phaseInputExt Ilasm = "il"
+phaseInputExt Ilx2Il = "ilx"
+phaseInputExt Ilasm = "il"
#endif
-haskellish_suffix = (`elem` [ "hs", "lhs", "hspp", "hscpp", "hcr", "hc", "raw_s" ])
-haskellish_src_suffix = (`elem` [ "hs", "lhs", "hspp", "hscpp", "hcr"])
-cish_suffix = (`elem` [ "c", "cpp", "C", "cc", "cxx", "s", "S" ])
-extcoreish_suffix = (`elem` [ "hcr" ])
+haskellish_src_suffixes = haskellish_user_src_suffixes ++
+ [ "hspp", "hscpp", "hcr", "cmm" ]
+haskellish_suffixes = haskellish_src_suffixes ++ ["hc", "raw_s"]
+cish_suffixes = [ "c", "cpp", "C", "cc", "cxx", "s", "S" ]
+extcoreish_suffixes = [ "hcr" ]
+haskellish_user_src_suffixes = [ "hs", "lhs", "hs-boot", "lhs-boot" ] -- Will not be deleted as temp files
-- Use the appropriate suffix for the system on which
-- the GHC-compiled code will run
#if mingw32_TARGET_OS || cygwin32_TARGET_OS
-objish_suffix = (`elem` [ "o", "O", "obj", "OBJ" ])
+objish_suffixes = [ "o", "O", "obj", "OBJ" ]
#else
-objish_suffix = (`elem` [ "o" ])
+objish_suffixes = [ "o" ]
#endif
-haskellish_file = haskellish_suffix . getFileSuffix
-haskellish_src_file = haskellish_src_suffix . getFileSuffix
-cish_file = cish_suffix . getFileSuffix
-isExtCore_file = extcoreish_suffix . getFileSuffix
-objish_file = objish_suffix . getFileSuffix
+#ifdef mingw32_TARGET_OS
+dynlib_suffixes = ["dll", "DLL"]
+#elif defined(darwin_TARGET_OS)
+dynlib_suffixes = ["dylib"]
+#else
+dynlib_suffixes = ["so"]
+#endif
+
+isHaskellishSuffix s = s `elem` haskellish_suffixes
+isHaskellSrcSuffix s = s `elem` haskellish_src_suffixes
+isCishSuffix s = s `elem` cish_suffixes
+isExtCoreSuffix s = s `elem` extcoreish_suffixes
+isObjectSuffix s = s `elem` objish_suffixes
+isHaskellUserSrcSuffix s = s `elem` haskellish_user_src_suffixes
+isDynLibSuffix s = s `elem` dynlib_suffixes
+
+isSourceSuffix suff = isHaskellishSuffix suff || isCishSuffix suff
+
+isHaskellishFilename f = isHaskellishSuffix (suffixOf f)
+isHaskellSrcFilename f = isHaskellSrcSuffix (suffixOf f)
+isCishFilename f = isCishSuffix (suffixOf f)
+isExtCoreFilename f = isExtCoreSuffix (suffixOf f)
+isObjectFilename f = isObjectSuffix (suffixOf f)
+isHaskellUserSrcFilename f = isHaskellUserSrcSuffix (suffixOf f)
+isDynLibFilename f = isDynLibSuffix (suffixOf f)
+isSourceFilename f = isSourceSuffix (suffixOf f)
+
-isSourceFile :: FilePath -> Bool
-isSourceFile f =
- haskellish_file f ||
- cish_file f