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