621e480ffa251e108d274de56bfd7bc1dcf3a240
[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 Constants        ( uF_SIZE, sCC_UF_SIZE, sEQ_FRAME_SIZE, sCC_SEQ_FRAME_SIZE )
15 import PrimRep          ( PrimRep(..) )
16 import CgStackery       ( allocStackTop )
17 import CgUsages         ( getVirtSp, getSpRelOffset )
18 import CmdLineOpts      ( opt_SccProfilingOn )
19 import Panic            ( assertPanic )
20 \end{code}
21
22
23 %********************************************************
24 %*                                                      *
25 %*              Setting up update frames                *
26 %*                                                      *
27 %********************************************************
28 \subsection[setting-update-frames]{Setting up update frames}
29
30 @pushUpdateFrame@ $updatee$ pushes a general update frame which
31 points to $updatee$ as the thing to be updated.  It is only used
32 when a thunk has just been entered, so the (real) stack pointers
33 are guaranteed to be nicely aligned with the top of stack.
34 @pushUpdateFrame@ adjusts the virtual and tail stack pointers
35 to reflect the frame pushed.
36
37 \begin{code}
38 pushUpdateFrame :: CAddrMode -> Code -> Code
39
40 pushUpdateFrame updatee code
41   = let
42         -- frame_size *includes* the return address
43         frame_size = if opt_SccProfilingOn
44                      then sCC_UF_SIZE
45                      else uF_SIZE
46     in
47 #ifdef DEBUG
48     getEndOfBlockInfo                   `thenFC` \ eob_info ->
49     ASSERT(case eob_info of { EndOfBlockInfo _ (OnStack _) -> True; 
50                               _ -> False})
51 #endif
52
53     allocStackTop frame_size    `thenFC` \ _ ->
54     getVirtSp                   `thenFC` \ vsp ->
55
56     setEndOfBlockInfo (EndOfBlockInfo vsp UpdateCode) (
57
58                 -- Emit the push macro
59             absC (CMacroStmt PUSH_UPD_FRAME [
60                         updatee,
61                         int_CLit0  -- we just entered a closure, so must be zero
62             ])
63             `thenC` code
64     )
65
66 int_CLit0 = mkIntCLit 0 -- out here to avoid pushUpdateFrame CAF (sigh)
67 \end{code}
68
69 We push a SEQ frame just before evaluating the scrutinee of a case, if
70 the scrutinee has a polymorphic or function type.  The SEQ frame acts
71 as a barrier in case the scrutinee evaluates to a partial application.
72
73 reserveSeqFrame takes the EndOfBlockInfo for the case expression and
74 updates the sequel to a SeqFrame, reserving room for the frame at
75 args_sp.  When the scrutinee comes around to pushing a return address,
76 it will also push the SEQ frame, using pushSeqFrame.
77
78 \begin{code}
79 seq_frame_size | opt_SccProfilingOn = sCC_SEQ_FRAME_SIZE
80                | otherwise          = sEQ_FRAME_SIZE
81
82 reserveSeqFrame :: EndOfBlockInfo -> EndOfBlockInfo
83 reserveSeqFrame (EndOfBlockInfo args_sp (CaseAlts amode stuff)) 
84   = EndOfBlockInfo (args_sp + seq_frame_size) (SeqFrame amode stuff)
85
86 pushSeqFrame :: VirtualSpOffset -> FCode VirtualSpOffset
87 pushSeqFrame args_sp
88   = getSpRelOffset args_sp  `thenFC` \ sp_rel ->
89     absC (CMacroStmt PUSH_SEQ_FRAME [CAddr sp_rel]) `thenC`
90     returnFC (args_sp - seq_frame_size)
91 \end{code}