2 % (c) The GRASP/AQUA Project, Glasgow University, 1993-1996
4 \section[IdInfo]{@IdInfos@: Non-essential information about @Ids@}
6 (And a pretty good illustration of quite a few things wrong with
17 exactArity, atLeastArity, unknownArity,
18 arityInfo, addArityInfo, ppArityInfo,
21 noDemandInfo, mkDemandInfo, demandInfo, ppDemandInfo, addDemandInfo, willBeDemanded,
23 StrictnessInfo(..), -- Non-abstract
24 Demand(..), NewOrData, -- Non-abstract
27 mkStrictnessInfo, mkBottomStrictnessInfo, noStrictnessInfo, bottomIsGuaranteed,
28 strictnessInfo, ppStrictnessInfo, addStrictnessInfo,
30 unfoldInfo, addUnfoldInfo,
32 IdSpecEnv, specInfo, setSpecInfo,
34 UpdateInfo, UpdateSpec,
35 mkUpdateInfo, updateInfo, updateInfoMaybe, ppUpdateInfo, addUpdateInfo,
37 ArgUsageInfo, ArgUsage(..), ArgUsageType,
38 mkArgUsageInfo, argUsageInfo, addArgUsageInfo, getArgUsage,
40 FBTypeInfo, FBType(..), FBConsum(..), FBProd(..),
41 fbTypeInfo, ppFBTypeInfo, addFBTypeInfo, mkFBTypeInfo, getFBType
44 #include "HsVersions.h"
47 import {-# SOURCE #-} CoreUnfold ( Unfolding, noUnfolding )
48 import {-# SOURCE #-} CoreSyn ( SimplifiableCoreExpr )
50 -- for mkdependHS, CoreSyn.hi-boot refers to it:
51 import BinderInfo ( BinderInfo )
53 import SpecEnv ( SpecEnv, emptySpecEnv )
54 import BasicTypes ( NewOrData )
62 An @IdInfo@ gives {\em optional} information about an @Id@. If
63 present it never lies, but it may not be present, in which case there
64 is always a conservative assumption which can be made.
66 Two @Id@s may have different info even though they have the same
67 @Unique@ (and are hence the same @Id@); for example, one might lack
68 the properties attached to the other.
70 The @IdInfo@ gives information about the value, or definition, of the
71 @Id@. It does {\em not} contain information about the @Id@'s usage
72 (except for @DemandInfo@? ToDo).
77 ArityInfo -- Its arity
79 DemandInfo -- Whether or not it is definitely
82 IdSpecEnv -- Specialisations of this function which exist
84 StrictnessInfo -- Strictness properties
86 Unfolding -- Its unfolding; for locally-defined
87 -- things, this can *only* be NoUnfolding
89 UpdateInfo -- Which args should be updated
91 ArgUsageInfo -- how this Id uses its arguments
93 FBTypeInfo -- the Foldr/Build W/W property of this function.
97 noIdInfo = IdInfo UnknownArity UnknownDemand emptySpecEnv NoStrictnessInfo noUnfolding
98 NoUpdateInfo NoArgUsageInfo NoFBTypeInfo
102 ppIdInfo :: Bool -- True <=> print specialisations, please
106 ppIdInfo specs_please
107 (IdInfo arity demand specenv strictness unfold update arg_usage fbtype)
109 -- order is important!:
113 ppStrictnessInfo strictness,
116 then empty -- ToDo -- sty (not (isDataCon for_this_id))
117 -- better_id_fn inline_env (mEnvToList specenv)
120 -- DemandInfo needn't be printed since it has no effect on interfaces
126 %************************************************************************
128 \subsection[arity-IdInfo]{Arity info about an @Id@}
130 %************************************************************************
134 = UnknownArity -- No idea
135 | ArityExactly Int -- Arity is exactly this
136 | ArityAtLeast Int -- Arity is this or greater
140 exactArity = ArityExactly
141 atLeastArity = ArityAtLeast
142 unknownArity = UnknownArity
144 arityInfo (IdInfo arity _ _ _ _ _ _ _) = arity
146 addArityInfo (IdInfo _ a b c d e f g) arity = IdInfo arity a b c d e f g
148 ppArityInfo UnknownArity = empty
149 ppArityInfo (ArityExactly arity) = hsep [ptext SLIT("_A_"), int arity]
150 ppArityInfo (ArityAtLeast arity) = hsep [ptext SLIT("_A>_"), int arity]
153 %************************************************************************
155 \subsection[demand-IdInfo]{Demand info about an @Id@}
157 %************************************************************************
159 Whether a value is certain to be demanded or not. (This is the
160 information that is computed by the ``front-end'' of the strictness
163 This information is only used within a module, it is not exported
169 | DemandedAsPer Demand
173 noDemandInfo = UnknownDemand
175 mkDemandInfo :: Demand -> DemandInfo
176 mkDemandInfo demand = DemandedAsPer demand
178 willBeDemanded :: DemandInfo -> Bool
179 willBeDemanded (DemandedAsPer demand) = isStrict demand
180 willBeDemanded _ = False
184 demandInfo (IdInfo _ demand _ _ _ _ _ _) = demand
186 addDemandInfo (IdInfo a _ c d e f g h) demand = IdInfo a demand c d e f g h
188 ppDemandInfo UnknownDemand = text "{-# L #-}"
189 ppDemandInfo (DemandedAsPer info) = hsep [text "{-#", text (showList [info] ""), text "#-}"]
192 %************************************************************************
194 \subsection[specialisation-IdInfo]{Specialisation info about an @Id@}
196 %************************************************************************
198 A @IdSpecEnv@ holds details of an @Id@'s specialisations.
201 type IdSpecEnv = SpecEnv SimplifiableCoreExpr
204 For example, if \tr{f}'s @SpecEnv@ contains the mapping:
206 [List a, b] ===> (\d -> f' a b)
208 then when we find an application of f to matching types, we simply replace
209 it by the matching RHS:
211 f (List Int) Bool ===> (\d -> f' Int Bool)
213 All the stuff about how many dictionaries to discard, and what types
214 to apply the specialised function to, are handled by the fact that the
215 SpecEnv contains a template for the result of the specialisation.
217 There is one more exciting case, which is dealt with in exactly the same
218 way. If the specialised value is unboxed then it is lifted at its
219 definition site and unlifted at its uses. For example:
221 pi :: forall a. Num a => a
223 might have a specialisation
225 [Int#] ===> (case pi' of Lift pi# -> pi#)
227 where pi' :: Lift Int# is the specialised version of pi.
231 specInfo :: IdInfo -> IdSpecEnv
232 specInfo (IdInfo _ _ spec _ _ _ _ _) = spec
234 setSpecInfo (IdInfo a b _ d e f g h) spec = IdInfo a b spec d e f g h
238 %************************************************************************
240 \subsection[strictness-IdInfo]{Strictness info about an @Id@}
242 %************************************************************************
244 We specify the strictness of a function by giving information about
245 each of the ``wrapper's'' arguments (see the description about
246 worker/wrapper-style transformations in the PJ/Launchbury paper on
249 The list of @Demands@ specifies: (a)~the strictness properties
250 of a function's arguments; (b)~the {\em existence} of a ``worker''
251 version of the function; and (c)~the type signature of that worker (if
252 it exists); i.e. its calling convention.
258 | BottomGuaranteed -- This Id guarantees never to return;
259 -- it is bottom regardless of its arguments.
260 -- Useful for "error" and other disguised
263 | StrictnessInfo [Demand]
264 Bool -- True <=> there is a worker. There might not be, even for a
265 -- strict function, because:
266 -- (a) the function might be small enough to inline,
267 -- so no need for w/w split
268 -- (b) the strictness info might be "SSS" or something, so no w/w split.
270 -- Worker's Id, if applicable, and a list of the constructors
271 -- mentioned by the wrapper. This is necessary so that the
272 -- renamer can slurp them in. Without this info, the renamer doesn't
273 -- know which data types to slurp in concretely. Remember, for
274 -- strict things we don't put the unfolding in the interface file, to save space.
275 -- This constructor list allows the renamer to behave much as if the
276 -- unfolding *was* in the interface file.
280 mkStrictnessInfo :: [Demand] -> Bool -> StrictnessInfo
282 mkStrictnessInfo xs has_wrkr
283 | all is_lazy xs = NoStrictnessInfo -- Uninteresting
284 | otherwise = StrictnessInfo xs has_wrkr
286 is_lazy (WwLazy False) = True -- NB "Absent" args do *not* count!
287 is_lazy _ = False -- (as they imply a worker)
289 noStrictnessInfo = NoStrictnessInfo
290 mkBottomStrictnessInfo = BottomGuaranteed
292 bottomIsGuaranteed BottomGuaranteed = True
293 bottomIsGuaranteed other = False
295 strictnessInfo (IdInfo _ _ _ strict _ _ _ _) = strict
297 addStrictnessInfo id_info NoStrictnessInfo = id_info
298 addStrictnessInfo (IdInfo a b d _ e f g h) strict = IdInfo a b d strict e f g h
300 ppStrictnessInfo NoStrictnessInfo = empty
301 ppStrictnessInfo BottomGuaranteed = ptext SLIT("_bot_")
303 ppStrictnessInfo (StrictnessInfo wrapper_args wrkr_maybe)
304 = hsep [ptext SLIT("_S_"), text (showList wrapper_args "")]
309 workerExists :: StrictnessInfo -> Bool
310 workerExists (StrictnessInfo _ worker_exists) = worker_exists
311 workerExists other = False
315 %************************************************************************
317 \subsection[unfolding-IdInfo]{Unfolding info about an @Id@}
319 %************************************************************************
322 unfoldInfo (IdInfo _ _ _ _ unfolding _ _ _) = unfolding
324 addUnfoldInfo (IdInfo a b d e _ f g h) uf = IdInfo a b d e uf f g h
327 %************************************************************************
329 \subsection[update-IdInfo]{Update-analysis info about an @Id@}
331 %************************************************************************
336 | SomeUpdateInfo UpdateSpec
338 -- we need Eq/Ord to cross-chk update infos in interfaces
340 -- the form in which we pass update-analysis info between modules:
341 type UpdateSpec = [Int]
345 mkUpdateInfo = SomeUpdateInfo
347 updateInfoMaybe NoUpdateInfo = Nothing
348 updateInfoMaybe (SomeUpdateInfo []) = Nothing
349 updateInfoMaybe (SomeUpdateInfo u) = Just u
352 Text instance so that the update annotations can be read in.
355 instance Read UpdateInfo where
356 readsPrec p s | null s = panic "IdInfo: empty update pragma?!"
357 | otherwise = [(SomeUpdateInfo (map ok_digit s),"")]
359 ok_digit c | c >= '0' && c <= '2' = ord c - ord '0'
360 | otherwise = panic "IdInfo: not a digit while reading update pragma"
362 updateInfo (IdInfo _ _ _ _ _ update _ _) = update
364 addUpdateInfo id_info NoUpdateInfo = id_info
365 addUpdateInfo (IdInfo a b d e f _ g h) upd_info = IdInfo a b d e f upd_info g h
367 ppUpdateInfo NoUpdateInfo = empty
368 ppUpdateInfo (SomeUpdateInfo []) = empty
369 ppUpdateInfo (SomeUpdateInfo spec) = (<>) (ptext SLIT("_U_ ")) (hcat (map int spec))
372 %************************************************************************
374 \subsection[argUsage-IdInfo]{Argument Usage info about an @Id@}
376 %************************************************************************
381 | SomeArgUsageInfo ArgUsageType
382 -- ??? deriving (Eq, Ord)
384 data ArgUsage = ArgUsage Int -- number of arguments (is linear!)
386 type ArgUsageType = [ArgUsage] -- c_1 -> ... -> BLOB
390 mkArgUsageInfo [] = NoArgUsageInfo
391 mkArgUsageInfo au = SomeArgUsageInfo au
393 getArgUsage :: ArgUsageInfo -> ArgUsageType
394 getArgUsage NoArgUsageInfo = []
395 getArgUsage (SomeArgUsageInfo u) = u
399 argUsageInfo (IdInfo _ _ _ _ _ _ au _) = au
401 addArgUsageInfo id_info NoArgUsageInfo = id_info
402 addArgUsageInfo (IdInfo a b d e f g _ h) au_info = IdInfo a b d e f g au_info h
405 ppArgUsageInfo NoArgUsageInfo = empty
406 ppArgUsageInfo (SomeArgUsageInfo aut) = (<>) (ptext SLIT("_L_ ")) (ppArgUsageType aut)
409 ppArgUsage (ArgUsage n) = int n
410 ppArgUsage (UnknownArgUsage) = char '-'
412 ppArgUsageType aut = hcat
414 hcat (punctuate comma (map ppArgUsage aut)),
418 %************************************************************************
420 \subsection[FBType-IdInfo]{Type of an expression through Foldr/build's eyes}
422 %************************************************************************
427 | SomeFBTypeInfo FBType
429 data FBType = FBType [FBConsum] FBProd deriving (Eq)
431 data FBConsum = FBGoodConsum | FBBadConsum deriving(Eq)
432 data FBProd = FBGoodProd | FBBadProd deriving(Eq)
436 mkFBTypeInfo = SomeFBTypeInfo
438 getFBType :: FBTypeInfo -> Maybe FBType
439 getFBType NoFBTypeInfo = Nothing
440 getFBType (SomeFBTypeInfo u) = Just u
444 fbTypeInfo (IdInfo _ _ _ _ _ _ _ fb) = fb
446 addFBTypeInfo id_info NoFBTypeInfo = id_info
447 addFBTypeInfo (IdInfo a b d e f g h _) fb_info = IdInfo a b d e f g h fb_info
449 ppFBTypeInfo NoFBTypeInfo = empty
450 ppFBTypeInfo (SomeFBTypeInfo (FBType cons prod))
451 = (<>) (ptext SLIT("_F_ ")) (ppFBType cons prod)
453 ppFBType cons prod = hcat
454 ([ char '"' ] ++ map ppCons cons ++ [ char '-', ppProd prod, char '"' ])
456 ppCons FBGoodConsum = char 'G'
457 ppCons FBBadConsum = char 'B'
458 ppProd FBGoodProd = char 'G'
459 ppProd FBBadProd = char 'B'