[project @ 2001-12-21 10:05:11 by simonpj]
[ghc-hetmet.git] / ghc / compiler / codeGen / CodeGen.lhs
index 6bd024d..c9d3522 100644 (file)
@@ -19,105 +19,147 @@ module CodeGen ( codeGen ) where
 
 #include "HsVersions.h"
 
 
 #include "HsVersions.h"
 
+-- Kludge (??) so that CgExpr is reached via at least one non-SOURCE
+-- import.  Before, that wasn't the case, and CM therefore didn't 
+-- bother to compile it.
+import CgExpr           ( {-NOTHING!-} )       -- DO NOT DELETE THIS IMPORT
+
 import StgSyn
 import CgMonad
 import AbsCSyn
 import StgSyn
 import CgMonad
 import AbsCSyn
-import CLabel          ( CLabel, mkSRTLabel, mkClosureLabel )
+import CLabel          ( CLabel, mkSRTLabel, mkClosureLabel, mkModuleInitLabel )
 
 
-import AbsCUtils       ( mkAbstractCs, mkAbsCStmts )
-import CgBindery       ( CgIdInfo )
+import PprAbsC         ( dumpRealC )
+import AbsCUtils       ( mkAbstractCs, flattenAbsC )
+import CgBindery       ( CgIdInfo, addBindC, addBindsC, getCAddrModeAndInfo )
 import CgClosure       ( cgTopRhsClosure )
 import CgCon           ( cgTopRhsCon )
 import CgConTbls       ( genStaticConBits )
 import ClosureInfo     ( mkClosureLFInfo )
 import CgClosure       ( cgTopRhsClosure )
 import CgCon           ( cgTopRhsCon )
 import CgConTbls       ( genStaticConBits )
 import ClosureInfo     ( mkClosureLFInfo )
-import CmdLineOpts     ( opt_SccProfilingOn, opt_EnsureSplittableC, 
-                                             opt_SccGroup
-                       )
-import CostCentre       ( CostCentre, CostCentreStack )
-import FiniteMap       ( FiniteMap )
-import Id               ( Id, idName )
-import Name             ( Module, moduleString )
-import PrimRep         ( getPrimRepSize, PrimRep(..) )
-import Type             ( Type )
-import TyCon            ( TyCon )
+import CmdLineOpts     ( DynFlags, DynFlag(..),
+                         opt_SccProfilingOn, opt_EnsureSplittableC )
+import CostCentre       ( CollectedCCs )
+import Id               ( Id, idName, setIdName )
+import Name            ( nameSrcLoc, nameOccName, nameUnique, isLocalName, mkGlobalName )
+import OccName         ( mkLocalOcc )
+import Module           ( Module )
+import PrimRep         ( PrimRep(..) )
+import TyCon            ( TyCon, isDataTyCon )
 import BasicTypes      ( TopLevelFlag(..) )
 import BasicTypes      ( TopLevelFlag(..) )
-import Util
+import UniqSupply      ( mkSplitUniqSupply )
+import ErrUtils                ( dumpIfSet_dyn, showPass )
 import Panic           ( assertPanic )
 import Panic           ( assertPanic )
+
+#ifdef DEBUG
+import Outputable
+#endif
+\end{code}
+
+\begin{code}
+codeGen :: DynFlags
+       -> Module               -- Module name
+       -> [Module]             -- Import names
+       -> CollectedCCs         -- (Local/global) cost-centres needing declaring/registering.
+       -> [Id]                 -- foreign-exported binders
+       -> [TyCon]              -- Local tycons, including ones from classes
+       -> [(StgBinding,[Id])]  -- Bindings to convert, with SRTs
+       -> IO AbstractC         -- Output
+
+codeGen dflags mod_name imported_modules cost_centre_info fe_binders
+       tycons stg_binds
+  = do { showPass dflags "CodeGen"
+       ; fl_uniqs <- mkSplitUniqSupply 'f'
+       ; dumpIfSet_dyn dflags Opt_D_dump_absC "Abstract C" (dumpRealC abstractC)
+       ; let flat_abstractC = flattenAbsC fl_uniqs abstractC
+       ; return flat_abstractC
+       }
+  where
+    data_tycons    = filter isDataTyCon tycons
+    cinfo          = MkCompInfo mod_name
+
+    datatype_stuff = genStaticConBits cinfo data_tycons
+    code_stuff     = initC cinfo (mapCs cgTopBinding stg_binds)
+    init_stuff     = mkModuleInit fe_binders mod_name imported_modules 
+                                         cost_centre_info
+
+    abstractC = mkAbstractCs [ maybeSplitCode,
+                              init_stuff, 
+                              code_stuff,
+                              datatype_stuff]
+       -- 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
+
 \end{code}
 
 \end{code}
 
+%************************************************************************
+%*                                                                     *
+\subsection[codegen-init]{Module initialisation code}
+%*                                                                     *
+%************************************************************************
+
 \begin{code}
 \begin{code}
-codeGen :: Module              -- module name
-       -> ([CostCentre],       -- local cost-centres needing declaring/registering
-           [CostCentre],       -- "extern" cost-centres needing declaring
-           [CostCentreStack])  -- pre-defined "singleton" cost centre stacks
+mkModuleInit 
+       :: [Id]                 -- foreign exported functions
+       -> Module               -- module name
        -> [Module]             -- import names
        -> [Module]             -- import names
-       -> [TyCon]              -- tycons with data constructors to convert
-       -> FiniteMap TyCon [(Bool, [Maybe Type])]
-                               -- tycon specialisation info
-       -> [(StgBinding,[Id])]  -- bindings to convert, with SRTs
-       -> AbstractC            -- output
-
-codeGen mod_name (local_CCs, extern_CCs, singleton_CCSs) 
-       import_names gen_tycons tycon_specs stg_pgm
+       -> CollectedCCs         -- cost centre info
+       -> AbstractC
+mkModuleInit fe_binders mod imps cost_centre_info
   = let
   = let
-       maybe_split       = if opt_EnsureSplittableC 
-                               then CSplitMarker 
-                               else AbsCNop
-       cinfo             = MkCompInfo mod_name
+       register_fes = 
+          map (\f -> CMacroStmt REGISTER_FOREIGN_EXPORT [f]) fe_labels
+
+       fe_labels = 
+          map (\f -> CLbl (mkClosureLabel (idName f)) PtrRep) fe_binders
+
+       (cc_decls, cc_regs) = mkCostCentreStuff cost_centre_info
+
+       mk_import_register imp =
+           CMacroStmt REGISTER_IMPORT [
+               CLbl (mkModuleInitLabel imp) AddrRep
+           ]
+
+       register_imports = map mk_import_register imps
     in
     in
-    let 
-       module_code = mkAbstractCs [
-           genStaticConBits cinfo gen_tycons tycon_specs,
-           initC cinfo (cgTopBindings maybe_split stg_pgm) ]
-
-        -- Cost-centre profiling:
-        -- Besides the usual stuff, we must produce:
-        --
-        -- * Declarations for the cost-centres defined in this module;
-        -- * Code to participate in "registering" all the cost-centres
-        --   in the program (done at startup time when the pgm is run).
-        --
-        -- (The local cost-centres involved in this are passed
-        -- into the code-generator, as are the imported-modules' names.)
-        --
-        --
-       cost_centre_stuff 
-               | not opt_SccProfilingOn = AbsCNop
-               | otherwise = mkAbstractCs (
-                   map (CCostCentreDecl True)   local_CCs ++
-                   map (CCostCentreDecl False)  extern_CCs ++
-                   map CCostCentreStackDecl     singleton_CCSs ++
-                   mkCcRegister local_CCs singleton_CCSs import_names
-                  )
-   in
-   mkAbstractCs [ cost_centre_stuff, module_code ]
+    mkAbstractCs [
+       cc_decls,
+        CModuleInitBlock (mkModuleInitLabel mod)
+                        (mkAbstractCs (register_fes ++
+                                       cc_regs :
+                                       register_imports))
+    ]
+\end{code}
 
 
+Cost-centre profiling: Besides the usual stuff, we must produce
+declarations for the cost-centres defined in this module;
+
+(The local cost-centres involved in this are passed into the
+code-generator.)
+
+\begin{code}
+mkCostCentreStuff (local_CCs, extern_CCs, singleton_CCSs)
+  | not opt_SccProfilingOn = (AbsCNop, AbsCNop)
+  | otherwise = 
+       ( mkAbstractCs (
+               map (CCostCentreDecl True)   local_CCs ++
+               map (CCostCentreDecl False)  extern_CCs ++
+               map CCostCentreStackDecl     singleton_CCSs),
+         mkAbstractCs (mkCcRegister local_CCs singleton_CCSs)
+       )
   where
   where
-    mkCcRegister ccs cc_stacks import_names
+    mkCcRegister ccs cc_stacks
       = let
       = let
-           register_ccs     = mkAbstractCs (map mk_register ccs)
-           register_imports
-             = foldr (mkAbsCStmts . mk_import_register) AbsCNop import_names
+           register_ccs       = mkAbstractCs (map mk_register ccs)
            register_cc_stacks = mkAbstractCs (map mk_register_ccs cc_stacks)
        in
            register_cc_stacks = mkAbstractCs (map mk_register_ccs cc_stacks)
        in
-       [
-           CCallProfCCMacro SLIT("START_REGISTER_CCS") 
-              [ CLitLit (_PK_ ("_reg" ++ moduleString mod_name)) AddrRep],
-           register_ccs,
-           register_cc_stacks,
-           register_imports,
-           CCallProfCCMacro SLIT("END_REGISTER_CCS") []
-       ]
+       [ register_ccs, register_cc_stacks ]
       where
        mk_register cc
          = CCallProfCCMacro SLIT("REGISTER_CC") [mkCCostCentre cc]
 
        mk_register_ccs ccs
          = CCallProfCCMacro SLIT("REGISTER_CCS") [mkCCostCentreStack ccs]
       where
        mk_register cc
          = CCallProfCCMacro SLIT("REGISTER_CC") [mkCCostCentre cc]
 
        mk_register_ccs ccs
          = CCallProfCCMacro SLIT("REGISTER_CCS") [mkCCostCentreStack ccs]
-
-       mk_import_register import_name
-         = CCallProfCCMacro SLIT("REGISTER_IMPORT") 
-             [CLitLit (_PK_ ("_reg" ++ moduleString import_name)) AddrRep]
 \end{code}
 
 %************************************************************************
 \end{code}
 
 %************************************************************************
@@ -126,7 +168,7 @@ codeGen mod_name (local_CCs, extern_CCs, singleton_CCSs)
 %*                                                                     *
 %************************************************************************
 
 %*                                                                     *
 %************************************************************************
 
-@cgTopBindings@ is only used for top-level bindings, since they need
+@cgTopBinding@ is only used for top-level bindings, since they need
 to be allocated statically (not in the heap) and need to be labelled.
 No unboxed bindings can happen at top level.
 
 to be allocated statically (not in the heap) and need to be labelled.
 No unboxed bindings can happen at top level.
 
@@ -137,53 +179,101 @@ style, with the increasing static environment being plumbed as a state
 variable.
 
 \begin{code}
 variable.
 
 \begin{code}
-cgTopBindings :: AbstractC -> [(StgBinding,[Id])] -> Code
-
-cgTopBindings split bindings = mapCs (cgTopBinding split) bindings
-
-cgTopBinding :: AbstractC -> (StgBinding,[Id]) -> Code
-
-cgTopBinding split ((StgNonRec name rhs), srt)
-  = absC split                 `thenC`
-    absC (mkSRT srt_label srt)         `thenC`
+cgTopBinding :: (StgBinding,[Id]) -> Code
+cgTopBinding (StgNonRec srt_info id rhs, srt)
+  = absC maybeSplitCode                `thenC`
+    maybeGlobaliseId id                `thenFC` \ id' ->
+    let
+       srt_label = mkSRTLabel (idName id')
+    in
+    mkSRT srt_label srt []     `thenC`
     setSRTLabel srt_label (
     setSRTLabel srt_label (
-    cgTopRhs name rhs          `thenFC` \ (name, info) ->
-    addBindC name info
+    cgTopRhs id' rhs srt_info          `thenFC` \ (id, info) ->
+    addBindC id info   -- Add the un-globalised Id to the envt, so we
+                       -- find it when we look up occurrences
     )
     )
-  where
-    srt_label = mkSRTLabel (idName name)
 
 
-cgTopBinding split ((StgRec pairs@((name,rhs):_)), srt)
-  = absC split                 `thenC`
-    absC (mkSRT srt_label srt)         `thenC`
+cgTopBinding (StgRec srt_info pairs, srt)
+  = absC maybeSplitCode                        `thenC`
+    let
+        (bndrs, rhss) = unzip pairs
+    in
+    mapFCs maybeGlobaliseId bndrs      `thenFC` \ bndrs'@(id:_) ->
+    let
+       srt_label = mkSRTLabel (idName id)
+       pairs'    = zip bndrs' rhss
+    in
+    mkSRT srt_label srt bndrs'         `thenC`
     setSRTLabel srt_label (
     setSRTLabel srt_label (
-    fixC (\ new_binds -> addBindsC new_binds   `thenC`
-                        mapFCs ( \ (b,e) -> cgTopRhs b e ) pairs
-    )                    `thenFC` \ new_binds ->
-    addBindsC new_binds
+       fixC (\ new_binds -> 
+               addBindsC new_binds             `thenC`
+               mapFCs ( \ (b,e) -> cgTopRhs b e srt_info ) pairs'
+       )  `thenFC` \ new_binds -> nopC
     )
     )
-  where
-    srt_label = mkSRTLabel (idName name)
 
 
-mkSRT :: CLabel -> [Id] -> AbstractC
-mkSRT lbl []  = AbsCNop
-mkSRT lbl ids = CSRT lbl (map (mkClosureLabel . idName) ids)
+mkSRT :: CLabel -> [Id] -> [Id] -> Code
+mkSRT lbl []  these = nopC
+mkSRT lbl ids these
+  = mapFCs remap ids `thenFC` \ ids ->
+    absC (CSRT lbl (map (mkClosureLabel . idName) ids))
+  where
+       -- sigh, better map all the ids against the environment in case they've
+       -- been globalised (see maybeGlobaliseId below).
+    remap id = case filter (==id) these of
+               [] ->  getCAddrModeAndInfo id 
+                               `thenFC` \ (id, _, _) -> returnFC id
+               (id':_) -> returnFC id'
 
 -- Urgh!  I tried moving the forkStatics call from the rhss of cgTopRhs
 -- to enclose the listFCs in cgTopBinding, but that tickled the
 -- statics "error" call in initC.  I DON'T UNDERSTAND WHY!
 
 
 -- Urgh!  I tried moving the forkStatics call from the rhss of cgTopRhs
 -- to enclose the listFCs in cgTopBinding, but that tickled the
 -- statics "error" call in initC.  I DON'T UNDERSTAND WHY!
 
-cgTopRhs :: Id -> StgRhs -> FCode (Id, CgIdInfo)
-       -- the Id is passed along for setting up a binding...
+cgTopRhs :: Id -> StgRhs -> SRT -> FCode (Id, CgIdInfo)
+       -- The Id is passed along for setting up a binding...
+       -- It's already been globalised if necessary
 
 
-cgTopRhs bndr (StgRhsCon cc con args)
-  = forkStatics (cgTopRhsCon bndr con args (all zero_size args))
-  where
-    zero_size atom = getPrimRepSize (getArgPrimRep atom) == 0
+cgTopRhs bndr (StgRhsCon cc con args) srt
+  = forkStatics (cgTopRhsCon bndr con args)
 
 
-cgTopRhs bndr (StgRhsClosure cc bi srt fvs upd_flag args body)
-  = ASSERT(null fvs) -- There should be no free variables
+cgTopRhs bndr (StgRhsClosure cc bi fvs upd_flag args body) srt
+  =     -- There should be no free variables
+    ASSERT(null fvs)
+    let 
+       lf_info = mkClosureLFInfo bndr TopLevel [{-no fvs-}] upd_flag args
+    in
     forkStatics (cgTopRhsClosure bndr cc bi srt args body lf_info)
     forkStatics (cgTopRhsClosure bndr cc bi srt args body lf_info)
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
+\subsection{Stuff to support splitting}
+%*                                                                     *
+%************************************************************************
+
+If we're splitting the object, we need to globalise all the top-level names
+(and then make sure we only use the globalised one in any C label we use
+which refers to this name).
+
+\begin{code}
+maybeGlobaliseId :: Id -> FCode Id
+maybeGlobaliseId id
+  | opt_EnsureSplittableC,     -- Globalise the name for -split-objs
+    isLocalName name
+  = moduleName                          `thenFC` \ mod ->
+    returnFC (setIdName id (mkGlobalName uniq mod new_occ (nameSrcLoc name)))
+  | otherwise          
+  = returnFC id
   where
   where
-    lf_info = mkClosureLFInfo bndr TopLevel [{-no fvs-}] upd_flag args
+    name       = idName id
+    uniq       = nameUnique name
+    new_occ    = mkLocalOcc uniq (nameOccName name)
+       -- We want to conjure up a name that can't clash with any
+       -- existing name.  So we generate
+       --      Mod_$L243foo
+       -- where 243 is the unique.
+
+maybeSplitCode
+  | opt_EnsureSplittableC = CSplitMarker 
+  | otherwise             = AbsCNop
 \end{code}
 \end{code}