never executed always true always false
1
2 {-# LANGUAGE FlexibleContexts #-}
3
4 module GHC.Types.RepType
5 (
6 -- * Code generator views onto Types
7 UnaryType, NvUnaryType, isNvUnaryType,
8 unwrapType,
9
10 -- * Predicates on types
11 isVoidTy,
12
13 -- * Type representation for the code generator
14 typePrimRep, typePrimRep1, typeMonoPrimRep_maybe,
15 runtimeRepPrimRep, typePrimRepArgs,
16 PrimRep(..), primRepToType,
17 countFunRepArgs, countConRepArgs, tyConPrimRep, tyConPrimRep1,
18
19 -- * Unboxed sum representation type
20 ubxSumRepType, layoutUbxSum, typeSlotTy, SlotTy (..),
21 slotPrimRep, primRepSlot
22 ) where
23
24 import GHC.Prelude
25
26 import GHC.Types.Basic (Arity, RepArity)
27 import GHC.Core.DataCon
28 import GHC.Builtin.Names
29 import GHC.Core.Coercion
30 import GHC.Core.TyCon
31 import GHC.Core.TyCon.RecWalk
32 import GHC.Core.TyCo.Rep
33 import GHC.Core.Type
34 import GHC.Builtin.Types.Prim
35 import {-# SOURCE #-} GHC.Builtin.Types ( anyTypeOfKind, runtimeRepTy )
36
37 import GHC.Utils.Misc
38 import GHC.Utils.Outputable
39 import GHC.Utils.Panic
40 import GHC.Utils.Panic.Plain
41
42 import Data.List (sort)
43 import qualified Data.IntSet as IS
44
45 {- **********************************************************************
46 * *
47 Representation types
48 * *
49 ********************************************************************** -}
50
51 type NvUnaryType = Type
52 type UnaryType = Type
53 -- Both are always a value type; i.e. its kind is TYPE rr
54 -- for some rr; moreover the rr is never a variable.
55 --
56 -- NvUnaryType : never an unboxed tuple or sum, or void
57 --
58 -- UnaryType : never an unboxed tuple or sum;
59 -- can be Void# or (# #)
60
61 isNvUnaryType :: Type -> Bool
62 isNvUnaryType ty
63 | [_] <- typePrimRep ty
64 = True
65 | otherwise
66 = False
67
68 -- INVARIANT: the result list is never empty.
69 typePrimRepArgs :: HasDebugCallStack => Type -> [PrimRep]
70 typePrimRepArgs ty
71 | [] <- reps
72 = [VoidRep]
73 | otherwise
74 = reps
75 where
76 reps = typePrimRep ty
77
78 -- | Gets rid of the stuff that prevents us from understanding the
79 -- runtime representation of a type. Including:
80 -- 1. Casts
81 -- 2. Newtypes
82 -- 3. Foralls
83 -- 4. Synonyms
84 -- But not type/data families, because we don't have the envs to hand.
85 unwrapType :: Type -> Type
86 unwrapType ty
87 | Just (_, unwrapped)
88 <- topNormaliseTypeX stepper mappend inner_ty
89 = unwrapped
90 | otherwise
91 = inner_ty
92 where
93 inner_ty = go ty
94
95 go t | Just t' <- coreView t = go t'
96 go (ForAllTy _ t) = go t
97 go (CastTy t _) = go t
98 go t = t
99
100 -- cf. Coercion.unwrapNewTypeStepper
101 stepper rec_nts tc tys
102 | Just (ty', _) <- instNewTyCon_maybe tc tys
103 = case checkRecTc rec_nts tc of
104 Just rec_nts' -> NS_Step rec_nts' (go ty') ()
105 Nothing -> NS_Abort -- infinite newtypes
106 | otherwise
107 = NS_Done
108
109 countFunRepArgs :: Arity -> Type -> RepArity
110 countFunRepArgs 0 _
111 = 0
112 countFunRepArgs n ty
113 | FunTy _ _ arg res <- unwrapType ty
114 = length (typePrimRepArgs arg) + countFunRepArgs (n - 1) res
115 | otherwise
116 = pprPanic "countFunRepArgs: arity greater than type can handle" (ppr (n, ty, typePrimRep ty))
117
118 countConRepArgs :: DataCon -> RepArity
119 countConRepArgs dc = go (dataConRepArity dc) (dataConRepType dc)
120 where
121 go :: Arity -> Type -> RepArity
122 go 0 _
123 = 0
124 go n ty
125 | FunTy _ _ arg res <- unwrapType ty
126 = length (typePrimRep arg) + go (n - 1) res
127 | otherwise
128 = pprPanic "countConRepArgs: arity greater than type can handle" (ppr (n, ty, typePrimRep ty))
129
130 -- | True if the type has zero width.
131 isVoidTy :: Type -> Bool
132 isVoidTy = null . typePrimRep
133
134
135 {- **********************************************************************
136 * *
137 Unboxed sums
138 See Note [Translating unboxed sums to unboxed tuples] in GHC.Stg.Unarise
139 * *
140 ********************************************************************** -}
141
142 type SortedSlotTys = [SlotTy]
143
144 -- | Given the arguments of a sum type constructor application,
145 -- return the unboxed sum rep type.
146 --
147 -- E.g.
148 --
149 -- (# Int# | Maybe Int | (# Int#, Float# #) #)
150 --
151 -- We call `ubxSumRepType [ [IntRep], [LiftedRep], [IntRep, FloatRep] ]`,
152 -- which returns [WordSlot, PtrSlot, WordSlot, FloatSlot]
153 --
154 -- INVARIANT: Result slots are sorted (via Ord SlotTy), except that at the head
155 -- of the list we have the slot for the tag.
156 ubxSumRepType :: [[PrimRep]] -> [SlotTy]
157 ubxSumRepType constrs0
158 -- These first two cases never classify an actual unboxed sum, which always
159 -- has at least two disjuncts. But it could happen if a user writes, e.g.,
160 -- forall (a :: TYPE (SumRep [IntRep])). ...
161 -- which could never be instantiated. We still don't want to panic.
162 | constrs0 `lengthLessThan` 2
163 = [WordSlot]
164
165 | otherwise
166 = let
167 combine_alts :: [SortedSlotTys] -- slots of constructors
168 -> SortedSlotTys -- final slots
169 combine_alts constrs = foldl' merge [] constrs
170
171 merge :: SortedSlotTys -> SortedSlotTys -> SortedSlotTys
172 merge existing_slots []
173 = existing_slots
174 merge [] needed_slots
175 = needed_slots
176 merge (es : ess) (s : ss)
177 | Just s' <- s `fitsIn` es
178 = -- found a slot, use it
179 s' : merge ess ss
180 | s < es
181 = -- we need a new slot and this is the right place for it
182 s : merge (es : ess) ss
183 | otherwise
184 = -- keep searching for a slot
185 es : merge ess (s : ss)
186
187 -- Nesting unboxed tuples and sums is OK, so we need to flatten first.
188 rep :: [PrimRep] -> SortedSlotTys
189 rep ty = sort (map primRepSlot ty)
190
191 sumRep = WordSlot : combine_alts (map rep constrs0)
192 -- WordSlot: for the tag of the sum
193 in
194 sumRep
195
196 layoutUbxSum :: SortedSlotTys -- Layout of sum. Does not include tag.
197 -- We assume that they are in increasing order
198 -> [SlotTy] -- Slot types of things we want to map to locations in the
199 -- sum layout
200 -> [Int] -- Where to map 'things' in the sum layout
201 layoutUbxSum sum_slots0 arg_slots0 =
202 go arg_slots0 IS.empty
203 where
204 go :: [SlotTy] -> IS.IntSet -> [Int]
205 go [] _
206 = []
207 go (arg : args) used
208 = let slot_idx = findSlot arg 0 sum_slots0 used
209 in slot_idx : go args (IS.insert slot_idx used)
210
211 findSlot :: SlotTy -> Int -> SortedSlotTys -> IS.IntSet -> Int
212 findSlot arg slot_idx (slot : slots) useds
213 | not (IS.member slot_idx useds)
214 , Just slot == arg `fitsIn` slot
215 = slot_idx
216 | otherwise
217 = findSlot arg (slot_idx + 1) slots useds
218 findSlot _ _ [] _
219 = pprPanic "findSlot" (text "Can't find slot" $$ ppr sum_slots0 $$ ppr arg_slots0)
220
221 --------------------------------------------------------------------------------
222
223 -- We have 3 kinds of slots:
224 --
225 -- - Pointer slot: Only shared between actual pointers to Haskell heap (i.e.
226 -- boxed objects). These come in two variants: Lifted and unlifted (see
227 -- #19645).
228 --
229 -- - Word slots: Shared between IntRep, WordRep, Int64Rep, Word64Rep, AddrRep.
230 --
231 -- - Float slots: Shared between floating point types.
232 --
233 -- - Void slots: Shared between void types. Not used in sums.
234 --
235 -- TODO(michalt): We should probably introduce `SlotTy`s for 8-/16-/32-bit
236 -- values, so that we can pack things more tightly.
237 data SlotTy = PtrLiftedSlot | PtrUnliftedSlot | WordSlot | Word64Slot | FloatSlot | DoubleSlot
238 deriving (Eq, Ord)
239 -- Constructor order is important! If slot A could fit into slot B
240 -- then slot A must occur first. E.g. FloatSlot before DoubleSlot
241 --
242 -- We are assuming that WordSlot is smaller than or equal to Word64Slot
243 -- (would not be true on a 128-bit machine)
244
245 instance Outputable SlotTy where
246 ppr PtrLiftedSlot = text "PtrLiftedSlot"
247 ppr PtrUnliftedSlot = text "PtrUnliftedSlot"
248 ppr Word64Slot = text "Word64Slot"
249 ppr WordSlot = text "WordSlot"
250 ppr DoubleSlot = text "DoubleSlot"
251 ppr FloatSlot = text "FloatSlot"
252
253 typeSlotTy :: UnaryType -> Maybe SlotTy
254 typeSlotTy ty
255 | isVoidTy ty
256 = Nothing
257 | otherwise
258 = Just (primRepSlot (typePrimRep1 ty))
259
260 primRepSlot :: PrimRep -> SlotTy
261 primRepSlot VoidRep = pprPanic "primRepSlot" (text "No slot for VoidRep")
262 primRepSlot LiftedRep = PtrLiftedSlot
263 primRepSlot UnliftedRep = PtrUnliftedSlot
264 primRepSlot IntRep = WordSlot
265 primRepSlot Int8Rep = WordSlot
266 primRepSlot Int16Rep = WordSlot
267 primRepSlot Int32Rep = WordSlot
268 primRepSlot Int64Rep = Word64Slot
269 primRepSlot WordRep = WordSlot
270 primRepSlot Word8Rep = WordSlot
271 primRepSlot Word16Rep = WordSlot
272 primRepSlot Word32Rep = WordSlot
273 primRepSlot Word64Rep = Word64Slot
274 primRepSlot AddrRep = WordSlot
275 primRepSlot FloatRep = FloatSlot
276 primRepSlot DoubleRep = DoubleSlot
277 primRepSlot VecRep{} = pprPanic "primRepSlot" (text "No slot for VecRep")
278
279 slotPrimRep :: SlotTy -> PrimRep
280 slotPrimRep PtrLiftedSlot = LiftedRep
281 slotPrimRep PtrUnliftedSlot = UnliftedRep
282 slotPrimRep Word64Slot = Word64Rep
283 slotPrimRep WordSlot = WordRep
284 slotPrimRep DoubleSlot = DoubleRep
285 slotPrimRep FloatSlot = FloatRep
286
287 -- | Returns the bigger type if one fits into the other. (commutative)
288 --
289 -- Note that lifted and unlifted pointers are *not* in a fits-in relation for
290 -- the reasons described in Note [Don't merge lifted and unlifted slots] in
291 -- GHC.Stg.Unarise.
292 fitsIn :: SlotTy -> SlotTy -> Maybe SlotTy
293 fitsIn ty1 ty2
294 | ty1 == ty2
295 = Just ty1
296 | isWordSlot ty1 && isWordSlot ty2
297 = Just (max ty1 ty2)
298 | isFloatSlot ty1 && isFloatSlot ty2
299 = Just (max ty1 ty2)
300 | otherwise
301 = Nothing
302 where
303 isWordSlot Word64Slot = True
304 isWordSlot WordSlot = True
305 isWordSlot _ = False
306
307 isFloatSlot DoubleSlot = True
308 isFloatSlot FloatSlot = True
309 isFloatSlot _ = False
310
311
312 {- **********************************************************************
313 * *
314 PrimRep
315 * *
316 *************************************************************************
317
318 Note [RuntimeRep and PrimRep]
319 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
320 This Note describes the relationship between GHC.Types.RuntimeRep
321 (of levity/representation polymorphism fame) and GHC.Core.TyCon.PrimRep,
322 as these types are closely related.
323
324 A "primitive entity" is one that can be
325 * stored in one register
326 * manipulated with one machine instruction
327
328
329 Examples include:
330 * a 32-bit integer
331 * a 32-bit float
332 * a 64-bit float
333 * a machine address (heap pointer), etc.
334 * a quad-float (on a machine with SIMD register and instructions)
335 * ...etc...
336
337 The "representation or a primitive entity" specifies what kind of register is
338 needed and how many bits are required. The data type GHC.Core.TyCon.PrimRep
339 enumerates all the possibilities.
340
341 data PrimRep
342 = VoidRep -- See Note [VoidRep]
343 | LiftedRep -- ^ Lifted pointer
344 | UnliftedRep -- ^ Unlifted pointer
345 | Int8Rep -- ^ Signed, 8-bit value
346 | Int16Rep -- ^ Signed, 16-bit value
347 ...etc...
348 | VecRep Int PrimElemRep -- ^ SIMD fixed-width vector
349
350 The Haskell source language is a bit more flexible: a single value may need multiple PrimReps.
351 For example
352
353 utup :: (# Int, Int #) -> Bool
354 utup x = ...
355
356 Here x :: (# Int, Int #), and that takes two registers, and two instructions to move around.
357 Unboxed sums are similar.
358
359 Every Haskell expression e has a type ty, whose kind is of form TYPE rep
360 e :: ty :: TYPE rep
361 where rep :: RuntimeRep. Here rep describes the runtime representation for e's value,
362 but RuntimeRep has some extra cases:
363
364 data RuntimeRep = VecRep VecCount VecElem -- ^ a SIMD vector type
365 | TupleRep [RuntimeRep] -- ^ An unboxed tuple of the given reps
366 | SumRep [RuntimeRep] -- ^ An unboxed sum of the given reps
367 | BoxedRep Levity -- ^ boxed; represented by a pointer
368 | IntRep -- ^ signed, word-sized value
369 ...etc...
370 data Levity = Lifted
371 | Unlifted
372
373 It's all in 1-1 correspondence with PrimRep except for TupleRep and SumRep,
374 which describe unboxed products and sums respectively. RuntimeRep is defined
375 in the library ghc-prim:GHC.Types. It is also "wired-in" to GHC: see
376 GHC.Builtin.Types.runtimeRepTyCon. The unarisation pass, in GHC.Stg.Unarise, transforms the
377 program, so that every variable has a type that has a PrimRep. For
378 example, unarisation transforms our utup function above, to take two Int
379 arguments instead of one (# Int, Int #) argument.
380
381 Also, note that boxed types are represented slightly differently in RuntimeRep
382 and PrimRep. PrimRep just has the nullary LiftedRep and UnliftedRep data
383 constructors. RuntimeRep has a BoxedRep data constructor, which accepts a
384 Levity. The subtle distinction is that since BoxedRep can accept a variable
385 argument, RuntimeRep can talk about levity polymorphic types. PrimRep, by
386 contrast, cannot.
387
388 See also Note [Getting from RuntimeRep to PrimRep] and Note [VoidRep].
389
390 Note [VoidRep]
391 ~~~~~~~~~~~~~~
392 PrimRep contains a constructor VoidRep, while RuntimeRep does
393 not. Yet representations are often characterised by a list of PrimReps,
394 where a void would be denoted as []. (See also Note [RuntimeRep and PrimRep].)
395
396 However, after the unariser, all identifiers have exactly one PrimRep, but
397 void arguments still exist. Thus, PrimRep includes VoidRep to describe these
398 binders. Perhaps post-unariser representations (which need VoidRep) should be
399 a different type than pre-unariser representations (which use a list and do
400 not need VoidRep), but we have what we have.
401
402 RuntimeRep instead uses TupleRep '[] to denote a void argument. When
403 converting a TupleRep '[] into a list of PrimReps, we get an empty list.
404
405 Note [Getting from RuntimeRep to PrimRep]
406 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
407 General info on RuntimeRep and PrimRep is in Note [RuntimeRep and PrimRep].
408
409 How do we get from an Id to the list or PrimReps used to store it? We get
410 the Id's type ty (using idType), then ty's kind ki (using typeKind), then
411 pattern-match on ki to extract rep (in kindPrimRep), then extract the PrimRep
412 from the RuntimeRep (in runtimeRepPrimRep).
413
414 We now must convert the RuntimeRep to a list of PrimReps. Let's look at two
415 examples:
416
417 1. x :: Int#
418 2. y :: (# Int, Word# #)
419
420 With these types, we can extract these kinds:
421
422 1. Int# :: TYPE IntRep
423 2. (# Int, Word# #) :: TYPE (TupleRep [LiftedRep, WordRep])
424
425 In the end, we will get these PrimReps:
426
427 1. [IntRep]
428 2. [LiftedRep, WordRep]
429
430 It would thus seem that we should have a function somewhere of
431 type `RuntimeRep -> [PrimRep]`. This doesn't work though: when we
432 look at the argument of TYPE, we get something of type Type (of course).
433 RuntimeRep exists in the user's program, but not in GHC as such.
434 Instead, we must decompose the Type of kind RuntimeRep into tycons and
435 extract the PrimReps from the TyCons. This is what runtimeRepPrimRep does:
436 it takes a Type and returns a [PrimRep]
437
438 runtimeRepPrimRep works by using tyConRuntimeRepInfo. That function
439 should be passed the TyCon produced by promoting one of the constructors
440 of RuntimeRep into type-level data. The RuntimeRep promoted datacons are
441 associated with a RuntimeRepInfo (stored directly in the PromotedDataCon
442 constructor of TyCon). This pairing happens in GHC.Builtin.Types. A RuntimeRepInfo
443 usually(*) contains a function from [Type] to [PrimRep]: the [Type] are
444 the arguments to the promoted datacon. These arguments are necessary
445 for the TupleRep and SumRep constructors, so that this process can recur,
446 producing a flattened list of PrimReps. Calling this extracted function
447 happens in runtimeRepPrimRep; the functions themselves are defined in
448 tupleRepDataCon and sumRepDataCon, both in GHC.Builtin.Types.
449
450 The (*) above is to support vector representations. RuntimeRep refers
451 to VecCount and VecElem, whose promoted datacons have nuggets of information
452 related to vectors; these form the other alternatives for RuntimeRepInfo.
453
454 Returning to our examples, the Types we get (after stripping off TYPE) are
455
456 1. TyConApp (PromotedDataCon "IntRep") []
457 2. TyConApp (PromotedDataCon "TupleRep")
458 [TyConApp (PromotedDataCon ":")
459 [ TyConApp (AlgTyCon "RuntimeRep") []
460 , TyConApp (PromotedDataCon "LiftedRep") []
461 , TyConApp (PromotedDataCon ":")
462 [ TyConApp (AlgTyCon "RuntimeRep") []
463 , TyConApp (PromotedDataCon "WordRep") []
464 , TyConApp (PromotedDataCon "'[]")
465 [TyConApp (AlgTyCon "RuntimeRep") []]]]]
466
467 runtimeRepPrimRep calls tyConRuntimeRepInfo on (PromotedDataCon "IntRep"), resp.
468 (PromotedDataCon "TupleRep"), extracting a function that will produce the PrimReps.
469 In example 1, this function is passed an empty list (the empty list of args to IntRep)
470 and returns the PrimRep IntRep. (See the definition of runtimeRepSimpleDataCons in
471 GHC.Builtin.Types and its helper function mk_runtime_rep_dc.) Example 2 passes the promoted
472 list as the one argument to the extracted function. The extracted function is defined
473 as prim_rep_fun within tupleRepDataCon in GHC.Builtin.Types. It takes one argument, decomposes
474 the promoted list (with extractPromotedList), and then recurs back to runtimeRepPrimRep
475 to process the LiftedRep and WordRep, concatentating the results.
476
477 -}
478
479 -- | Discovers the primitive representation of a 'Type'. Returns
480 -- a list of 'PrimRep': it's a list because of the possibility of
481 -- no runtime representation (void) or multiple (unboxed tuple/sum)
482 -- See also Note [Getting from RuntimeRep to PrimRep]
483 typePrimRep :: HasDebugCallStack => Type -> [PrimRep]
484 typePrimRep ty = kindPrimRep (text "typePrimRep" <+>
485 parens (ppr ty <+> dcolon <+> ppr (typeKind ty)))
486 (typeKind ty)
487
488 -- | Like 'typePrimRep', but assumes that there is precisely one 'PrimRep' output;
489 -- an empty list of PrimReps becomes a VoidRep.
490 -- This assumption holds after unarise, see Note [Post-unarisation invariants].
491 -- Before unarise it may or may not hold.
492 -- See also Note [RuntimeRep and PrimRep] and Note [VoidRep]
493 typePrimRep1 :: HasDebugCallStack => UnaryType -> PrimRep
494 typePrimRep1 ty = case typePrimRep ty of
495 [] -> VoidRep
496 [rep] -> rep
497 _ -> pprPanic "typePrimRep1" (ppr ty $$ ppr (typePrimRep ty))
498
499 -- | Like 'typePrimRep', but returns 'Nothing' instead of panicking, when
500 --
501 -- * The @ty@ was not of form @TYPE rep@
502 -- * @rep@ was not monomorphic
503 --
504 typeMonoPrimRep_maybe :: Type -> Maybe [PrimRep]
505 typeMonoPrimRep_maybe ty = getRuntimeRep_maybe ty >>= runtimeRepMonoPrimRep_maybe
506
507 -- | Find the runtime representation of a 'TyCon'. Defined here to
508 -- avoid module loops. Returns a list of the register shapes necessary.
509 -- See also Note [Getting from RuntimeRep to PrimRep]
510 tyConPrimRep :: HasDebugCallStack => TyCon -> [PrimRep]
511 tyConPrimRep tc
512 = kindPrimRep (text "kindRep tc" <+> ppr tc $$ ppr res_kind)
513 res_kind
514 where
515 res_kind = tyConResKind tc
516
517 -- | Like 'tyConPrimRep', but assumed that there is precisely zero or
518 -- one 'PrimRep' output
519 -- See also Note [Getting from RuntimeRep to PrimRep] and Note [VoidRep]
520 tyConPrimRep1 :: HasDebugCallStack => TyCon -> PrimRep
521 tyConPrimRep1 tc = case tyConPrimRep tc of
522 [] -> VoidRep
523 [rep] -> rep
524 _ -> pprPanic "tyConPrimRep1" (ppr tc $$ ppr (tyConPrimRep tc))
525
526 -- | Take a kind (of shape @TYPE rr@) and produce the 'PrimRep's
527 -- of values of types of this kind.
528 -- See also Note [Getting from RuntimeRep to PrimRep]
529 kindPrimRep :: HasDebugCallStack => SDoc -> Kind -> [PrimRep]
530 kindPrimRep doc ki
531 | Just ki' <- coreView ki
532 = kindPrimRep doc ki'
533 kindPrimRep doc (TyConApp typ [runtime_rep])
534 = assert (typ `hasKey` tYPETyConKey) $
535 runtimeRepPrimRep doc runtime_rep
536 kindPrimRep doc ki
537 = pprPanic "kindPrimRep" (ppr ki $$ doc)
538
539 -- | Take a type of kind RuntimeRep and extract the list of 'PrimRep' that
540 -- it encodes if it's a monomorphic rep. Otherwise returns 'Nothing'.
541 -- See also Note [Getting from RuntimeRep to PrimRep]
542 runtimeRepMonoPrimRep_maybe :: HasDebugCallStack => Type -> Maybe [PrimRep]
543 runtimeRepMonoPrimRep_maybe rr_ty
544 | Just (rr_dc, args) <- splitTyConApp_maybe rr_ty
545 , assertPpr (runtimeRepTy `eqType` typeKind rr_ty) (ppr rr_ty) True
546 , RuntimeRep fun <- tyConRuntimeRepInfo rr_dc
547 = Just (fun args)
548 | otherwise
549 = Nothing -- not mono rep
550
551 -- | Take a type of kind RuntimeRep and extract the list of 'PrimRep' that
552 -- it encodes. See also Note [Getting from RuntimeRep to PrimRep]
553 -- The [PrimRep] is the final runtime representation /after/ unarisation
554 runtimeRepPrimRep :: HasDebugCallStack => SDoc -> Type -> [PrimRep]
555 runtimeRepPrimRep doc rr_ty
556 | Just rr_ty' <- coreView rr_ty
557 = runtimeRepPrimRep doc rr_ty'
558 | TyConApp rr_dc args <- rr_ty
559 , RuntimeRep fun <- tyConRuntimeRepInfo rr_dc
560 = fun args
561 | otherwise
562 = pprPanic "runtimeRepPrimRep" (doc $$ ppr rr_ty)
563
564 -- | Convert a PrimRep back to a Type. Used only in the unariser to give types
565 -- to fresh Ids. Really, only the type's representation matters.
566 -- See also Note [RuntimeRep and PrimRep]
567 primRepToType :: PrimRep -> Type
568 primRepToType = anyTypeOfKind . tYPE . primRepToRuntimeRep