summaryrefslogtreecommitdiff
path: root/compiler/GHC/Stg/InferTags/Types.hs
blob: 2beb1523fecc52da5a8c6d5d1bb184ce44285491 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
{-# LANGUAGE TypeFamilies, DataKinds, GADTs, FlexibleInstances #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE ConstraintKinds #-}

{-# LANGUAGE UndecidableInstances #-}
 -- To permit: type instance XLet 'InferTaggedBinders = XLet 'Vanilla

module GHC.Stg.InferTags.Types

where

#include "HsVersions.h"


import GHC.Prelude

import GHC.Core.DataCon
import GHC.Types.Id
import GHC.Stg.Syntax
import GHC.Types.Basic ( Arity )
import GHC.Types.Var.Env
import GHC.Utils.Outputable
import GHC.Utils.Misc( zipWithEqual )

{- *********************************************************************
*                                                                      *
                         Supporting data types
*                                                                      *
********************************************************************* -}

type instance BinderP 'InferTaggedBinders = (Id, TagSig)
type instance XLet         'InferTaggedBinders = XLet         'Vanilla
type instance XLetNoEscape 'InferTaggedBinders = XLetNoEscape 'Vanilla
type instance XRhsClosure  'InferTaggedBinders = XRhsClosure  'Vanilla
type instance XStgApp      'InferTaggedBinders = XStgApp      'Vanilla

type InferStgTopBinding = GenStgTopBinding 'InferTaggedBinders
type InferStgBinding    = GenStgBinding    'InferTaggedBinders
type InferStgExpr       = GenStgExpr       'InferTaggedBinders
type InferStgRhs        = GenStgRhs        'InferTaggedBinders
type InferStgAlt        = GenStgAlt        'InferTaggedBinders

instance OutputableBndr (Id,TagSig) where
  pprInfixOcc  = ppr
  pprPrefixOcc = ppr

data TagInfo
  = TagDunno
  | TagTuple [TagInfo]  -- Unboxed tuple
  | TagProper           -- Heap pointer to properly-tagged value
                        -- Bottom of the domain
  deriving( Eq )

instance Outputable TagInfo where
  ppr TagDunno       = text "TagDunno"
  ppr TagProper      = text "TagProper"
  ppr (TagTuple tis) = text "TagTuple" <> brackets (pprWithCommas ppr tis)

combineAltInfo :: TagInfo -> TagInfo -> TagInfo
combineAltInfo TagDunno         _              = TagDunno
combineAltInfo TagProper        ti             = ti
combineAltInfo (TagTuple {})    TagDunno       = TagDunno
combineAltInfo ti@(TagTuple {}) TagProper      = ti
combineAltInfo (TagTuple is1)   (TagTuple is2) = TagTuple (zipWithEqual "combineAltInfo" combineAltInfo is1 is2)

type TagSigEnv = IdEnv TagSig
data TagEnv p = TE { te_env :: TagSigEnv
                   , te_get :: BinderP p -> Id
                   , te_ext :: ExtEqEv (XLet p)
                                       (XLetNoEscape p) (XRhsClosure p) }

instance Outputable (TagEnv p) where
    ppr te = ppr (te_env te)


getBinderId :: TagEnv p -> BinderP p -> Id
getBinderId = te_get

-- This tiresome value is a proof that the extension fields
-- have the same type in pass p as in pass Tagged
-- ToDo: write a Note to explain properly
data ExtEqEv b c d where
  ExtEqEv :: ExtEqEv (XLet 'InferTaggedBinders)
                     (XLetNoEscape 'InferTaggedBinders) (XRhsClosure 'InferTaggedBinders)

initEnv :: TagEnv 'Vanilla
initEnv = TE { te_env = emptyVarEnv
             , te_get = \x -> x
             , te_ext = ExtEqEv }

-- | Simple convert env to a env of the 'InferTaggedBinders pass
-- with no other changes.
makeTagged :: TagEnv p -> TagEnv 'InferTaggedBinders
makeTagged env = TE { te_env = te_env env
                    , te_get = fst
                    , te_ext = ExtEqEv }

data TagSig  -- The signature for each binding
  = TagSig Arity TagInfo -- TODO: I think we can skip the arity, it should always be available via idArity
                         -- for all cases where we compute it.
  deriving( Eq )

instance Outputable TagSig where
  ppr (TagSig ar ti) = char '<' <> ppr ar <> comma <> ppr ti <> char '>'

noSig :: TagEnv p -> BinderP p -> (Id, TagSig)
noSig env bndr = (getBinderId env bndr, TagSig 0 TagDunno)

lookupSig :: TagEnv p -> Id -> Maybe TagSig
lookupSig env fun = lookupVarEnv (te_env env) fun

lookupInfo :: TagEnv p -> StgArg -> TagInfo
lookupInfo env (StgVarArg var)
  -- Nullary data constructors like True, False
  | Just dc <- isDataConWorkId_maybe var
  , isNullaryRepDataCon dc
  = TagProper

  -- Variables in the environment
  | Just (TagSig 0 info) <- lookupVarEnv (te_env env) var
  = info

  | otherwise
  = TagDunno

lookupInfo _ (StgLitArg {})
  = TagProper

isDunnoSig :: TagSig -> Bool
isDunnoSig (TagSig _ TagDunno) = True
isDunnoSig (TagSig _ TagProper) = False
isDunnoSig (TagSig _ TagTuple{}) = False

isTaggedSig :: TagSig -> Bool
isTaggedSig (TagSig _ TagProper) = True
isTaggedSig _ = False

extendSigEnv :: TagEnv p -> [(Id,TagSig)] -> TagEnv p
extendSigEnv env@(TE { te_env = sig_env }) bndrs
  = env { te_env = extendVarEnvList sig_env bndrs }