| 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, |
|---|
| 15 | phaseInputExt, |
|---|
| 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 |
|---|
| 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 | | Cobjcpp |
|---|
| 80 | | HCc -- Haskellised C (as opposed to vanilla C) compilation |
|---|
| 81 | | Splitter -- Assembly file splitter (part of '-split-objs') |
|---|
| 82 | | SplitAs -- Assembler for split assembly files (part of '-split-objs') |
|---|
| 83 | | As -- Assembler for regular assembly files |
|---|
| 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 | | MergeStub -- merge in the stub object file |
|---|
| 90 | |
|---|
| 91 | -- The final phase is a pseudo-phase that tells the pipeline to stop. |
|---|
| 92 | -- There is no runPhase case for it. |
|---|
| 93 | | StopLn -- Stop, but linking will follow, so generate .o file |
|---|
| 94 | deriving (Eq, Show) |
|---|
| 95 | |
|---|
| 96 | instance Outputable Phase where |
|---|
| 97 | ppr p = text (show p) |
|---|
| 98 | |
|---|
| 99 | anyHsc :: Phase |
|---|
| 100 | anyHsc = Hsc (panic "anyHsc") |
|---|
| 101 | |
|---|
| 102 | isStopLn :: Phase -> Bool |
|---|
| 103 | isStopLn StopLn = True |
|---|
| 104 | isStopLn _ = False |
|---|
| 105 | |
|---|
| 106 | eqPhase :: Phase -> Phase -> Bool |
|---|
| 107 | -- Equality of constructors, ignoring the HscSource field |
|---|
| 108 | -- NB: the HscSource field can be 'bot'; see anyHsc above |
|---|
| 109 | eqPhase (Unlit _) (Unlit _) = True |
|---|
| 110 | eqPhase (Cpp _) (Cpp _) = True |
|---|
| 111 | eqPhase (HsPp _) (HsPp _) = True |
|---|
| 112 | eqPhase (Hsc _) (Hsc _) = True |
|---|
| 113 | eqPhase Ccpp Ccpp = True |
|---|
| 114 | eqPhase Cc Cc = True |
|---|
| 115 | eqPhase Cobjc Cobjc = True |
|---|
| 116 | eqPhase Cobjcpp Cobjcpp = True |
|---|
| 117 | eqPhase HCc HCc = True |
|---|
| 118 | eqPhase Splitter Splitter = True |
|---|
| 119 | eqPhase SplitAs SplitAs = True |
|---|
| 120 | eqPhase As As = True |
|---|
| 121 | eqPhase LlvmOpt LlvmOpt = True |
|---|
| 122 | eqPhase LlvmLlc LlvmLlc = True |
|---|
| 123 | eqPhase LlvmMangle LlvmMangle = True |
|---|
| 124 | eqPhase CmmCpp CmmCpp = True |
|---|
| 125 | eqPhase Cmm Cmm = True |
|---|
| 126 | eqPhase MergeStub MergeStub = True |
|---|
| 127 | eqPhase StopLn StopLn = True |
|---|
| 128 | eqPhase _ _ = False |
|---|
| 129 | |
|---|
| 130 | -- Partial ordering on phases: we want to know which phases will occur before |
|---|
| 131 | -- which others. This is used for sanity checking, to ensure that the |
|---|
| 132 | -- pipeline will stop at some point (see DriverPipeline.runPipeline). |
|---|
| 133 | happensBefore :: Phase -> Phase -> Bool |
|---|
| 134 | StopLn `happensBefore` _ = False |
|---|
| 135 | x `happensBefore` y = after_x `eqPhase` y || after_x `happensBefore` y |
|---|
| 136 | where |
|---|
| 137 | after_x = nextPhase x |
|---|
| 138 | |
|---|
| 139 | nextPhase :: Phase -> Phase |
|---|
| 140 | -- A conservative approximation to the next phase, used in happensBefore |
|---|
| 141 | nextPhase (Unlit sf) = Cpp sf |
|---|
| 142 | nextPhase (Cpp sf) = HsPp sf |
|---|
| 143 | nextPhase (HsPp sf) = Hsc sf |
|---|
| 144 | nextPhase (Hsc _) = HCc |
|---|
| 145 | nextPhase Splitter = SplitAs |
|---|
| 146 | nextPhase LlvmOpt = LlvmLlc |
|---|
| 147 | nextPhase LlvmLlc = LlvmMangle |
|---|
| 148 | nextPhase LlvmMangle = As |
|---|
| 149 | nextPhase SplitAs = MergeStub |
|---|
| 150 | nextPhase As = MergeStub |
|---|
| 151 | nextPhase Ccpp = As |
|---|
| 152 | nextPhase Cc = As |
|---|
| 153 | nextPhase Cobjc = As |
|---|
| 154 | nextPhase Cobjcpp = As |
|---|
| 155 | nextPhase CmmCpp = Cmm |
|---|
| 156 | nextPhase Cmm = HCc |
|---|
| 157 | nextPhase HCc = As |
|---|
| 158 | nextPhase MergeStub = StopLn |
|---|
| 159 | nextPhase StopLn = panic "nextPhase: nothing after StopLn" |
|---|
| 160 | |
|---|
| 161 | -- the first compilation phase for a given file is determined |
|---|
| 162 | -- by its suffix. |
|---|
| 163 | startPhase :: String -> Phase |
|---|
| 164 | startPhase "lhs" = Unlit HsSrcFile |
|---|
| 165 | startPhase "lhs-boot" = Unlit HsBootFile |
|---|
| 166 | startPhase "hs" = Cpp HsSrcFile |
|---|
| 167 | startPhase "hs-boot" = Cpp HsBootFile |
|---|
| 168 | startPhase "hscpp" = HsPp HsSrcFile |
|---|
| 169 | startPhase "hspp" = Hsc HsSrcFile |
|---|
| 170 | startPhase "hcr" = Hsc ExtCoreFile |
|---|
| 171 | startPhase "hc" = HCc |
|---|
| 172 | startPhase "c" = Cc |
|---|
| 173 | startPhase "cpp" = Ccpp |
|---|
| 174 | startPhase "C" = Cc |
|---|
| 175 | startPhase "m" = Cobjc |
|---|
| 176 | startPhase "M" = Cobjcpp |
|---|
| 177 | startPhase "mm" = Cobjcpp |
|---|
| 178 | startPhase "cc" = Ccpp |
|---|
| 179 | startPhase "cxx" = Ccpp |
|---|
| 180 | startPhase "split_s" = Splitter |
|---|
| 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 Cobjcpp = "mm" |
|---|
| 208 | phaseInputExt Cc = "c" |
|---|
| 209 | phaseInputExt Splitter = "split_s" |
|---|
| 210 | phaseInputExt As = "s" |
|---|
| 211 | phaseInputExt LlvmOpt = "ll" |
|---|
| 212 | phaseInputExt LlvmLlc = "bc" |
|---|
| 213 | phaseInputExt LlvmMangle = "lm_s" |
|---|
| 214 | phaseInputExt SplitAs = "split_s" |
|---|
| 215 | phaseInputExt CmmCpp = "cmm" |
|---|
| 216 | phaseInputExt Cmm = "cmmcpp" |
|---|
| 217 | phaseInputExt MergeStub = "o" |
|---|
| 218 | phaseInputExt StopLn = "o" |
|---|
| 219 | |
|---|
| 220 | haskellish_src_suffixes, haskellish_suffixes, cish_suffixes, |
|---|
| 221 | extcoreish_suffixes, haskellish_user_src_suffixes |
|---|
| 222 | :: [String] |
|---|
| 223 | haskellish_src_suffixes = haskellish_user_src_suffixes ++ |
|---|
| 224 | [ "hspp", "hscpp", "hcr", "cmm", "cmmcpp" ] |
|---|
| 225 | haskellish_suffixes = haskellish_src_suffixes ++ ["hc", "raw_s"] |
|---|
| 226 | cish_suffixes = [ "c", "cpp", "C", "cc", "cxx", "s", "S", "ll", "bc", "lm_s", "m", "M", "mm" ] |
|---|
| 227 | extcoreish_suffixes = [ "hcr" ] |
|---|
| 228 | -- Will not be deleted as temp files: |
|---|
| 229 | haskellish_user_src_suffixes = [ "hs", "lhs", "hs-boot", "lhs-boot" ] |
|---|
| 230 | |
|---|
| 231 | objish_suffixes :: [String] |
|---|
| 232 | -- Use the appropriate suffix for the system on which |
|---|
| 233 | -- the GHC-compiled code will run |
|---|
| 234 | #if mingw32_TARGET_OS || cygwin32_TARGET_OS |
|---|
| 235 | objish_suffixes = [ "o", "O", "obj", "OBJ" ] |
|---|
| 236 | #else |
|---|
| 237 | objish_suffixes = [ "o" ] |
|---|
| 238 | #endif |
|---|
| 239 | |
|---|
| 240 | dynlib_suffixes :: [String] |
|---|
| 241 | #ifdef mingw32_TARGET_OS |
|---|
| 242 | dynlib_suffixes = ["dll", "DLL"] |
|---|
| 243 | #elif defined(darwin_TARGET_OS) |
|---|
| 244 | dynlib_suffixes = ["dylib"] |
|---|
| 245 | #else |
|---|
| 246 | dynlib_suffixes = ["so"] |
|---|
| 247 | #endif |
|---|
| 248 | |
|---|
| 249 | isHaskellishSuffix, isHaskellSrcSuffix, isCishSuffix, isExtCoreSuffix, |
|---|
| 250 | isObjectSuffix, isHaskellUserSrcSuffix, isDynLibSuffix |
|---|
| 251 | :: String -> Bool |
|---|
| 252 | isHaskellishSuffix s = s `elem` haskellish_suffixes |
|---|
| 253 | isHaskellSrcSuffix s = s `elem` haskellish_src_suffixes |
|---|
| 254 | isCishSuffix s = s `elem` cish_suffixes |
|---|
| 255 | isExtCoreSuffix s = s `elem` extcoreish_suffixes |
|---|
| 256 | isObjectSuffix s = s `elem` objish_suffixes |
|---|
| 257 | isHaskellUserSrcSuffix s = s `elem` haskellish_user_src_suffixes |
|---|
| 258 | isDynLibSuffix s = s `elem` dynlib_suffixes |
|---|
| 259 | |
|---|
| 260 | isSourceSuffix :: String -> Bool |
|---|
| 261 | isSourceSuffix suff = isHaskellishSuffix suff || isCishSuffix suff |
|---|
| 262 | |
|---|
| 263 | isHaskellishFilename, isHaskellSrcFilename, isCishFilename, |
|---|
| 264 | isExtCoreFilename, isObjectFilename, isHaskellUserSrcFilename, |
|---|
| 265 | isDynLibFilename, isSourceFilename |
|---|
| 266 | :: FilePath -> Bool |
|---|
| 267 | -- takeExtension return .foo, so we drop 1 to get rid of the . |
|---|
| 268 | isHaskellishFilename f = isHaskellishSuffix (drop 1 $ takeExtension f) |
|---|
| 269 | isHaskellSrcFilename f = isHaskellSrcSuffix (drop 1 $ takeExtension f) |
|---|
| 270 | isCishFilename f = isCishSuffix (drop 1 $ takeExtension f) |
|---|
| 271 | isExtCoreFilename f = isExtCoreSuffix (drop 1 $ takeExtension f) |
|---|
| 272 | isObjectFilename f = isObjectSuffix (drop 1 $ takeExtension f) |
|---|
| 273 | isHaskellUserSrcFilename f = isHaskellUserSrcSuffix (drop 1 $ takeExtension f) |
|---|
| 274 | isDynLibFilename f = isDynLibSuffix (drop 1 $ takeExtension f) |
|---|
| 275 | isSourceFilename f = isSourceSuffix (drop 1 $ takeExtension f) |
|---|