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