1 -----------------------------------------------------------------------------
2 -- $Id: DriverPhases.hs,v 1.36 2005/03/31 10:16:38 simonmar Exp $
6 -- (c) The University of Glasgow 2002
8 -----------------------------------------------------------------------------
11 HscSource(..), isHsBoot, hscSourceString,
13 happensBefore, eqPhase, anyHsc, isStopLn,
14 startPhase, -- :: String -> Phase
15 phaseInputExt, -- :: Phase -> String
23 isHaskellUserSrcFilename,
24 isSourceFilename -- :: FilePath -> Bool
27 import Util ( getFileSuffix )
28 import Panic ( panic )
30 -----------------------------------------------------------------------------
34 Phase of the | Suffix saying | Flag saying | (suffix of)
35 compilation system | ``start here''| ``stop after''| output file
37 literate pre-processor | .lhs | - | -
38 C pre-processor (opt.) | - | -E | -
39 Haskell compiler | .hs | -C, -S | .hc, .s
40 C compiler (opt.) | .hc or .c | -S | .s
41 assembler | .s or .S | -c | .o
42 linker | other | - | a.out
46 = HsSrcFile | HsBootFile | ExtCoreFile
47 deriving( Eq, Ord, Show )
48 -- Ord needed for the finite maps we build in CompManager
51 hscSourceString :: HscSource -> String
52 hscSourceString HsSrcFile = ""
53 hscSourceString HsBootFile = "[boot]"
54 hscSourceString ExtCoreFile = "[ext core]"
56 isHsBoot :: HscSource -> Bool
57 isHsBoot HsBootFile = True
58 isHsBoot other = False
66 | HCc -- Haskellised C (as opposed to vanilla C) compilation
67 | Mangle -- assembly mangling, now done by a separate script.
68 | SplitMangle -- after mangler if splitting
71 | CmmCpp -- pre-process Cmm source
72 | Cmm -- parse & compile Cmm code
74 -- The final phase is a pseudo-phase that tells the pipeline to stop.
75 -- There is no runPhase case for it.
76 | StopLn -- Stop, but linking will follow, so generate .o file
80 anyHsc = Hsc (panic "anyHsc")
82 isStopLn :: Phase -> Bool
83 isStopLn StopLn = True
84 isStopLn other = False
86 eqPhase :: Phase -> Phase -> Bool
87 -- Equality of constructors, ignoring the HscSource field
88 -- NB: the HscSource field can be 'bot'; see anyHsc above
89 eqPhase (Unlit _) (Unlit _) = True
90 eqPhase (Cpp _) (Cpp _) = True
91 eqPhase (HsPp _) (HsPp _) = True
92 eqPhase (Hsc _) (Hsc _) = True
94 eqPhase HCc HCc = True
95 eqPhase Mangle Mangle = True
96 eqPhase SplitMangle SplitMangle = True
97 eqPhase SplitAs SplitAs = True
99 eqPhase CmmCpp CmmCpp = True
100 eqPhase Cmm Cmm = True
101 eqPhase StopLn StopLn = True
104 -- Partial ordering on phases: we want to know which phases will occur before
105 -- which others. This is used for sanity checking, to ensure that the
106 -- pipeline will stop at some point (see DriverPipeline.runPipeline).
107 StopLn `happensBefore` y = False
108 x `happensBefore` y = after_x `eqPhase` y || after_x `happensBefore` y
110 after_x = nextPhase x
112 nextPhase :: Phase -> Phase
113 -- A conservative approximation the next phase, used in happensBefore
114 nextPhase (Unlit sf) = Cpp sf
115 nextPhase (Cpp sf) = HsPp sf
116 nextPhase (HsPp sf) = Hsc sf
117 nextPhase (Hsc sf) = HCc
118 nextPhase HCc = Mangle
119 nextPhase Mangle = SplitMangle
120 nextPhase SplitMangle = As
121 nextPhase As = SplitAs
122 nextPhase SplitAs = StopLn
124 nextPhase CmmCpp = Cmm
126 nextPhase StopLn = panic "nextPhase: nothing after StopLn"
128 -- the first compilation phase for a given file is determined
130 startPhase "lhs" = Unlit HsSrcFile
131 startPhase "lhs-boot" = Unlit HsBootFile
132 startPhase "hs" = Cpp HsSrcFile
133 startPhase "hs-boot" = Cpp HsBootFile
134 startPhase "hscpp" = HsPp HsSrcFile
135 startPhase "hspp" = Hsc HsSrcFile
136 startPhase "hcr" = Hsc ExtCoreFile
137 startPhase "hc" = HCc
139 startPhase "cpp" = Cc
142 startPhase "cxx" = Cc
143 startPhase "raw_s" = Mangle
146 startPhase "o" = StopLn
147 startPhase "cmm" = CmmCpp
148 startPhase "cmmcpp" = Cmm
149 startPhase _ = StopLn -- all unknown file types
151 -- This is used to determine the extension for the output from the
152 -- current phase (if it generates a new file). The extension depends
153 -- on the next phase in the pipeline.
154 phaseInputExt (Unlit HsSrcFile) = "lhs"
155 phaseInputExt (Unlit HsBootFile) = "lhs-boot"
156 phaseInputExt (Unlit ExtCoreFile) = "lhcr"
157 phaseInputExt (Cpp _) = "lpp" -- intermediate only
158 phaseInputExt (HsPp _) = "hscpp" -- intermediate only
159 phaseInputExt (Hsc _) = "hspp" -- intermediate only
160 -- NB: as things stand, phaseInputExt (Hsc x) must not evaluate x
161 -- because runPipeline uses the StopBefore phase to pick the
162 -- output filename. That could be fixed, but watch out.
163 phaseInputExt HCc = "hc"
164 phaseInputExt Cc = "c"
165 phaseInputExt Mangle = "raw_s"
166 phaseInputExt SplitMangle = "split_s" -- not really generated
167 phaseInputExt As = "s"
168 phaseInputExt SplitAs = "split_s" -- not really generated
169 phaseInputExt CmmCpp = "cmm"
170 phaseInputExt Cmm = "cmmcpp"
171 phaseInputExt StopLn = "o"
173 phaseInputExt Ilx2Il = "ilx"
174 phaseInputExt Ilasm = "il"
177 haskellish_src_suffixes = haskellish_user_src_suffixes ++
178 [ "hspp", "hscpp", "hcr", "cmm" ]
179 haskellish_suffixes = haskellish_src_suffixes ++ ["hc", "raw_s"]
180 cish_suffixes = [ "c", "cpp", "C", "cc", "cxx", "s", "S" ]
181 extcoreish_suffixes = [ "hcr" ]
182 haskellish_user_src_suffixes = [ "hs", "lhs", "hs-boot", "lhs-boot" ] -- Will not be deleted as temp files
184 -- Use the appropriate suffix for the system on which
185 -- the GHC-compiled code will run
186 #if mingw32_TARGET_OS || cygwin32_TARGET_OS
187 objish_suffixes = [ "o", "O", "obj", "OBJ" ]
189 objish_suffixes = [ "o" ]
192 #ifdef mingw32_TARGET_OS
193 dynlib_suffixes = ["dll", "DLL"]
194 #elif defined(darwin_TARGET_OS)
195 dynlib_suffixes = ["dylib"]
197 dynlib_suffixes = ["so"]
200 isHaskellishFilename f = getFileSuffix f `elem` haskellish_suffixes
201 isHaskellSrcFilename f = getFileSuffix f `elem` haskellish_src_suffixes
202 isCishFilename f = getFileSuffix f `elem` cish_suffixes
203 isExtCoreFilename f = getFileSuffix f `elem` extcoreish_suffixes
204 isObjectFilename f = getFileSuffix f `elem` objish_suffixes
205 isHaskellUserSrcFilename f = getFileSuffix f `elem` haskellish_user_src_suffixes
206 isDynLibFilename f = getFileSuffix f `elem` dynlib_suffixes
208 isSourceFilename :: FilePath -> Bool
210 isHaskellishFilename f ||