Teach GHC to compile objective-c files; trac #5025
[ghc.git] / compiler / main / DriverPhases.hs
1 -----------------------------------------------------------------------------
2 -- $Id: DriverPhases.hs,v 1.38 2005/05/17 11:01:59 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 Phase(..),
13 happensBefore, eqPhase, anyHsc, isStopLn,
14 startPhase, -- :: String -> Phase
15 phaseInputExt, -- :: Phase -> String
16
17 isHaskellishSuffix,
18 isHaskellSrcSuffix,
19 isObjectSuffix,
20 isCishSuffix,
21 isExtCoreSuffix,
22 isDynLibSuffix,
23 isHaskellUserSrcSuffix,
24 isSourceSuffix,
25
26 isHaskellishFilename,
27 isHaskellSrcFilename,
28 isObjectFilename,
29 isCishFilename,
30 isExtCoreFilename,
31 isDynLibFilename,
32 isHaskellUserSrcFilename,
33 isSourceFilename -- :: FilePath -> Bool
34 ) where
35
36 #include "HsVersions.h"
37
38 import Outputable
39 import System.FilePath
40
41 -----------------------------------------------------------------------------
42 -- Phases
43
44 {-
45 Phase of the | Suffix saying | Flag saying | (suffix of)
46 compilation system | ``start here''| ``stop after''| output file
47
48 literate pre-processor | .lhs | - | -
49 C pre-processor (opt.) | - | -E | -
50 Haskell compiler | .hs | -C, -S | .hc, .s
51 C compiler (opt.) | .hc or .c | -S | .s
52 assembler | .s or .S | -c | .o
53 linker | other | - | a.out
54 -}
55
56 data HscSource
57 = HsSrcFile | HsBootFile | ExtCoreFile
58 deriving( Eq, Ord, Show )
59 -- Ord needed for the finite maps we build in CompManager
60
61
62 hscSourceString :: HscSource -> String
63 hscSourceString HsSrcFile = ""
64 hscSourceString HsBootFile = "[boot]"
65 hscSourceString ExtCoreFile = "[ext core]"
66
67 isHsBoot :: HscSource -> Bool
68 isHsBoot HsBootFile = True
69 isHsBoot _ = False
70
71 data Phase
72 = Unlit HscSource
73 | Cpp HscSource
74 | HsPp HscSource
75 | Hsc HscSource
76 | Ccpp
77 | Cc
78 | Cobjc
79 | HCc -- Haskellised C (as opposed to vanilla C) compilation
80 | Mangle -- assembly mangling, now done by a separate script.
81 | SplitMangle -- after mangler if splitting
82 | SplitAs
83 | As
84 | LlvmOpt -- Run LLVM opt tool over llvm assembly
85 | LlvmLlc -- LLVM bitcode to native assembly
86 | LlvmMangle -- Fix up TNTC by processing assembly produced by LLVM
87 | CmmCpp -- pre-process Cmm source
88 | Cmm -- parse & compile Cmm code
89
90 -- The final phase is a pseudo-phase that tells the pipeline to stop.
91 -- There is no runPhase case for it.
92 | StopLn -- Stop, but linking will follow, so generate .o file
93 deriving (Eq, Show)
94
95 instance Outputable Phase where
96 ppr p = text (show p)
97
98 anyHsc :: Phase
99 anyHsc = Hsc (panic "anyHsc")
100
101 isStopLn :: Phase -> Bool
102 isStopLn StopLn = True
103 isStopLn _ = False
104
105 eqPhase :: Phase -> Phase -> Bool
106 -- Equality of constructors, ignoring the HscSource field
107 -- NB: the HscSource field can be 'bot'; see anyHsc above
108 eqPhase (Unlit _) (Unlit _) = True
109 eqPhase (Cpp _) (Cpp _) = True
110 eqPhase (HsPp _) (HsPp _) = True
111 eqPhase (Hsc _) (Hsc _) = True
112 eqPhase Ccpp Ccpp = True
113 eqPhase Cc Cc = True
114 eqPhase Cobjc Cobjc = True
115 eqPhase HCc HCc = True
116 eqPhase Mangle Mangle = True
117 eqPhase SplitMangle SplitMangle = True
118 eqPhase SplitAs SplitAs = True
119 eqPhase As As = True
120 eqPhase LlvmOpt LlvmOpt = True
121 eqPhase LlvmLlc LlvmLlc = True
122 eqPhase LlvmMangle LlvmMangle = True
123 eqPhase CmmCpp CmmCpp = True
124 eqPhase Cmm Cmm = True
125 eqPhase StopLn StopLn = True
126 eqPhase _ _ = False
127
128 -- Partial ordering on phases: we want to know which phases will occur before
129 -- which others. This is used for sanity checking, to ensure that the
130 -- pipeline will stop at some point (see DriverPipeline.runPipeline).
131 happensBefore :: Phase -> Phase -> Bool
132 StopLn `happensBefore` _ = False
133 x `happensBefore` y = after_x `eqPhase` y || after_x `happensBefore` y
134 where
135 after_x = nextPhase x
136
137 nextPhase :: Phase -> Phase
138 -- A conservative approximation the next phase, used in happensBefore
139 nextPhase (Unlit sf) = Cpp sf
140 nextPhase (Cpp sf) = HsPp sf
141 nextPhase (HsPp sf) = Hsc sf
142 nextPhase (Hsc _) = HCc
143 nextPhase HCc = Mangle
144 nextPhase Mangle = SplitMangle
145 nextPhase SplitMangle = As
146 nextPhase As = SplitAs
147 nextPhase LlvmOpt = LlvmLlc
148 #if darwin_TARGET_OS
149 nextPhase LlvmLlc = LlvmMangle
150 #else
151 nextPhase LlvmLlc = As
152 #endif
153 nextPhase LlvmMangle = As
154 nextPhase SplitAs = StopLn
155 nextPhase Ccpp = As
156 nextPhase Cc = As
157 nextPhase Cobjc = As
158 nextPhase CmmCpp = Cmm
159 nextPhase Cmm = HCc
160 nextPhase StopLn = panic "nextPhase: nothing after StopLn"
161
162 -- the first compilation phase for a given file is determined
163 -- by its suffix.
164 startPhase :: String -> Phase
165 startPhase "lhs" = Unlit HsSrcFile
166 startPhase "lhs-boot" = Unlit HsBootFile
167 startPhase "hs" = Cpp HsSrcFile
168 startPhase "hs-boot" = Cpp HsBootFile
169 startPhase "hscpp" = HsPp HsSrcFile
170 startPhase "hspp" = Hsc HsSrcFile
171 startPhase "hcr" = Hsc ExtCoreFile
172 startPhase "hc" = HCc
173 startPhase "c" = Cc
174 startPhase "cpp" = Ccpp
175 startPhase "C" = Cc
176 startPhase "m" = Cobjc
177 startPhase "cc" = Ccpp
178 startPhase "cxx" = Ccpp
179 startPhase "raw_s" = Mangle
180 startPhase "split_s" = SplitMangle
181 startPhase "s" = As
182 startPhase "S" = As
183 startPhase "ll" = LlvmOpt
184 startPhase "bc" = LlvmLlc
185 startPhase "lm_s" = LlvmMangle
186 startPhase "o" = StopLn
187 startPhase "cmm" = CmmCpp
188 startPhase "cmmcpp" = Cmm
189 startPhase _ = StopLn -- all unknown file types
190
191 -- This is used to determine the extension for the output from the
192 -- current phase (if it generates a new file). The extension depends
193 -- on the next phase in the pipeline.
194 phaseInputExt :: Phase -> String
195 phaseInputExt (Unlit HsSrcFile) = "lhs"
196 phaseInputExt (Unlit HsBootFile) = "lhs-boot"
197 phaseInputExt (Unlit ExtCoreFile) = "lhcr"
198 phaseInputExt (Cpp _) = "lpp" -- intermediate only
199 phaseInputExt (HsPp _) = "hscpp" -- intermediate only
200 phaseInputExt (Hsc _) = "hspp" -- intermediate only
201 -- NB: as things stand, phaseInputExt (Hsc x) must not evaluate x
202 -- because runPipeline uses the StopBefore phase to pick the
203 -- output filename. That could be fixed, but watch out.
204 phaseInputExt HCc = "hc"
205 phaseInputExt Ccpp = "cpp"
206 phaseInputExt Cobjc = "m"
207 phaseInputExt Cc = "c"
208 phaseInputExt Mangle = "raw_s"
209 phaseInputExt SplitMangle = "split_s" -- not really generated
210 phaseInputExt As = "s"
211 phaseInputExt LlvmOpt = "ll"
212 phaseInputExt LlvmLlc = "bc"
213 phaseInputExt LlvmMangle = "lm_s"
214 phaseInputExt SplitAs = "split_s" -- not really generated
215 phaseInputExt CmmCpp = "cmm"
216 phaseInputExt Cmm = "cmmcpp"
217 phaseInputExt StopLn = "o"
218
219 haskellish_src_suffixes, haskellish_suffixes, cish_suffixes,
220 extcoreish_suffixes, haskellish_user_src_suffixes
221 :: [String]
222 haskellish_src_suffixes = haskellish_user_src_suffixes ++
223 [ "hspp", "hscpp", "hcr", "cmm", "cmmcpp" ]
224 haskellish_suffixes = haskellish_src_suffixes ++ ["hc", "raw_s"]
225 cish_suffixes = [ "c", "cpp", "C", "cc", "cxx", "s", "S", "ll", "bc", "m" ]
226 extcoreish_suffixes = [ "hcr" ]
227 -- Will not be deleted as temp files:
228 haskellish_user_src_suffixes = [ "hs", "lhs", "hs-boot", "lhs-boot" ]
229
230 objish_suffixes :: [String]
231 -- Use the appropriate suffix for the system on which
232 -- the GHC-compiled code will run
233 #if mingw32_TARGET_OS || cygwin32_TARGET_OS
234 objish_suffixes = [ "o", "O", "obj", "OBJ" ]
235 #else
236 objish_suffixes = [ "o" ]
237 #endif
238
239 dynlib_suffixes :: [String]
240 #ifdef mingw32_TARGET_OS
241 dynlib_suffixes = ["dll", "DLL"]
242 #elif defined(darwin_TARGET_OS)
243 dynlib_suffixes = ["dylib"]
244 #else
245 dynlib_suffixes = ["so"]
246 #endif
247
248 isHaskellishSuffix, isHaskellSrcSuffix, isCishSuffix, isExtCoreSuffix,
249 isObjectSuffix, isHaskellUserSrcSuffix, isDynLibSuffix
250 :: String -> Bool
251 isHaskellishSuffix s = s `elem` haskellish_suffixes
252 isHaskellSrcSuffix s = s `elem` haskellish_src_suffixes
253 isCishSuffix s = s `elem` cish_suffixes
254 isExtCoreSuffix s = s `elem` extcoreish_suffixes
255 isObjectSuffix s = s `elem` objish_suffixes
256 isHaskellUserSrcSuffix s = s `elem` haskellish_user_src_suffixes
257 isDynLibSuffix s = s `elem` dynlib_suffixes
258
259 isSourceSuffix :: String -> Bool
260 isSourceSuffix suff = isHaskellishSuffix suff || isCishSuffix suff
261
262 isHaskellishFilename, isHaskellSrcFilename, isCishFilename,
263 isExtCoreFilename, isObjectFilename, isHaskellUserSrcFilename,
264 isDynLibFilename, isSourceFilename
265 :: FilePath -> Bool
266 -- takeExtension return .foo, so we drop 1 to get rid of the .
267 isHaskellishFilename f = isHaskellishSuffix (drop 1 $ takeExtension f)
268 isHaskellSrcFilename f = isHaskellSrcSuffix (drop 1 $ takeExtension f)
269 isCishFilename f = isCishSuffix (drop 1 $ takeExtension f)
270 isExtCoreFilename f = isExtCoreSuffix (drop 1 $ takeExtension f)
271 isObjectFilename f = isObjectSuffix (drop 1 $ takeExtension f)
272 isHaskellUserSrcFilename f = isHaskellUserSrcSuffix (drop 1 $ takeExtension f)
273 isDynLibFilename f = isDynLibSuffix (drop 1 $ takeExtension f)
274 isSourceFilename f = isSourceSuffix (drop 1 $ takeExtension f)
275
276