| 1 | |
|---|
| 2 | % (c) The GRASP/AQUA Project, Glasgow University, 1992-1998 |
|---|
| 3 | % |
|---|
| 4 | \section{Tidying up Core} |
|---|
| 5 | |
|---|
| 6 | \begin{code} |
|---|
| 7 | {-# OPTIONS -fno-warn-tabs #-} |
|---|
| 8 | -- The above warning supression flag is a temporary kludge. |
|---|
| 9 | -- While working on this module you are encouraged to remove it and |
|---|
| 10 | -- detab the module (please do the detabbing in a separate patch). See |
|---|
| 11 | -- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#TabsvsSpaces |
|---|
| 12 | -- for details |
|---|
| 13 | |
|---|
| 14 | module TidyPgm ( |
|---|
| 15 | mkBootModDetailsTc, tidyProgram, globaliseAndTidyId |
|---|
| 16 | ) where |
|---|
| 17 | |
|---|
| 18 | #include "HsVersions.h" |
|---|
| 19 | |
|---|
| 20 | import TcRnTypes |
|---|
| 21 | import DynFlags |
|---|
| 22 | import CoreSyn |
|---|
| 23 | import CoreUnfold |
|---|
| 24 | import CoreFVs |
|---|
| 25 | import CoreTidy |
|---|
| 26 | import CoreMonad |
|---|
| 27 | import CoreUtils |
|---|
| 28 | import Literal |
|---|
| 29 | import Rules |
|---|
| 30 | import CoreArity ( exprArity, exprBotStrictness_maybe ) |
|---|
| 31 | import VarEnv |
|---|
| 32 | import VarSet |
|---|
| 33 | import Var |
|---|
| 34 | import Id |
|---|
| 35 | import IdInfo |
|---|
| 36 | import InstEnv |
|---|
| 37 | import FamInstEnv |
|---|
| 38 | import Demand |
|---|
| 39 | import BasicTypes |
|---|
| 40 | import Name hiding (varName) |
|---|
| 41 | import NameSet |
|---|
| 42 | import NameEnv |
|---|
| 43 | import Avail |
|---|
| 44 | import IfaceEnv |
|---|
| 45 | import TcType |
|---|
| 46 | import DataCon |
|---|
| 47 | import TyCon |
|---|
| 48 | import Class |
|---|
| 49 | import Module |
|---|
| 50 | import Packages( isDllName ) |
|---|
| 51 | import HscTypes |
|---|
| 52 | import Maybes |
|---|
| 53 | import UniqSupply |
|---|
| 54 | import Outputable |
|---|
| 55 | import FastBool hiding ( fastOr ) |
|---|
| 56 | import Util |
|---|
| 57 | import FastString |
|---|
| 58 | |
|---|
| 59 | import Control.Monad ( when ) |
|---|
| 60 | import Data.List ( sortBy ) |
|---|
| 61 | import Data.IORef ( IORef, readIORef, writeIORef ) |
|---|
| 62 | \end{code} |
|---|
| 63 | |
|---|
| 64 | |
|---|
| 65 | Constructing the TypeEnv, Instances, Rules, VectInfo from which the |
|---|
| 66 | ModIface is constructed, and which goes on to subsequent modules in |
|---|
| 67 | --make mode. |
|---|
| 68 | |
|---|
| 69 | Most of the interface file is obtained simply by serialising the |
|---|
| 70 | TypeEnv. One important consequence is that if the *interface file* |
|---|
| 71 | has pragma info if and only if the final TypeEnv does. This is not so |
|---|
| 72 | important for *this* module, but it's essential for ghc --make: |
|---|
| 73 | subsequent compilations must not see (e.g.) the arity if the interface |
|---|
| 74 | file does not contain arity If they do, they'll exploit the arity; |
|---|
| 75 | then the arity might change, but the iface file doesn't change => |
|---|
| 76 | recompilation does not happen => disaster. |
|---|
| 77 | |
|---|
| 78 | For data types, the final TypeEnv will have a TyThing for the TyCon, |
|---|
| 79 | plus one for each DataCon; the interface file will contain just one |
|---|
| 80 | data type declaration, but it is de-serialised back into a collection |
|---|
| 81 | of TyThings. |
|---|
| 82 | |
|---|
| 83 | %************************************************************************ |
|---|
| 84 | %* * |
|---|
| 85 | Plan A: simpleTidyPgm |
|---|
| 86 | %* * |
|---|
| 87 | %************************************************************************ |
|---|
| 88 | |
|---|
| 89 | |
|---|
| 90 | Plan A: mkBootModDetails: omit pragmas, make interfaces small |
|---|
| 91 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 92 | * Ignore the bindings |
|---|
| 93 | |
|---|
| 94 | * Drop all WiredIn things from the TypeEnv |
|---|
| 95 | (we never want them in interface files) |
|---|
| 96 | |
|---|
| 97 | * Retain all TyCons and Classes in the TypeEnv, to avoid |
|---|
| 98 | having to find which ones are mentioned in the |
|---|
| 99 | types of exported Ids |
|---|
| 100 | |
|---|
| 101 | * Trim off the constructors of non-exported TyCons, both |
|---|
| 102 | from the TyCon and from the TypeEnv |
|---|
| 103 | |
|---|
| 104 | * Drop non-exported Ids from the TypeEnv |
|---|
| 105 | |
|---|
| 106 | * Tidy the types of the DFunIds of Instances, |
|---|
| 107 | make them into GlobalIds, (they already have External Names) |
|---|
| 108 | and add them to the TypeEnv |
|---|
| 109 | |
|---|
| 110 | * Tidy the types of the (exported) Ids in the TypeEnv, |
|---|
| 111 | make them into GlobalIds (they already have External Names) |
|---|
| 112 | |
|---|
| 113 | * Drop rules altogether |
|---|
| 114 | |
|---|
| 115 | * Tidy the bindings, to ensure that the Caf and Arity |
|---|
| 116 | information is correct for each top-level binder; the |
|---|
| 117 | code generator needs it. And to ensure that local names have |
|---|
| 118 | distinct OccNames in case of object-file splitting |
|---|
| 119 | |
|---|
| 120 | \begin{code} |
|---|
| 121 | -- This is Plan A: make a small type env when typechecking only, |
|---|
| 122 | -- or when compiling a hs-boot file, or simply when not using -O |
|---|
| 123 | -- |
|---|
| 124 | -- We don't look at the bindings at all -- there aren't any |
|---|
| 125 | -- for hs-boot files |
|---|
| 126 | |
|---|
| 127 | mkBootModDetailsTc :: HscEnv -> TcGblEnv -> IO ModDetails |
|---|
| 128 | mkBootModDetailsTc hsc_env |
|---|
| 129 | TcGblEnv{ tcg_exports = exports, |
|---|
| 130 | tcg_type_env = type_env, -- just for the Ids |
|---|
| 131 | tcg_tcs = tcs, |
|---|
| 132 | tcg_insts = insts, |
|---|
| 133 | tcg_fam_insts = fam_insts |
|---|
| 134 | } |
|---|
| 135 | = do { let dflags = hsc_dflags hsc_env |
|---|
| 136 | ; showPass dflags CoreTidy |
|---|
| 137 | |
|---|
| 138 | ; let { insts' = tidyInstances globaliseAndTidyId insts |
|---|
| 139 | ; dfun_ids = map instanceDFunId insts' |
|---|
| 140 | ; type_env1 = mkBootTypeEnv (availsToNameSet exports) |
|---|
| 141 | (typeEnvIds type_env) tcs fam_insts |
|---|
| 142 | ; type_env' = extendTypeEnvWithIds type_env1 dfun_ids |
|---|
| 143 | } |
|---|
| 144 | ; return (ModDetails { md_types = type_env' |
|---|
| 145 | , md_insts = insts' |
|---|
| 146 | , md_fam_insts = fam_insts |
|---|
| 147 | , md_rules = [] |
|---|
| 148 | , md_anns = [] |
|---|
| 149 | , md_exports = exports |
|---|
| 150 | , md_vect_info = noVectInfo |
|---|
| 151 | }) |
|---|
| 152 | } |
|---|
| 153 | where |
|---|
| 154 | |
|---|
| 155 | mkBootTypeEnv :: NameSet -> [Id] -> [TyCon] -> [FamInst] -> TypeEnv |
|---|
| 156 | mkBootTypeEnv exports ids tcs fam_insts |
|---|
| 157 | = tidyTypeEnv True False exports $ |
|---|
| 158 | typeEnvFromEntities final_ids tcs fam_insts |
|---|
| 159 | where |
|---|
| 160 | -- Find the LocalIds in the type env that are exported |
|---|
| 161 | -- Make them into GlobalIds, and tidy their types |
|---|
| 162 | -- |
|---|
| 163 | -- It's very important to remove the non-exported ones |
|---|
| 164 | -- because we don't tidy the OccNames, and if we don't remove |
|---|
| 165 | -- the non-exported ones we'll get many things with the |
|---|
| 166 | -- same name in the interface file, giving chaos. |
|---|
| 167 | -- |
|---|
| 168 | -- Do make sure that we keep Ids that are already Global. |
|---|
| 169 | -- When typechecking an .hs-boot file, the Ids come through as |
|---|
| 170 | -- GlobalIds. |
|---|
| 171 | final_ids = [ if isLocalId id then globaliseAndTidyId id |
|---|
| 172 | else id |
|---|
| 173 | | id <- ids |
|---|
| 174 | , keep_it id ] |
|---|
| 175 | |
|---|
| 176 | -- default methods have their export flag set, but everything |
|---|
| 177 | -- else doesn't (yet), because this is pre-desugaring, so we |
|---|
| 178 | -- must test both. |
|---|
| 179 | keep_it id = isExportedId id || idName id `elemNameSet` exports |
|---|
| 180 | |
|---|
| 181 | |
|---|
| 182 | |
|---|
| 183 | globaliseAndTidyId :: Id -> Id |
|---|
| 184 | -- Takes an LocalId with an External Name, |
|---|
| 185 | -- makes it into a GlobalId |
|---|
| 186 | -- * unchanged Name (might be Internal or External) |
|---|
| 187 | -- * unchanged details |
|---|
| 188 | -- * VanillaIdInfo (makes a conservative assumption about Caf-hood) |
|---|
| 189 | globaliseAndTidyId id |
|---|
| 190 | = Id.setIdType (globaliseId id) tidy_type |
|---|
| 191 | where |
|---|
| 192 | tidy_type = tidyTopType (idType id) |
|---|
| 193 | \end{code} |
|---|
| 194 | |
|---|
| 195 | |
|---|
| 196 | %************************************************************************ |
|---|
| 197 | %* * |
|---|
| 198 | Plan B: tidy bindings, make TypeEnv full of IdInfo |
|---|
| 199 | %* * |
|---|
| 200 | %************************************************************************ |
|---|
| 201 | |
|---|
| 202 | Plan B: include pragmas, make interfaces |
|---|
| 203 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 204 | * Figure out which Ids are externally visible |
|---|
| 205 | |
|---|
| 206 | * Tidy the bindings, externalising appropriate Ids |
|---|
| 207 | |
|---|
| 208 | * Drop all Ids from the TypeEnv, and add all the External Ids from |
|---|
| 209 | the bindings. (This adds their IdInfo to the TypeEnv; and adds |
|---|
| 210 | floated-out Ids that weren't even in the TypeEnv before.) |
|---|
| 211 | |
|---|
| 212 | Step 1: Figure out external Ids |
|---|
| 213 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 214 | Note [choosing external names] |
|---|
| 215 | |
|---|
| 216 | See also the section "Interface stability" in the |
|---|
| 217 | RecompilationAvoidance commentary: |
|---|
| 218 | http://hackage.haskell.org/trac/ghc/wiki/Commentary/Compiler/RecompilationAvoidance |
|---|
| 219 | |
|---|
| 220 | First we figure out which Ids are "external" Ids. An |
|---|
| 221 | "external" Id is one that is visible from outside the compilation |
|---|
| 222 | unit. These are |
|---|
| 223 | a) the user exported ones |
|---|
| 224 | b) ones mentioned in the unfoldings, workers, |
|---|
| 225 | rules of externally-visible ones , |
|---|
| 226 | or vectorised versions of externally-visible ones |
|---|
| 227 | |
|---|
| 228 | While figuring out which Ids are external, we pick a "tidy" OccName |
|---|
| 229 | for each one. That is, we make its OccName distinct from the other |
|---|
| 230 | external OccNames in this module, so that in interface files and |
|---|
| 231 | object code we can refer to it unambiguously by its OccName. The |
|---|
| 232 | OccName for each binder is prefixed by the name of the exported Id |
|---|
| 233 | that references it; e.g. if "f" references "x" in its unfolding, then |
|---|
| 234 | "x" is renamed to "f_x". This helps distinguish the different "x"s |
|---|
| 235 | from each other, and means that if "f" is later removed, things that |
|---|
| 236 | depend on the other "x"s will not need to be recompiled. Of course, |
|---|
| 237 | if there are multiple "f_x"s, then we have to disambiguate somehow; we |
|---|
| 238 | use "f_x0", "f_x1" etc. |
|---|
| 239 | |
|---|
| 240 | As far as possible we should assign names in a deterministic fashion. |
|---|
| 241 | Each time this module is compiled with the same options, we should end |
|---|
| 242 | up with the same set of external names with the same types. That is, |
|---|
| 243 | the ABI hash in the interface should not change. This turns out to be |
|---|
| 244 | quite tricky, since the order of the bindings going into the tidy |
|---|
| 245 | phase is already non-deterministic, as it is based on the ordering of |
|---|
| 246 | Uniques, which are assigned unpredictably. |
|---|
| 247 | |
|---|
| 248 | To name things in a stable way, we do a depth-first-search of the |
|---|
| 249 | bindings, starting from the exports sorted by name. This way, as long |
|---|
| 250 | as the bindings themselves are deterministic (they sometimes aren't!), |
|---|
| 251 | the order in which they are presented to the tidying phase does not |
|---|
| 252 | affect the names we assign. |
|---|
| 253 | |
|---|
| 254 | Step 2: Tidy the program |
|---|
| 255 | ~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 256 | Next we traverse the bindings top to bottom. For each *top-level* |
|---|
| 257 | binder |
|---|
| 258 | |
|---|
| 259 | 1. Make it into a GlobalId; its IdDetails becomes VanillaGlobal, |
|---|
| 260 | reflecting the fact that from now on we regard it as a global, |
|---|
| 261 | not local, Id |
|---|
| 262 | |
|---|
| 263 | 2. Give it a system-wide Unique. |
|---|
| 264 | [Even non-exported things need system-wide Uniques because the |
|---|
| 265 | byte-code generator builds a single Name->BCO symbol table.] |
|---|
| 266 | |
|---|
| 267 | We use the NameCache kept in the HscEnv as the |
|---|
| 268 | source of such system-wide uniques. |
|---|
| 269 | |
|---|
| 270 | For external Ids, use the original-name cache in the NameCache |
|---|
| 271 | to ensure that the unique assigned is the same as the Id had |
|---|
| 272 | in any previous compilation run. |
|---|
| 273 | |
|---|
| 274 | 3. Rename top-level Ids according to the names we chose in step 1. |
|---|
| 275 | If it's an external Id, make it have a External Name, otherwise |
|---|
| 276 | make it have an Internal Name. This is used by the code generator |
|---|
| 277 | to decide whether to make the label externally visible |
|---|
| 278 | |
|---|
| 279 | 4. Give it its UTTERLY FINAL IdInfo; in ptic, |
|---|
| 280 | * its unfolding, if it should have one |
|---|
| 281 | |
|---|
| 282 | * its arity, computed from the number of visible lambdas |
|---|
| 283 | |
|---|
| 284 | * its CAF info, computed from what is free in its RHS |
|---|
| 285 | |
|---|
| 286 | |
|---|
| 287 | Finally, substitute these new top-level binders consistently |
|---|
| 288 | throughout, including in unfoldings. We also tidy binders in |
|---|
| 289 | RHSs, so that they print nicely in interfaces. |
|---|
| 290 | |
|---|
| 291 | \begin{code} |
|---|
| 292 | tidyProgram :: HscEnv -> ModGuts -> IO (CgGuts, ModDetails) |
|---|
| 293 | tidyProgram hsc_env (ModGuts { mg_module = mod |
|---|
| 294 | , mg_exports = exports |
|---|
| 295 | , mg_tcs = tcs |
|---|
| 296 | , mg_insts = insts |
|---|
| 297 | , mg_fam_insts = fam_insts |
|---|
| 298 | , mg_binds = binds |
|---|
| 299 | , mg_rules = imp_rules |
|---|
| 300 | , mg_vect_info = vect_info |
|---|
| 301 | , mg_anns = anns |
|---|
| 302 | , mg_deps = deps |
|---|
| 303 | , mg_foreign = foreign_stubs |
|---|
| 304 | , mg_hpc_info = hpc_info |
|---|
| 305 | , mg_modBreaks = modBreaks |
|---|
| 306 | }) |
|---|
| 307 | |
|---|
| 308 | = do { let { dflags = hsc_dflags hsc_env |
|---|
| 309 | ; omit_prags = dopt Opt_OmitInterfacePragmas dflags |
|---|
| 310 | ; expose_all = dopt Opt_ExposeAllUnfoldings dflags |
|---|
| 311 | ; th = xopt Opt_TemplateHaskell dflags |
|---|
| 312 | ; data_kinds = xopt Opt_DataKinds dflags |
|---|
| 313 | ; no_trim_types = th || data_kinds |
|---|
| 314 | -- See Note [When we can't trim types] |
|---|
| 315 | } |
|---|
| 316 | ; showPass dflags CoreTidy |
|---|
| 317 | |
|---|
| 318 | ; let { type_env = typeEnvFromEntities [] tcs fam_insts |
|---|
| 319 | |
|---|
| 320 | ; implicit_binds |
|---|
| 321 | = concatMap getClassImplicitBinds (typeEnvClasses type_env) ++ |
|---|
| 322 | concatMap getTyConImplicitBinds (typeEnvTyCons type_env) |
|---|
| 323 | } |
|---|
| 324 | |
|---|
| 325 | ; (unfold_env, tidy_occ_env) |
|---|
| 326 | <- chooseExternalIds hsc_env mod omit_prags expose_all |
|---|
| 327 | binds implicit_binds imp_rules (vectInfoVar vect_info) |
|---|
| 328 | ; let { ext_rules = findExternalRules omit_prags binds imp_rules unfold_env } |
|---|
| 329 | -- Glom together imp_rules and rules currently attached to binders |
|---|
| 330 | -- Then pick just the ones we need to expose |
|---|
| 331 | -- See Note [Which rules to expose] |
|---|
| 332 | |
|---|
| 333 | ; let { (tidy_env, tidy_binds) |
|---|
| 334 | = tidyTopBinds hsc_env unfold_env tidy_occ_env binds } |
|---|
| 335 | |
|---|
| 336 | ; let { export_set = availsToNameSet exports |
|---|
| 337 | ; final_ids = [ id | id <- bindersOfBinds tidy_binds, |
|---|
| 338 | isExternalName (idName id)] |
|---|
| 339 | |
|---|
| 340 | ; tidy_type_env = tidyTypeEnv omit_prags no_trim_types export_set |
|---|
| 341 | (extendTypeEnvWithIds type_env final_ids) |
|---|
| 342 | |
|---|
| 343 | ; tidy_insts = tidyInstances (lookup_dfun tidy_type_env) insts |
|---|
| 344 | -- A DFunId will have a binding in tidy_binds, and so |
|---|
| 345 | -- will now be in final_env, replete with IdInfo |
|---|
| 346 | -- Its name will be unchanged since it was born, but |
|---|
| 347 | -- we want Global, IdInfo-rich (or not) DFunId in the |
|---|
| 348 | -- tidy_insts |
|---|
| 349 | |
|---|
| 350 | ; tidy_rules = tidyRules tidy_env ext_rules |
|---|
| 351 | -- You might worry that the tidy_env contains IdInfo-rich stuff |
|---|
| 352 | -- and indeed it does, but if omit_prags is on, ext_rules is |
|---|
| 353 | -- empty |
|---|
| 354 | |
|---|
| 355 | ; tidy_vect_info = tidyVectInfo tidy_env vect_info |
|---|
| 356 | |
|---|
| 357 | -- See Note [Injecting implicit bindings] |
|---|
| 358 | ; all_tidy_binds = implicit_binds ++ tidy_binds |
|---|
| 359 | |
|---|
| 360 | -- get the TyCons to generate code for. Careful! We must use |
|---|
| 361 | -- the untidied TypeEnv here, because we need |
|---|
| 362 | -- (a) implicit TyCons arising from types and classes defined |
|---|
| 363 | -- in this module |
|---|
| 364 | -- (b) wired-in TyCons, which are normally removed from the |
|---|
| 365 | -- TypeEnv we put in the ModDetails |
|---|
| 366 | -- (c) Constructors even if they are not exported (the |
|---|
| 367 | -- tidied TypeEnv has trimmed these away) |
|---|
| 368 | ; alg_tycons = filter isAlgTyCon (typeEnvTyCons type_env) |
|---|
| 369 | } |
|---|
| 370 | |
|---|
| 371 | ; endPass dflags CoreTidy all_tidy_binds tidy_rules |
|---|
| 372 | |
|---|
| 373 | -- If the endPass didn't print the rules, but ddump-rules is |
|---|
| 374 | -- on, print now |
|---|
| 375 | ; dumpIfSet (dopt Opt_D_dump_rules dflags |
|---|
| 376 | && (not (dopt Opt_D_dump_simpl dflags))) |
|---|
| 377 | CoreTidy |
|---|
| 378 | (ptext (sLit "rules")) |
|---|
| 379 | (pprRulesForUser tidy_rules) |
|---|
| 380 | |
|---|
| 381 | -- Print one-line size info |
|---|
| 382 | ; let cs = coreBindsStats tidy_binds |
|---|
| 383 | ; when (dopt Opt_D_dump_core_stats dflags) |
|---|
| 384 | (printDump (ptext (sLit "Tidy size (terms,types,coercions)") |
|---|
| 385 | <+> ppr (moduleName mod) <> colon |
|---|
| 386 | <+> int (cs_tm cs) |
|---|
| 387 | <+> int (cs_ty cs) |
|---|
| 388 | <+> int (cs_co cs) )) |
|---|
| 389 | |
|---|
| 390 | ; return (CgGuts { cg_module = mod, |
|---|
| 391 | cg_tycons = alg_tycons, |
|---|
| 392 | cg_binds = all_tidy_binds, |
|---|
| 393 | cg_foreign = foreign_stubs, |
|---|
| 394 | cg_dep_pkgs = map fst $ dep_pkgs deps, |
|---|
| 395 | cg_hpc_info = hpc_info, |
|---|
| 396 | cg_modBreaks = modBreaks }, |
|---|
| 397 | |
|---|
| 398 | ModDetails { md_types = tidy_type_env, |
|---|
| 399 | md_rules = tidy_rules, |
|---|
| 400 | md_insts = tidy_insts, |
|---|
| 401 | md_vect_info = tidy_vect_info, |
|---|
| 402 | md_fam_insts = fam_insts, |
|---|
| 403 | md_exports = exports, |
|---|
| 404 | md_anns = anns -- are already tidy |
|---|
| 405 | }) |
|---|
| 406 | } |
|---|
| 407 | |
|---|
| 408 | lookup_dfun :: TypeEnv -> Var -> Id |
|---|
| 409 | lookup_dfun type_env dfun_id |
|---|
| 410 | = case lookupTypeEnv type_env (idName dfun_id) of |
|---|
| 411 | Just (AnId dfun_id') -> dfun_id' |
|---|
| 412 | _other -> pprPanic "lookup_dfun" (ppr dfun_id) |
|---|
| 413 | |
|---|
| 414 | -------------------------- |
|---|
| 415 | tidyTypeEnv :: Bool -- Compiling without -O, so omit prags |
|---|
| 416 | -> Bool -- Type-trimming flag |
|---|
| 417 | -> NameSet -> TypeEnv -> TypeEnv |
|---|
| 418 | |
|---|
| 419 | -- The competed type environment is gotten from |
|---|
| 420 | -- a) the types and classes defined here (plus implicit things) |
|---|
| 421 | -- b) adding Ids with correct IdInfo, including unfoldings, |
|---|
| 422 | -- gotten from the bindings |
|---|
| 423 | -- From (b) we keep only those Ids with External names; |
|---|
| 424 | -- the CoreTidy pass makes sure these are all and only |
|---|
| 425 | -- the externally-accessible ones |
|---|
| 426 | -- This truncates the type environment to include only the |
|---|
| 427 | -- exported Ids and things needed from them, which saves space |
|---|
| 428 | |
|---|
| 429 | tidyTypeEnv omit_prags no_trim_types exports type_env |
|---|
| 430 | = let |
|---|
| 431 | type_env1 = filterNameEnv (not . isWiredInName . getName) type_env |
|---|
| 432 | -- (1) remove wired-in things |
|---|
| 433 | type_env2 | omit_prags = mapNameEnv (trimThing no_trim_types exports) type_env1 |
|---|
| 434 | | otherwise = type_env1 |
|---|
| 435 | -- (2) trimmed if necessary |
|---|
| 436 | in |
|---|
| 437 | type_env2 |
|---|
| 438 | |
|---|
| 439 | -------------------------- |
|---|
| 440 | trimThing :: Bool -> NameSet -> TyThing -> TyThing |
|---|
| 441 | -- Trim off inessentials, for boot files and no -O |
|---|
| 442 | trimThing no_trim_types exports (ATyCon tc) |
|---|
| 443 | | not (mustExposeTyCon no_trim_types exports tc) |
|---|
| 444 | = ATyCon (makeTyConAbstract tc) -- Note [When we can't trim types] |
|---|
| 445 | |
|---|
| 446 | trimThing _th _exports (AnId id) |
|---|
| 447 | | not (isImplicitId id) |
|---|
| 448 | = AnId (id `setIdInfo` vanillaIdInfo) |
|---|
| 449 | |
|---|
| 450 | trimThing _th _exports other_thing |
|---|
| 451 | = other_thing |
|---|
| 452 | |
|---|
| 453 | |
|---|
| 454 | {- Note [When we can't trim types] |
|---|
| 455 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 456 | The basic idea of type trimming is to export algebraic data types |
|---|
| 457 | abstractly (without their data constructors) when compiling without |
|---|
| 458 | -O, unless of course they are explicitly exported by the user. |
|---|
| 459 | |
|---|
| 460 | We always export synonyms, because they can be mentioned in the type |
|---|
| 461 | of an exported Id. We could do a full dependency analysis starting |
|---|
| 462 | from the explicit exports, but that's quite painful, and not done for |
|---|
| 463 | now. |
|---|
| 464 | |
|---|
| 465 | But there are some times we can't do that, indicated by the 'no_trim_types' flag. |
|---|
| 466 | |
|---|
| 467 | First, Template Haskell. Consider (Trac #2386) this |
|---|
| 468 | module M(T, makeOne) where |
|---|
| 469 | data T = Yay String |
|---|
| 470 | makeOne = [| Yay "Yep" |] |
|---|
| 471 | Notice that T is exported abstractly, but makeOne effectively exports it too! |
|---|
| 472 | A module that splices in $(makeOne) will then look for a declartion of Yay, |
|---|
| 473 | so it'd better be there. Hence, brutally but simply, we switch off type |
|---|
| 474 | constructor trimming if TH is enabled in this module. |
|---|
| 475 | |
|---|
| 476 | Second, data kinds. Consider (Trac #5912) |
|---|
| 477 | {-# LANGUAGE DataKinds #-} |
|---|
| 478 | module M() where |
|---|
| 479 | data UnaryTypeC a = UnaryDataC a |
|---|
| 480 | type Bug = 'UnaryDataC |
|---|
| 481 | We always export synonyms, so Bug is exposed, and that means that |
|---|
| 482 | UnaryTypeC must be too, even though it's not explicitly exported. In |
|---|
| 483 | effect, DataKinds means that we'd need to do a full dependency analysis |
|---|
| 484 | to see what data constructors are mentioned. But we don't do that yet. |
|---|
| 485 | |
|---|
| 486 | In these two cases we just switch off type trimming altogether. |
|---|
| 487 | -} |
|---|
| 488 | |
|---|
| 489 | mustExposeTyCon :: Bool -- Type-trimming flag |
|---|
| 490 | -> NameSet -- Exports |
|---|
| 491 | -> TyCon -- The tycon |
|---|
| 492 | -> Bool -- Can its rep be hidden? |
|---|
| 493 | -- We are compiling without -O, and thus trying to write as little as |
|---|
| 494 | -- possible into the interface file. But we must expose the details of |
|---|
| 495 | -- any data types whose constructors or fields are exported |
|---|
| 496 | mustExposeTyCon no_trim_types exports tc |
|---|
| 497 | | no_trim_types -- See Note [When we can't trim types] |
|---|
| 498 | = True |
|---|
| 499 | |
|---|
| 500 | | not (isAlgTyCon tc) -- Always expose synonyms (otherwise we'd have to |
|---|
| 501 | -- figure out whether it was mentioned in the type |
|---|
| 502 | -- of any other exported thing) |
|---|
| 503 | = True |
|---|
| 504 | |
|---|
| 505 | | isEnumerationTyCon tc -- For an enumeration, exposing the constructors |
|---|
| 506 | = True -- won't lead to the need for further exposure |
|---|
| 507 | |
|---|
| 508 | | isFamilyTyCon tc -- Open type family |
|---|
| 509 | = True |
|---|
| 510 | |
|---|
| 511 | -- Below here we just have data/newtype decls or family instances |
|---|
| 512 | |
|---|
| 513 | | null data_cons -- Ditto if there are no data constructors |
|---|
| 514 | = True -- (NB: empty data types do not count as enumerations |
|---|
| 515 | -- see Note [Enumeration types] in TyCon |
|---|
| 516 | |
|---|
| 517 | | any exported_con data_cons -- Expose rep if any datacon or field is exported |
|---|
| 518 | = True |
|---|
| 519 | |
|---|
| 520 | | isNewTyCon tc && isFFITy (snd (newTyConRhs tc)) |
|---|
| 521 | = True -- Expose the rep for newtypes if the rep is an FFI type. |
|---|
| 522 | -- For a very annoying reason. 'Foreign import' is meant to |
|---|
| 523 | -- be able to look through newtypes transparently, but it |
|---|
| 524 | -- can only do that if it can "see" the newtype representation |
|---|
| 525 | |
|---|
| 526 | | otherwise |
|---|
| 527 | = False |
|---|
| 528 | where |
|---|
| 529 | data_cons = tyConDataCons tc |
|---|
| 530 | exported_con con = any (`elemNameSet` exports) |
|---|
| 531 | (dataConName con : dataConFieldLabels con) |
|---|
| 532 | |
|---|
| 533 | tidyInstances :: (DFunId -> DFunId) -> [ClsInst] -> [ClsInst] |
|---|
| 534 | tidyInstances tidy_dfun ispecs |
|---|
| 535 | = map tidy ispecs |
|---|
| 536 | where |
|---|
| 537 | tidy ispec = setInstanceDFunId ispec $ |
|---|
| 538 | tidy_dfun (instanceDFunId ispec) |
|---|
| 539 | \end{code} |
|---|
| 540 | |
|---|
| 541 | \begin{code} |
|---|
| 542 | tidyVectInfo :: TidyEnv -> VectInfo -> VectInfo |
|---|
| 543 | tidyVectInfo (_, var_env) info@(VectInfo { vectInfoVar = vars |
|---|
| 544 | , vectInfoScalarVars = scalarVars |
|---|
| 545 | }) |
|---|
| 546 | = info { vectInfoVar = tidy_vars |
|---|
| 547 | , vectInfoScalarVars = tidy_scalarVars |
|---|
| 548 | } |
|---|
| 549 | where |
|---|
| 550 | -- we only export mappings whose domain and co-domain is exported (otherwise, the iface is |
|---|
| 551 | -- inconsistent) |
|---|
| 552 | tidy_vars = mkVarEnv [ (tidy_var, (tidy_var, tidy_var_v)) |
|---|
| 553 | | (var, var_v) <- varEnvElts vars |
|---|
| 554 | , let tidy_var = lookup_var var |
|---|
| 555 | tidy_var_v = lookup_var var_v |
|---|
| 556 | , isExportedId tidy_var |
|---|
| 557 | , isExportedId tidy_var_v |
|---|
| 558 | , isDataConWorkId var || not (isImplicitId var) |
|---|
| 559 | ] |
|---|
| 560 | |
|---|
| 561 | tidy_scalarVars = mkVarSet [ lookup_var var |
|---|
| 562 | | var <- varSetElems scalarVars |
|---|
| 563 | , isGlobalId var || isExportedId var] |
|---|
| 564 | |
|---|
| 565 | lookup_var var = lookupWithDefaultVarEnv var_env var var |
|---|
| 566 | \end{code} |
|---|
| 567 | |
|---|
| 568 | |
|---|
| 569 | %************************************************************************ |
|---|
| 570 | %* * |
|---|
| 571 | Implicit bindings |
|---|
| 572 | %* * |
|---|
| 573 | %************************************************************************ |
|---|
| 574 | |
|---|
| 575 | Note [Injecting implicit bindings] |
|---|
| 576 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 577 | We inject the implict bindings right at the end, in CoreTidy. |
|---|
| 578 | Some of these bindings, notably record selectors, are not |
|---|
| 579 | constructed in an optimised form. E.g. record selector for |
|---|
| 580 | data T = MkT { x :: {-# UNPACK #-} !Int } |
|---|
| 581 | Then the unfolding looks like |
|---|
| 582 | x = \t. case t of MkT x1 -> let x = I# x1 in x |
|---|
| 583 | This generates bad code unless it's first simplified a bit. That is |
|---|
| 584 | why CoreUnfold.mkImplicitUnfolding uses simleExprOpt to do a bit of |
|---|
| 585 | optimisation first. (Only matters when the selector is used curried; |
|---|
| 586 | eg map x ys.) See Trac #2070. |
|---|
| 587 | |
|---|
| 588 | [Oct 09: in fact, record selectors are no longer implicit Ids at all, |
|---|
| 589 | because we really do want to optimise them properly. They are treated |
|---|
| 590 | much like any other Id. But doing "light" optimisation on an implicit |
|---|
| 591 | Id still makes sense.] |
|---|
| 592 | |
|---|
| 593 | At one time I tried injecting the implicit bindings *early*, at the |
|---|
| 594 | beginning of SimplCore. But that gave rise to real difficulty, |
|---|
| 595 | becuase GlobalIds are supposed to have *fixed* IdInfo, but the |
|---|
| 596 | simplifier and other core-to-core passes mess with IdInfo all the |
|---|
| 597 | time. The straw that broke the camels back was when a class selector |
|---|
| 598 | got the wrong arity -- ie the simplifier gave it arity 2, whereas |
|---|
| 599 | importing modules were expecting it to have arity 1 (Trac #2844). |
|---|
| 600 | It's much safer just to inject them right at the end, after tidying. |
|---|
| 601 | |
|---|
| 602 | Oh: two other reasons for injecting them late: |
|---|
| 603 | |
|---|
| 604 | - If implicit Ids are already in the bindings when we start TidyPgm, |
|---|
| 605 | we'd have to be careful not to treat them as external Ids (in |
|---|
| 606 | the sense of findExternalIds); else the Ids mentioned in *their* |
|---|
| 607 | RHSs will be treated as external and you get an interface file |
|---|
| 608 | saying a18 = <blah> |
|---|
| 609 | but nothing refererring to a18 (because the implicit Id is the |
|---|
| 610 | one that does, and implicit Ids don't appear in interface files). |
|---|
| 611 | |
|---|
| 612 | - More seriously, the tidied type-envt will include the implicit |
|---|
| 613 | Id replete with a18 in its unfolding; but we won't take account |
|---|
| 614 | of a18 when computing a fingerprint for the class; result chaos. |
|---|
| 615 | |
|---|
| 616 | There is one sort of implicit binding that is injected still later, |
|---|
| 617 | namely those for data constructor workers. Reason (I think): it's |
|---|
| 618 | really just a code generation trick.... binding itself makes no sense. |
|---|
| 619 | See CorePrep Note [Data constructor workers]. |
|---|
| 620 | |
|---|
| 621 | \begin{code} |
|---|
| 622 | getTyConImplicitBinds :: TyCon -> [CoreBind] |
|---|
| 623 | getTyConImplicitBinds tc = map get_defn (mapCatMaybes dataConWrapId_maybe (tyConDataCons tc)) |
|---|
| 624 | |
|---|
| 625 | getClassImplicitBinds :: Class -> [CoreBind] |
|---|
| 626 | getClassImplicitBinds cls = map get_defn (classAllSelIds cls) |
|---|
| 627 | |
|---|
| 628 | get_defn :: Id -> CoreBind |
|---|
| 629 | get_defn id = NonRec id (unfoldingTemplate (realIdUnfolding id)) |
|---|
| 630 | \end{code} |
|---|
| 631 | |
|---|
| 632 | |
|---|
| 633 | %************************************************************************ |
|---|
| 634 | %* * |
|---|
| 635 | \subsection{Step 1: finding externals} |
|---|
| 636 | %* * |
|---|
| 637 | %************************************************************************ |
|---|
| 638 | |
|---|
| 639 | See Note [Choosing external names]. |
|---|
| 640 | |
|---|
| 641 | \begin{code} |
|---|
| 642 | type UnfoldEnv = IdEnv (Name{-new name-}, Bool {-show unfolding-}) |
|---|
| 643 | -- Maps each top-level Id to its new Name (the Id is tidied in step 2) |
|---|
| 644 | -- The Unique is unchanged. If the new Name is external, it will be |
|---|
| 645 | -- visible in the interface file. |
|---|
| 646 | -- |
|---|
| 647 | -- Bool => expose unfolding or not. |
|---|
| 648 | |
|---|
| 649 | chooseExternalIds :: HscEnv |
|---|
| 650 | -> Module |
|---|
| 651 | -> Bool -> Bool |
|---|
| 652 | -> [CoreBind] |
|---|
| 653 | -> [CoreBind] |
|---|
| 654 | -> [CoreRule] |
|---|
| 655 | -> VarEnv (Var, Var) |
|---|
| 656 | -> IO (UnfoldEnv, TidyOccEnv) |
|---|
| 657 | -- Step 1 from the notes above |
|---|
| 658 | |
|---|
| 659 | chooseExternalIds hsc_env mod omit_prags expose_all binds implicit_binds imp_id_rules vect_vars |
|---|
| 660 | = do { (unfold_env1,occ_env1) <- search init_work_list emptyVarEnv init_occ_env |
|---|
| 661 | ; let internal_ids = filter (not . (`elemVarEnv` unfold_env1)) binders |
|---|
| 662 | ; tidy_internal internal_ids unfold_env1 occ_env1 } |
|---|
| 663 | where |
|---|
| 664 | nc_var = hsc_NC hsc_env |
|---|
| 665 | |
|---|
| 666 | -- init_ext_ids is the intial list of Ids that should be |
|---|
| 667 | -- externalised. It serves as the starting point for finding a |
|---|
| 668 | -- deterministic, tidy, renaming for all external Ids in this |
|---|
| 669 | -- module. |
|---|
| 670 | -- |
|---|
| 671 | -- It is sorted, so that it has adeterministic order (i.e. it's the |
|---|
| 672 | -- same list every time this module is compiled), in contrast to the |
|---|
| 673 | -- bindings, which are ordered non-deterministically. |
|---|
| 674 | init_work_list = zip init_ext_ids init_ext_ids |
|---|
| 675 | init_ext_ids = sortBy (compare `on` getOccName) $ |
|---|
| 676 | filter is_external binders |
|---|
| 677 | |
|---|
| 678 | -- An Id should be external if either (a) it is exported, |
|---|
| 679 | -- (b) it appears in the RHS of a local rule for an imported Id, or |
|---|
| 680 | -- (c) it is the vectorised version of an imported Id |
|---|
| 681 | -- See Note [Which rules to expose] |
|---|
| 682 | is_external id = isExportedId id || id `elemVarSet` rule_rhs_vars || id `elemVarSet` vect_var_vs |
|---|
| 683 | rule_rhs_vars = foldr (unionVarSet . ruleRhsFreeVars) emptyVarSet imp_id_rules |
|---|
| 684 | vect_var_vs = mkVarSet [var_v | (var, var_v) <- nameEnvElts vect_vars, isGlobalId var] |
|---|
| 685 | |
|---|
| 686 | binders = bindersOfBinds binds |
|---|
| 687 | implicit_binders = bindersOfBinds implicit_binds |
|---|
| 688 | binder_set = mkVarSet binders |
|---|
| 689 | |
|---|
| 690 | avoids = [getOccName name | bndr <- binders ++ implicit_binders, |
|---|
| 691 | let name = idName bndr, |
|---|
| 692 | isExternalName name ] |
|---|
| 693 | -- In computing our "avoids" list, we must include |
|---|
| 694 | -- all implicit Ids |
|---|
| 695 | -- all things with global names (assigned once and for |
|---|
| 696 | -- all by the renamer) |
|---|
| 697 | -- since their names are "taken". |
|---|
| 698 | -- The type environment is a convenient source of such things. |
|---|
| 699 | -- In particular, the set of binders doesn't include |
|---|
| 700 | -- implicit Ids at this stage. |
|---|
| 701 | |
|---|
| 702 | -- We also make sure to avoid any exported binders. Consider |
|---|
| 703 | -- f{-u1-} = 1 -- Local decl |
|---|
| 704 | -- ... |
|---|
| 705 | -- f{-u2-} = 2 -- Exported decl |
|---|
| 706 | -- |
|---|
| 707 | -- The second exported decl must 'get' the name 'f', so we |
|---|
| 708 | -- have to put 'f' in the avoids list before we get to the first |
|---|
| 709 | -- decl. tidyTopId then does a no-op on exported binders. |
|---|
| 710 | init_occ_env = initTidyOccEnv avoids |
|---|
| 711 | |
|---|
| 712 | |
|---|
| 713 | search :: [(Id,Id)] -- The work-list: (external id, referrring id) |
|---|
| 714 | -- Make a tidy, external Name for the external id, |
|---|
| 715 | -- add it to the UnfoldEnv, and do the same for the |
|---|
| 716 | -- transitive closure of Ids it refers to |
|---|
| 717 | -- The referring id is used to generate a tidy |
|---|
| 718 | --- name for the external id |
|---|
| 719 | -> UnfoldEnv -- id -> (new Name, show_unfold) |
|---|
| 720 | -> TidyOccEnv -- occ env for choosing new Names |
|---|
| 721 | -> IO (UnfoldEnv, TidyOccEnv) |
|---|
| 722 | |
|---|
| 723 | search [] unfold_env occ_env = return (unfold_env, occ_env) |
|---|
| 724 | |
|---|
| 725 | search ((idocc,referrer) : rest) unfold_env occ_env |
|---|
| 726 | | idocc `elemVarEnv` unfold_env = search rest unfold_env occ_env |
|---|
| 727 | | otherwise = do |
|---|
| 728 | (occ_env', name') <- tidyTopName mod nc_var (Just referrer) occ_env idocc |
|---|
| 729 | let |
|---|
| 730 | (new_ids, show_unfold) |
|---|
| 731 | | omit_prags = ([], False) |
|---|
| 732 | | otherwise = addExternal expose_all refined_id |
|---|
| 733 | |
|---|
| 734 | -- 'idocc' is an *occurrence*, but we need to see the |
|---|
| 735 | -- unfolding in the *definition*; so look up in binder_set |
|---|
| 736 | refined_id = case lookupVarSet binder_set idocc of |
|---|
| 737 | Just id -> id |
|---|
| 738 | Nothing -> WARN( True, ppr idocc ) idocc |
|---|
| 739 | |
|---|
| 740 | unfold_env' = extendVarEnv unfold_env idocc (name',show_unfold) |
|---|
| 741 | referrer' | isExportedId refined_id = refined_id |
|---|
| 742 | | otherwise = referrer |
|---|
| 743 | -- |
|---|
| 744 | search (zip new_ids (repeat referrer') ++ rest) unfold_env' occ_env' |
|---|
| 745 | |
|---|
| 746 | tidy_internal :: [Id] -> UnfoldEnv -> TidyOccEnv |
|---|
| 747 | -> IO (UnfoldEnv, TidyOccEnv) |
|---|
| 748 | tidy_internal [] unfold_env occ_env = return (unfold_env,occ_env) |
|---|
| 749 | tidy_internal (id:ids) unfold_env occ_env = do |
|---|
| 750 | (occ_env', name') <- tidyTopName mod nc_var Nothing occ_env id |
|---|
| 751 | let unfold_env' = extendVarEnv unfold_env id (name',False) |
|---|
| 752 | tidy_internal ids unfold_env' occ_env' |
|---|
| 753 | |
|---|
| 754 | addExternal :: Bool -> Id -> ([Id], Bool) |
|---|
| 755 | addExternal expose_all id = (new_needed_ids, show_unfold) |
|---|
| 756 | where |
|---|
| 757 | new_needed_ids = bndrFvsInOrder show_unfold id |
|---|
| 758 | idinfo = idInfo id |
|---|
| 759 | show_unfold = show_unfolding (unfoldingInfo idinfo) |
|---|
| 760 | never_active = isNeverActive (inlinePragmaActivation (inlinePragInfo idinfo)) |
|---|
| 761 | loop_breaker = isStrongLoopBreaker (occInfo idinfo) |
|---|
| 762 | bottoming_fn = isBottomingSig (strictnessInfo idinfo `orElse` topSig) |
|---|
| 763 | |
|---|
| 764 | -- Stuff to do with the Id's unfolding |
|---|
| 765 | -- We leave the unfolding there even if there is a worker |
|---|
| 766 | -- In GHCi the unfolding is used by importers |
|---|
| 767 | |
|---|
| 768 | show_unfolding (CoreUnfolding { uf_src = src, uf_guidance = guidance }) |
|---|
| 769 | = expose_all -- 'expose_all' says to expose all |
|---|
| 770 | -- unfoldings willy-nilly |
|---|
| 771 | |
|---|
| 772 | || isStableSource src -- Always expose things whose |
|---|
| 773 | -- source is an inline rule |
|---|
| 774 | |
|---|
| 775 | || not (bottoming_fn -- No need to inline bottom functions |
|---|
| 776 | || never_active -- Or ones that say not to |
|---|
| 777 | || loop_breaker -- Or that are loop breakers |
|---|
| 778 | || neverUnfoldGuidance guidance) |
|---|
| 779 | show_unfolding (DFunUnfolding {}) = True |
|---|
| 780 | show_unfolding _ = False |
|---|
| 781 | \end{code} |
|---|
| 782 | |
|---|
| 783 | %************************************************************************ |
|---|
| 784 | %* * |
|---|
| 785 | Deterministic free variables |
|---|
| 786 | %* * |
|---|
| 787 | %************************************************************************ |
|---|
| 788 | |
|---|
| 789 | We want a deterministic free-variable list. exprFreeVars gives us |
|---|
| 790 | a VarSet, which is in a non-deterministic order when converted to a |
|---|
| 791 | list. Hence, here we define a free-variable finder that returns |
|---|
| 792 | the free variables in the order that they are encountered. |
|---|
| 793 | |
|---|
| 794 | See Note [Choosing external names] |
|---|
| 795 | |
|---|
| 796 | \begin{code} |
|---|
| 797 | bndrFvsInOrder :: Bool -> Id -> [Id] |
|---|
| 798 | bndrFvsInOrder show_unfold id |
|---|
| 799 | = run (dffvLetBndr show_unfold id) |
|---|
| 800 | |
|---|
| 801 | run :: DFFV () -> [Id] |
|---|
| 802 | run (DFFV m) = case m emptyVarSet (emptyVarSet, []) of |
|---|
| 803 | ((_,ids),_) -> ids |
|---|
| 804 | |
|---|
| 805 | newtype DFFV a |
|---|
| 806 | = DFFV (VarSet -- Envt: non-top-level things that are in scope |
|---|
| 807 | -- we don't want to record these as free vars |
|---|
| 808 | -> (VarSet, [Var]) -- Input State: (set, list) of free vars so far |
|---|
| 809 | -> ((VarSet,[Var]),a)) -- Output state |
|---|
| 810 | |
|---|
| 811 | instance Monad DFFV where |
|---|
| 812 | return a = DFFV $ \_ st -> (st, a) |
|---|
| 813 | (DFFV m) >>= k = DFFV $ \env st -> |
|---|
| 814 | case m env st of |
|---|
| 815 | (st',a) -> case k a of |
|---|
| 816 | DFFV f -> f env st' |
|---|
| 817 | |
|---|
| 818 | extendScope :: Var -> DFFV a -> DFFV a |
|---|
| 819 | extendScope v (DFFV f) = DFFV (\env st -> f (extendVarSet env v) st) |
|---|
| 820 | |
|---|
| 821 | extendScopeList :: [Var] -> DFFV a -> DFFV a |
|---|
| 822 | extendScopeList vs (DFFV f) = DFFV (\env st -> f (extendVarSetList env vs) st) |
|---|
| 823 | |
|---|
| 824 | insert :: Var -> DFFV () |
|---|
| 825 | insert v = DFFV $ \ env (set, ids) -> |
|---|
| 826 | let keep_me = isLocalId v && |
|---|
| 827 | not (v `elemVarSet` env) && |
|---|
| 828 | not (v `elemVarSet` set) |
|---|
| 829 | in if keep_me |
|---|
| 830 | then ((extendVarSet set v, v:ids), ()) |
|---|
| 831 | else ((set, ids), ()) |
|---|
| 832 | |
|---|
| 833 | |
|---|
| 834 | dffvExpr :: CoreExpr -> DFFV () |
|---|
| 835 | dffvExpr (Var v) = insert v |
|---|
| 836 | dffvExpr (App e1 e2) = dffvExpr e1 >> dffvExpr e2 |
|---|
| 837 | dffvExpr (Lam v e) = extendScope v (dffvExpr e) |
|---|
| 838 | dffvExpr (Tick (Breakpoint _ ids) e) = mapM_ insert ids >> dffvExpr e |
|---|
| 839 | dffvExpr (Tick _other e) = dffvExpr e |
|---|
| 840 | dffvExpr (Cast e _) = dffvExpr e |
|---|
| 841 | dffvExpr (Let (NonRec x r) e) = dffvBind (x,r) >> extendScope x (dffvExpr e) |
|---|
| 842 | dffvExpr (Let (Rec prs) e) = extendScopeList (map fst prs) $ |
|---|
| 843 | (mapM_ dffvBind prs >> dffvExpr e) |
|---|
| 844 | dffvExpr (Case e b _ as) = dffvExpr e >> extendScope b (mapM_ dffvAlt as) |
|---|
| 845 | dffvExpr _other = return () |
|---|
| 846 | |
|---|
| 847 | dffvAlt :: (t, [Var], CoreExpr) -> DFFV () |
|---|
| 848 | dffvAlt (_,xs,r) = extendScopeList xs (dffvExpr r) |
|---|
| 849 | |
|---|
| 850 | dffvBind :: (Id, CoreExpr) -> DFFV () |
|---|
| 851 | dffvBind(x,r) |
|---|
| 852 | | not (isId x) = dffvExpr r |
|---|
| 853 | | otherwise = dffvLetBndr False x >> dffvExpr r |
|---|
| 854 | -- Pass False because we are doing the RHS right here |
|---|
| 855 | -- If you say True you'll get *exponential* behaviour! |
|---|
| 856 | |
|---|
| 857 | dffvLetBndr :: Bool -> Id -> DFFV () |
|---|
| 858 | -- Gather the free vars of the RULES and unfolding of a binder |
|---|
| 859 | -- We always get the free vars of a *stable* unfolding, but |
|---|
| 860 | -- for a *vanilla* one (InlineRhs), the flag controls what happens: |
|---|
| 861 | -- True <=> get fvs of even a *vanilla* unfolding |
|---|
| 862 | -- False <=> ignore an InlineRhs |
|---|
| 863 | -- For nested bindings (call from dffvBind) we always say "False" because |
|---|
| 864 | -- we are taking the fvs of the RHS anyway |
|---|
| 865 | -- For top-level bindings (call from addExternal, via bndrFvsInOrder) |
|---|
| 866 | -- we say "True" if we are exposing that unfolding |
|---|
| 867 | dffvLetBndr vanilla_unfold id |
|---|
| 868 | = do { go_unf (unfoldingInfo idinfo) |
|---|
| 869 | ; mapM_ go_rule (specInfoRules (specInfo idinfo)) } |
|---|
| 870 | where |
|---|
| 871 | idinfo = idInfo id |
|---|
| 872 | |
|---|
| 873 | go_unf (CoreUnfolding { uf_tmpl = rhs, uf_src = src }) |
|---|
| 874 | = case src of |
|---|
| 875 | InlineRhs | vanilla_unfold -> dffvExpr rhs |
|---|
| 876 | | otherwise -> return () |
|---|
| 877 | InlineWrapper v -> insert v |
|---|
| 878 | _ -> dffvExpr rhs |
|---|
| 879 | -- For a wrapper, externalise the wrapper id rather than the |
|---|
| 880 | -- fvs of the rhs. The two usually come down to the same thing |
|---|
| 881 | -- but I've seen cases where we had a wrapper id $w but a |
|---|
| 882 | -- rhs where $w had been inlined; see Trac #3922 |
|---|
| 883 | |
|---|
| 884 | go_unf (DFunUnfolding _ _ args) = mapM_ dffvExpr args |
|---|
| 885 | go_unf _ = return () |
|---|
| 886 | |
|---|
| 887 | go_rule (BuiltinRule {}) = return () |
|---|
| 888 | go_rule (Rule { ru_bndrs = bndrs, ru_rhs = rhs }) |
|---|
| 889 | = extendScopeList bndrs (dffvExpr rhs) |
|---|
| 890 | \end{code} |
|---|
| 891 | |
|---|
| 892 | |
|---|
| 893 | %************************************************************************ |
|---|
| 894 | %* * |
|---|
| 895 | tidyTopName |
|---|
| 896 | %* * |
|---|
| 897 | %************************************************************************ |
|---|
| 898 | |
|---|
| 899 | This is where we set names to local/global based on whether they really are |
|---|
| 900 | externally visible (see comment at the top of this module). If the name |
|---|
| 901 | was previously local, we have to give it a unique occurrence name if |
|---|
| 902 | we intend to externalise it. |
|---|
| 903 | |
|---|
| 904 | \begin{code} |
|---|
| 905 | tidyTopName :: Module -> IORef NameCache -> Maybe Id -> TidyOccEnv |
|---|
| 906 | -> Id -> IO (TidyOccEnv, Name) |
|---|
| 907 | tidyTopName mod nc_var maybe_ref occ_env id |
|---|
| 908 | | global && internal = return (occ_env, localiseName name) |
|---|
| 909 | |
|---|
| 910 | | global && external = return (occ_env, name) |
|---|
| 911 | -- Global names are assumed to have been allocated by the renamer, |
|---|
| 912 | -- so they already have the "right" unique |
|---|
| 913 | -- And it's a system-wide unique too |
|---|
| 914 | |
|---|
| 915 | -- Now we get to the real reason that all this is in the IO Monad: |
|---|
| 916 | -- we have to update the name cache in a nice atomic fashion |
|---|
| 917 | |
|---|
| 918 | | local && internal = do { nc <- readIORef nc_var |
|---|
| 919 | ; let (nc', new_local_name) = mk_new_local nc |
|---|
| 920 | ; writeIORef nc_var nc' |
|---|
| 921 | ; return (occ_env', new_local_name) } |
|---|
| 922 | -- Even local, internal names must get a unique occurrence, because |
|---|
| 923 | -- if we do -split-objs we externalise the name later, in the code generator |
|---|
| 924 | -- |
|---|
| 925 | -- Similarly, we must make sure it has a system-wide Unique, because |
|---|
| 926 | -- the byte-code generator builds a system-wide Name->BCO symbol table |
|---|
| 927 | |
|---|
| 928 | | local && external = do { nc <- readIORef nc_var |
|---|
| 929 | ; let (nc', new_external_name) = mk_new_external nc |
|---|
| 930 | ; writeIORef nc_var nc' |
|---|
| 931 | ; return (occ_env', new_external_name) } |
|---|
| 932 | |
|---|
| 933 | | otherwise = panic "tidyTopName" |
|---|
| 934 | where |
|---|
| 935 | name = idName id |
|---|
| 936 | external = isJust maybe_ref |
|---|
| 937 | global = isExternalName name |
|---|
| 938 | local = not global |
|---|
| 939 | internal = not external |
|---|
| 940 | loc = nameSrcSpan name |
|---|
| 941 | |
|---|
| 942 | old_occ = nameOccName name |
|---|
| 943 | new_occ |
|---|
| 944 | | Just ref <- maybe_ref, ref /= id = |
|---|
| 945 | mkOccName (occNameSpace old_occ) $ |
|---|
| 946 | let |
|---|
| 947 | ref_str = occNameString (getOccName ref) |
|---|
| 948 | occ_str = occNameString old_occ |
|---|
| 949 | in |
|---|
| 950 | case occ_str of |
|---|
| 951 | '$':'w':_ -> occ_str |
|---|
| 952 | -- workers: the worker for a function already |
|---|
| 953 | -- includes the occname for its parent, so there's |
|---|
| 954 | -- no need to prepend the referrer. |
|---|
| 955 | _other | isSystemName name -> ref_str |
|---|
| 956 | | otherwise -> ref_str ++ '_' : occ_str |
|---|
| 957 | -- If this name was system-generated, then don't bother |
|---|
| 958 | -- to retain its OccName, just use the referrer. These |
|---|
| 959 | -- system-generated names will become "f1", "f2", etc. for |
|---|
| 960 | -- a referrer "f". |
|---|
| 961 | | otherwise = old_occ |
|---|
| 962 | |
|---|
| 963 | (occ_env', occ') = tidyOccName occ_env new_occ |
|---|
| 964 | |
|---|
| 965 | mk_new_local nc = (nc { nsUniqs = us }, mkInternalName uniq occ' loc) |
|---|
| 966 | where |
|---|
| 967 | (uniq, us) = takeUniqFromSupply (nsUniqs nc) |
|---|
| 968 | |
|---|
| 969 | mk_new_external nc = allocateGlobalBinder nc mod occ' loc |
|---|
| 970 | -- If we want to externalise a currently-local name, check |
|---|
| 971 | -- whether we have already assigned a unique for it. |
|---|
| 972 | -- If so, use it; if not, extend the table. |
|---|
| 973 | -- All this is done by allcoateGlobalBinder. |
|---|
| 974 | -- This is needed when *re*-compiling a module in GHCi; we must |
|---|
| 975 | -- use the same name for externally-visible things as we did before. |
|---|
| 976 | \end{code} |
|---|
| 977 | |
|---|
| 978 | \begin{code} |
|---|
| 979 | findExternalRules :: Bool -- Omit pragmas |
|---|
| 980 | -> [CoreBind] |
|---|
| 981 | -> [CoreRule] -- Local rules for imported fns |
|---|
| 982 | -> UnfoldEnv -- Ids that are exported, so we need their rules |
|---|
| 983 | -> [CoreRule] |
|---|
| 984 | -- The complete rules are gotten by combining |
|---|
| 985 | -- a) local rules for imported Ids |
|---|
| 986 | -- b) rules embedded in the top-level Ids |
|---|
| 987 | findExternalRules omit_prags binds imp_id_rules unfold_env |
|---|
| 988 | | omit_prags = [] |
|---|
| 989 | | otherwise = filterOut internal_rule (imp_id_rules ++ local_rules) |
|---|
| 990 | where |
|---|
| 991 | local_rules = [ rule |
|---|
| 992 | | id <- bindersOfBinds binds, |
|---|
| 993 | external_id id, |
|---|
| 994 | rule <- idCoreRules id |
|---|
| 995 | ] |
|---|
| 996 | |
|---|
| 997 | internal_rule rule |
|---|
| 998 | = any (not . external_id) (varSetElems (ruleLhsFreeIds rule)) |
|---|
| 999 | -- Don't export a rule whose LHS mentions a locally-defined |
|---|
| 1000 | -- Id that is completely internal (i.e. not visible to an |
|---|
| 1001 | -- importing module) |
|---|
| 1002 | |
|---|
| 1003 | external_id id |
|---|
| 1004 | | Just (name,_) <- lookupVarEnv unfold_env id = isExternalName name |
|---|
| 1005 | | otherwise = False |
|---|
| 1006 | \end{code} |
|---|
| 1007 | |
|---|
| 1008 | Note [Which rules to expose] |
|---|
| 1009 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| 1010 | findExternalRules filters imp_rules to avoid binders that |
|---|
| 1011 | aren't externally visible; but the externally-visible binders |
|---|
| 1012 | are computed (by findExternalIds) assuming that all orphan |
|---|
| 1013 | rules are externalised (see init_ext_ids in function |
|---|
| 1014 | 'search'). So in fact we may export more than we need. |
|---|
| 1015 | (It's a sort of mutual recursion.) |
|---|
| 1016 | |
|---|
| 1017 | %************************************************************************ |
|---|
| 1018 | %* * |
|---|
| 1019 | \subsection{Step 2: top-level tidying} |
|---|
| 1020 | %* * |
|---|
| 1021 | %************************************************************************ |
|---|
| 1022 | |
|---|
| 1023 | |
|---|
| 1024 | \begin{code} |
|---|
| 1025 | -- TopTidyEnv: when tidying we need to know |
|---|
| 1026 | -- * nc_var: The NameCache, containing a unique supply and any pre-ordained Names. |
|---|
| 1027 | -- These may have arisen because the |
|---|
| 1028 | -- renamer read in an interface file mentioning M.$wf, say, |
|---|
| 1029 | -- and assigned it unique r77. If, on this compilation, we've |
|---|
| 1030 | -- invented an Id whose name is $wf (but with a different unique) |
|---|
| 1031 | -- we want to rename it to have unique r77, so that we can do easy |
|---|
| 1032 | -- comparisons with stuff from the interface file |
|---|
| 1033 | -- |
|---|
| 1034 | -- * occ_env: The TidyOccEnv, which tells us which local occurrences |
|---|
| 1035 | -- are 'used' |
|---|
| 1036 | -- |
|---|
| 1037 | -- * subst_env: A Var->Var mapping that substitutes the new Var for the old |
|---|
| 1038 | |
|---|
| 1039 | tidyTopBinds :: HscEnv |
|---|
| 1040 | -> UnfoldEnv |
|---|
| 1041 | -> TidyOccEnv |
|---|
| 1042 | -> CoreProgram |
|---|
| 1043 | -> (TidyEnv, CoreProgram) |
|---|
| 1044 | |
|---|
| 1045 | tidyTopBinds hsc_env unfold_env init_occ_env binds |
|---|
| 1046 | = tidy init_env binds |
|---|
| 1047 | where |
|---|
| 1048 | init_env = (init_occ_env, emptyVarEnv) |
|---|
| 1049 | |
|---|
| 1050 | this_pkg = thisPackage (hsc_dflags hsc_env) |
|---|
| 1051 | |
|---|
| 1052 | tidy env [] = (env, []) |
|---|
| 1053 | tidy env (b:bs) = let (env1, b') = tidyTopBind this_pkg unfold_env env b |
|---|
| 1054 | (env2, bs') = tidy env1 bs |
|---|
| 1055 | in |
|---|
| 1056 | (env2, b':bs') |
|---|
| 1057 | |
|---|
| 1058 | ------------------------ |
|---|
| 1059 | tidyTopBind :: PackageId |
|---|
| 1060 | -> UnfoldEnv |
|---|
| 1061 | -> TidyEnv |
|---|
| 1062 | -> CoreBind |
|---|
| 1063 | -> (TidyEnv, CoreBind) |
|---|
| 1064 | |
|---|
| 1065 | tidyTopBind this_pkg unfold_env (occ_env,subst1) (NonRec bndr rhs) |
|---|
| 1066 | = (tidy_env2, NonRec bndr' rhs') |
|---|
| 1067 | where |
|---|
| 1068 | Just (name',show_unfold) = lookupVarEnv unfold_env bndr |
|---|
| 1069 | caf_info = hasCafRefs this_pkg subst1 (idArity bndr) rhs |
|---|
| 1070 | (bndr', rhs') = tidyTopPair show_unfold tidy_env2 caf_info name' (bndr, rhs) |
|---|
| 1071 | subst2 = extendVarEnv subst1 bndr bndr' |
|---|
| 1072 | tidy_env2 = (occ_env, subst2) |
|---|
| 1073 | |
|---|
| 1074 | tidyTopBind this_pkg unfold_env (occ_env,subst1) (Rec prs) |
|---|
| 1075 | = (tidy_env2, Rec prs') |
|---|
| 1076 | where |
|---|
| 1077 | prs' = [ tidyTopPair show_unfold tidy_env2 caf_info name' (id,rhs) |
|---|
| 1078 | | (id,rhs) <- prs, |
|---|
| 1079 | let (name',show_unfold) = |
|---|
| 1080 | expectJust "tidyTopBind" $ lookupVarEnv unfold_env id |
|---|
| 1081 | ] |
|---|
| 1082 | |
|---|
| 1083 | subst2 = extendVarEnvList subst1 (bndrs `zip` map fst prs') |
|---|
| 1084 | tidy_env2 = (occ_env, subst2) |
|---|
| 1085 | |
|---|
| 1086 | bndrs = map fst prs |
|---|
| 1087 | |
|---|
| 1088 | -- the CafInfo for a recursive group says whether *any* rhs in |
|---|
| 1089 | -- the group may refer indirectly to a CAF (because then, they all do). |
|---|
| 1090 | caf_info |
|---|
| 1091 | | or [ mayHaveCafRefs (hasCafRefs this_pkg subst1 (idArity bndr) rhs) |
|---|
| 1092 | | (bndr,rhs) <- prs ] = MayHaveCafRefs |
|---|
| 1093 | | otherwise = NoCafRefs |
|---|
| 1094 | |
|---|
| 1095 | ----------------------------------------------------------- |
|---|
| 1096 | tidyTopPair :: Bool -- show unfolding |
|---|
| 1097 | -> TidyEnv -- The TidyEnv is used to tidy the IdInfo |
|---|
| 1098 | -- It is knot-tied: don't look at it! |
|---|
| 1099 | -> CafInfo |
|---|
| 1100 | -> Name -- New name |
|---|
| 1101 | -> (Id, CoreExpr) -- Binder and RHS before tidying |
|---|
| 1102 | -> (Id, CoreExpr) |
|---|
| 1103 | -- This function is the heart of Step 2 |
|---|
| 1104 | -- The rec_tidy_env is the one to use for the IdInfo |
|---|
| 1105 | -- It's necessary because when we are dealing with a recursive |
|---|
| 1106 | -- group, a variable late in the group might be mentioned |
|---|
| 1107 | -- in the IdInfo of one early in the group |
|---|
| 1108 | |
|---|
| 1109 | tidyTopPair show_unfold rhs_tidy_env caf_info name' (bndr, rhs) |
|---|
| 1110 | = (bndr1, rhs1) |
|---|
| 1111 | where |
|---|
| 1112 | bndr1 = mkGlobalId details name' ty' idinfo' |
|---|
| 1113 | details = idDetails bndr -- Preserve the IdDetails |
|---|
| 1114 | ty' = tidyTopType (idType bndr) |
|---|
| 1115 | rhs1 = tidyExpr rhs_tidy_env rhs |
|---|
| 1116 | idinfo' = tidyTopIdInfo rhs_tidy_env name' rhs rhs1 (idInfo bndr) |
|---|
| 1117 | show_unfold caf_info |
|---|
| 1118 | |
|---|
| 1119 | -- tidyTopIdInfo creates the final IdInfo for top-level |
|---|
| 1120 | -- binders. There are two delicate pieces: |
|---|
| 1121 | -- |
|---|
| 1122 | -- * Arity. After CoreTidy, this arity must not change any more. |
|---|
| 1123 | -- Indeed, CorePrep must eta expand where necessary to make |
|---|
| 1124 | -- the manifest arity equal to the claimed arity. |
|---|
| 1125 | -- |
|---|
| 1126 | -- * CAF info. This must also remain valid through to code generation. |
|---|
| 1127 | -- We add the info here so that it propagates to all |
|---|
| 1128 | -- occurrences of the binders in RHSs, and hence to occurrences in |
|---|
| 1129 | -- unfoldings, which are inside Ids imported by GHCi. Ditto RULES. |
|---|
| 1130 | -- CoreToStg makes use of this when constructing SRTs. |
|---|
| 1131 | tidyTopIdInfo :: TidyEnv -> Name -> CoreExpr -> CoreExpr |
|---|
| 1132 | -> IdInfo -> Bool -> CafInfo -> IdInfo |
|---|
| 1133 | tidyTopIdInfo rhs_tidy_env name orig_rhs tidy_rhs idinfo show_unfold caf_info |
|---|
| 1134 | | not is_external -- For internal Ids (not externally visible) |
|---|
| 1135 | = vanillaIdInfo -- we only need enough info for code generation |
|---|
| 1136 | -- Arity and strictness info are enough; |
|---|
| 1137 | -- c.f. CoreTidy.tidyLetBndr |
|---|
| 1138 | `setCafInfo` caf_info |
|---|
| 1139 | `setArityInfo` arity |
|---|
| 1140 | `setStrictnessInfo` final_sig |
|---|
| 1141 | |
|---|
| 1142 | | otherwise -- Externally-visible Ids get the whole lot |
|---|
| 1143 | = vanillaIdInfo |
|---|
| 1144 | `setCafInfo` caf_info |
|---|
| 1145 | `setArityInfo` arity |
|---|
| 1146 | `setStrictnessInfo` final_sig |
|---|
| 1147 | `setOccInfo` robust_occ_info |
|---|
| 1148 | `setInlinePragInfo` (inlinePragInfo idinfo) |
|---|
| 1149 | `setUnfoldingInfo` unfold_info |
|---|
| 1150 | -- NB: we throw away the Rules |
|---|
| 1151 | -- They have already been extracted by findExternalRules |
|---|
| 1152 | where |
|---|
| 1153 | is_external = isExternalName name |
|---|
| 1154 | |
|---|
| 1155 | --------- OccInfo ------------ |
|---|
| 1156 | robust_occ_info = zapFragileOcc (occInfo idinfo) |
|---|
| 1157 | -- It's important to keep loop-breaker information |
|---|
| 1158 | -- when we are doing -fexpose-all-unfoldings |
|---|
| 1159 | |
|---|
| 1160 | --------- Strictness ------------ |
|---|
| 1161 | final_sig | Just sig <- strictnessInfo idinfo |
|---|
| 1162 | = WARN( _bottom_hidden sig, ppr name ) Just sig |
|---|
| 1163 | | Just (_, sig) <- mb_bot_str = Just sig |
|---|
| 1164 | | otherwise = Nothing |
|---|
| 1165 | |
|---|
| 1166 | -- If the cheap-and-cheerful bottom analyser can see that |
|---|
| 1167 | -- the RHS is bottom, it should jolly well be exposed |
|---|
| 1168 | _bottom_hidden id_sig = case mb_bot_str of |
|---|
| 1169 | Nothing -> False |
|---|
| 1170 | Just (arity, _) -> not (appIsBottom id_sig arity) |
|---|
| 1171 | |
|---|
| 1172 | mb_bot_str = exprBotStrictness_maybe orig_rhs |
|---|
| 1173 | |
|---|
| 1174 | --------- Unfolding ------------ |
|---|
| 1175 | unf_info = unfoldingInfo idinfo |
|---|
| 1176 | unfold_info | show_unfold = tidyUnfolding rhs_tidy_env unf_info unf_from_rhs |
|---|
| 1177 | | otherwise = noUnfolding |
|---|
| 1178 | unf_from_rhs = mkTopUnfolding is_bot tidy_rhs |
|---|
| 1179 | is_bot = case final_sig of |
|---|
| 1180 | Just sig -> isBottomingSig sig |
|---|
| 1181 | Nothing -> False |
|---|
| 1182 | -- NB: do *not* expose the worker if show_unfold is off, |
|---|
| 1183 | -- because that means this thing is a loop breaker or |
|---|
| 1184 | -- marked NOINLINE or something like that |
|---|
| 1185 | -- This is important: if you expose the worker for a loop-breaker |
|---|
| 1186 | -- then you can make the simplifier go into an infinite loop, because |
|---|
| 1187 | -- in effect the unfolding is exposed. See Trac #1709 |
|---|
| 1188 | -- |
|---|
| 1189 | -- You might think that if show_unfold is False, then the thing should |
|---|
| 1190 | -- not be w/w'd in the first place. But a legitimate reason is this: |
|---|
| 1191 | -- the function returns bottom |
|---|
| 1192 | -- In this case, show_unfold will be false (we don't expose unfoldings |
|---|
| 1193 | -- for bottoming functions), but we might still have a worker/wrapper |
|---|
| 1194 | -- split (see Note [Worker-wrapper for bottoming functions] in WorkWrap.lhs |
|---|
| 1195 | |
|---|
| 1196 | --------- Arity ------------ |
|---|
| 1197 | -- Usually the Id will have an accurate arity on it, because |
|---|
| 1198 | -- the simplifier has just run, but not always. |
|---|
| 1199 | -- One case I found was when the last thing the simplifier |
|---|
| 1200 | -- did was to let-bind a non-atomic argument and then float |
|---|
| 1201 | -- it to the top level. So it seems more robust just to |
|---|
| 1202 | -- fix it here. |
|---|
| 1203 | arity = exprArity orig_rhs |
|---|
| 1204 | \end{code} |
|---|
| 1205 | |
|---|
| 1206 | %************************************************************************ |
|---|
| 1207 | %* * |
|---|
| 1208 | \subsection{Figuring out CafInfo for an expression} |
|---|
| 1209 | %* * |
|---|
| 1210 | %************************************************************************ |
|---|
| 1211 | |
|---|
| 1212 | hasCafRefs decides whether a top-level closure can point into the dynamic heap. |
|---|
| 1213 | We mark such things as `MayHaveCafRefs' because this information is |
|---|
| 1214 | used to decide whether a particular closure needs to be referenced |
|---|
| 1215 | in an SRT or not. |
|---|
| 1216 | |
|---|
| 1217 | There are two reasons for setting MayHaveCafRefs: |
|---|
| 1218 | a) The RHS is a CAF: a top-level updatable thunk. |
|---|
| 1219 | b) The RHS refers to something that MayHaveCafRefs |
|---|
| 1220 | |
|---|
| 1221 | Possible improvement: In an effort to keep the number of CAFs (and |
|---|
| 1222 | hence the size of the SRTs) down, we could also look at the expression and |
|---|
| 1223 | decide whether it requires a small bounded amount of heap, so we can ignore |
|---|
| 1224 | it as a CAF. In these cases however, we would need to use an additional |
|---|
| 1225 | CAF list to keep track of non-collectable CAFs. |
|---|
| 1226 | |
|---|
| 1227 | \begin{code} |
|---|
| 1228 | hasCafRefs :: PackageId -> VarEnv Var -> Arity -> CoreExpr -> CafInfo |
|---|
| 1229 | hasCafRefs this_pkg p arity expr |
|---|
| 1230 | | is_caf || mentions_cafs = MayHaveCafRefs |
|---|
| 1231 | | otherwise = NoCafRefs |
|---|
| 1232 | where |
|---|
| 1233 | mentions_cafs = isFastTrue (cafRefsE p expr) |
|---|
| 1234 | is_dynamic_name = isDllName this_pkg |
|---|
| 1235 | is_caf = not (arity > 0 || rhsIsStatic is_dynamic_name expr) |
|---|
| 1236 | |
|---|
| 1237 | -- NB. we pass in the arity of the expression, which is expected |
|---|
| 1238 | -- to be calculated by exprArity. This is because exprArity |
|---|
| 1239 | -- knows how much eta expansion is going to be done by |
|---|
| 1240 | -- CorePrep later on, and we don't want to duplicate that |
|---|
| 1241 | -- knowledge in rhsIsStatic below. |
|---|
| 1242 | |
|---|
| 1243 | cafRefsE :: VarEnv Id -> Expr a -> FastBool |
|---|
| 1244 | cafRefsE p (Var id) = cafRefsV p id |
|---|
| 1245 | cafRefsE p (Lit lit) = cafRefsL p lit |
|---|
| 1246 | cafRefsE p (App f a) = fastOr (cafRefsE p f) (cafRefsE p) a |
|---|
| 1247 | cafRefsE p (Lam _ e) = cafRefsE p e |
|---|
| 1248 | cafRefsE p (Let b e) = fastOr (cafRefsEs p (rhssOfBind b)) (cafRefsE p) e |
|---|
| 1249 | cafRefsE p (Case e _bndr _ alts) = fastOr (cafRefsE p e) (cafRefsEs p) (rhssOfAlts alts) |
|---|
| 1250 | cafRefsE p (Tick _n e) = cafRefsE p e |
|---|
| 1251 | cafRefsE p (Cast e _co) = cafRefsE p e |
|---|
| 1252 | cafRefsE _ (Type _) = fastBool False |
|---|
| 1253 | cafRefsE _ (Coercion _) = fastBool False |
|---|
| 1254 | |
|---|
| 1255 | cafRefsEs :: VarEnv Id -> [Expr a] -> FastBool |
|---|
| 1256 | cafRefsEs _ [] = fastBool False |
|---|
| 1257 | cafRefsEs p (e:es) = fastOr (cafRefsE p e) (cafRefsEs p) es |
|---|
| 1258 | |
|---|
| 1259 | cafRefsL :: VarEnv Id -> Literal -> FastBool |
|---|
| 1260 | -- Don't forget that the embeded mk_integer id might have Caf refs! |
|---|
| 1261 | -- See Note [Integer literals] in Literal |
|---|
| 1262 | cafRefsL p (LitInteger _ mk_integer) = cafRefsV p mk_integer |
|---|
| 1263 | cafRefsL _ _ = fastBool False |
|---|
| 1264 | |
|---|
| 1265 | cafRefsV :: VarEnv Id -> Id -> FastBool |
|---|
| 1266 | cafRefsV p id |
|---|
| 1267 | | not (isLocalId id) = fastBool (mayHaveCafRefs (idCafInfo id)) |
|---|
| 1268 | | Just id' <- lookupVarEnv p id = fastBool (mayHaveCafRefs (idCafInfo id')) |
|---|
| 1269 | | otherwise = fastBool False |
|---|
| 1270 | |
|---|
| 1271 | fastOr :: FastBool -> (a -> FastBool) -> a -> FastBool |
|---|
| 1272 | -- hack for lazy-or over FastBool. |
|---|
| 1273 | fastOr a f x = fastBool (isFastTrue a || isFastTrue (f x)) |
|---|
| 1274 | \end{code} |
|---|