2 % (c) The GRASP Project, Glasgow University, 1992-1995
4 \section[CgRetConv]{Return conventions for the code generator}
6 The datatypes and functions here encapsulate what there is to know
7 about return conventions.
10 #include "HsVersions.h"
13 CtrlReturnConvention(..), DataReturnConvention(..),
18 mkLiveRegsBitMask, noLiveRegsMask,
22 assignPrimOpResultRegs,
26 -- and to make the interface self-sufficient...
27 MagicId, PrimKind, Id, CLabel, TyCon
32 import AbsPrel ( PrimOp(..), PrimOpResultInfo(..), primOpCanTriggerGC,
33 getPrimOpResultInfo, integerDataCon, PrimKind
34 IF_ATTACK_PRAGMAS(COMMA tagOf_PrimOp)
35 IF_ATTACK_PRAGMAS(COMMA pprPrimOp)
37 import AbsUniType ( getTyConFamilySize, kindFromType, getTyConDataCons,
38 TyVarTemplate, TyCon, Class,
39 TauType(..), ThetaType(..), UniType
40 IF_ATTACK_PRAGMAS(COMMA cmpTyCon COMMA cmpClass)
41 IF_ATTACK_PRAGMAS(COMMA cmpUniType)
43 import CgCompInfo -- various things
44 import CgMonad ( IntSwitchChecker(..) )
45 import CmdLineOpts ( GlobalSwitch(..) )
46 import Id ( Id, getDataConSig, fIRST_TAG, isDataCon,
47 DataCon(..), ConTag(..)
49 import Maybes ( catMaybes, Maybe(..) )
55 %************************************************************************
57 \subsection[CgRetConv-possibilities]{Data types that encode possible return conventions}
59 %************************************************************************
61 A @CtrlReturnConvention@ says how {\em control} is returned.
63 data CtrlReturnConvention
64 = VectoredReturn Int -- size of the vector table (family size)
65 | UnvectoredReturn Int -- family size
68 A @DataReturnConvention@ says how the data for a particular
69 data-constructor is returned.
71 data DataReturnConvention
73 | ReturnInRegs [MagicId]
75 The register assignment given by a @ReturnInRegs@ obeys three rules:
78 \item R2 points to the info table for the phantom constructor
79 \item The list of @MagicId@ is in the same order as the arguments
84 %************************************************************************
86 \subsection[CgRetConv-algebraic]{Return conventions for algebraic datatypes}
88 %************************************************************************
91 ctrlReturnConvAlg :: TyCon -> CtrlReturnConvention
93 ctrlReturnConvAlg tycon
94 = case (getTyConFamilySize tycon) of
95 Nothing -> -- pprPanic "ctrlReturnConvAlg:" (ppr PprDebug tycon)
96 UnvectoredReturn 0 -- e.g., w/ "data Bin"
98 Just size -> -- we're supposed to know...
99 if (size > (1::Int) && size <= mAX_FAMILY_SIZE_FOR_VEC_RETURNS) then
102 UnvectoredReturn size
105 @dataReturnConvAlg@ determines the return conventions from the
106 (possibly specialised) data constructor.
108 (See also @getDataConReturnConv@ (in @Id@).) We grab the types
109 of the data constructor's arguments. We feed them and a list of
110 available registers into @assign_reg@, which sequentially assigns
111 registers of the appropriate types to the arguments, based on the
112 types. If @assign_reg@ runs out of a particular kind of register,
113 then it gives up, returning @ReturnInHeap@.
116 dataReturnConvAlg :: IntSwitchChecker -> DataCon -> DataReturnConvention
118 dataReturnConvAlg isw_chkr data_con
119 = ASSERT(isDataCon data_con)
120 case leftover_kinds of
121 [] -> ReturnInRegs reg_assignment
122 other -> ReturnInHeap -- Didn't fit in registers
124 (_, _, arg_tys, _) = getDataConSig data_con
126 (reg_assignment, leftover_kinds)
127 = assignRegs isw_chkr_to_use
128 [node, infoptr] -- taken...
129 (map kindFromType arg_tys)
131 isw_chkr_to_use = isw_chkr
133 = if is_prim_result_ty {-and therefore *ignore* any return-in-regs threshold-}
137 is_prim_result_ty = data_con == integerDataCon -- ***HACK***! (WDP 95/11)
141 noLiveRegsMask :: Int -- Mask indicating nothing live
145 :: [MagicId] -- Candidate live regs; depends what they have in them
148 mkLiveRegsBitMask regs
149 = foldl do_reg noLiveRegsMask regs
151 do_reg acc (VanillaReg kind reg_no)
152 | isFollowableKind kind
153 = acc + (reg_tbl !! IBOX(reg_no _SUB_ ILIT(1)))
155 do_reg acc anything_else = acc
157 reg_tbl -- ToDo: mk Array!
158 = [lIVENESS_R1, lIVENESS_R2, lIVENESS_R3, lIVENESS_R4,
159 lIVENESS_R5, lIVENESS_R6, lIVENESS_R7, lIVENESS_R8]
162 -- Completely opaque code. ADR
163 -- What's wrong with: (untested)
165 mkLiveRegsBitMask regs
166 = foldl (+) noLiveRegsMask (map liveness_bit regs)
168 liveness_bit (VanillaReg kind reg_no)
169 | isFollowableKind kind
170 = reg_tbl !! (reg_no - 1)
172 liveness_bit anything_else
176 = [lIVENESS_R1, lIVENESS_R2, lIVENESS_R3, lIVENESS_R4,
177 lIVENESS_R5, lIVENESS_R6, lIVENESS_R7, lIVENESS_R8]
182 %************************************************************************
184 \subsection[CgRetConv-prim]{Return conventions for primitive datatypes}
186 %************************************************************************
188 WARNING! If you add a return convention which can return a pointer,
189 make sure you alter CgCase (cgPrimDefault) to generate the right sort
192 dataReturnConvPrim :: PrimKind -> MagicId
195 dataReturnConvPrim IntKind = VanillaReg IntKind ILIT(1)
196 dataReturnConvPrim WordKind = VanillaReg WordKind ILIT(1)
197 dataReturnConvPrim AddrKind = VanillaReg AddrKind ILIT(1)
198 dataReturnConvPrim CharKind = VanillaReg CharKind ILIT(1)
199 dataReturnConvPrim FloatKind = FloatReg ILIT(1)
200 dataReturnConvPrim DoubleKind = DoubleReg ILIT(1)
201 dataReturnConvPrim VoidKind = VoidReg
203 -- Return a primitive-array pointer in the usual register:
204 dataReturnConvPrim ArrayKind = VanillaReg ArrayKind ILIT(1)
205 dataReturnConvPrim ByteArrayKind = VanillaReg ByteArrayKind ILIT(1)
207 dataReturnConvPrim StablePtrKind = VanillaReg StablePtrKind ILIT(1)
208 dataReturnConvPrim MallocPtrKind = VanillaReg MallocPtrKind ILIT(1)
210 dataReturnConvPrim PtrKind = panic "dataReturnConvPrim: PtrKind"
211 dataReturnConvPrim _ = panic "dataReturnConvPrim: other"
214 dataReturnConvPrim VoidKind = VoidReg
215 dataReturnConvPrim PtrKind = panic "dataReturnConvPrim: PtrKind"
216 dataReturnConvPrim kind = DataReg kind 2 -- Don't Hog a Modifier reg.
217 #endif {- Data Parallel Haskell -}
221 %********************************************************
223 \subsection[primop-stuff]{Argument and return conventions for Prim Ops}
225 %********************************************************
228 assignPrimOpResultRegs
229 :: PrimOp -- The constructors in canonical order
230 -> [MagicId] -- The return regs all concatenated to together,
231 -- (*including* one for the tag if necy)
233 assignPrimOpResultRegs op
234 = case (getPrimOpResultInfo op) of
236 ReturnsPrim kind -> [dataReturnConvPrim kind]
240 cons = getTyConDataCons tycon
241 result_regs = concat (map get_return_regs cons)
243 -- As R1 is dead, it can hold the tag if necessary
246 other -> (VanillaReg IntKind ILIT(1)) : result_regs
249 = case (dataReturnConvAlg fake_isw_chkr con) of
250 ReturnInRegs regs -> regs
251 ReturnInHeap -> panic "getPrimOpAlgResultRegs"
253 fake_isw_chkr :: IntSwitchChecker
254 fake_isw_chkr x = Nothing
257 @assignPrimOpArgsRobust@ is used only for primitive ops which may
258 trigger GC. [MAYBE (WDP 94/05)] For these, we pass all (nonRobust)
259 arguments in registers. This function assigns them and tells us which
260 of those registers are now live (because we've shoved a followable
263 Bug: it is assumed that robust amodes cannot contain pointers. This
264 seems reasonable but isn't true. For example, \tr{Array#}'s
265 \tr{MallocPtr#}'s are pointers. (This is only known to bite on
266 \tr{_ccall_GC_} with a MallocPtr argument.)
268 See after for some ADR comments...
273 -> [CAddrMode] -- Arguments
274 -> ([CAddrMode], -- Arg registers
275 Int, -- Liveness mask
276 AbstractC) -- Simultaneous assignments to assign args to regs
278 makePrimOpArgsRobust op arg_amodes
279 = ASSERT (primOpCanTriggerGC op)
281 non_robust_amodes = filter (not . amodeCanSurviveGC) arg_amodes
282 arg_kinds = map getAmodeKind non_robust_amodes
284 (arg_regs, extra_args)
285 = assignRegs fake_isw_chkr [{-nothing live-}] arg_kinds
287 -- Check that all the args fit before returning arg_regs
288 final_arg_regs = case extra_args of
290 other -> error ("Cannot allocate enough registers for primop (try rearranging code or reducing number of arguments?) " ++ ppShow 80 (ppr PprDebug op))
292 arg_assts = mkAbstractCs (zipWith assign_to_reg final_arg_regs non_robust_amodes)
293 assign_to_reg reg_id amode = CAssign (CReg reg_id) amode
296 | amodeCanSurviveGC arg = (regs, arg)
297 | otherwise = (tail regs, CReg (head regs))
298 safe_amodes = snd (mapAccumL safe_arg final_arg_regs arg_amodes)
300 liveness_mask = mkLiveRegsBitMask final_arg_regs
302 (safe_amodes, liveness_mask, arg_assts)
304 fake_isw_chkr :: IntSwitchChecker
305 fake_isw_chkr x = Nothing
308 %************************************************************************
310 \subsubsection[CgRetConv-regs]{Register assignment}
312 %************************************************************************
314 How to assign registers.
315 Registers are assigned in order.
317 If we run out, we don't attempt to assign
318 any further registers (even though we might have run out of only one kind of
319 register); we just return immediately with the left-overs specified.
322 assignRegs :: IntSwitchChecker
323 -> [MagicId] -- Unavailable registers
324 -> [PrimKind] -- Arg or result kinds to assign
325 -> ([MagicId], -- Register assignment in same order
326 -- for *initial segment of* input list
327 [PrimKind])-- leftover kinds
329 assignRegs isw_chkr regs_in_use kinds
330 = assign_reg kinds [] (mkRegTbl isw_chkr regs_in_use)
333 assign_reg :: [PrimKind] -- arg kinds being scrutinized
334 -> [MagicId] -- accum. regs assigned so far (reversed)
335 -> ([Int], [Int], [Int])
336 -- regs still avail: Vanilla, Float, Double
337 -> ([MagicId], [PrimKind])
339 assign_reg (VoidKind:ks) acc supply
340 = assign_reg ks (VoidReg:acc) supply -- one VoidReg is enough for everybody!
342 assign_reg (FloatKind:ks) acc (vanilla_rs, IBOX(f):float_rs, double_rs)
343 = assign_reg ks (FloatReg f:acc) (vanilla_rs, float_rs, double_rs)
345 assign_reg (DoubleKind:ks) acc (vanilla_rs, float_rs, IBOX(d):double_rs)
346 = assign_reg ks (DoubleReg d:acc) (vanilla_rs, float_rs, double_rs)
348 assign_reg (k:ks) acc (IBOX(v):vanilla_rs, float_rs, double_rs)
349 | not (isFloatingKind k)
350 = assign_reg ks (VanillaReg k v:acc) (vanilla_rs, float_rs, double_rs)
352 -- The catch-all. It can happen because either
353 -- (a) we've assigned all the regs so leftover_ks is []
354 -- (b) we couldn't find a spare register in the appropriate supply
356 -- (c) we came across a Kind we couldn't handle (this one shouldn't happen)
357 assign_reg leftover_ks acc _ = (reverse acc, leftover_ks)
360 Register supplies. Vanilla registers can contain pointers, Ints, Chars.
363 vanillaRegNos :: [Int]
364 vanillaRegNos = [1 .. mAX_Vanilla_REG]
367 Floats and doubles have separate register supplies.
370 floatRegNos, doubleRegNos :: [Int]
371 floatRegNos = [1 .. mAX_Float_REG]
372 doubleRegNos = [1 .. mAX_Double_REG]
374 mkRegTbl :: IntSwitchChecker -> [MagicId] -> ([Int], [Int], [Int])
376 mkRegTbl isw_chkr regs_in_use
377 = (ok_vanilla, ok_float, ok_double)
379 ok_vanilla = catMaybes (map (select (VanillaReg VoidKind)) (taker vanillaRegNos))
380 ok_float = catMaybes (map (select FloatReg) floatRegNos)
381 ok_double = catMaybes (map (select DoubleReg) doubleRegNos)
383 taker :: [Int] -> [Int]
385 = case (isw_chkr ReturnInRegsThreshold) of
386 Nothing -> rs -- no flag set; use all of them
389 select :: (FAST_INT -> MagicId) -> Int{-cand-} -> Maybe Int
390 -- one we've unboxed the Int, we make a MagicId
391 -- and see if it is already in use; if not, return its number.
393 select mk_reg_fun cand@IBOX(i)
397 if reg `not_elem` regs_in_use
401 not_elem = isn'tIn "mkRegTbl"