[project @ 2005-01-28 12:55:17 by simonmar]
[ghc-hetmet.git] / ghc / compiler / main / DriverPhases.hs
1 -----------------------------------------------------------------------------
2 -- $Id: DriverPhases.hs,v 1.33 2005/01/28 12:55:33 simonmar Exp $
3 --
4 -- GHC Driver
5 --
6 -- (c) The University of Glasgow 2002
7 --
8 -----------------------------------------------------------------------------
9
10 module DriverPhases (
11    HscSource(..), isHsBoot, hscSourceString,
12    HscTarget(..), Phase(..),
13    happensBefore, eqPhase, anyHsc, isStopPhase,
14    startPhase,          -- :: String -> Phase
15    phaseInputExt,       -- :: Phase -> String
16
17    isHaskellishFilename, 
18    isHaskellSrcFilename,
19    isObjectFilename,
20    isCishFilename,
21    isExtCoreFilename,
22    isDynLibFilename,
23    isHaskellUserSrcFilename,
24    isSourceFilename         -- :: FilePath -> Bool
25  ) where
26
27 import DriverUtil
28 import Panic            ( panic )
29
30 -----------------------------------------------------------------------------
31 -- Phases
32
33 {-
34    Phase of the           | Suffix saying | Flag saying   | (suffix of)
35    compilation system     | ``start here''| ``stop after''| output file
36    
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
43 -}
44
45 data HscSource
46    = HsSrcFile | HsBootFile | ExtCoreFile
47      deriving( Eq, Ord, Show )
48         -- Ord needed for the finite maps we build in CompManager
49
50
51 hscSourceString :: HscSource -> String
52 hscSourceString HsSrcFile   = ""
53 hscSourceString HsBootFile  = "[boot]"
54 hscSourceString ExtCoreFile = "[ext core]"
55
56 isHsBoot :: HscSource -> Bool
57 isHsBoot HsBootFile = True
58 isHsBoot other      = False
59
60 data HscTarget
61   = HscC
62   | HscAsm
63   | HscJava
64   | HscILX
65   | HscInterpreted
66   | HscNothing
67   deriving (Eq, Show)
68
69 data Phase 
70         = Unlit HscSource
71         | Cpp   HscSource
72         | HsPp  HscSource
73         | Hsc   HscSource
74         | Cc
75         | HCc           -- Haskellised C (as opposed to vanilla C) compilation
76         | Mangle        -- assembly mangling, now done by a separate script.
77         | SplitMangle   -- after mangler if splitting
78         | SplitAs
79         | As
80         | CmmCpp        -- pre-process Cmm source
81         | Cmm           -- parse & compile Cmm code
82 #ifdef ILX
83         | Ilx2Il
84         | Ilasm
85 #endif
86
87         -- The final phase is a pseudo-phase that tells the pipeline to stop.
88         -- There is no runPhase case for it.
89         | StopLn        -- Stop, but linking will follow, so generate .o file
90
91   deriving (Show)
92
93 anyHsc :: Phase
94 anyHsc = Hsc (panic "anyHsc")
95
96 isStopPhase :: Phase -> Bool
97 isStopPhase StopLn = True
98 isStopPhase other  = False
99
100 eqPhase :: Phase -> Phase -> Bool
101 -- Equality of constructors, ignoring the HscSource field
102 eqPhase (Unlit _)   (Unlit _)   = True
103 eqPhase (Cpp   _)   (Cpp   _)   = True
104 eqPhase (HsPp  _)   (HsPp  _)   = True
105 eqPhase (Hsc   _)   (Hsc   _)   = True
106 eqPhase Cc          Cc          = True
107 eqPhase HCc         HCc         = True
108 eqPhase Mangle      Mangle      = True
109 eqPhase SplitMangle SplitMangle = True
110 eqPhase SplitAs     SplitAs     = True
111 eqPhase As          As          = True
112 eqPhase CmmCpp      CmmCpp      = True
113 eqPhase Cmm         Cmm         = True
114 eqPhase StopLn      StopLn      = True
115 eqPhase _           _           = False
116
117 -- Partial ordering on phases: we want to know which phases will occur before 
118 -- which others.  This is used for sanity checking, to ensure that the
119 -- pipeline will stop at some point (see DriverPipeline.runPipeline).
120 StopLn `happensBefore` y = False
121 x      `happensBefore` y = after_x `eqPhase` y || after_x `happensBefore` y
122         where
123           after_x = nextPhase x
124
125 nextPhase :: Phase -> Phase
126 -- A conservative approximation the next phase, used in happensBefore
127 nextPhase (Unlit sf)    = Cpp  sf
128 nextPhase (Cpp   sf)    = HsPp sf
129 nextPhase (HsPp  sf)    = Hsc  sf
130 nextPhase (Hsc   sf)    = HCc
131 nextPhase HCc           = Mangle
132 nextPhase Mangle        = SplitMangle
133 nextPhase SplitMangle   = As
134 nextPhase As            = SplitAs
135 nextPhase SplitAs       = StopLn
136 nextPhase Cc            = As
137 nextPhase CmmCpp        = Cmm
138 nextPhase Cmm           = HCc
139 nextPhase StopLn        = panic "nextPhase: nothing after StopLn"
140
141 -- the first compilation phase for a given file is determined
142 -- by its suffix.
143 startPhase "lhs"      = Unlit HsSrcFile
144 startPhase "lhs-boot" = Unlit HsBootFile
145 startPhase "hs"       = Cpp   HsSrcFile
146 startPhase "hs-boot"  = Cpp   HsBootFile
147 startPhase "hscpp"    = HsPp  HsSrcFile
148 startPhase "hspp"     = Hsc   HsSrcFile
149 startPhase "hcr"      = Hsc   ExtCoreFile
150 startPhase "hc"       = HCc
151 startPhase "c"        = Cc
152 startPhase "cpp"      = Cc
153 startPhase "C"        = Cc
154 startPhase "cc"       = Cc
155 startPhase "cxx"      = Cc
156 startPhase "raw_s"    = Mangle
157 startPhase "s"        = As
158 startPhase "S"        = As
159 startPhase "o"        = StopLn
160 startPhase "cmm"      = CmmCpp
161 startPhase "cmmcpp"   = Cmm
162 startPhase _          = StopLn     -- all unknown file types
163
164 -- This is used to determine the extension for the output from the
165 -- current phase (if it generates a new file).  The extension depends
166 -- on the next phase in the pipeline.
167 phaseInputExt (Unlit HsSrcFile)   = "lhs"
168 phaseInputExt (Unlit HsBootFile)  = "lhs-boot"
169 phaseInputExt (Unlit ExtCoreFile) = "lhcr"
170 phaseInputExt (Cpp   _)           = "lpp"       -- intermediate only
171 phaseInputExt (HsPp  _)           = "hscpp"     -- intermediate only
172 phaseInputExt (Hsc   _)           = "hspp"      -- intermediate only
173         -- NB: as things stand, phaseInputExt (Hsc x) must not evaluate x
174         --     because runPipeline uses the StopBefore phase to pick the
175         --     output filename.  That could be fixed, but watch out.
176 phaseInputExt HCc                 = "hc"  
177 phaseInputExt Cc                  = "c"
178 phaseInputExt Mangle              = "raw_s"
179 phaseInputExt SplitMangle         = "split_s"   -- not really generated
180 phaseInputExt As                  = "s"
181 phaseInputExt SplitAs             = "split_s"   -- not really generated
182 phaseInputExt CmmCpp              = "cmm"
183 phaseInputExt Cmm                 = "cmmcpp"
184 phaseInputExt StopLn              = "o"
185 #ifdef ILX
186 phaseInputExt Ilx2Il              = "ilx"
187 phaseInputExt Ilasm               = "il"
188 #endif
189
190 haskellish_src_suffixes      = haskellish_user_src_suffixes ++
191                                [ "hspp", "hscpp", "hcr", "cmm" ]
192 haskellish_suffixes          = haskellish_src_suffixes ++ ["hc", "raw_s"]
193 cish_suffixes                = [ "c", "cpp", "C", "cc", "cxx", "s", "S" ]
194 extcoreish_suffixes          = [ "hcr" ]
195 haskellish_user_src_suffixes = [ "hs", "lhs", "hs-boot", "lhs-boot" ]   -- Will not be deleted as temp files
196
197 -- Use the appropriate suffix for the system on which 
198 -- the GHC-compiled code will run
199 #if mingw32_TARGET_OS || cygwin32_TARGET_OS
200 objish_suffixes     = [ "o", "O", "obj", "OBJ" ]
201 #else
202 objish_suffixes     = [ "o" ]
203 #endif
204
205 #ifdef mingw32_TARGET_OS
206 dynlib_suffixes = ["dll", "DLL"]
207 #elif defined(darwin_TARGET_OS)
208 dynlib_suffixes = ["dylib"]
209 #else
210 dynlib_suffixes = ["so"]
211 #endif
212
213 isHaskellishFilename     f = getFileSuffix f `elem` haskellish_suffixes
214 isHaskellSrcFilename     f = getFileSuffix f `elem` haskellish_src_suffixes
215 isCishFilename           f = getFileSuffix f `elem` cish_suffixes
216 isExtCoreFilename        f = getFileSuffix f `elem` extcoreish_suffixes
217 isObjectFilename         f = getFileSuffix f `elem` objish_suffixes
218 isHaskellUserSrcFilename f = getFileSuffix f `elem` haskellish_user_src_suffixes
219 isDynLibFilename         f = getFileSuffix f `elem` dynlib_suffixes
220
221 isSourceFilename :: FilePath -> Bool
222 isSourceFilename f  =
223    isHaskellishFilename f ||
224    isCishFilename f