[project @ 2004-08-12 11:19:39 by simonmar]
[ghc-hetmet.git] / ghc / compiler / main / DriverPipeline.hs
index 87977cb..072978a 100644 (file)
@@ -41,6 +41,7 @@ import Module
 import ErrUtils
 import CmdLineOpts
 import Config
+import RdrName         ( GlobalRdrEnv )
 import Panic
 import Util
 import BasicTypes      ( SuccessFlag(..) )
@@ -51,9 +52,7 @@ import ParserCoreUtils ( getCoreModuleName )
 import EXCEPTION
 import DATA_IOREF      ( readIORef, writeIORef )
 
-#ifdef GHCI
-import Time            ( getClockTime )
-#endif
+import Time            ( ClockTime )
 import Directory
 import System
 import IO
@@ -69,7 +68,7 @@ import Maybe
 
 preprocess :: FilePath -> IO FilePath
 preprocess filename =
-  ASSERT(haskellish_src_file filename) 
+  ASSERT(isHaskellSrcFilename filename) 
   do restoreDynFlags   -- Restore to state of last save
      runPipeline (StopBefore Hsc) ("preprocess") 
        False{-temporary output file-}
@@ -95,29 +94,30 @@ preprocess filename =
 
 -- NB.  No old interface can also mean that the source has changed.
 
-compile :: GhciMode                -- distinguish batch from interactive
+compile :: HscEnv
        -> Module
        -> ModLocation
+       -> ClockTime               -- timestamp of original source file
        -> Bool                    -- True <=> source unchanged
        -> Bool                    -- True <=> have object
         -> Maybe ModIface          -- old interface, if available
-        -> HomePackageTable        -- For home-module stuff
-        -> PersistentCompilerState -- persistent compiler state
         -> IO CompResult
 
 data CompResult
-   = CompOK   PersistentCompilerState  -- Updated PCS
-              ModDetails               -- New details
+   = CompOK   ModDetails               -- New details
+             (Maybe GlobalRdrEnv)      -- Lexical environment for the module
+                                       -- (Maybe because we may have loaded it from
+                                       --  its precompiled interface)
               ModIface                 -- New iface
               (Maybe Linkable) -- New code; Nothing => compilation was not reqd
                                --                      (old code is still valid)
 
-   | CompErrs PersistentCompilerState  -- Updated PCS
+   | CompErrs 
 
 
-compile ghci_mode this_mod location
+compile hsc_env this_mod location src_timestamp
        source_unchanged have_object 
-       old_iface hpt pcs = do 
+       old_iface = do 
 
    dyn_flags <- restoreDynFlags                -- Restore to the state of the last save
 
@@ -154,20 +154,18 @@ compile ghci_mode this_mod location
    -- -no-recomp should also work with --make
    do_recomp <- readIORef v_Recomp
    let source_unchanged' = source_unchanged && do_recomp
-       hsc_env = HscEnv { hsc_mode = ghci_mode,
-                         hsc_dflags = dyn_flags',
-                         hsc_HPT    = hpt }
+       hsc_env' = hsc_env { hsc_dflags = dyn_flags' }
 
    -- run the compiler
-   hsc_result <- hscMain hsc_env pcs this_mod location
+   hsc_result <- hscMain hsc_env' printErrorsAndWarnings this_mod location
                         source_unchanged' have_object old_iface
 
    case hsc_result of
-      HscFail pcs -> return (CompErrs pcs)
+      HscFail -> return CompErrs
 
-      HscNoRecomp pcs details iface -> return (CompOK pcs details iface Nothing)
+      HscNoRecomp details iface -> return (CompOK details Nothing iface Nothing)
 
-      HscRecomp pcs details iface
+      HscRecomp details rdr_env iface
        stub_h_exists stub_c_exists maybe_interpreted_code -> do
           let 
           maybe_stub_o <- compileStub dyn_flags' stub_c_exists
@@ -183,8 +181,13 @@ compile ghci_mode this_mod location
                HscInterpreted -> 
                    case maybe_interpreted_code of
 #ifdef GHCI
-                      Just comp_bc -> do tm <- getClockTime 
-                                          return ([BCOs comp_bc], tm)
+                      Just comp_bc -> return ([BCOs comp_bc], src_timestamp)
+                       -- Why do we use the timestamp of the source file here,
+                       -- rather than the current time?  This works better in
+                       -- the case where the local clock is out of sync
+                       -- with the filesystem's clock.  It's just as accurate:
+                       -- if the source is modified, then the linkable will
+                       -- be out of date.
 #endif
                       Nothing -> panic "compile: no interpreted code"
 
@@ -202,7 +205,7 @@ compile ghci_mode this_mod location
           let linkable = LM unlinked_time mod_name
                             (hs_unlinked ++ stub_unlinked)
 
-          return (CompOK pcs details iface (Just linkable))
+          return (CompOK details rdr_env iface (Just linkable))
 
 -----------------------------------------------------------------------------
 -- stub .h and .c files (for foreign export support)
@@ -383,7 +386,8 @@ pipeLoop phase stop_phase input_fn orig_basename orig_suff
   
 genOutputFilenameFunc :: Bool -> Maybe FilePath -> Phase -> String
   -> IO (Phase{-next phase-} -> Maybe ModLocation -> IO FilePath)
-genOutputFilenameFunc keep_output maybe_output_filename stop_phase basename
+genOutputFilenameFunc keep_final_output maybe_output_filename 
+               stop_phase basename
  = do
    hcsuf      <- readIORef v_HC_suf
    odir       <- readIORef v_Output_dir
@@ -401,23 +405,30 @@ genOutputFilenameFunc keep_output maybe_output_filename stop_phase basename
         myPhaseInputExt other = phaseInputExt other
 
        func next_phase maybe_location
-               | next_phase == stop_phase
-                     = case maybe_output_filename of
-                            Just file -> return file
-                            Nothing
-                                | Ln <- next_phase -> return odir_persistent
-                                | keep_output      -> return persistent
-                                | otherwise        -> newTempName suffix
-                       -- sometimes, we keep output from intermediate stages
-               | otherwise
-                    = case next_phase of
-                            Ln                  -> return odir_persistent
-                            Mangle | keep_raw_s -> return persistent
-                            As     | keep_s     -> return persistent
-                            HCc    | keep_hc    -> return persistent
-                            _other              -> newTempName suffix
+               | is_last_phase, Just f <- maybe_output_filename = return f
+               | is_last_phase && keep_final_output = persistent_fn
+               | keep_this_output                   = persistent_fn
+               | otherwise                          = newTempName suffix
+
           where
+               is_last_phase = next_phase == stop_phase
+
+               -- sometimes, we keep output from intermediate stages
+               keep_this_output = 
+                    case next_phase of
+                            Ln                  -> True
+                            Mangle | keep_raw_s -> True
+                            As     | keep_s     -> True
+                            HCc    | keep_hc    -> True
+                            _other              -> False
+
                suffix = myPhaseInputExt next_phase
+
+               -- persistent object files get put in odir
+               persistent_fn 
+                  | Ln <- next_phase  = return odir_persistent
+                  | otherwise         = return persistent
+
                persistent = basename ++ '.':suffix
 
                odir_persistent
@@ -563,7 +574,7 @@ runPhase Hsc basename suff input_fn get_output_fn _maybe_loc = do
        
   -- gather the imports and module name
         (_,_,mod_name) <- 
-            if extcoreish_suffix suff
+            if isExtCoreFilename ('.':suff)
             then do
                -- no explicit imports in ExtCore input.
               m <- getCoreModuleName input_fn
@@ -620,14 +631,10 @@ runPhase Hsc basename suff input_fn get_output_fn _maybe_loc = do
                                     hscStubCOutName = basename ++ "_stub.c",
                                     hscStubHOutName = basename ++ "_stub.h",
                                     extCoreName = basename ++ ".hcr" }
-           hsc_env = HscEnv { hsc_mode = OneShot,
-                              hsc_dflags = dyn_flags',
-                              hsc_HPT    = emptyHomePackageTable }
-                       
+       hsc_env <- newHscEnv OneShot dyn_flags'
 
   -- run the compiler!
-        pcs <- initPersistentCompilerState
-       result <- hscMain hsc_env pcs mod
+       result <- hscMain hsc_env printErrorsAndWarnings mod
                          location{ ml_hspp_file=Just input_fn }
                          source_unchanged
                          False
@@ -635,13 +642,14 @@ runPhase Hsc basename suff input_fn get_output_fn _maybe_loc = do
 
        case result of
 
-           HscFail pcs -> throwDyn (PhaseFailed "hsc" (ExitFailure 1))
+           HscFail -> throwDyn (PhaseFailed "hsc" (ExitFailure 1))
 
-            HscNoRecomp pcs details iface -> do
+            HscNoRecomp details iface -> do
                SysTools.touch "Touching object file" o_file
                return (Nothing, Just location, output_fn)
 
-           HscRecomp _pcs _details _iface stub_h_exists stub_c_exists
+           HscRecomp _details _rdr_env _iface 
+                     stub_h_exists stub_c_exists
                      _maybe_interpreted_code -> do
 
                -- deal with stubs
@@ -1023,6 +1031,30 @@ staticLink o_files dep_packages = do
 
     [rts_pkg, std_pkg] <- getPackageDetails [rtsPackage, basePackage]
 
+    ways <- readIORef v_Ways
+
+    -- Here are some libs that need to be linked at the *end* of
+    -- the command line, because they contain symbols that are referred to
+    -- by the RTS.  We can't therefore use the ordinary way opts for these.
+    let
+       debug_opts | WayDebug `elem` ways = [ 
+#if defined(HAVE_LIBBFD)
+                       "-lbfd", "-liberty"
+#endif
+                        ]
+                  | otherwise            = []
+
+    let
+       thread_opts | WayThreaded `elem` ways = [ 
+#if !defined(mingw32_TARGET_OS) && !defined(freebsd_TARGET_OS)
+                       "-lpthread"
+#endif
+#if defined(osf3_TARGET_OS)
+                       , "-lexc"
+#endif
+                       ]
+                   | otherwise               = []
+
     let extra_os = if static || no_hs_main
                    then []
                    else [ head (library_dirs rts_pkg) ++ "/Main.dll_o",
@@ -1050,6 +1082,8 @@ staticLink o_files dep_packages = do
                      ++ pkg_framework_path_opts
                      ++ pkg_framework_opts
 #endif
+                     ++ debug_opts
+                     ++ thread_opts
                    ))
 
     -- parallel only: move binary to another dir -- HWL