Reorganisation of the source tree
[ghc-hetmet.git] / ghc / compiler / codeGen / CgExpr.lhs
diff --git a/ghc/compiler/codeGen/CgExpr.lhs b/ghc/compiler/codeGen/CgExpr.lhs
deleted file mode 100644 (file)
index 33d72f1..0000000
+++ /dev/null
@@ -1,454 +0,0 @@
-%
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
-%
-% $Id: CgExpr.lhs,v 1.62 2005/06/21 10:44:41 simonmar Exp $
-%
-%********************************************************
-%*                                                     *
-\section[CgExpr]{Converting @StgExpr@s}
-%*                                                     *
-%********************************************************
-
-\begin{code}
-module CgExpr ( cgExpr ) where
-
-#include "HsVersions.h"
-
-import Constants       ( mAX_SPEC_SELECTEE_SIZE, mAX_SPEC_AP_SIZE )
-import StgSyn
-import CgMonad
-
-import SMRep           ( fixedHdrSize, isFollowableArg, CgRep(..), argMachRep,
-                         nonVoidArg, idCgRep, typeCgRep, typeHint,
-                         primRepToCgRep )
-import CoreSyn         ( AltCon(..) )
-import CgProf          ( emitSetCCC )
-import CgHeapery       ( layOutDynConstr )
-import CgBindery       ( getArgAmodes, getArgAmode, CgIdInfo, 
-                         nukeDeadBindings, addBindC, addBindsC )
-import CgCase          ( cgCase, saveVolatileVarsAndRegs )
-import CgClosure       ( cgRhsClosure, cgStdRhsClosure )
-import CgCon           ( buildDynCon, cgReturnDataCon )
-import CgLetNoEscape   ( cgLetNoEscapeClosure )
-import CgCallConv      ( dataReturnConvPrim )
-import CgTailCall
-import CgInfoTbls      ( emitDirectReturnInstr )
-import CgForeignCall   ( emitForeignCall, shimForeignCallArg )
-import CgPrimOp                ( cgPrimOp )
-import CgUtils         ( addIdReps, newTemp, assignTemp, cgLit, tagToClosure )
-import ClosureInfo     ( mkSelectorLFInfo, mkApLFInfo )
-import Cmm             ( CmmExpr(..), CmmStmt(..), CmmReg, nodeReg )
-import MachOp          ( wordRep, MachHint )
-import VarSet
-import Literal         ( literalType )
-import PrimOp          ( primOpOutOfLine, getPrimOpResultInfo, 
-                         PrimOp(..), PrimOpResultInfo(..) )
-import Id              ( Id )
-import TyCon           ( isUnboxedTupleTyCon, isEnumerationTyCon )
-import Type            ( Type, tyConAppArgs, tyConAppTyCon, repType,
-                         PrimRep(VoidRep) )
-import Maybes          ( maybeToBool )
-import ListSetOps      ( assocMaybe )
-import BasicTypes      ( RecFlag(..) )
-import Util             ( lengthIs )
-import Outputable
-\end{code}
-
-This module provides the support code for @StgToAbstractC@ to deal
-with STG {\em expressions}.  See also @CgClosure@, which deals
-with closures, and @CgCon@, which deals with constructors.
-
-\begin{code}
-cgExpr :: StgExpr              -- input
-       -> Code                 -- output
-\end{code}
-
-%********************************************************
-%*                                                     *
-%*             Tail calls                              *
-%*                                                     *
-%********************************************************
-
-``Applications'' mean {\em tail calls}, a service provided by module
-@CgTailCall@.  This includes literals, which show up as
-@(STGApp (StgLitArg 42) [])@.
-
-\begin{code}
-cgExpr (StgApp fun args) = cgTailCall fun args
-\end{code}
-
-%********************************************************
-%*                                                     *
-%*             STG ConApps  (for inline versions)      *
-%*                                                     *
-%********************************************************
-
-\begin{code}
-cgExpr (StgConApp con args)
-  = do { amodes <- getArgAmodes args
-       ; cgReturnDataCon con amodes }
-\end{code}
-
-Literals are similar to constructors; they return by putting
-themselves in an appropriate register and returning to the address on
-top of the stack.
-
-\begin{code}
-cgExpr (StgLit lit)
-  = do  { cmm_lit <- cgLit lit
-       ; performPrimReturn rep (CmmLit cmm_lit) }
-  where
-    rep = typeCgRep (literalType lit)
-\end{code}
-
-
-%********************************************************
-%*                                                     *
-%*     PrimOps and foreign calls.
-%*                                                     *
-%********************************************************
-
-NOTE about "safe" foreign calls: a safe foreign call is never compiled
-inline in a case expression.  When we see
-
-       case (ccall ...) of { ... }
-
-We generate a proper return address for the alternatives and push the
-stack frame before doing the call, so that in the event that the call
-re-enters the RTS the stack is in a sane state.
-
-\begin{code}
-cgExpr (StgOpApp (StgFCallOp fcall _) stg_args res_ty) = do
-    {-
-       First, copy the args into temporaries.  We're going to push
-       a return address right before doing the call, so the args
-       must be out of the way.
-    -}
-    reps_n_amodes <- getArgAmodes stg_args
-    let 
-       -- Get the *non-void* args, and jiggle them with shimForeignCall
-       arg_exprs = [ shimForeignCallArg stg_arg expr 
-                   | (stg_arg, (rep,expr)) <- stg_args `zip` reps_n_amodes, 
-                     nonVoidArg rep]
-
-    -- in
-    arg_tmps <- mapM assignTemp arg_exprs
-    let
-       arg_hints = zip arg_tmps (map (typeHint.stgArgType) stg_args)
-    -- in
-    {-
-       Now, allocate some result regs.
-    -}
-    (res_reps,res_regs,res_hints)  <- newUnboxedTupleRegs res_ty
-    ccallReturnUnboxedTuple (zip res_reps (map CmmReg res_regs)) $
-       emitForeignCall (zip res_regs res_hints) fcall 
-          arg_hints emptyVarSet{-no live vars-}
-      
--- tagToEnum# is special: we need to pull the constructor out of the table,
--- and perform an appropriate return.
-
-cgExpr (StgOpApp (StgPrimOp TagToEnumOp) [arg] res_ty) 
-  = ASSERT(isEnumerationTyCon tycon)
-    do { (_,amode) <- getArgAmode arg
-       ; amode' <- assignTemp amode    -- We're going to use it twice,
-                                       -- so save in a temp if non-trivial
-       ; hmods <- getHomeModules
-       ; stmtC (CmmAssign nodeReg (tagToClosure hmods tycon amode'))
-       ; performReturn (emitAlgReturnCode tycon amode') }
-   where
-         -- If you're reading this code in the attempt to figure
-         -- out why the compiler panic'ed here, it is probably because
-         -- you used tagToEnum# in a non-monomorphic setting, e.g., 
-         --         intToTg :: Enum a => Int -> a ; intToTg (I# x#) = tagToEnum# x#
-         -- That won't work.
-       tycon = tyConAppTyCon res_ty
-
-
-cgExpr x@(StgOpApp op@(StgPrimOp primop) args res_ty)
-  | primOpOutOfLine primop
-       = tailCallPrimOp primop args
-
-  | ReturnsPrim VoidRep <- result_info
-       = do cgPrimOp [] primop args emptyVarSet
-            performReturn emitDirectReturnInstr
-
-  | ReturnsPrim rep <- result_info
-       = do cgPrimOp [dataReturnConvPrim (primRepToCgRep rep)] 
-                       primop args emptyVarSet
-            performReturn emitDirectReturnInstr
-
-  | ReturnsAlg tycon <- result_info, isUnboxedTupleTyCon tycon
-       = do (reps, regs, _hints) <- newUnboxedTupleRegs res_ty
-            cgPrimOp regs primop args emptyVarSet{-no live vars-}
-            returnUnboxedTuple (zip reps (map CmmReg regs))
-
-  | ReturnsAlg tycon <- result_info, isEnumerationTyCon tycon
-       -- c.f. cgExpr (...TagToEnumOp...)
-       = do tag_reg <- newTemp wordRep
-            hmods <- getHomeModules
-            cgPrimOp [tag_reg] primop args emptyVarSet
-            stmtC (CmmAssign nodeReg (tagToClosure hmods tycon (CmmReg tag_reg)))
-            performReturn (emitAlgReturnCode tycon (CmmReg tag_reg))
-  where
-       result_info = getPrimOpResultInfo primop
-\end{code}
-
-%********************************************************
-%*                                                     *
-%*             Case expressions                        *
-%*                                                     *
-%********************************************************
-Case-expression conversion is complicated enough to have its own
-module, @CgCase@.
-\begin{code}
-
-cgExpr (StgCase expr live_vars save_vars bndr srt alt_type alts)
-  = cgCase expr live_vars save_vars bndr srt alt_type alts
-\end{code}
-
-
-%********************************************************
-%*                                                     *
-%*             Let and letrec                          *
-%*                                                     *
-%********************************************************
-\subsection[let-and-letrec-codegen]{Converting @StgLet@ and @StgLetrec@}
-
-\begin{code}
-cgExpr (StgLet (StgNonRec name rhs) expr)
-  = cgRhs name rhs     `thenFC` \ (name, info) ->
-    addBindC name info         `thenC`
-    cgExpr expr
-
-cgExpr (StgLet (StgRec pairs) expr)
-  = fixC (\ new_bindings -> addBindsC new_bindings `thenC`
-                           listFCs [ cgRhs b e | (b,e) <- pairs ]
-    ) `thenFC` \ new_bindings ->
-
-    addBindsC new_bindings `thenC`
-    cgExpr expr
-\end{code}
-
-\begin{code}
-cgExpr (StgLetNoEscape live_in_whole_let live_in_rhss bindings body)
-  = do {       -- Figure out what volatile variables to save
-       ; nukeDeadBindings live_in_whole_let
-       ; (save_assts, rhs_eob_info, maybe_cc_slot) 
-               <- saveVolatileVarsAndRegs live_in_rhss
-
-       -- Save those variables right now!
-       ; emitStmts save_assts
-
-       -- Produce code for the rhss
-       -- and add suitable bindings to the environment
-       ; cgLetNoEscapeBindings live_in_rhss rhs_eob_info 
-                               maybe_cc_slot bindings
-
-       -- Do the body
-       ; setEndOfBlockInfo rhs_eob_info (cgExpr body) }
-\end{code}
-
-
-%********************************************************
-%*                                                     *
-%*             SCC Expressions                         *
-%*                                                     *
-%********************************************************
-
-SCC expressions are treated specially. They set the current cost
-centre.
-
-\begin{code}
-cgExpr (StgSCC cc expr) = do emitSetCCC cc; cgExpr expr
-\end{code}
-
-%********************************************************
-%*                                                     *
-%*             Non-top-level bindings                  *
-%*                                                     *
-%********************************************************
-\subsection[non-top-level-bindings]{Converting non-top-level bindings}
-
-We rely on the support code in @CgCon@ (to do constructors) and
-in @CgClosure@ (to do closures).
-
-\begin{code}
-cgRhs :: Id -> StgRhs -> FCode (Id, CgIdInfo)
-       -- the Id is passed along so a binding can be set up
-
-cgRhs name (StgRhsCon maybe_cc con args)
-  = do { amodes <- getArgAmodes args
-       ; idinfo <- buildDynCon name maybe_cc con amodes
-       ; returnFC (name, idinfo) }
-
-cgRhs name (StgRhsClosure cc bi fvs upd_flag srt args body)
-  = do hmods <- getHomeModules
-       mkRhsClosure hmods name cc bi srt fvs upd_flag args body
-\end{code}
-
-mkRhsClosure looks for two special forms of the right-hand side:
-       a) selector thunks.
-       b) AP thunks
-
-If neither happens, it just calls mkClosureLFInfo.  You might think
-that mkClosureLFInfo should do all this, but it seems wrong for the
-latter to look at the structure of an expression
-
-Selectors
-~~~~~~~~~
-We look at the body of the closure to see if it's a selector---turgid,
-but nothing deep.  We are looking for a closure of {\em exactly} the
-form:
-
-...  = [the_fv] \ u [] ->
-        case the_fv of
-          con a_1 ... a_n -> a_i
-
-
-\begin{code}
-mkRhsClosure   hmods bndr cc bi srt
-               [the_fv]                -- Just one free var
-               upd_flag                -- Updatable thunk
-               []                      -- A thunk
-               body@(StgCase (StgApp scrutinee [{-no args-}])
-                     _ _ _ _   -- ignore uniq, etc.
-                     (AlgAlt tycon)
-                     [(DataAlt con, params, use_mask,
-                           (StgApp selectee [{-no args-}]))])
-  |  the_fv == scrutinee               -- Scrutinee is the only free variable
-  && maybeToBool maybe_offset          -- Selectee is a component of the tuple
-  && offset_into_int <= mAX_SPEC_SELECTEE_SIZE -- Offset is small enough
-  = -- NOT TRUE: ASSERT(is_single_constructor)
-    -- The simplifier may have statically determined that the single alternative
-    -- is the only possible case and eliminated the others, even if there are
-    -- other constructors in the datatype.  It's still ok to make a selector
-    -- thunk in this case, because we *know* which constructor the scrutinee
-    -- will evaluate to.
-    cgStdRhsClosure bndr cc bi [the_fv] [] body lf_info [StgVarArg the_fv]
-  where
-    lf_info              = mkSelectorLFInfo bndr offset_into_int
-                                (isUpdatable upd_flag)
-    (_, params_w_offsets) = layOutDynConstr hmods con (addIdReps params)
-                       -- Just want the layout
-    maybe_offset         = assocMaybe params_w_offsets selectee
-    Just the_offset      = maybe_offset
-    offset_into_int       = the_offset - fixedHdrSize
-\end{code}
-
-Ap thunks
-~~~~~~~~~
-
-A more generic AP thunk of the form
-
-       x = [ x_1...x_n ] \.. [] -> x_1 ... x_n
-
-A set of these is compiled statically into the RTS, so we just use
-those.  We could extend the idea to thunks where some of the x_i are
-global ids (and hence not free variables), but this would entail
-generating a larger thunk.  It might be an option for non-optimising
-compilation, though.
-
-We only generate an Ap thunk if all the free variables are pointers,
-for semi-obvious reasons.
-
-\begin{code}
-mkRhsClosure   hmods bndr cc bi srt
-               fvs
-               upd_flag
-               []                      -- No args; a thunk
-               body@(StgApp fun_id args)
-
-  | args `lengthIs` (arity-1)
-       && all isFollowableArg (map idCgRep fvs) 
-       && isUpdatable upd_flag
-       && arity <= mAX_SPEC_AP_SIZE 
-
-                  -- Ha! an Ap thunk
-       = cgStdRhsClosure bndr cc bi fvs [] body lf_info payload
-
-   where
-       lf_info = mkApLFInfo bndr upd_flag arity
-       -- the payload has to be in the correct order, hence we can't
-       -- just use the fvs.
-       payload = StgVarArg fun_id : args
-       arity   = length fvs
-\end{code}
-
-The default case
-~~~~~~~~~~~~~~~~
-\begin{code}
-mkRhsClosure hmods bndr cc bi srt fvs upd_flag args body
-  = cgRhsClosure bndr cc bi srt fvs upd_flag args body
-\end{code}
-
-
-%********************************************************
-%*                                                     *
-%*             Let-no-escape bindings
-%*                                                     *
-%********************************************************
-\begin{code}
-cgLetNoEscapeBindings live_in_rhss rhs_eob_info maybe_cc_slot 
-       (StgNonRec binder rhs)
-  = do { (binder,info) <- cgLetNoEscapeRhs live_in_rhss rhs_eob_info 
-                                           maybe_cc_slot       
-                                           NonRecursive binder rhs 
-       ; addBindC binder info }
-
-cgLetNoEscapeBindings live_in_rhss rhs_eob_info maybe_cc_slot (StgRec pairs)
-  = do { new_bindings <- fixC (\ new_bindings -> do
-               { addBindsC new_bindings
-               ; listFCs [ cgLetNoEscapeRhs full_live_in_rhss 
-                               rhs_eob_info maybe_cc_slot Recursive b e 
-                         | (b,e) <- pairs ] })
-
-       ; addBindsC new_bindings }
-  where
-    -- We add the binders to the live-in-rhss set so that we don't
-    -- delete the bindings for the binder from the environment!
-    full_live_in_rhss = live_in_rhss `unionVarSet` (mkVarSet [b | (b,r) <- pairs])
-
-cgLetNoEscapeRhs
-    :: StgLiveVars     -- Live in rhss
-    -> EndOfBlockInfo
-    -> Maybe VirtualSpOffset
-    -> RecFlag
-    -> Id
-    -> StgRhs
-    -> FCode (Id, CgIdInfo)
-
-cgLetNoEscapeRhs full_live_in_rhss rhs_eob_info maybe_cc_slot rec binder
-                (StgRhsClosure cc bi _ upd_flag srt args body)
-  = -- We could check the update flag, but currently we don't switch it off
-    -- for let-no-escaped things, so we omit the check too!
-    -- case upd_flag of
-    --     Updatable -> panic "cgLetNoEscapeRhs"       -- Nothing to update!
-    --     other     -> cgLetNoEscapeClosure binder cc bi live_in_whole_let live_in_rhss args body
-    cgLetNoEscapeClosure binder cc bi srt full_live_in_rhss rhs_eob_info
-       maybe_cc_slot rec args body
-
--- For a constructor RHS we want to generate a single chunk of code which
--- can be jumped to from many places, which will return the constructor.
--- It's easy; just behave as if it was an StgRhsClosure with a ConApp inside!
-cgLetNoEscapeRhs full_live_in_rhss rhs_eob_info maybe_cc_slot rec binder
-                (StgRhsCon cc con args)
-  = cgLetNoEscapeClosure binder cc noBinderInfo{-safe-} NoSRT
-                        full_live_in_rhss rhs_eob_info maybe_cc_slot rec
-       []      --No args; the binder is data structure, not a function
-       (StgConApp con args)
-\end{code}
-
-Little helper for primitives that return unboxed tuples.
-
-\begin{code}
-newUnboxedTupleRegs :: Type -> FCode ([CgRep], [CmmReg], [MachHint])
-newUnboxedTupleRegs res_ty =
-   let
-       ty_args = tyConAppArgs (repType res_ty)
-       (reps,hints) = unzip [ (rep, typeHint ty) | ty <- ty_args, 
-                                                   let rep = typeCgRep ty,
-                                                   nonVoidArg rep ]
-   in do
-   regs <- mapM (newTemp . argMachRep) reps
-   return (reps,regs,hints)
-\end{code}