Add PrimCall to the STG layer and update Core -> STG translation
[ghc-hetmet.git] / compiler / codeGen / CgTailCall.lhs
index cd51fba..89c0504 100644 (file)
@@ -11,6 +11,7 @@ module CgTailCall (
        returnUnboxedTuple, ccallReturnUnboxedTuple,
        pushUnboxedTuple,
        tailCallPrimOp,
+        tailCallPrimCall,
 
        pushReturnAddress
     ) where
@@ -27,7 +28,6 @@ import CgUtils
 import CgTicky
 import ClosureInfo
 import SMRep
-import MachOp
 import Cmm     
 import CmmUtils
 import CLabel
@@ -36,6 +36,7 @@ import Id
 import StgSyn
 import PrimOp
 import Outputable
+import StaticFlags
 
 import Control.Monad
 
@@ -108,9 +109,9 @@ performTailCall fun_info arg_amodes pending_assts
              opt_node_asst | nodeMustPointToIt lf_info = node_asst
                            | otherwise                 = noStmts
        ; EndOfBlockInfo sp _ <- getEndOfBlockInfo
-       ; this_pkg <- getThisPackage
 
-       ; case (getCallMethod fun_name lf_info (length arg_amodes)) of
+       ; dflags <- getDynFlags
+       ; case (getCallMethod dflags fun_name fun_has_cafs lf_info (length arg_amodes)) of
 
            -- Node must always point to things we enter
            EnterIt -> do
@@ -135,7 +136,7 @@ performTailCall fun_info arg_amodes pending_assts
            -- A real constructor.  Don't bother entering it, 
            -- just do the right sort of return instead.
            -- As with any return, Node must point to it.
-           ReturnCon con -> do
+           ReturnCon _ -> do
                { emitSimultaneously (node_asst `plusStmts` pending_assts)
                ; doFinalJump sp False emitReturnInstr }
 
@@ -177,12 +178,17 @@ performTailCall fun_info arg_amodes pending_assts
                }
        }
   where
-    fun_name  = idName (cgIdInfoId fun_info)
+    fun_id    = cgIdInfoId fun_info
+    fun_name  = idName fun_id
     lf_info   = cgIdInfoLF fun_info
+    fun_has_cafs = idCafInfo fun_id
     untag_node = CmmAssign nodeReg (cmmUntag (CmmReg nodeReg))
     -- Test if closure is a constructor
     maybeSwitchOnCons enterClosure eob
-              | EndOfBlockInfo _ (CaseAlts lbl _ _) <- eob
+              | EndOfBlockInfo _ (CaseAlts lbl _ _) <- eob,
+                not opt_SccProfilingOn
+                -- we can't shortcut when profiling is on, because we have
+                -- to enter a closure to mark it as "used" for LDV profiling
               = do { is_constr <- newLabelC
                    -- Is the pointer tagged?
                    -- Yes, jump to switch statement
@@ -220,6 +226,7 @@ performTailCall fun_info arg_amodes pending_assts
         where
           --cond1 tag  = cmmULtWord tag lowCons
           -- More efficient than the above?
+{-
           tag_expr   = cmmGetClosureType (CmmReg nodeReg)
           cond1 tag  = cmmEqWord tag (CmmLit (mkIntCLit 0))
           cond2 tag  = cmmUGtWord tag highCons
@@ -227,11 +234,11 @@ performTailCall fun_info arg_amodes pending_assts
             -- CONSTR
           highCons   = CmmLit (mkIntCLit 8)
             -- CONSTR_NOCAF_STATIC (from ClosureType.h)
+-}
 
-
-untagCmmAssign (CmmAssign r cmmExpr) = CmmAssign r (cmmUntag cmmExpr)
-untagCmmAssign stmt                  = stmt
-
+directCall :: VirtualSpOffset -> CLabel -> [(CgRep, CmmExpr)]
+           -> [(CgRep, CmmExpr)] -> CmmStmts
+           -> Code
 directCall sp lbl args extra_args assts = do
   let
        -- First chunk of args go in registers
@@ -282,7 +289,7 @@ performReturn :: Code       -- The code to execute to actually do the return
              -> Code
 
 performReturn finish_code
-  = do  { EndOfBlockInfo args_sp sequel <- getEndOfBlockInfo
+  = do  { EndOfBlockInfo args_sp _sequel <- getEndOfBlockInfo
        ; doFinalJump args_sp False{-not a LNE-} finish_code }
 
 -- ----------------------------------------------------------------------------
@@ -314,7 +321,7 @@ performPrimReturn rep amode
 
 returnUnboxedTuple :: [(CgRep, CmmExpr)] -> Code
 returnUnboxedTuple amodes
-  = do         { eob@(EndOfBlockInfo args_sp sequel) <- getEndOfBlockInfo
+  = do         { (EndOfBlockInfo args_sp _sequel) <- getEndOfBlockInfo
        ; tickyUnboxedTupleReturn (length amodes)
        ; (final_sp, assts) <- pushUnboxedTuple args_sp amodes
        ; emitSimultaneously assts
@@ -376,13 +383,21 @@ ccallReturnUnboxedTuple amodes before_jump
 -- Calling an out-of-line primop
 
 tailCallPrimOp :: PrimOp -> [StgArg] -> Code
-tailCallPrimOp op args
+tailCallPrimOp op
+ = tailCallPrim (mkRtsPrimOpLabel op)
+
+tailCallPrimCall :: PrimCall -> [StgArg] -> Code
+tailCallPrimCall primcall
+ = tailCallPrim (mkPrimCallLabel primcall)
+
+tailCallPrim :: CLabel -> [StgArg] -> Code
+tailCallPrim lbl args
  = do  {       -- We're going to perform a normal-looking tail call, 
                -- except that *all* the arguments will be in registers.
                -- Hence the ASSERT( null leftovers )
          arg_amodes <- getArgAmodes args
        ; let (arg_regs, leftovers) = assignPrimOpCallRegs arg_amodes
-             jump_to_primop = jumpToLbl (mkRtsPrimOpLabel op)
+             jump_to_primop = jumpToLbl lbl
 
        ; ASSERT(null leftovers) -- no stack-resident args
          emitSimultaneously (assignToRegs arg_regs)
@@ -408,7 +423,7 @@ tailCallPrimOp op args
 
 pushReturnAddress :: EndOfBlockInfo -> Code
 
-pushReturnAddress (EndOfBlockInfo args_sp sequel@(CaseAlts lbl _ _))
+pushReturnAddress (EndOfBlockInfo args_sp (CaseAlts lbl _ _))
   = do { sp_rel <- getSpRelOffset args_sp
        ; stmtC (CmmStore sp_rel (mkLblExpr lbl)) }
 
@@ -468,3 +483,4 @@ adjustSpAndHp newRealSp
        ; setRealHp vHp
        }
 \end{code}
+