2 % (c) The AQUA Project, Glasgow University, 1993-1995
6 #include "HsVersions.h"
9 genMacroCode, doHeapCheck, smStablePtrTable,
11 Target, StixTree, SplitUniqSupply, CAddrMode, CExprMacro,
16 import AbsPrel ( PrimOp(..)
17 IF_ATTACK_PRAGMAS(COMMA tagOf_PrimOp)
18 IF_ATTACK_PRAGMAS(COMMA pprPrimOp)
20 import MachDesc {- lots -}
21 import CgCompInfo ( sTD_UF_SIZE, uF_RET, uF_SUA, uF_SUB, uF_UPDATEE )
29 The @ARGS_CHK_A{_LOAD_NODE}@ macros check for sufficient arguments on
30 the A stack, and perform a tail call to @UpdatePAP@ if the arguments are
31 not there. The @_LOAD_NODE@ version also loads R1 with an appropriate
35 mkIntCLit_0 = mkIntCLit 0 -- out here to avoid CAF (sigh)
36 mkIntCLit_3 = mkIntCLit 3
40 -> CStmtMacro -- statement macro
41 -> [CAddrMode] -- args
42 -> SUniqSM StixTreeList
44 genMacroCode target ARGS_CHK_A_LOAD_NODE args =
45 getUniqLabelNCG `thenSUs` \ ulbl ->
46 let [words, lbl] = map (amodeToStix target) args
47 temp = StIndex PtrKind stgSpA words
48 test = StPrim AddrGeOp [stgSuA, temp]
49 cjmp = StCondJump ulbl test
50 assign = StAssign PtrKind stgNode lbl
53 returnSUs (\xs -> cjmp : assign : updatePAP : join : xs)
55 genMacroCode target ARGS_CHK_A [words] =
56 getUniqLabelNCG `thenSUs` \ ulbl ->
57 let temp = StIndex PtrKind stgSpA (amodeToStix target words)
58 test = StPrim AddrGeOp [stgSuA, temp]
59 cjmp = StCondJump ulbl test
62 returnSUs (\xs -> cjmp : updatePAP : join : xs)
66 Like the macros above, the @ARGS_CHK_B{_LOAD_NODE}@ macros check for
67 sufficient arguments on the B stack, and perform a tail call to
68 @UpdatePAP@ if the arguments are not there. The @_LOAD_NODE@ version
69 also loads R1 with an appropriate closure address. Note that the
70 directions are swapped relative to the A stack.
74 genMacroCode target ARGS_CHK_B_LOAD_NODE args =
75 getUniqLabelNCG `thenSUs` \ ulbl ->
76 let [words, lbl] = map (amodeToStix target) args
77 temp = StIndex PtrKind stgSuB (StPrim IntNegOp [words])
78 test = StPrim AddrGeOp [stgSpB, temp]
79 cjmp = StCondJump ulbl test
80 assign = StAssign PtrKind stgNode lbl
83 returnSUs (\xs -> cjmp : assign : updatePAP : join : xs)
85 genMacroCode target ARGS_CHK_B [words] =
86 getUniqLabelNCG `thenSUs` \ ulbl ->
87 let temp = StIndex PtrKind stgSuB (StPrim IntNegOp [amodeToStix target words])
88 test = StPrim AddrGeOp [stgSpB, temp]
89 cjmp = StCondJump ulbl test
92 returnSUs (\xs -> cjmp : updatePAP : join : xs)
96 The @HEAP_CHK@ macro checks to see that there are enough words
97 available in the heap (before reaching @HpLim@). When a heap check
98 fails, it has to call @PerformGC@ via the @PerformGC_wrapper@. The
99 call wrapper saves all of our volatile registers so that we don't have to.
101 Since there are @HEAP_CHK@s buried at unfortunate places in the integer
102 primOps, this is just a wrapper.
106 genMacroCode target HEAP_CHK args =
107 let [liveness,words,reenter] = map (amodeToStix target) args
109 doHeapCheck target liveness words reenter
113 The @STK_CHK@ macro checks for enough space on the stack between @SpA@
114 and @SpB@. A stack check can be complicated in the parallel world,
115 but for the sequential case, we just need to ensure that we have
116 enough space to continue. Not that @_StackOverflow@ doesn't return,
117 so we don't have to @callWrapper@ it.
121 genMacroCode target STK_CHK [liveness, aWords, bWords, spa, spb, prim, reenter] =
122 {- Need to check to see if we are compiling with stack checks
123 getUniqLabelNCG `thenSUs` \ ulbl ->
124 let words = StPrim IntNegOp
125 [StPrim IntAddOp [amodeToStix target aWords, amodeToStix target bWords]]
126 temp = StIndex PtrKind stgSpA words
127 test = StPrim AddrGtOp [temp, stgSpB]
128 cjmp = StCondJump ulbl test
131 returnSUs (\xs -> cjmp : stackOverflow : join : xs)
137 @UPD_CAF@ involves changing the info pointer of the closure, adding an indirection,
138 and putting the new CAF on a linked list for the storage manager.
142 genMacroCode target UPD_CAF args =
143 let [cafptr,bhptr] = map (amodeToStix target) args
144 w0 = StInd PtrKind cafptr
145 w1 = StInd PtrKind (StIndex PtrKind cafptr (StInt 1))
146 w2 = StInd PtrKind (StIndex PtrKind cafptr (StInt 2))
147 a1 = StAssign PtrKind w0 caf_info
148 a2 = StAssign PtrKind w1 smCAFlist
149 a3 = StAssign PtrKind w2 bhptr
150 a4 = StAssign PtrKind smCAFlist cafptr
152 returnSUs (\xs -> a1 : a2 : a3 : a4 : xs)
156 @UPD_IND@ is complicated by the fact that we are supporting the
157 Appel-style garbage collector by default. This means some extra work
158 if we update an old generation object.
162 genMacroCode target UPD_IND args =
163 getUniqLabelNCG `thenSUs` \ ulbl ->
164 let [updptr, heapptr] = map (amodeToStix target) args
165 test = StPrim AddrGtOp [updptr, smOldLim]
166 cjmp = StCondJump ulbl test
167 updRoots = StAssign PtrKind smOldMutables updptr
169 upd0 = StAssign PtrKind (StInd PtrKind updptr) ind_info
170 upd1 = StAssign PtrKind (StInd PtrKind
171 (StIndex PtrKind updptr (StInt 1))) smOldMutables
172 upd2 = StAssign PtrKind (StInd PtrKind
173 (StIndex PtrKind updptr (StInt 2))) heapptr
175 returnSUs (\xs -> cjmp : upd1 : updRoots : join : upd0 : upd2 : xs)
179 @UPD_INPLACE_NOPTRS@ is only needed for ticky-ticky profiling.
183 genMacroCode target UPD_INPLACE_NOPTRS args = returnSUs id
187 @UPD_INPLACE_PTRS@ is complicated by the fact that we are supporting
188 the Appel-style garbage collector by default. This means some extra work
189 if we update an old generation object.
193 genMacroCode target UPD_INPLACE_PTRS [liveness] =
194 getUniqLabelNCG `thenSUs` \ ulbl ->
195 let cjmp = StCondJump ulbl testOldLim
196 testOldLim = StPrim AddrGtOp [stgNode, smOldLim]
198 updUpd0 = StAssign PtrKind (StInd PtrKind stgNode) ind_info
199 updUpd1 = StAssign PtrKind (StInd PtrKind
200 (StIndex PtrKind stgNode (StInt 1))) smOldMutables
201 updUpd2 = StAssign PtrKind (StInd PtrKind
202 (StIndex PtrKind stgNode (StInt 2))) hpBack2
203 hpBack2 = StIndex PtrKind stgHp (StInt (-2))
204 updOldMutables = StAssign PtrKind smOldMutables stgNode
205 updUpdReg = StAssign PtrKind stgNode hpBack2
207 genMacroCode target HEAP_CHK [liveness, mkIntCLit_3, mkIntCLit_0]
208 `thenSUs` \ heap_chk ->
209 returnSUs (\xs -> (cjmp :
210 heap_chk (updUpd0 : updUpd1 : updUpd2 :
211 updOldMutables : updUpdReg : join : xs)))
215 @UPD_BH_UPDATABLE@ is only used when running concurrent threads (in
216 the sequential case, the GC takes care of this). However, we do need
217 to handle @UPD_BH_SINGLE_ENTRY@ in all cases.
221 genMacroCode target UPD_BH_UPDATABLE args = returnSUs id
223 genMacroCode target UPD_BH_SINGLE_ENTRY [arg] =
225 update = StAssign PtrKind (StInd PtrKind (amodeToStix target arg)) bh_info
227 returnSUs (\xs -> update : xs)
231 Push a four word update frame on the stack and slide the Su[AB]
232 registers to the current Sp[AB] locations.
236 genMacroCode target PUSH_STD_UPD_FRAME args =
237 let [bhptr, aWords, bWords] = map (amodeToStix target) args
238 frame n = StInd PtrKind
239 (StIndex PtrKind stgSpB (StPrim IntAddOp
240 [bWords, StInt (toInteger (sTD_UF_SIZE - n))]))
242 a1 = StAssign PtrKind (frame uF_RET) stgRetReg
243 a2 = StAssign PtrKind (frame uF_SUB) stgSuB
244 a3 = StAssign PtrKind (frame uF_SUA) stgSuA
245 a4 = StAssign PtrKind (frame uF_UPDATEE) bhptr
247 updSuB = StAssign PtrKind
248 stgSuB (StIndex PtrKind stgSpB (StPrim IntAddOp
249 [bWords, StInt (toInteger sTD_UF_SIZE)]))
250 updSuA = StAssign PtrKind
251 stgSuA (StIndex PtrKind stgSpA (StPrim IntNegOp [aWords]))
253 returnSUs (\xs -> a1 : a2 : a3 : a4 : updSuB : updSuA : xs)
257 Pop a standard update frame.
261 genMacroCode target POP_STD_UPD_FRAME args =
262 let frame n = StInd PtrKind (StIndex PtrKind stgSpB (StInt (toInteger (-n))))
264 grabRet = StAssign PtrKind stgRetReg (frame uF_RET)
265 grabSuB = StAssign PtrKind stgSuB (frame uF_SUB)
266 grabSuA = StAssign PtrKind stgSuA (frame uF_SUA)
268 updSpB = StAssign PtrKind
269 stgSpB (StIndex PtrKind stgSpB (StInt (toInteger (-sTD_UF_SIZE))))
271 returnSUs (\xs -> grabRet : grabSuB : grabSuA : updSpB : xs)
275 @PUSH_CON_UPD_FRAME@ appears to be unused at the moment.
279 genMacroCode target PUSH_CON_UPD_FRAME args =
280 panic "genMacroCode:PUSH_CON_UPD_FRAME"
284 The @SET_ARITY@ and @CHK_ARITY@ macros are disabled for ``normal'' compilation.
288 genMacroCode target SET_ARITY args = returnSUs id
289 genMacroCode target CHK_ARITY args = returnSUs id
293 This one only applies if we have a machine register devoted to TagReg.
297 genMacroCode target SET_TAG [tag] =
298 let set_tag = StAssign IntKind stgTagReg (amodeToStix target tag)
300 case stgReg target TagReg of
301 Always _ -> returnSUs id
302 Save _ -> returnSUs (\xs -> set_tag : xs)
306 Do the business for a @HEAP_CHK@, having converted the args to Trees
313 -> StixTree -- liveness
314 -> StixTree -- words needed
315 -> StixTree -- always reenter node? (boolean)
316 -> SUniqSM StixTreeList
318 doHeapCheck target liveness words reenter =
319 getUniqLabelNCG `thenSUs` \ ulbl ->
320 let newHp = StIndex PtrKind stgHp words
321 assign = StAssign PtrKind stgHp newHp
322 test = StPrim AddrLeOp [stgHp, stgHpLim]
323 cjmp = StCondJump ulbl test
324 arg = StPrim IntAddOp [StPrim IntMulOp [words, StInt 256], liveness]
325 -- ToDo: Overflow? (JSM)
326 gc = StCall SLIT("PerformGC_wrapper") VoidKind [arg]
329 returnSUs (\xs -> assign : cjmp : gc : join : xs)
333 Let's make sure that these CAFs are lifted out, shall we?
337 -- Some common labels
339 bh_info, caf_info, ind_info :: StixTree
341 bh_info = sStLitLbl SLIT("BH_SINGLE_info")
342 caf_info = sStLitLbl SLIT("Caf_info")
343 ind_info = sStLitLbl SLIT("Ind_info")
345 -- Some common call trees
347 updatePAP, stackOverflow :: StixTree
349 updatePAP = StJump (sStLitLbl SLIT("UpdatePAP"))
350 stackOverflow = StCall SLIT("StackOverflow") VoidKind []
354 Storage manager nonsense. Note that the indices are dependent on
355 the definition of the smInfo structure in SMinterface.lh
359 #include "../../includes/platform.h"
361 #if alpha_TARGET_ARCH
362 #include "../../includes/alpha-dec-osf1.h"
365 #include "../../includes/sparc-sun-sunos4.h"
367 #include "../../includes/sparc-sun-solaris2.h"
371 storageMgrInfo, smCAFlist, smOldMutables, smOldLim :: StixTree
373 storageMgrInfo = sStLitLbl SLIT("StorageMgrInfo")
374 smCAFlist = StInd PtrKind (StIndex PtrKind storageMgrInfo (StInt SM_CAFLIST))
375 smOldMutables = StInd PtrKind (StIndex PtrKind storageMgrInfo (StInt SM_OLDMUTABLES))
376 smOldLim = StInd PtrKind (StIndex PtrKind storageMgrInfo (StInt SM_OLDLIM))
378 smStablePtrTable = StInd PtrKind
379 (StIndex PtrKind storageMgrInfo (StInt SM_STABLEPOINTERTABLE))