DriverPhases.hs 12.2 KB
Newer Older
1 2
{-# LANGUAGE CPP #-}

3
-----------------------------------------------------------------------------
4
--  $Id: DriverPhases.hs,v 1.38 2005/05/17 11:01:59 simonmar Exp $
5 6 7
--
-- GHC Driver
--
8
-- (c) The University of Glasgow 2002
9 10 11 12
--
-----------------------------------------------------------------------------

module DriverPhases (
13
   HscSource(..), isHsBoot, hscSourceString,
14
   Phase(..),
15
   happensBefore, eqPhase, anyHsc, isStopLn,
dterei's avatar
dterei committed
16 17
   startPhase,
   phaseInputExt,
18

Ian Lynagh's avatar
Ian Lynagh committed
19
   isHaskellishSuffix,
20 21 22 23 24 25 26
   isHaskellSrcSuffix,
   isObjectSuffix,
   isCishSuffix,
   isDynLibSuffix,
   isHaskellUserSrcSuffix,
   isSourceSuffix,

Ian Lynagh's avatar
Ian Lynagh committed
27
   isHaskellishFilename,
28 29 30 31 32
   isHaskellSrcFilename,
   isObjectFilename,
   isCishFilename,
   isDynLibFilename,
   isHaskellUserSrcFilename,
dterei's avatar
dterei committed
33
   isSourceFilename
34 35
 ) where

36 37
#include "HsVersions.h"

38
import {-# SOURCE #-} DynFlags
39
import Outputable
40
import Platform
Ian Lynagh's avatar
Ian Lynagh committed
41
import System.FilePath
42
import Binary
43 44 45 46 47 48 49

-----------------------------------------------------------------------------
-- Phases

{-
   Phase of the           | Suffix saying | Flag saying   | (suffix of)
   compilation system     | ``start here''| ``stop after''| output file
Ian Lynagh's avatar
Ian Lynagh committed
50

51 52 53 54 55 56 57 58
   literate pre-processor | .lhs          | -             | -
   C pre-processor (opt.) | -             | -E            | -
   Haskell compiler       | .hs           | -C, -S        | .hc, .s
   C compiler (opt.)      | .hc or .c     | -S            | .s
   assembler              | .s  or .S     | -c            | .o
   linker                 | other         | -             | a.out
-}

59 60
-- Note [HscSource types]
-- ~~~~~~~~~~~~~~~~~~~~~~
61
-- There are two types of source file for user-written Haskell code:
62 63 64
--
--      * HsSrcFile is an ordinary hs file which contains code,
--
65 66 67 68 69
--      * HsBootFile is an hs-boot file.  Within a unit, it can
--        be used to break recursive module imports, in which case there's an
--        HsSrcFile associated with it.  However, externally, it can
--        also be used to specify the *requirements* of a package,
--        in which case there is an HsBootMerge associated with it.
70
--
71 72 73 74
-- An HsBootMerge is a "fake" source file, which is constructed
-- by collecting up non-recursive HsBootFiles into a single interface.
-- HsBootMerges get an hi and o file, and are treated as "non-boot"
-- sources.
75

76
data HscSource
77
   = HsSrcFile | HsBootFile | HsBootMerge
78
     deriving( Eq, Ord, Show )
Ian Lynagh's avatar
Ian Lynagh committed
79
        -- Ord needed for the finite maps we build in CompManager
80

81 82 83 84 85
instance Outputable HscSource where
    ppr HsSrcFile = text "HsSrcFile"
    ppr HsBootFile = text "HsBootFile"
    ppr HsBootMerge = text "HsBootMerge"

86 87 88
instance Binary HscSource where
    put_ bh HsSrcFile = putByte bh 0
    put_ bh HsBootFile = putByte bh 1
89
    put_ bh HsBootMerge = putByte bh 2
90 91 92 93 94
    get bh = do
        h <- getByte bh
        case h of
            0 -> return HsSrcFile
            1 -> return HsBootFile
95
            _ -> return HsBootMerge
96

97 98 99
hscSourceString :: HscSource -> String
hscSourceString HsSrcFile   = ""
hscSourceString HsBootFile  = "[boot]"
100
hscSourceString HsBootMerge = "[merge]"
101

102 103 104 105
isHsBoot :: HscSource -> Bool
isHsBoot HsBootFile  = True
isHsBoot HsSrcFile   = False
isHsBoot HsBootMerge = False
106

Ian Lynagh's avatar
Ian Lynagh committed
107 108 109 110 111
data Phase
        = Unlit HscSource
        | Cpp   HscSource
        | HsPp  HscSource
        | Hsc   HscSource
thomie's avatar
thomie committed
112
        | Ccxx          -- Compile C++
113 114
        | Cc            -- Compile C
        | Cobjc         -- Compile Objective-C
thomie's avatar
thomie committed
115
        | Cobjcxx       -- Compile Objective-C++
Ian Lynagh's avatar
Ian Lynagh committed
116
        | HCc           -- Haskellised C (as opposed to vanilla C) compilation
117 118
        | Splitter      -- Assembly file splitter (part of '-split-objs')
        | SplitAs       -- Assembler for split assembly files (part of '-split-objs')
Simon Marlow's avatar
Simon Marlow committed
119
        | As Bool       -- Assembler for regular assembly files (Bool: with-cpp)
120 121
        | LlvmOpt       -- Run LLVM opt tool over llvm assembly
        | LlvmLlc       -- LLVM bitcode to native assembly
122
        | LlvmMangle    -- Fix up TNTC by processing assembly produced by LLVM
Ian Lynagh's avatar
Ian Lynagh committed
123 124
        | CmmCpp        -- pre-process Cmm source
        | Cmm           -- parse & compile Cmm code
125
        | MergeStub     -- merge in the stub object file
Ian Lynagh's avatar
Ian Lynagh committed
126 127 128 129

        -- 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
130
  deriving (Eq, Show)
131

132 133 134
instance Outputable Phase where
    ppr p = text (show p)

135 136 137
anyHsc :: Phase
anyHsc = Hsc (panic "anyHsc")

138 139
isStopLn :: Phase -> Bool
isStopLn StopLn = True
140
isStopLn _      = False
141 142 143

eqPhase :: Phase -> Phase -> Bool
-- Equality of constructors, ignoring the HscSource field
144
-- NB: the HscSource field can be 'bot'; see anyHsc above
145 146 147 148 149 150 151 152 153
eqPhase (Unlit _)   (Unlit _)  = True
eqPhase (Cpp   _)   (Cpp   _)  = True
eqPhase (HsPp  _)   (HsPp  _)  = True
eqPhase (Hsc   _)   (Hsc   _)  = True
eqPhase Cc          Cc         = True
eqPhase Cobjc       Cobjc      = True
eqPhase HCc         HCc        = True
eqPhase Splitter    Splitter   = True
eqPhase SplitAs     SplitAs    = True
Simon Marlow's avatar
Simon Marlow committed
154
eqPhase (As x)      (As y)     = x == y
dterei's avatar
dterei committed
155 156
eqPhase LlvmOpt     LlvmOpt    = True
eqPhase LlvmLlc     LlvmLlc    = True
157 158 159 160 161
eqPhase LlvmMangle  LlvmMangle = True
eqPhase CmmCpp      CmmCpp     = True
eqPhase Cmm         Cmm        = True
eqPhase MergeStub   MergeStub  = True
eqPhase StopLn      StopLn     = True
thomie's avatar
thomie committed
162 163 164
eqPhase Ccxx        Ccxx       = True
eqPhase Cobjcxx     Cobjcxx    = True
eqPhase _           _          = False
Ian Lynagh's avatar
Ian Lynagh committed
165

166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
{- Note [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).

A < B iff A occurs before B in a normal compilation pipeline.

There is explicitly not a total ordering on phases, because in registerised
builds, the phase `HsC` doesn't happen before nor after any other phase.

Although we check that a normal user doesn't set the stop_phase to HsC through
use of -C with registerised builds (in Main.checkOptions), it is still
possible for a ghc-api user to do so. So be careful when using the function
happensBefore, and don't think that `not (a <= b)` implies `b < a`.
-}
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
happensBefore :: DynFlags -> Phase -> Phase -> Bool
happensBefore dflags p1 p2 = p1 `happensBefore'` p2
    where StopLn `happensBefore'` _ = False
          x      `happensBefore'` y = after_x `eqPhase` y
                                   || after_x `happensBefore'` y
              where after_x = nextPhase dflags x

nextPhase :: DynFlags -> Phase -> Phase
nextPhase dflags p
    -- A conservative approximation to the next phase, used in happensBefore
    = case p of
      Unlit sf   -> Cpp  sf
      Cpp   sf   -> HsPp sf
      HsPp  sf   -> Hsc  sf
      Hsc   _    -> maybeHCc
      Splitter   -> SplitAs
      LlvmOpt    -> LlvmLlc
      LlvmLlc    -> LlvmMangle
Simon Marlow's avatar
Simon Marlow committed
200
      LlvmMangle -> As False
201
      SplitAs    -> MergeStub
Simon Marlow's avatar
Simon Marlow committed
202
      As _       -> MergeStub
thomie's avatar
thomie committed
203
      Ccxx       -> As False
Simon Marlow's avatar
Simon Marlow committed
204 205
      Cc         -> As False
      Cobjc      -> As False
thomie's avatar
thomie committed
206
      Cobjcxx    -> As False
207 208
      CmmCpp     -> Cmm
      Cmm        -> maybeHCc
Simon Marlow's avatar
Simon Marlow committed
209
      HCc        -> As False
210 211 212 213
      MergeStub  -> StopLn
      StopLn     -> panic "nextPhase: nothing after StopLn"
    where maybeHCc = if platformUnregisterised (targetPlatform dflags)
                     then HCc
Simon Marlow's avatar
Simon Marlow committed
214
                     else As False
215

216 217
-- the first compilation phase for a given file is determined
-- by its suffix.
218
startPhase :: String -> Phase
219 220 221 222 223 224 225 226
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 "hc"       = HCc
startPhase "c"        = Cc
thomie's avatar
thomie committed
227
startPhase "cpp"      = Ccxx
228
startPhase "C"        = Cc
229
startPhase "m"        = Cobjc
thomie's avatar
thomie committed
230 231 232 233
startPhase "M"        = Cobjcxx
startPhase "mm"       = Cobjcxx
startPhase "cc"       = Ccxx
startPhase "cxx"      = Ccxx
234
startPhase "split_s"  = Splitter
Simon Marlow's avatar
Simon Marlow committed
235 236
startPhase "s"        = As False
startPhase "S"        = As True
237 238
startPhase "ll"       = LlvmOpt
startPhase "bc"       = LlvmLlc
239
startPhase "lm_s"     = LlvmMangle
240 241 242
startPhase "o"        = StopLn
startPhase "cmm"      = CmmCpp
startPhase "cmmcpp"   = Cmm
Ian Lynagh's avatar
Ian Lynagh committed
243
startPhase _          = StopLn     -- all unknown file types
244

245 246 247
-- 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.
248
phaseInputExt :: Phase -> String
249 250
phaseInputExt (Unlit HsSrcFile)   = "lhs"
phaseInputExt (Unlit HsBootFile)  = "lhs-boot"
251 252 253
phaseInputExt (Unlit HsBootMerge) = panic "phaseInputExt: Unlit HsBootMerge"
        -- You can't Unlit an HsBootMerge, because there's no source
        -- file to Unlit!
Ian Lynagh's avatar
Ian Lynagh committed
254 255 256 257 258 259 260
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"
thomie's avatar
thomie committed
261
phaseInputExt Ccxx                = "cpp"
262
phaseInputExt Cobjc               = "m"
thomie's avatar
thomie committed
263
phaseInputExt Cobjcxx             = "mm"
Ian Lynagh's avatar
Ian Lynagh committed
264
phaseInputExt Cc                  = "c"
265
phaseInputExt Splitter            = "split_s"
Simon Marlow's avatar
Simon Marlow committed
266 267
phaseInputExt (As True)           = "S"
phaseInputExt (As False)          = "s"
268 269
phaseInputExt LlvmOpt             = "ll"
phaseInputExt LlvmLlc             = "bc"
270
phaseInputExt LlvmMangle          = "lm_s"
271
phaseInputExt SplitAs             = "split_s"
Ian Lynagh's avatar
Ian Lynagh committed
272 273
phaseInputExt CmmCpp              = "cmm"
phaseInputExt Cmm                 = "cmmcpp"
274
phaseInputExt MergeStub           = "o"
Ian Lynagh's avatar
Ian Lynagh committed
275
phaseInputExt StopLn              = "o"
276

277
haskellish_src_suffixes, haskellish_suffixes, cish_suffixes,
278
    haskellish_user_src_suffixes
279
 :: [String]
280 281
-- When a file with an extension in the haskellish_src_suffixes group is
-- loaded in --make mode, its imports will be loaded too.
282
haskellish_src_suffixes      = haskellish_user_src_suffixes ++
283
                               [ "hspp", "hscpp" ]
284
haskellish_suffixes          = haskellish_src_suffixes ++
285
                               [ "hc", "cmm", "cmmcpp" ]
286
cish_suffixes                = [ "c", "cpp", "C", "cc", "cxx", "s", "S", "ll", "bc", "lm_s", "m", "M", "mm" ]
287

288
-- Will not be deleted as temp files:
289
haskellish_user_src_suffixes = [ "hs", "lhs", "hs-boot", "lhs-boot" ]
290

291
objish_suffixes :: Platform -> [String]
292
-- Use the appropriate suffix for the system on which
293
-- the GHC-compiled code will run
294
objish_suffixes platform = case platformOS platform of
Austin Seipp's avatar
Austin Seipp committed
295 296
  OSMinGW32 -> [ "o", "O", "obj", "OBJ" ]
  _         -> [ "o" ]
297

298 299
dynlib_suffixes :: Platform -> [String]
dynlib_suffixes platform = case platformOS platform of
Austin Seipp's avatar
Austin Seipp committed
300 301 302
  OSMinGW32 -> ["dll", "DLL"]
  OSDarwin  -> ["dylib", "so"]
  _         -> ["so"]
303

Austin Seipp's avatar
Austin Seipp committed
304
isHaskellishSuffix, isHaskellSrcSuffix, isCishSuffix,
305
    isHaskellUserSrcSuffix
306
 :: String -> Bool
307 308 309 310
isHaskellishSuffix     s = s `elem` haskellish_suffixes
isHaskellSrcSuffix     s = s `elem` haskellish_src_suffixes
isCishSuffix           s = s `elem` cish_suffixes
isHaskellUserSrcSuffix s = s `elem` haskellish_user_src_suffixes
311 312 313 314

isObjectSuffix, isDynLibSuffix :: Platform -> String -> Bool
isObjectSuffix platform s = s `elem` objish_suffixes platform
isDynLibSuffix platform s = s `elem` dynlib_suffixes platform
315

316
isSourceSuffix :: String -> Bool
317 318
isSourceSuffix suff  = isHaskellishSuffix suff || isCishSuffix suff

319
isHaskellishFilename, isHaskellSrcFilename, isCishFilename,
320
    isHaskellUserSrcFilename, isSourceFilename
321
 :: FilePath -> Bool
Ian Lynagh's avatar
Ian Lynagh committed
322 323 324 325 326 327
-- takeExtension return .foo, so we drop 1 to get rid of the .
isHaskellishFilename     f = isHaskellishSuffix     (drop 1 $ takeExtension f)
isHaskellSrcFilename     f = isHaskellSrcSuffix     (drop 1 $ takeExtension f)
isCishFilename           f = isCishSuffix           (drop 1 $ takeExtension f)
isHaskellUserSrcFilename f = isHaskellUserSrcSuffix (drop 1 $ takeExtension f)
isSourceFilename         f = isSourceSuffix         (drop 1 $ takeExtension f)
328

329 330 331 332
isObjectFilename, isDynLibFilename :: Platform -> FilePath -> Bool
isObjectFilename platform f = isObjectSuffix platform (drop 1 $ takeExtension f)
isDynLibFilename platform f = isDynLibSuffix platform (drop 1 $ takeExtension f)