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(..),
20 assignPrimOpResultRegs,
26 IMPORT_DELOOPER(AbsCLoop) -- paranoia checking
28 import AbsCSyn -- quite a few things
29 import AbsCUtils ( mkAbstractCs, getAmodeRep,
32 import CgCompInfo ( mAX_FAMILY_SIZE_FOR_VEC_RETURNS,
33 mAX_Vanilla_REG, mAX_Float_REG,
36 import CmdLineOpts ( opt_ReturnInRegsThreshold )
37 import Id ( isDataCon, dataConRawArgTys,
38 SYN_IE(DataCon), GenId{-instance Eq-}
40 import Maybes ( catMaybes )
41 import PprStyle ( PprStyle(..) )
42 import PprType ( TyCon{-instance Outputable-} )
43 import PrimOp ( primOpCanTriggerGC,
44 getPrimOpResultInfo, PrimOpResultInfo(..),
45 PrimOp{-instance Outputable-}
47 import PrimRep ( isFloatingRep, PrimRep(..) )
48 import TyCon ( tyConDataCons, tyConFamilySize )
49 import Type ( typePrimRep )
50 import Util ( zipWithEqual, mapAccumL, isn'tIn,
51 pprError, pprTrace, panic, assertPanic
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 (tyConFamilySize tycon) of
95 0 -> pprTrace "ctrlReturnConvAlg:" (ppr PprDebug tycon) $
96 UnvectoredReturn 0 -- e.g., w/ "data Bin"
98 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 :: DataCon -> DataReturnConvention
118 dataReturnConvAlg 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 = dataConRawArgTys data_con
126 (reg_assignment, leftover_kinds)
127 = assignRegs [node, infoptr] -- taken...
128 (map typePrimRep arg_tys)
131 %************************************************************************
133 \subsection[CgRetConv-prim]{Return conventions for primitive datatypes}
135 %************************************************************************
137 WARNING! If you add a return convention which can return a pointer,
138 make sure you alter CgCase (cgPrimDefault) to generate the right sort
141 dataReturnConvPrim :: PrimRep -> MagicId
143 dataReturnConvPrim IntRep = VanillaReg IntRep ILIT(1)
144 dataReturnConvPrim WordRep = VanillaReg WordRep ILIT(1)
145 dataReturnConvPrim AddrRep = VanillaReg AddrRep ILIT(1)
146 dataReturnConvPrim CharRep = VanillaReg CharRep ILIT(1)
147 dataReturnConvPrim FloatRep = FloatReg ILIT(1)
148 dataReturnConvPrim DoubleRep = DoubleReg ILIT(1)
149 dataReturnConvPrim VoidRep = VoidReg
151 -- Return a primitive-array pointer in the usual register:
152 dataReturnConvPrim ArrayRep = VanillaReg ArrayRep ILIT(1)
153 dataReturnConvPrim ByteArrayRep = VanillaReg ByteArrayRep ILIT(1)
155 dataReturnConvPrim StablePtrRep = VanillaReg StablePtrRep ILIT(1)
156 dataReturnConvPrim ForeignObjRep = VanillaReg ForeignObjRep ILIT(1)
159 dataReturnConvPrim PtrRep = panic "dataReturnConvPrim: PtrRep"
160 dataReturnConvPrim _ = panic "dataReturnConvPrim: other"
164 %********************************************************
166 \subsection[primop-stuff]{Argument and return conventions for Prim Ops}
168 %********************************************************
171 assignPrimOpResultRegs
172 :: PrimOp -- The constructors in canonical order
173 -> [MagicId] -- The return regs all concatenated to together,
174 -- (*including* one for the tag if necy)
176 assignPrimOpResultRegs op
177 = case (getPrimOpResultInfo op) of
179 ReturnsPrim kind -> [dataReturnConvPrim kind]
183 cons = tyConDataCons tycon
184 result_regs = concat (map get_return_regs cons)
186 -- As R1 is dead, it can hold the tag if necessary
189 other -> (VanillaReg IntRep ILIT(1)) : result_regs
192 = case (dataReturnConvAlg con) of
193 ReturnInRegs regs -> regs
194 ReturnInHeap -> panic "getPrimOpAlgResultRegs"
197 @assignPrimOpArgsRobust@ is used only for primitive ops which may
198 trigger GC. [MAYBE (WDP 94/05)] For these, we pass all (nonRobust)
199 arguments in registers. This function assigns them and tells us which
200 of those registers are now live (because we've shoved a followable
203 Bug: it is assumed that robust amodes cannot contain pointers. This
204 seems reasonable but isn't true. For example, \tr{Array#}'s
205 \tr{ForeignObj#}'s are pointers. (This is only known to bite on
206 \tr{_ccall_GC_} with a ForeignObj argument.)
208 See after for some ADR comments...
213 -> [CAddrMode] -- Arguments
214 -> ([CAddrMode], -- Arg registers
215 Int, -- Liveness mask
216 AbstractC) -- Simultaneous assignments to assign args to regs
218 makePrimOpArgsRobust op arg_amodes
219 = ASSERT (primOpCanTriggerGC op)
221 non_robust_amodes = filter (not . amodeCanSurviveGC) arg_amodes
222 arg_kinds = map getAmodeRep non_robust_amodes
224 (arg_regs, extra_args)
225 = assignRegs [{-nothing live-}] arg_kinds
227 -- Check that all the args fit before returning arg_regs
228 final_arg_regs = case extra_args of
230 other -> pprError "Cannot allocate enough registers for primop (try rearranging code or reducing number of arguments?)" (ppr PprDebug op)
233 = mkAbstractCs (zipWithEqual "assign_to_reg" assign_to_reg final_arg_regs non_robust_amodes)
235 assign_to_reg reg_id amode = CAssign (CReg reg_id) amode
238 | amodeCanSurviveGC arg = (regs, arg)
239 | otherwise = (tail regs, CReg (head regs))
240 safe_amodes = snd (mapAccumL safe_arg final_arg_regs arg_amodes)
242 liveness_mask = mkLiveRegsMask final_arg_regs
244 (safe_amodes, liveness_mask, arg_assts)
247 %************************************************************************
249 \subsubsection[CgRetConv-regs]{Register assignment}
251 %************************************************************************
253 How to assign registers.
254 Registers are assigned in order.
256 If we run out, we don't attempt to assign
257 any further registers (even though we might have run out of only one kind of
258 register); we just return immediately with the left-overs specified.
261 assignRegs :: [MagicId] -- Unavailable registers
262 -> [PrimRep] -- Arg or result kinds to assign
263 -> ([MagicId], -- Register assignment in same order
264 -- for *initial segment of* input list
265 [PrimRep])-- leftover kinds
267 assignRegs regs_in_use kinds
268 = assign_reg kinds [] (mkRegTbl regs_in_use)
271 assign_reg :: [PrimRep] -- arg kinds being scrutinized
272 -> [MagicId] -- accum. regs assigned so far (reversed)
273 -> ([Int], [Int], [Int])
274 -- regs still avail: Vanilla, Float, Double
275 -> ([MagicId], [PrimRep])
277 assign_reg (VoidRep:ks) acc supply
278 = assign_reg ks (VoidReg:acc) supply -- one VoidReg is enough for everybody!
280 assign_reg (FloatRep:ks) acc (vanilla_rs, IBOX(f):float_rs, double_rs)
281 = assign_reg ks (FloatReg f:acc) (vanilla_rs, float_rs, double_rs)
283 assign_reg (DoubleRep:ks) acc (vanilla_rs, float_rs, IBOX(d):double_rs)
284 = assign_reg ks (DoubleReg d:acc) (vanilla_rs, float_rs, double_rs)
286 assign_reg (k:ks) acc (IBOX(v):vanilla_rs, float_rs, double_rs)
287 | not (isFloatingRep k)
288 = assign_reg ks (VanillaReg k v:acc) (vanilla_rs, float_rs, double_rs)
290 -- The catch-all. It can happen because either
291 -- (a) we've assigned all the regs so leftover_ks is []
292 -- (b) we couldn't find a spare register in the appropriate supply
294 -- (c) we came across a Kind we couldn't handle (this one shouldn't happen)
295 assign_reg leftover_ks acc _ = (reverse acc, leftover_ks)
298 Register supplies. Vanilla registers can contain pointers, Ints, Chars.
301 vanillaRegNos :: [Int]
302 vanillaRegNos = [1 .. mAX_Vanilla_REG]
305 Floats and doubles have separate register supplies.
308 floatRegNos, doubleRegNos :: [Int]
309 floatRegNos = [1 .. mAX_Float_REG]
310 doubleRegNos = [1 .. mAX_Double_REG]
312 mkRegTbl :: [MagicId] -> ([Int], [Int], [Int])
315 = (ok_vanilla, ok_float, ok_double)
317 ok_vanilla = catMaybes (map (select (VanillaReg VoidRep)) (taker vanillaRegNos))
318 ok_float = catMaybes (map (select FloatReg) floatRegNos)
319 ok_double = catMaybes (map (select DoubleReg) doubleRegNos)
321 taker :: [Int] -> [Int]
323 = case (opt_ReturnInRegsThreshold) of
324 Nothing -> rs -- no flag set; use all of them
327 select :: (FAST_INT -> MagicId) -> Int{-cand-} -> Maybe Int
328 -- one we've unboxed the Int, we make a MagicId
329 -- and see if it is already in use; if not, return its number.
331 select mk_reg_fun cand@IBOX(i)
335 if reg `not_elem` regs_in_use
339 not_elem = isn'tIn "mkRegTbl"