-non_wired x = not (isWiredInName (getName x)) --ToDo:move?
-
-ifaceDecls Nothing{-no iface handle-} _ = return ()
-
-ifaceDecls (Just if_hdl) (vals, tycons, classes, _)
- = ASSERT(all isLocallyDefined vals)
- ASSERT(all isLocallyDefined tycons)
- ASSERT(all isLocallyDefined classes)
- let
- nonwired_classes = filter non_wired classes
- nonwired_tycons = filter non_wired tycons
- nonwired_vals = filter non_wired vals
-
- lt_lexical a b = origName "lt_lexical" a < origName "lt_lexical" b
-
- sorted_classes = sortLt lt_lexical nonwired_classes
- sorted_tycons = sortLt lt_lexical nonwired_tycons
- sorted_vals = sortLt lt_lexical nonwired_vals
- in
- if (null sorted_classes && null sorted_tycons && null sorted_vals) then
- -- You could have a module with just (re-)exports/instances in it
- return ()
- else
- hPutStr if_hdl "\n__declarations__\n" >>
- hPutStr if_hdl (uppShow 0 (uppAboves [
- uppAboves (map ppr_class sorted_classes),
- uppAboves (map ppr_tycon sorted_tycons),
- uppAboves [ppr_val v (idType v) | v <- sorted_vals]]))
+mkFinalId :: IdSet -- The Ids with arity info from the code generator
+ -> Bool -- True <=> recursive, so don't include unfolding
+ -> Id
+ -> CoreExpr -- The Id's right hand side
+ -> (Id, IdSet) -- The emitted id, plus any *extra* needed Ids
+
+mkFinalId codegen_ids is_rec id rhs
+ = (id `setIdInfo` new_idinfo, new_needed_ids)
+ where
+ core_idinfo = idInfo id
+ stg_idinfo = case lookupVarSet codegen_ids id of
+ Just id' -> idInfo id'
+ Nothing -> pprTrace "ifaceBinds not found:" (ppr id) $
+ idInfo id
+
+ new_idinfo | opt_OmitInterfacePragmas
+ = vanillaIdInfo
+ | otherwise
+ = core_idinfo `setArityInfo` arity_info
+ `setCafInfo` cafInfo stg_idinfo
+ `setUnfoldingInfo` unfold_info
+ `setWorkerInfo` worker_info
+ `setSpecInfo` emptyCoreRules
+ -- We zap the specialisations because they are
+ -- passed on separately through the modules IdCoreRules
+
+ ------------ Arity --------------
+ arity_info = arityInfo stg_idinfo
+ stg_arity = arityLowerBound arity_info
+
+ ------------ Worker --------------
+ -- We only treat a function as having a worker if
+ -- the exported arity (which is now the number of visible lambdas)
+ -- is the same as the arity at the moment of the w/w split
+ -- If so, we can safely omit the unfolding inside the wrapper, and
+ -- instead re-generate it from the type/arity/strictness info
+ -- But if the arity has changed, we just take the simple path and
+ -- put the unfolding into the interface file, forgetting the fact
+ -- that it's a wrapper.
+ --
+ -- How can this happen? Sometimes we get
+ -- f = coerce t (\x y -> $wf x y)
+ -- at the moment of w/w split; but the eta reducer turns it into
+ -- f = coerce t $wf
+ -- which is perfectly fine except that the exposed arity so far as
+ -- the code generator is concerned (zero) differs from the arity
+ -- when we did the split (2).
+ --
+ -- All this arises because we use 'arity' to mean "exactly how many
+ -- top level lambdas are there" in interface files; but during the
+ -- compilation of this module it means "how many things can I apply
+ -- this to".
+ worker_info = case workerInfo core_idinfo of
+ info@(HasWorker work_id wrap_arity)
+ | wrap_arity == stg_arity -> info
+ | otherwise -> pprTrace "ifaceId: arity change:" (ppr id)
+ NoWorker
+ NoWorker -> NoWorker
+
+ has_worker = case worker_info of
+ HasWorker _ _ -> True
+ other -> False
+
+ HasWorker work_id _ = worker_info
+
+ ------------ Unfolding --------------
+ inline_pragma = inlinePragInfo core_idinfo
+ dont_inline = isNeverInlinePrag inline_pragma
+ loop_breaker = isLoopBreaker (occInfo core_idinfo)
+ bottoming_fn = isBottomingStrictness (strictnessInfo core_idinfo)
+
+ unfolding = mkTopUnfolding rhs
+ rhs_is_small = neverUnfold unfolding
+
+ unfold_info | show_unfold = unfolding
+ | otherwise = noUnfolding
+
+ show_unfold = not has_worker && -- Not unnecessary
+ not bottoming_fn && -- Not necessary
+ not dont_inline &&
+ not loop_breaker &&
+ rhs_is_small && -- Small enough
+ okToUnfoldInHiFile rhs -- No casms etc
+
+
+ ------------ Extra free Ids --------------
+ new_needed_ids | opt_OmitInterfacePragmas = emptyVarSet
+ | otherwise = worker_ids `unionVarSet`
+ unfold_ids `unionVarSet`
+ spec_ids
+
+ spec_ids = filterVarSet interestingId (rulesRhsFreeVars (specInfo core_idinfo))
+
+ worker_ids | has_worker && interestingId work_id = unitVarSet work_id
+ -- Conceivably, the worker might come from
+ -- another module
+ | otherwise = emptyVarSet
+
+ unfold_ids | show_unfold = find_fvs rhs
+ | otherwise = emptyVarSet
+
+ find_fvs expr = exprSomeFreeVars interestingId expr
+
+interestingId id = isId id && isLocallyDefined id && not (hasNoBinding id)