Reorganisation of the source tree
[ghc-hetmet.git] / ghc / compiler / codeGen / CgBindery.lhs
diff --git a/ghc/compiler/codeGen/CgBindery.lhs b/ghc/compiler/codeGen/CgBindery.lhs
deleted file mode 100644 (file)
index f78edda..0000000
+++ /dev/null
@@ -1,494 +0,0 @@
-%
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
-%
-\section[CgBindery]{Utility functions related to doing @CgBindings@}
-
-\begin{code}
-module CgBindery (
-       CgBindings, CgIdInfo,
-       StableLoc, VolatileLoc,
-
-       cgIdInfoId, cgIdInfoArgRep, cgIdInfoLF,
-
-       stableIdInfo, heapIdInfo, 
-       letNoEscapeIdInfo, idInfoToAmode,
-
-       addBindC, addBindsC,
-
-       nukeVolatileBinds,
-       nukeDeadBindings,
-       getLiveStackSlots,
-
-       bindArgsToStack,  rebindToStack,
-       bindNewToNode, bindNewToReg, bindArgsToRegs,
-       bindNewToTemp, 
-       getArgAmode, getArgAmodes, 
-       getCgIdInfo, 
-       getCAddrModeIfVolatile, getVolatileRegs,
-       maybeLetNoEscape, 
-    ) where
-
-#include "HsVersions.h"
-
-import CgMonad
-import CgHeapery       ( getHpRelOffset )
-import CgStackery      ( freeStackSlots, getSpRelOffset )
-import CgUtils         ( cgLit, cmmOffsetW )
-import CLabel          ( mkClosureLabel, pprCLabel )
-import ClosureInfo     ( mkLFImported, mkLFArgument, LambdaFormInfo )
-
-import Cmm
-import PprCmm          ( {- instance Outputable -} )
-import SMRep           ( CgRep(..), WordOff, isFollowableArg, 
-                         isVoidArg, cgRepSizeW, argMachRep, 
-                         idCgRep, typeCgRep )
-import Id              ( Id, idName )
-import VarEnv
-import VarSet          ( varSetElems )
-import Literal         ( literalType )
-import Maybes          ( catMaybes )
-import Name            ( isExternalName )
-import StgSyn          ( StgArg, StgLiveVars, GenStgArg(..), isStgTypeArg )
-import Unique           ( Uniquable(..) )
-import UniqSet         ( elementOfUniqSet )
-import Outputable
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-\subsection[Bindery-datatypes]{Data types}
-%*                                                                     *
-%************************************************************************
-
-@(CgBinding a b)@ is a type of finite maps from a to b.
-
-The assumption used to be that @lookupCgBind@ must get exactly one
-match.  This is {\em completely wrong} in the case of compiling
-letrecs (where knot-tying is used).  An initial binding is fed in (and
-never evaluated); eventually, a correct binding is put into the
-environment.  So there can be two bindings for a given name.
-
-\begin{code}
-type CgBindings = IdEnv CgIdInfo
-
-data CgIdInfo
-  = CgIdInfo   
-       { cg_id :: Id   -- Id that this is the info for
-                       -- Can differ from the Id at occurrence sites by 
-                       -- virtue of being externalised, for splittable C
-       , cg_rep :: CgRep
-       , cg_vol :: VolatileLoc
-       , cg_stb :: StableLoc
-       , cg_lf  :: LambdaFormInfo }
-
-mkCgIdInfo id vol stb lf
-  = CgIdInfo { cg_id = id, cg_vol = vol, cg_stb = stb, 
-              cg_lf = lf, cg_rep = idCgRep id }
-
-voidIdInfo id = CgIdInfo { cg_id = id, cg_vol = NoVolatileLoc
-                        , cg_stb = VoidLoc, cg_lf = mkLFArgument id
-                        , cg_rep = VoidArg }
-       -- Used just for VoidRep things
-
-data VolatileLoc       -- These locations die across a call
-  = NoVolatileLoc
-  | RegLoc     CmmReg             -- In one of the registers (global or local)
-  | VirHpLoc   VirtualHpOffset  -- Hp+offset (address of closure)
-  | VirNodeLoc VirtualHpOffset  -- Cts of offset indirect from Node
-                                  -- ie *(Node+offset)
-\end{code}
-
-@StableLoc@ encodes where an Id can be found, used by
-the @CgBindings@ environment in @CgBindery@.
-
-\begin{code}
-data StableLoc
-  = NoStableLoc
-
-  | VirStkLoc  VirtualSpOffset         -- The thing is held in this
-                                       -- stack slot
-
-  | VirStkLNE  VirtualSpOffset         -- A let-no-escape thing; the
-                                       -- value is this stack pointer
-                                       -- (as opposed to the contents of the slot)
-
-  | StableLoc  CmmExpr
-  | VoidLoc    -- Used only for VoidRep variables.  They never need to
-               -- be saved, so it makes sense to treat treat them as
-               -- having a stable location
-\end{code}
-
-\begin{code}
-instance Outputable CgIdInfo where
-  ppr (CgIdInfo id rep vol stb lf)
-    = ppr id <+> ptext SLIT("-->") <+> vcat [ppr vol, ppr stb]
-
-instance Outputable VolatileLoc where
-  ppr NoVolatileLoc = empty
-  ppr (RegLoc r)     = ptext SLIT("reg") <+> ppr r
-  ppr (VirHpLoc v)   = ptext SLIT("vh")  <+> ppr v
-  ppr (VirNodeLoc v) = ptext SLIT("vn")  <+> ppr v
-
-instance Outputable StableLoc where
-  ppr NoStableLoc   = empty
-  ppr VoidLoc       = ptext SLIT("void")
-  ppr (VirStkLoc v) = ptext SLIT("vs")    <+> ppr v
-  ppr (VirStkLNE v) = ptext SLIT("lne")    <+> ppr v
-  ppr (StableLoc a) = ptext SLIT("amode") <+> ppr a
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[Bindery-idInfo]{Manipulating IdInfo}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-stableIdInfo id amode   lf_info = mkCgIdInfo id NoVolatileLoc (StableLoc amode) lf_info
-heapIdInfo id offset    lf_info = mkCgIdInfo id (VirHpLoc offset) NoStableLoc lf_info
-letNoEscapeIdInfo id sp lf_info = mkCgIdInfo id NoVolatileLoc (VirStkLNE sp) lf_info
-stackIdInfo id sp      lf_info = mkCgIdInfo id NoVolatileLoc (VirStkLoc sp) lf_info
-nodeIdInfo id offset    lf_info = mkCgIdInfo id (VirNodeLoc offset) NoStableLoc lf_info
-regIdInfo id reg        lf_info = mkCgIdInfo id (RegLoc reg) NoStableLoc lf_info
-
-idInfoToAmode :: CgIdInfo -> FCode CmmExpr
-idInfoToAmode info
-  = case cg_vol info of {
-      RegLoc reg       -> returnFC (CmmReg reg) ;
-      VirNodeLoc nd_off -> returnFC (CmmLoad (cmmOffsetW (CmmReg nodeReg) nd_off) mach_rep) ;
-      VirHpLoc hp_off   -> getHpRelOffset hp_off ;
-      NoVolatileLoc -> 
-
-    case cg_stb info of
-      StableLoc amode  -> returnFC amode
-      VirStkLoc sp_off -> do { sp_rel <- getSpRelOffset sp_off
-                            ; return (CmmLoad sp_rel mach_rep) }
-
-      VirStkLNE sp_off -> getSpRelOffset sp_off
-
-      VoidLoc -> return $ pprPanic "idInfoToAmode: void" (ppr (cg_id info))
-               -- We return a 'bottom' amode, rather than panicing now
-               -- In this way getArgAmode returns a pair of (VoidArg, bottom)
-               -- and that's exactly what we want
-
-      NoStableLoc -> pprPanic "idInfoToAmode: no loc" (ppr (cg_id info))
-    }
-  where
-    mach_rep = argMachRep (cg_rep info)
-
-cgIdInfoId :: CgIdInfo -> Id
-cgIdInfoId = cg_id 
-
-cgIdInfoLF :: CgIdInfo -> LambdaFormInfo
-cgIdInfoLF = cg_lf
-
-cgIdInfoArgRep :: CgIdInfo -> CgRep
-cgIdInfoArgRep = cg_rep
-
-maybeLetNoEscape (CgIdInfo { cg_stb = VirStkLNE sp_off }) = Just sp_off
-maybeLetNoEscape other                                   = Nothing
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[CgMonad-bindery]{Monad things for fiddling with @CgBindings@}
-%*                                                                     *
-%************************************************************************
-
-.There are three basic routines, for adding (@addBindC@), modifying
-(@modifyBindC@) and looking up (@getCgIdInfo@) bindings.
-
-A @Id@ is bound to a @(VolatileLoc, StableLoc)@ triple.
-The name should not already be bound. (nice ASSERT, eh?)
-
-\begin{code}
-addBindC :: Id -> CgIdInfo -> Code
-addBindC name stuff_to_bind = do
-       binds <- getBinds
-       setBinds $ extendVarEnv binds name stuff_to_bind
-
-addBindsC :: [(Id, CgIdInfo)] -> Code
-addBindsC new_bindings = do
-       binds <- getBinds
-       let new_binds = foldl (\ binds (name,info) -> extendVarEnv binds name info)
-                             binds
-                             new_bindings
-       setBinds new_binds
-
-modifyBindC :: Id -> (CgIdInfo -> CgIdInfo) -> Code
-modifyBindC name mangle_fn = do
-       binds <- getBinds
-       setBinds $ modifyVarEnv mangle_fn binds name
-
-getCgIdInfo :: Id -> FCode CgIdInfo
-getCgIdInfo id
-  = do {       -- Try local bindings first
-       ; local_binds  <- getBinds
-       ; case lookupVarEnv local_binds id of {
-           Just info -> return info ;
-           Nothing   -> do
-
-       {       -- Try top-level bindings
-         static_binds <- getStaticBinds
-       ; case lookupVarEnv static_binds id of {
-           Just info -> return info ;
-           Nothing   ->
-
-               -- Should be imported; make up a CgIdInfo for it
-       let 
-           name = idName id
-       in
-       if isExternalName name then do
-           hmods <- getHomeModules 
-           let ext_lbl = CmmLit (CmmLabel (mkClosureLabel hmods name))
-           return (stableIdInfo id ext_lbl (mkLFImported id))
-       else
-       if isVoidArg (idCgRep id) then
-               -- Void things are never in the environment
-           return (voidIdInfo id)
-       else
-       -- Bug  
-       cgLookupPanic id
-       }}}}
-    
-                       
-cgLookupPanic :: Id -> FCode a
-cgLookupPanic id
-  = do static_binds <- getStaticBinds
-       local_binds <- getBinds
-       srt <- getSRTLabel
-       pprPanic "cgPanic"
-               (vcat [ppr id,
-               ptext SLIT("static binds for:"),
-               vcat [ ppr (cg_id info) | info <- varEnvElts static_binds ],
-               ptext SLIT("local binds for:"),
-               vcat [ ppr (cg_id info) | info <- varEnvElts local_binds ],
-               ptext SLIT("SRT label") <+> pprCLabel srt
-             ])
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[Bindery-nuke-volatile]{Nuking volatile bindings}
-%*                                                                     *
-%************************************************************************
-
-We sometimes want to nuke all the volatile bindings; we must be sure
-we don't leave any (NoVolatile, NoStable) binds around...
-
-\begin{code}
-nukeVolatileBinds :: CgBindings -> CgBindings
-nukeVolatileBinds binds
-  = mkVarEnv (foldr keep_if_stable [] (varEnvElts binds))
-  where
-    keep_if_stable (CgIdInfo { cg_stb = NoStableLoc }) acc = acc
-    keep_if_stable info acc
-      = (cg_id info, info { cg_vol = NoVolatileLoc }) : acc
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-\subsection[lookup-interface]{Interface functions to looking up bindings}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-getCAddrModeIfVolatile :: Id -> FCode (Maybe CmmExpr)
-getCAddrModeIfVolatile id
-  = do { info <- getCgIdInfo id
-       ; case cg_stb info of
-               NoStableLoc -> do -- Aha!  So it is volatile!
-                       amode <- idInfoToAmode info
-                       return $ Just amode
-               a_stable_loc -> return Nothing }
-\end{code}
-
-@getVolatileRegs@ gets a set of live variables, and returns a list of
-all registers on which these variables depend.  These are the regs
-which must be saved and restored across any C calls.  If a variable is
-both in a volatile location (depending on a register) {\em and} a
-stable one (notably, on the stack), we modify the current bindings to
-forget the volatile one.
-
-\begin{code}
-getVolatileRegs :: StgLiveVars -> FCode [GlobalReg]
-
-getVolatileRegs vars = do
-  do   { stuff <- mapFCs snaffle_it (varSetElems vars)
-       ; returnFC $ catMaybes stuff }
-  where
-    snaffle_it var = do
-       { info <- getCgIdInfo var 
-       ; let
-               -- commoned-up code...
-            consider_reg reg
-               =       -- We assume that all regs can die across C calls
-                       -- We leave it to the save-macros to decide which
-                       -- regs *really* need to be saved.
-                 case cg_stb info of
-                       NoStableLoc     -> returnFC (Just reg) -- got one!
-                       is_a_stable_loc -> do
-                               { -- has both volatile & stable locations;
-                                 -- force it to rely on the stable location
-                                 modifyBindC var nuke_vol_bind 
-                               ; return Nothing }
-
-       ; case cg_vol info of
-           RegLoc (CmmGlobal reg) -> consider_reg reg
-           VirNodeLoc _           -> consider_reg node
-           other_loc              -> returnFC Nothing  -- Local registers
-       }
-
-    nuke_vol_bind info = info { cg_vol = NoVolatileLoc }
-\end{code}
-
-\begin{code}
-getArgAmode :: StgArg -> FCode (CgRep, CmmExpr)
-getArgAmode (StgVarArg var) 
-  = do { info <- getCgIdInfo var
-       ; amode <- idInfoToAmode info
-       ; return (cgIdInfoArgRep info, amode ) }
-
-getArgAmode (StgLitArg lit) 
-  = do { cmm_lit <- cgLit lit
-       ; return (typeCgRep (literalType lit), CmmLit cmm_lit) }
-
-getArgAmode (StgTypeArg _) = panic "getArgAmode: type arg"
-
-getArgAmodes :: [StgArg] -> FCode [(CgRep, CmmExpr)]
-getArgAmodes [] = returnFC []
-getArgAmodes (atom:atoms)
-  | isStgTypeArg atom = getArgAmodes atoms
-  | otherwise        = do { amode  <- getArgAmode  atom 
-                          ; amodes <- getArgAmodes atoms
-                          ; return ( amode : amodes ) }
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[binding-and-rebinding-interface]{Interface functions for binding and re-binding names}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-bindArgsToStack :: [(Id, VirtualSpOffset)] -> Code
-bindArgsToStack args
-  = mapCs bind args
-  where
-    bind(id, offset) = addBindC id (stackIdInfo id offset (mkLFArgument id))
-
-bindArgsToRegs :: [(Id, GlobalReg)] -> Code
-bindArgsToRegs args
-  = mapCs bind args
-  where
-    bind (arg, reg) = bindNewToReg arg (CmmGlobal reg) (mkLFArgument arg)
-
-bindNewToNode :: Id -> VirtualHpOffset -> LambdaFormInfo -> Code
-bindNewToNode id offset lf_info
-  = addBindC id (nodeIdInfo id offset lf_info)
-
--- Create a new temporary whose unique is that in the id,
--- bind the id to it, and return the addressing mode for the
--- temporary.
-bindNewToTemp :: Id -> FCode CmmReg
-bindNewToTemp id
-  = do addBindC id (regIdInfo id temp_reg lf_info)
-       return temp_reg
-  where
-    uniq     = getUnique id
-    temp_reg = CmmLocal (LocalReg uniq (argMachRep (idCgRep id)))
-    lf_info  = mkLFArgument id -- Always used of things we
-                               -- know nothing about
-
-bindNewToReg :: Id -> CmmReg -> LambdaFormInfo -> Code
-bindNewToReg name reg lf_info
-  = addBindC name info
-  where
-    info = mkCgIdInfo name (RegLoc reg) NoStableLoc lf_info
-\end{code}
-
-\begin{code}
-rebindToStack :: Id -> VirtualSpOffset -> Code
-rebindToStack name offset
-  = modifyBindC name replace_stable_fn
-  where
-    replace_stable_fn info = info { cg_stb = VirStkLoc offset }
-\end{code}
-
-%************************************************************************
-%*                                                                     *
-\subsection[CgMonad-deadslots]{Finding dead stack slots}
-%*                                                                     *
-%************************************************************************
-
-nukeDeadBindings does the following:
-
-      -        Removes all bindings from the environment other than those
-       for variables in the argument to nukeDeadBindings.
-      -        Collects any stack slots so freed, and returns them to the  stack free
-       list.
-      -        Moves the virtual stack pointer to point to the topmost used
-       stack locations.
-
-You can have multi-word slots on the stack (where a Double# used to
-be, for instance); if dead, such a slot will be reported as *several*
-offsets (one per word).
-
-Probably *naughty* to look inside monad...
-
-\begin{code}
-nukeDeadBindings :: StgLiveVars  -- All the *live* variables
-                -> Code
-nukeDeadBindings live_vars = do
-       binds <- getBinds
-       let (dead_stk_slots, bs') =
-               dead_slots live_vars 
-                       [] []
-                       [ (cg_id b, b) | b <- varEnvElts binds ]
-       setBinds $ mkVarEnv bs'
-       freeStackSlots dead_stk_slots
-\end{code}
-
-Several boring auxiliary functions to do the dirty work.
-
-\begin{code}
-dead_slots :: StgLiveVars
-          -> [(Id,CgIdInfo)]
-          -> [VirtualSpOffset]
-          -> [(Id,CgIdInfo)]
-          -> ([VirtualSpOffset], [(Id,CgIdInfo)])
-
--- dead_slots carries accumulating parameters for
---     filtered bindings, dead slots
-dead_slots live_vars fbs ds []
-  = (ds, reverse fbs) -- Finished; rm the dups, if any
-
-dead_slots live_vars fbs ds ((v,i):bs)
-  | v `elementOfUniqSet` live_vars
-    = dead_slots live_vars ((v,i):fbs) ds bs
-         -- Live, so don't record it in dead slots
-         -- Instead keep it in the filtered bindings
-
-  | otherwise
-    = case cg_stb i of
-       VirStkLoc offset
-        | size > 0
-        -> dead_slots live_vars fbs ([offset-size+1 .. offset] ++ ds) bs
-
-       _ -> dead_slots live_vars fbs ds bs
-  where
-    size :: WordOff
-    size = cgRepSizeW (cg_rep i)
-\end{code}
-
-\begin{code}
-getLiveStackSlots :: FCode [VirtualSpOffset]
--- Return the offsets of slots in stack containig live pointers
-getLiveStackSlots 
-  = do         { binds <- getBinds
-       ; return [off | CgIdInfo { cg_stb = VirStkLoc off, 
-                                  cg_rep = rep } <- varEnvElts binds, 
-                       isFollowableArg rep] }
-\end{code}