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