Propagate scalar variables and tycons for vectorisation through 'HscTypes.VectInfo'.
[ghc-hetmet.git] / compiler / codeGen / CodeGen.lhs
index 4c08242..7a7bf48 100644 (file)
@@ -1,19 +1,15 @@
 %
+% (c) The University of Glasgow 2006
 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
-\section[CodeGen]{@CodeGen@: main module of the code generator}
+
+The Code Generator
 
 This module says how things get going at the top level.
 
 @codeGen@ is the interface to the outside world.  The \tr{cgTop*}
 functions drive the mangling of top-level bindings.
 
-%************************************************************************
-%*                                                                     *
-\subsection[codeGen-outside-interface]{The code generator's offering to the world}
-%*                                                                     *
-%************************************************************************
-
 \begin{code}
 module CodeGen ( codeGen ) where
 
@@ -25,54 +21,47 @@ module CodeGen ( codeGen ) where
 import CgExpr           ( {-NOTHING!-} )       -- DO NOT DELETE THIS IMPORT
 import CgProf
 import CgMonad
-import CgBindery       ( CgIdInfo, addBindC, addBindsC, getCgIdInfo,
-                         cgIdInfoId )
-import CgClosure       ( cgTopRhsClosure )
-import CgCon           ( cgTopRhsCon, cgTyCon )
-import CgUtils         ( cmmRegOffW, emitRODataLits, cmmNeWord )
+import CgBindery
+import CgClosure
+import CgCon
+import CgUtils
+import CgHpc
 
 import CLabel
-import Cmm
-import CmmUtils                ( zeroCLit, mkIntCLit, mkLblExpr )
-import PprCmm          ( pprCmms )
-import MachOp          ( wordRep )
+import OldCmm
+import OldPprCmm
 
 import StgSyn
-import PrelNames       ( gHC_PRIM, rOOT_MAIN, gHC_TOP_HANDLER )
-import DynFlags                ( DynFlags(..), DynFlag(..), dopt )
-import StaticFlags     ( opt_SccProfilingOn )
-
-import PackageConfig   ( PackageId )
-import HscTypes                ( ForeignStubs(..) )
-import CostCentre       ( CollectedCCs )
-import Id               ( Id, idName, setIdName )
-import Name            ( nameSrcLoc, nameOccName, nameUnique, isInternalName, mkExternalName )
-import OccName         ( mkLocalOcc )
-import TyCon            ( TyCon )
-import Module          ( Module )
-import ErrUtils                ( dumpIfSet_dyn, showPass )
-
-#ifdef DEBUG
-import Panic           ( assertPanic )
-#endif
+import PrelNames
+import DynFlags
+import StaticFlags
+
+import HscTypes
+import CostCentre
+import Id
+import Name
+import TyCon
+import Module
+import ErrUtils
+import Panic
 \end{code}
 
 \begin{code}
 codeGen :: DynFlags
        -> Module
        -> [TyCon]
-       -> ForeignStubs
-       -> [Module]             -- directly-imported modules
-       -> CollectedCCs         -- (Local/global) cost-centres needing declaring/registering.
+        -> CollectedCCs         -- (Local/global) cost-centres needing declaring/registering.
        -> [(StgBinding,[(Id,[Id])])]   -- Bindings to convert, with SRTs
+       -> HpcInfo
        -> IO [Cmm]             -- Output
 
-codeGen dflags this_mod data_tycons foreign_stubs imported_mods 
-       cost_centre_info stg_binds
+                -- N.B. returning '[Cmm]' and not 'Cmm' here makes it
+                -- possible for object splitting to split up the
+                -- pieces later.
+
+codeGen dflags this_mod data_tycons cost_centre_info stg_binds hpc_info
   = do 
   { showPass dflags "CodeGen"
-  ; let way = buildTag dflags
-        main_mod = mainModIs dflags
 
 -- Why?
 --   ; mapM_ (\x -> seq x (return ())) data_tycons
@@ -80,146 +69,47 @@ codeGen dflags this_mod data_tycons foreign_stubs imported_mods
   ; code_stuff <- initC dflags this_mod $ do 
                { cmm_binds  <- mapM (getCmm . cgTopBinding dflags) stg_binds
                ; cmm_tycons <- mapM cgTyCon data_tycons
-               ; cmm_init   <- getCmm (mkModuleInit dflags way cost_centre_info 
-                                            this_mod main_mod
-                                            foreign_stubs imported_mods)
-               ; return (cmm_binds ++ concat cmm_tycons ++ [cmm_init])
+               ; cmm_init   <- getCmm (mkModuleInit dflags cost_centre_info 
+                                             this_mod hpc_info)
+                ; return (cmm_init : cmm_binds ++ concat cmm_tycons)
                }
                -- Put datatype_stuff after code_stuff, because the
                -- datatype closure table (for enumeration types) to
                -- (say) PrelBase_True_closure, which is defined in
                -- code_stuff
 
+                -- Note [codegen-split-init] the cmm_init block must
+                -- come FIRST.  This is because when -split-objs is on
+                -- we need to combine this block with its
+                -- initialisation routines; see Note
+                -- [pipeline-split-init].
+
   ; dumpIfSet_dyn dflags Opt_D_dump_cmm "Cmm" (pprCmms code_stuff)
 
   ; return code_stuff }
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[codegen-init]{Module initialisation code}
-%*                                                                     *
-%************************************************************************
-
-/* -----------------------------------------------------------------------------
-   Module initialisation
 
-   The module initialisation code looks like this, roughly:
-
-       FN(__stginit_Foo) {
-         JMP_(__stginit_Foo_1_p)
-       }
-
-       FN(__stginit_Foo_1_p) {
-       ...
-       }
-
-   We have one version of the init code with a module version and the
-   'way' attached to it.  The version number helps to catch cases
-   where modules are not compiled in dependency order before being
-   linked: if a module has been compiled since any modules which depend on
-   it, then the latter modules will refer to a different version in their
-   init blocks and a link error will ensue.
-
-   The 'way' suffix helps to catch cases where modules compiled in different
-   ways are linked together (eg. profiled and non-profiled).
+mkModuleInit
+        :: DynFlags
+       -> CollectedCCs         -- cost centre info
+       -> Module
+        -> HpcInfo
+       -> Code
 
-   We provide a plain, unadorned, version of the module init code
-   which just jumps to the version with the label and way attached.  The
-   reason for this is that when using foreign exports, the caller of
-   startupHaskell() must supply the name of the init function for the "top"
-   module in the program, and we don't want to require that this name
-   has the version and way info appended to it.
-   --------------------------------------------------------------------------  */
+mkModuleInit dflags cost_centre_info this_mod hpc_info
+  = do { -- Allocate the static boolean that records if this
+        ; whenC (opt_Hpc) $
+              hpcTable this_mod hpc_info
 
-We initialise the module tree by keeping a work-stack, 
-       * pointed to by Sp
-       * that grows downward
-       * Sp points to the last occupied slot
+        ; whenC (opt_SccProfilingOn) $ do 
+           initCostCentres cost_centre_info
 
+            -- For backwards compatibility: user code may refer to this
+            -- label for calling hs_add_root().
+        ; emitData Data $ [ CmmDataLabel (mkPlainModuleInitLabel this_mod) ]
 
-\begin{code}
-mkModuleInit 
-       :: DynFlags
-       -> String               -- the "way"
-       -> CollectedCCs         -- cost centre info
-       -> Module
-       -> Module               -- name of the Main module
-       -> ForeignStubs
-       -> [Module]
-       -> Code
-mkModuleInit dflags way cost_centre_info this_mod main_mod foreign_stubs imported_mods
-  = do {       
-        if opt_SccProfilingOn
-            then do { -- Allocate the static boolean that records if this
-                      -- module has been registered already
-                     emitData Data [CmmDataLabel moduleRegdLabel, 
-                                    CmmStaticLit zeroCLit]
-
-                    ; emitSimpleProc real_init_lbl $ do
-                        { ret_blk <- forkLabelledCode ret_code
-
-                        ; init_blk <- forkLabelledCode $ do
-                                        { mod_init_code; stmtC (CmmBranch ret_blk) }
-                                    
-                        ; stmtC (CmmCondBranch (cmmNeWord (CmmLit zeroCLit) mod_reg_val)
-                                    ret_blk)
-                        ; stmtC (CmmBranch init_blk)       
-                        }
-                    }
-            else emitSimpleProc real_init_lbl ret_code
-
-           -- Make the "plain" procedure jump to the "real" init procedure
-       ; emitSimpleProc plain_init_lbl jump_to_init
-
-       -- When compiling the module in which the 'main' function lives,
-       -- (that is, this_mod == main_mod)
-       -- we inject an extra stg_init procedure for stg_init_ZCMain, for the 
-       -- RTS to invoke.  We must consult the -main-is flag in case the
-       -- user specified a different function to Main.main
-       ; whenC (this_mod == main_mod)
-               (emitSimpleProc plain_main_init_lbl jump_to_init)
+        ; whenC (this_mod == mainModIs dflags) $
+             emitSimpleProc (mkPlainModuleInitLabel rOOT_MAIN) $ return ()
     }
-  where
-    this_pkg = thisPackage dflags
-
-    plain_init_lbl = mkPlainModuleInitLabel this_pkg this_mod
-    real_init_lbl  = mkModuleInitLabel this_pkg this_mod way
-    plain_main_init_lbl = mkPlainModuleInitLabel this_pkg rOOT_MAIN
-
-    jump_to_init = stmtC (CmmJump (mkLblExpr real_init_lbl) [])
-
-    mod_reg_val = CmmLoad (mkLblExpr moduleRegdLabel) wordRep
-
-    -- Main refers to GHC.TopHandler.runIO, so make sure we call the
-    -- init function for GHC.TopHandler.
-    extra_imported_mods
-       | this_mod == main_mod = [gHC_TOP_HANDLER]
-       | otherwise            = []
-
-    mod_init_code = do
-       {       -- Set mod_reg to 1 to record that we've been here
-         stmtC (CmmStore (mkLblExpr moduleRegdLabel) (CmmLit (mkIntCLit 1)))
-
-               -- Now do local stuff
-       ; initCostCentres cost_centre_info
-       ; mapCs (registerModuleImport this_pkg way) 
-               (imported_mods++extra_imported_mods)
-       } 
-
-                    -- The return-code pops the work stack by 
-                    -- incrementing Sp, and then jumpd to the popped item
-    ret_code = stmtsC [ CmmAssign spReg (cmmRegOffW spReg 1)
-                      , CmmJump (CmmLoad (cmmRegOffW spReg (-1)) wordRep) [] ]
-
------------------------
-registerModuleImport :: PackageId -> String -> Module -> Code
-registerModuleImport this_pkg way mod 
-  | mod == gHC_PRIM
-  = nopC 
-  | otherwise  -- Push the init procedure onto the work stack
-  = stmtsC [ CmmAssign spReg (cmmRegOffW spReg (-1))
-          , CmmStore (CmmReg spReg) (mkLblExpr (mkModuleInitLabel this_pkg mod way)) ]
 \end{code}
 
 
@@ -238,9 +128,7 @@ initCostCentres (local_CCs, ___extern_CCs, singleton_CCSs)
   | otherwise
   = do { mapM_ emitCostCentreDecl       local_CCs
        ; mapM_ emitCostCentreStackDecl  singleton_CCSs
-       ; mapM_ emitRegisterCC           local_CCs
-       ; mapM_ emitRegisterCCS          singleton_CCSs
-       }
+        }
 \end{code}
 
 %************************************************************************
@@ -263,7 +151,7 @@ variable.
 cgTopBinding :: DynFlags -> (StgBinding,[(Id,[Id])]) -> Code
 cgTopBinding dflags (StgNonRec id rhs, srts)
   = do { id' <- maybeExternaliseId dflags id
-       ; mapM_ (mkSRT (thisPackage dflags) [id']) srts
+       ; mapM_ (mkSRT [id']) srts
        ; (id,info) <- cgTopRhs id' rhs
        ; addBindC id info      -- Add the *un-externalised* Id to the envt,
                                -- so we find it when we look up occurrences
@@ -273,19 +161,19 @@ cgTopBinding dflags (StgRec pairs, srts)
   = do { let (bndrs, rhss) = unzip pairs
        ; bndrs' <- mapFCs (maybeExternaliseId dflags) bndrs
        ; let pairs' = zip bndrs' rhss
-       ; mapM_ (mkSRT (thisPackage dflags) bndrs')  srts
+       ; mapM_ (mkSRT bndrs')  srts
        ; _new_binds <- fixC (\ new_binds -> do 
                { addBindsC new_binds
                ; mapFCs ( \ (b,e) -> cgTopRhs b e ) pairs' })
        ; nopC }
 
-mkSRT :: PackageId -> [Id] -> (Id,[Id]) -> Code
-mkSRT this_pkg these (id,[])  = nopC
-mkSRT this_pkg these (id,ids)
+mkSRT :: [Id] -> (Id,[Id]) -> Code
+mkSRT _ (_,[])  = nopC
+mkSRT these (id,ids)
   = do { ids <- mapFCs remap ids
        ; id  <- remap id
-       ; emitRODataLits (mkSRTLabel (idName id)) 
-                      (map (CmmLabel . mkClosureLabel this_pkg . idName) ids)
+       ; emitRODataLits "CodeGen.mkSRT" (mkSRTLabel (idName id) (idCafInfo id)) 
+              (map (\id -> CmmLabel $ mkClosureLabel (idName id) (idCafInfo id)) ids)
        }
   where
        -- Sigh, better map all the ids against the environment in 
@@ -302,13 +190,14 @@ cgTopRhs :: Id -> StgRhs -> FCode (Id, CgIdInfo)
        -- The Id is passed along for setting up a binding...
        -- It's already been externalised if necessary
 
-cgTopRhs bndr (StgRhsCon cc con args)
+cgTopRhs bndr (StgRhsCon _cc con args)
   = forkStatics (cgTopRhsCon bndr con args)
 
 cgTopRhs bndr (StgRhsClosure cc bi fvs upd_flag srt args body)
   = ASSERT(null fvs)    -- There should be no free variables
-    setSRTLabel (mkSRTLabel (idName bndr)) $ 
-    forkStatics (cgTopRhsClosure bndr cc bi srt upd_flag args body)
+    setSRTLabel (mkSRTLabel (idName bndr) (idCafInfo bndr)) $
+    setSRT srt $
+    forkStatics (cgTopRhsClosure bndr cc bi upd_flag args body)
 \end{code}
 
 
@@ -326,7 +215,7 @@ which refers to this name).
 maybeExternaliseId :: DynFlags -> Id -> FCode Id
 maybeExternaliseId dflags id
   | dopt Opt_SplitObjs dflags,         -- Externalise the name for -split-objs
-    isInternalName name = do { mod <- moduleName
+    isInternalName name = do { mod <- getModuleName
                             ; returnFC (setIdName id (externalise mod)) }
   | otherwise          = returnFC id
   where
@@ -334,7 +223,7 @@ maybeExternaliseId dflags id
     name    = idName id
     uniq    = nameUnique name
     new_occ = mkLocalOcc uniq (nameOccName name)
-    loc     = nameSrcLoc name
+    loc     = nameSrcSpan name
        -- We want to conjure up a name that can't clash with any
        -- existing name.  So we generate
        --      Mod_$L243foo