[project @ 1999-06-24 13:04:13 by simonmar]
[ghc-hetmet.git] / ghc / compiler / codeGen / CgUpdate.lhs
1 %
2 % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
3 %
4 \section[CgUpdate]{Manipulating update frames}
5
6 \begin{code}
7 module CgUpdate ( pushUpdateFrame, reserveSeqFrame, pushSeqFrame ) where
8
9 #include "HsVersions.h"
10
11 import CgMonad
12 import AbsCSyn
13
14 import PrimRep          ( PrimRep(..) )
15 import CgStackery       ( allocStackTop, updateFrameSize, seqFrameSize )
16 import CgUsages         ( getVirtSp, getSpRelOffset )
17 import CmdLineOpts      ( opt_SccProfilingOn )
18 import Panic            ( assertPanic )
19 \end{code}
20
21
22 %********************************************************
23 %*                                                      *
24 %*              Setting up update frames                *
25 %*                                                      *
26 %********************************************************
27 \subsection[setting-update-frames]{Setting up update frames}
28
29 @pushUpdateFrame@ $updatee$ pushes a general update frame which
30 points to $updatee$ as the thing to be updated.  It is only used
31 when a thunk has just been entered, so the (real) stack pointers
32 are guaranteed to be nicely aligned with the top of stack.
33 @pushUpdateFrame@ adjusts the virtual and tail stack pointers
34 to reflect the frame pushed.
35
36 \begin{code}
37 pushUpdateFrame :: CAddrMode -> Code -> Code
38
39 pushUpdateFrame updatee code
40   = 
41 #ifdef DEBUG
42     getEndOfBlockInfo                   `thenFC` \ eob_info ->
43     ASSERT(case eob_info of { EndOfBlockInfo _ (OnStack _) -> True; 
44                               _ -> False})
45 #endif
46
47     allocStackTop updateFrameSize       `thenFC` \ _ ->
48     getVirtSp                           `thenFC` \ vsp ->
49
50     setEndOfBlockInfo (EndOfBlockInfo vsp UpdateCode) (
51
52                 -- Emit the push macro
53             absC (CMacroStmt PUSH_UPD_FRAME [
54                         updatee,
55                         int_CLit0  -- we just entered a closure, so must be zero
56             ])
57             `thenC` code
58     )
59
60 int_CLit0 = mkIntCLit 0 -- out here to avoid pushUpdateFrame CAF (sigh)
61 \end{code}
62
63 We push a SEQ frame just before evaluating the scrutinee of a case, if
64 the scrutinee has a polymorphic or function type.  The SEQ frame acts
65 as a barrier in case the scrutinee evaluates to a partial application.
66
67 reserveSeqFrame takes the EndOfBlockInfo for the case expression and
68 updates the sequel to a SeqFrame, reserving room for the frame at
69 args_sp.  When the scrutinee comes around to pushing a return address,
70 it will also push the SEQ frame, using pushSeqFrame.
71
72 \begin{code}
73 reserveSeqFrame :: EndOfBlockInfo -> EndOfBlockInfo
74 reserveSeqFrame (EndOfBlockInfo args_sp (CaseAlts amode stuff)) 
75   = EndOfBlockInfo (args_sp + seqFrameSize) (SeqFrame amode stuff)
76
77 pushSeqFrame :: VirtualSpOffset -> FCode VirtualSpOffset
78 pushSeqFrame args_sp
79   = getSpRelOffset args_sp  `thenFC` \ sp_rel ->
80     absC (CMacroStmt PUSH_SEQ_FRAME [CAddr sp_rel]) `thenC`
81     returnFC (args_sp - seqFrameSize)
82 \end{code}