2 % (c) The GRASP Project, Glasgow University, 1992-1998
4 % $Id: CgRetConv.lhs,v 1.31 2002/01/28 16:52:37 simonpj Exp $
6 \section[CgRetConv]{Return conventions for the code generator}
8 The datatypes and functions here encapsulate what there is to know
9 about return conventions.
13 CtrlReturnConvention(..),
16 assignRegs, assignAllRegs
19 #include "HsVersions.h"
21 import AbsCSyn -- quite a few things
22 import Constants ( mAX_FAMILY_SIZE_FOR_VEC_RETURNS,
23 mAX_Vanilla_REG, mAX_Float_REG,
24 mAX_Double_REG, mAX_Long_REG,
25 mAX_Real_Vanilla_REG, mAX_Real_Float_REG,
26 mAX_Real_Double_REG, mAX_Real_Long_REG
28 import CmdLineOpts ( opt_Unregisterised )
29 import Maybes ( catMaybes )
30 import PrimRep ( isFloatingRep, PrimRep(..), is64BitRep )
31 import TyCon ( TyCon, tyConFamilySize )
32 import Util ( isn'tIn )
37 %************************************************************************
39 \subsection[CgRetConv-possibilities]{Data types that encode possible return conventions}
41 %************************************************************************
43 A @CtrlReturnConvention@ says how {\em control} is returned.
45 data CtrlReturnConvention
46 = VectoredReturn Int -- size of the vector table (family size)
47 | UnvectoredReturn Int -- family size
50 %************************************************************************
52 \subsection[CgRetConv-algebraic]{Return conventions for algebraic datatypes}
54 %************************************************************************
57 ctrlReturnConvAlg :: TyCon -> CtrlReturnConvention
59 ctrlReturnConvAlg tycon
60 = case (tyConFamilySize tycon) of
61 size -> -- we're supposed to know...
62 if (size > (1::Int) && size <= mAX_FAMILY_SIZE_FOR_VEC_RETURNS) then
66 -- NB: unvectored returns Include size 0 (no constructors), so that
67 -- the following perverse code compiles (it crashed GHC in 5.02)
69 -- data T2 = T2 !T1 Int
70 -- The only value of type T1 is bottom, which never returns anyway.
73 %************************************************************************
75 \subsection[CgRetConv-prim]{Return conventions for primitive datatypes}
77 %************************************************************************
80 dataReturnConvPrim :: PrimRep -> MagicId
82 dataReturnConvPrim IntRep = VanillaReg IntRep (_ILIT 1)
83 dataReturnConvPrim WordRep = VanillaReg WordRep (_ILIT 1)
84 dataReturnConvPrim Int32Rep = VanillaReg Int32Rep (_ILIT 1)
85 dataReturnConvPrim Word32Rep = VanillaReg Word32Rep (_ILIT 1)
86 dataReturnConvPrim Int64Rep = LongReg Int64Rep (_ILIT 1)
87 dataReturnConvPrim Word64Rep = LongReg Word64Rep (_ILIT 1)
88 dataReturnConvPrim AddrRep = VanillaReg AddrRep (_ILIT 1)
89 dataReturnConvPrim CharRep = VanillaReg CharRep (_ILIT 1)
90 dataReturnConvPrim Int8Rep = VanillaReg Int8Rep (_ILIT 1)
91 dataReturnConvPrim FloatRep = FloatReg (_ILIT 1)
92 dataReturnConvPrim DoubleRep = DoubleReg (_ILIT 1)
93 dataReturnConvPrim VoidRep = VoidReg
95 -- Return a primitive-array pointer in the usual register:
96 dataReturnConvPrim ArrayRep = VanillaReg ArrayRep (_ILIT 1)
97 dataReturnConvPrim ByteArrayRep = VanillaReg ByteArrayRep (_ILIT 1)
98 dataReturnConvPrim PrimPtrRep = VanillaReg PrimPtrRep (_ILIT 1)
99 dataReturnConvPrim ThreadIdRep = VanillaReg ThreadIdRep (_ILIT 1)
101 dataReturnConvPrim StablePtrRep = VanillaReg StablePtrRep (_ILIT 1)
102 dataReturnConvPrim ForeignObjRep = VanillaReg ForeignObjRep (_ILIT 1)
103 dataReturnConvPrim WeakPtrRep = VanillaReg WeakPtrRep (_ILIT 1)
106 dataReturnConvPrim rep = pprPanic "dataReturnConvPrim:" (ppr rep)
110 %************************************************************************
112 \subsubsection[CgRetConv-regs]{Register assignment}
114 %************************************************************************
116 How to assign registers for
118 1) Calling a fast entry point.
119 2) Returning an unboxed tuple.
120 3) Invoking an out-of-line PrimOp.
122 Registers are assigned in order.
124 If we run out, we don't attempt to assign any further registers (even
125 though we might have run out of only one kind of register); we just
126 return immediately with the left-overs specified.
128 The alternative version @assignAllRegs@ uses the complete set of
129 registers, including those that aren't mapped to real machine
130 registers. This is used for calling special RTS functions and PrimOps
131 which expect their arguments to always be in the same registers.
134 assignRegs, assignAllRegs
135 :: [MagicId] -- Unavailable registers
136 -> [PrimRep] -- Arg or result kinds to assign
137 -> ([MagicId], -- Register assignment in same order
138 -- for *initial segment of* input list
139 [PrimRep])-- leftover kinds
141 assignRegs regs_in_use kinds
142 = assign_reg kinds [] (mkRegTbl regs_in_use)
144 assignAllRegs regs_in_use kinds
145 = assign_reg kinds [] (mkRegTbl_allRegs regs_in_use)
148 :: [PrimRep] -- arg kinds being scrutinized
149 -> [MagicId] -- accum. regs assigned so far (reversed)
150 -> AvailRegs -- regs still avail: Vanilla, Float, Double, longs
151 -> ([MagicId], [PrimRep])
153 assign_reg (VoidRep:ks) acc supply
154 = assign_reg ks (VoidReg:acc) supply
155 -- one VoidReg is enough for everybody!
157 assign_reg (FloatRep:ks) acc (vanilla_rs, f:float_rs, double_rs, long_rs)
158 = assign_reg ks (FloatReg (iUnbox f):acc)
159 (vanilla_rs, float_rs, double_rs, long_rs)
161 assign_reg (DoubleRep:ks) acc (vanilla_rs, float_rs, d:double_rs, long_rs)
162 = assign_reg ks (DoubleReg (iUnbox d):acc)
163 (vanilla_rs, float_rs, double_rs, long_rs)
165 assign_reg (Word64Rep:ks) acc (vanilla_rs, float_rs, double_rs, u:long_rs)
166 = assign_reg ks (LongReg Word64Rep (iUnbox u):acc)
167 (vanilla_rs, float_rs, double_rs, long_rs)
169 assign_reg (Int64Rep:ks) acc (vanilla_rs, float_rs, double_rs, l:long_rs)
170 = assign_reg ks (LongReg Int64Rep (iUnbox l):acc)
171 (vanilla_rs, float_rs, double_rs, long_rs)
173 assign_reg (k:ks) acc (v:vanilla_rs, float_rs, double_rs, long_rs)
174 | not (isFloatingRep k || is64BitRep k)
175 = assign_reg ks (VanillaReg k (iUnbox v):acc)
176 (vanilla_rs, float_rs, double_rs, long_rs)
178 -- The catch-all. It can happen because either
179 -- (a) we've assigned all the regs so leftover_ks is []
180 -- (b) we couldn't find a spare register in the appropriate supply
182 -- (c) we came across a Kind we couldn't handle (this one shouldn't happen)
183 assign_reg leftover_ks acc _ = (reverse acc, leftover_ks)
187 Register supplies. Vanilla registers can contain pointers, Ints, Chars.
188 Floats and doubles have separate register supplies.
190 We take these register supplies from the *real* registers, i.e. those
191 that are guaranteed to map to machine registers.
194 useVanillaRegs | opt_Unregisterised = 0
195 | otherwise = mAX_Real_Vanilla_REG
196 useFloatRegs | opt_Unregisterised = 0
197 | otherwise = mAX_Real_Float_REG
198 useDoubleRegs | opt_Unregisterised = 0
199 | otherwise = mAX_Real_Double_REG
200 useLongRegs | opt_Unregisterised = 0
201 | otherwise = mAX_Real_Long_REG
203 vanillaRegNos, floatRegNos, doubleRegNos, longRegNos :: [Int]
204 vanillaRegNos = regList useVanillaRegs
205 floatRegNos = regList useFloatRegs
206 doubleRegNos = regList useDoubleRegs
207 longRegNos = regList useLongRegs
209 allVanillaRegNos, allFloatRegNos, allDoubleRegNos, allLongRegNos :: [Int]
210 allVanillaRegNos = regList mAX_Vanilla_REG
211 allFloatRegNos = regList mAX_Float_REG
212 allDoubleRegNos = regList mAX_Double_REG
213 allLongRegNos = regList mAX_Long_REG
218 type AvailRegs = ( [Int] -- available vanilla regs.
221 , [Int] -- longs (int64 and word64)
224 mkRegTbl :: [MagicId] -> AvailRegs
226 = mkRegTbl' regs_in_use vanillaRegNos floatRegNos doubleRegNos longRegNos
228 mkRegTbl_allRegs :: [MagicId] -> AvailRegs
229 mkRegTbl_allRegs regs_in_use
230 = mkRegTbl' regs_in_use allVanillaRegNos allFloatRegNos allDoubleRegNos allLongRegNos
232 mkRegTbl' regs_in_use vanillas floats doubles longs
233 = (ok_vanilla, ok_float, ok_double, ok_long)
235 ok_vanilla = catMaybes (map (select (VanillaReg VoidRep)) vanillas)
236 ok_float = catMaybes (map (select FloatReg) floats)
237 ok_double = catMaybes (map (select DoubleReg) doubles)
238 ok_long = catMaybes (map (select (LongReg Int64Rep)) longs)
239 -- rep isn't looked at, hence we can use any old rep.
241 select :: (FastInt -> MagicId) -> Int{-cand-} -> Maybe Int
242 -- one we've unboxed the Int, we make a MagicId
243 -- and see if it is already in use; if not, return its number.
245 select mk_reg_fun cand
247 reg = mk_reg_fun (iUnbox cand)
249 if reg `not_elem` regs_in_use
253 not_elem = isn'tIn "mkRegTbl"