Merge nb:ghc/git/ghc
[ghc.git] / compiler / vectorise / Vectorise / Generic / Description.hs
1 -- |Compute a description of the generic representation that we use for a user defined data type.
2 --
3 -- During vectorisation, we generate a PRepr and PA instance for each user defined
4 -- data type. The PA dictionary contains methods to convert the user type to and
5 -- from our generic representation. This module computes a description of what
6 -- that generic representation is.
7 --
8 module Vectorise.Generic.Description
9 ( CompRepr(..)
10 , ProdRepr(..)
11 , ConRepr(..)
12 , SumRepr(..)
13 , tyConRepr
14 , sumReprType
15 , compOrigType
16 )
17 where
18
19 import Vectorise.Utils
20 import Vectorise.Monad
21 import Vectorise.Builtins
22
23 import CoreSyn
24 import DataCon
25 import TyCon
26 import Type
27 import Control.Monad
28 import Outputable
29
30
31 -- | Describes the generic representation of a data type.
32 -- If the data type has multiple constructors then we bundle them
33 -- together into a generic sum type.
34 data SumRepr
35 = -- | Data type has no data constructors.
36 EmptySum
37
38 -- | Data type has a single constructor.
39 | UnarySum ConRepr
40
41 -- | Data type has multiple constructors.
42 | Sum { -- | Representation tycon for the sum (eg Sum2)
43 repr_sum_tc :: TyCon
44
45 -- | PData version of the sum tycon (eg PDataSum2)
46 -- This TyCon doesn't appear explicitly in the source program.
47 -- See Note [PData TyCons].
48 , repr_psum_tc :: TyCon
49
50 -- | PDatas version of the sum tycon (eg PDatasSum2)
51 , repr_psums_tc :: TyCon
52
53 -- | Type of the selector (eg Sel2)
54 , repr_sel_ty :: Type
55
56 -- | Type of multi-selector (eg Sel2s)
57 , repr_sels_ty :: Type
58
59 -- | Function to get the length of a Sels of this type.
60 , repr_selsLength_v :: CoreExpr
61
62 -- | Type of each data constructor.
63 , repr_con_tys :: [Type]
64
65 -- | Generic representation types of each data constructor.
66 , repr_cons :: [ConRepr]
67 }
68
69
70 -- | Describes the representation type of a data constructor.
71 data ConRepr
72 = ConRepr
73 { repr_dc :: DataCon
74 , repr_prod :: ProdRepr
75 }
76
77 -- | Describes the representation type of the fields \/ components of a constructor.
78 -- If the data constructor has multiple fields then we bundle them
79 -- together into a generic product type.
80 data ProdRepr
81 = -- | Data constructor has no fields.
82 EmptyProd
83
84 -- | Data constructor has a single field.
85 | UnaryProd CompRepr
86
87 -- | Data constructor has several fields.
88 | Prod { -- | Representation tycon for the product (eg Tuple2)
89 repr_tup_tc :: TyCon
90
91 -- | PData version of the product tycon (eg PDataTuple2)
92 , repr_ptup_tc :: TyCon
93
94 -- | PDatas version of the product tycon (eg PDatasTuple2s)
95 -- Not all lifted backends use `PDatas`.
96 , repr_ptups_tc :: TyCon
97
98 -- | Types of each field.
99 , repr_comp_tys :: [Type]
100
101 -- | Generic representation types for each field.
102 , repr_comps :: [CompRepr]
103 }
104
105
106 -- | Describes the representation type of a data constructor field.
107 data CompRepr
108 = Keep Type
109 CoreExpr -- PR dictionary for the type
110 | Wrap Type
111
112
113 -------------------------------------------------------------------------------
114
115 -- |Determine the generic representation of a data type, given its tycon.
116 --
117 tyConRepr :: TyCon -> VM SumRepr
118 tyConRepr tc
119 = sum_repr (tyConDataCons tc)
120 where
121 -- Build the representation type for a data type with the given constructors.
122 -- The representation types for each individual constructor are bundled
123 -- together into a generic sum type.
124 sum_repr :: [DataCon] -> VM SumRepr
125 sum_repr [] = return EmptySum
126 sum_repr [con] = liftM UnarySum (con_repr con)
127 sum_repr cons
128 = do let arity = length cons
129 rs <- mapM con_repr cons
130 tys <- mapM conReprType rs
131
132 -- Get the 'Sum' tycon of this arity (eg Sum2).
133 sum_tc <- builtin (sumTyCon arity)
134
135 -- Get the 'PData' and 'PDatas' tycons for the sum.
136 psum_tc <- pdataReprTyConExact sum_tc
137 psums_tc <- pdatasReprTyConExact sum_tc
138
139 sel_ty <- builtin (selTy arity)
140 sels_ty <- builtin (selsTy arity)
141 selsLength_v <- builtin (selsLength arity)
142 return $ Sum
143 { repr_sum_tc = sum_tc
144 , repr_psum_tc = psum_tc
145 , repr_psums_tc = psums_tc
146 , repr_sel_ty = sel_ty
147 , repr_sels_ty = sels_ty
148 , repr_selsLength_v = selsLength_v
149 , repr_con_tys = tys
150 , repr_cons = rs
151 }
152
153 -- Build the representation type for a single data constructor.
154 con_repr con = liftM (ConRepr con) (prod_repr (dataConRepArgTys con))
155
156 -- Build the representation type for the fields of a data constructor.
157 -- The representation types for each individual field are bundled
158 -- together into a generic product type.
159 prod_repr :: [Type] -> VM ProdRepr
160 prod_repr [] = return EmptyProd
161 prod_repr [ty] = liftM UnaryProd (comp_repr ty)
162 prod_repr tys
163 = do let arity = length tys
164 rs <- mapM comp_repr tys
165 tys' <- mapM compReprType rs
166
167 -- Get the Prod \/ Tuple tycon of this arity (eg Tuple2)
168 tup_tc <- builtin (prodTyCon arity)
169
170 -- Get the 'PData' and 'PDatas' tycons for the product.
171 ptup_tc <- pdataReprTyConExact tup_tc
172 ptups_tc <- pdatasReprTyConExact tup_tc
173
174 return $ Prod
175 { repr_tup_tc = tup_tc
176 , repr_ptup_tc = ptup_tc
177 , repr_ptups_tc = ptups_tc
178 , repr_comp_tys = tys'
179 , repr_comps = rs
180 }
181
182 -- Build the representation type for a single data constructor field.
183 comp_repr ty = liftM (Keep ty) (prDictOfReprType ty)
184 `orElseV` return (Wrap ty)
185
186 -- |Yield the type of this sum representation.
187 --
188 sumReprType :: SumRepr -> VM Type
189 sumReprType EmptySum = voidType
190 sumReprType (UnarySum r) = conReprType r
191 sumReprType (Sum { repr_sum_tc = sum_tc, repr_con_tys = tys })
192 = return $ mkTyConApp sum_tc tys
193
194 -- Yield the type of this constructor representation.
195 --
196 conReprType :: ConRepr -> VM Type
197 conReprType (ConRepr _ r) = prodReprType r
198
199 -- Yield the type of of this product representation.
200 --
201 prodReprType :: ProdRepr -> VM Type
202 prodReprType EmptyProd = voidType
203 prodReprType (UnaryProd r) = compReprType r
204 prodReprType (Prod { repr_tup_tc = tup_tc, repr_comp_tys = tys })
205 = return $ mkTyConApp tup_tc tys
206
207 -- Yield the type of this data constructor field \/ component representation.
208 --
209 compReprType :: CompRepr -> VM Type
210 compReprType (Keep ty _) = return ty
211 compReprType (Wrap ty) = mkWrapType ty
212
213 -- |Yield the original component type of a data constructor component representation.
214 --
215 compOrigType :: CompRepr -> Type
216 compOrigType (Keep ty _) = ty
217 compOrigType (Wrap ty) = ty
218
219
220 -- Outputable instances -------------------------------------------------------
221 instance Outputable SumRepr where
222 ppr ss
223 = case ss of
224 EmptySum
225 -> text "EmptySum"
226
227 UnarySum con
228 -> sep [text "UnarySum", ppr con]
229
230 Sum sumtc psumtc psumstc selty selsty selsLength contys cons
231 -> text "Sum" $+$ braces (nest 4
232 $ sep [ text "repr_sum_tc = " <> ppr sumtc
233 , text "repr_psum_tc = " <> ppr psumtc
234 , text "repr_psums_tc = " <> ppr psumstc
235 , text "repr_sel_ty = " <> ppr selty
236 , text "repr_sels_ty = " <> ppr selsty
237 , text "repr_selsLength_v = " <> ppr selsLength
238 , text "repr_con_tys = " <> ppr contys
239 , text "repr_cons = " <> ppr cons])
240
241
242 instance Outputable ConRepr where
243 ppr (ConRepr dc pr)
244 = text "ConRepr" $+$ braces (nest 4
245 $ sep [ text "repr_dc = " <> ppr dc
246 , text "repr_prod = " <> ppr pr])
247
248
249 instance Outputable ProdRepr where
250 ppr ss
251 = case ss of
252 EmptyProd
253 -> text "EmptyProd"
254
255 UnaryProd cr
256 -> sep [text "UnaryProd", ppr cr]
257
258 Prod tuptcs ptuptcs ptupstcs comptys comps
259 -> sep [text "Prod", ppr tuptcs, ppr ptuptcs, ppr ptupstcs, ppr comptys, ppr comps]
260
261
262 instance Outputable CompRepr where
263 ppr ss
264 = case ss of
265 Keep t ce
266 -> text "Keep" $+$ sep [ppr t, ppr ce]
267
268 Wrap t
269 -> sep [text "Wrap", ppr t]
270
271
272 -- Notes ----------------------------------------------------------------------
273 {-
274 Note [PData TyCons]
275 ~~~~~~~~~~~~~~~~~~~
276 When PData is a type family, the compiler generates a type constructor for each
277 instance, which is named after the family and instance type. This type
278 constructor does not appear in the source program. Rather, it is implicitly
279 defined by the data instance. For example with:
280 \b
281 data family PData a
282
283 data instance PData (Sum2 a b)
284 = PSum2 U.Sel2
285 (PData a)
286 (PData b)
287
288 The type constructor corresponding to the instance will be named 'PDataSum2',
289 and this is what we will get in the repr_psum_tc field of SumRepr.Sum.
290
291 -}
292