- = ds_lhs_binds (addSccs auto_scc exports) binds `thenDs` \ core_prs ->
- let
- add_inline (bndr,rhs) | Just prags <- lookupVarEnv inline_env bndr
- = addInlinePrags prags bndr rhs
- | otherwise = (bndr,rhs)
- inline_env = mkVarEnv [(lcl_id, prags) | (_, _, lcl_id, prags) <- exports]
-
- -- Rec because of mixed-up dictionary bindings
- core_bind = Rec (map add_inline core_prs)
-
- tup_expr = mkTupleExpr locals
- tup_ty = exprType tup_expr
- poly_tup_expr = mkLams all_tyvars $ mkLams dicts $
- Let core_bind tup_expr
- locals = [local | (_, _, local, _) <- exports]
- local_tys = map idType locals
- in
- newSysLocalDs (exprType poly_tup_expr) `thenDs` \ poly_tup_id ->
- let
- dict_args = map Var dicts
-
- mk_bind ((tyvars, global, local, prags), n) -- locals !! n == local
- = -- Need to make fresh locals to bind in the selector, because
- -- some of the tyvars will be bound to voidTy
- newSysLocalsDs (map substitute local_tys) `thenDs` \ locals' ->
- newSysLocalDs (substitute tup_ty) `thenDs` \ tup_id ->
- mapM (dsSpec all_tyvars dicts tyvars global local core_bind)
- prags `thenDs` \ mb_specs ->
- let
- (spec_binds, rules) = unzip (catMaybes mb_specs)
- global' = addIdSpecialisations global rules
- rhs = mkLams tyvars $ mkLams dicts $
- mkTupleSelector locals' (locals' !! n) tup_id $
- mkApps (mkTyApps (Var poly_tup_id) ty_args) dict_args
- in
- returnDs ((global', rhs) : spec_binds)
- where
- mk_ty_arg all_tyvar | all_tyvar `elem` tyvars = mkTyVarTy all_tyvar
- | otherwise = voidTy
- ty_args = map mk_ty_arg all_tyvars
- substitute = substTyWith all_tyvars ty_args
- in
- mappM mk_bind (exports `zip` [0..]) `thenDs` \ export_binds_s ->
- -- don't scc (auto-)annotate the tuple itself.
-
- returnDs ((poly_tup_id, poly_tup_expr) : (concat export_binds_s ++ rest))
+ = do { core_prs <- ds_lhs_binds NoSccs binds
+ ; let env = mkABEnv exports
+ ar_env = mkArityEnv binds
+ do_one (lcl_id,rhs) | Just (_, gbl_id, _, _prags) <- lookupVarEnv env lcl_id
+ = (lcl_id, addAutoScc auto_scc gbl_id rhs)
+ | otherwise = (lcl_id,rhs)
+
+ -- Rec because of mixed-up dictionary bindings
+ core_bind = Rec (map do_one core_prs)
+
+ tup_expr = mkBigCoreVarTup locals
+ tup_ty = exprType tup_expr
+ poly_tup_expr = mkLams all_tyvars $ mkLams dicts $
+ Let core_bind tup_expr
+ locals = [local | (_, _, local, _) <- exports]
+ local_tys = map idType locals
+
+ inl_prags :: [(Id, SrcSpan)]
+ inl_prags = [(id, loc) | (_, id, _, prags) <- exports
+ , L loc (InlinePrag {}) <- prags ]
+
+ ; mapM_ discardedInlineWarning inl_prags
+
+ ; poly_tup_id <- newSysLocalDs (exprType poly_tup_expr)
+
+ ; let dict_args = map Var dicts
+
+ mk_bind ((tyvars, global, local, prags), n) -- locals !! n == local
+ = -- Need to make fresh locals to bind in the selector, because
+ -- some of the tyvars will be bound to 'Any'
+ do { ty_args <- mapM mk_ty_arg all_tyvars
+ ; let substitute = substTyWith all_tyvars ty_args
+ ; locals' <- newSysLocalsDs (map substitute local_tys)
+ ; tup_id <- newSysLocalDs (substitute tup_ty)
+ ; mb_specs <- mapM (dsSpec all_tyvars dicts tyvars global local
+ (lookupArity ar_env local) core_bind)
+ prags
+ ; let (spec_binds, rules) = unzip (catMaybes mb_specs)
+ global' = addIdSpecialisations global rules
+ rhs = mkLams tyvars $ mkLams dicts $
+ mkTupleSelector locals' (locals' !! n) tup_id $
+ mkApps (mkTyApps (Var poly_tup_id) ty_args) dict_args
+ ; return ((global', rhs) : spec_binds) }
+ where
+ mk_ty_arg all_tyvar
+ | all_tyvar `elem` tyvars = return (mkTyVarTy all_tyvar)
+ | otherwise = dsMkArbitraryType all_tyvar
+
+ ; export_binds_s <- mapM mk_bind (exports `zip` [0..])
+ -- Don't scc (auto-)annotate the tuple itself.
+
+ ; return ((poly_tup_id, poly_tup_expr) :
+ (concat export_binds_s ++ rest)) }
+
+------------------------
+makeCorePair :: Id-> Arity -> [LPrag] -> CoreExpr -> (Id, CoreExpr)
+makeCorePair gbl_id arity prags rhs
+ = (addInline gbl_id arity rhs prags, rhs)
+
+------------------------
+discardedInlineWarning :: (Id, SrcSpan) -> DsM ()
+discardedInlineWarning (id, loc)
+ = putSrcSpanDs loc $
+ warnDs $ sep [ ptext (sLit "Discarding INLINE pragma for") <+> ppr id
+ , ptext (sLit "because it is bound by a pattern, or a mutual recursion") ]
+
+------------------------
+type AbsBindEnv = VarEnv ([TyVar], Id, Id, [LPrag])
+ -- Maps the "lcl_id" for an AbsBind to
+ -- its "gbl_id" and associated pragmas, if any
+
+mkABEnv :: [([TyVar], Id, Id, [LPrag])] -> AbsBindEnv
+-- Takes the exports of a AbsBinds, and returns a mapping
+-- lcl_id -> (tyvars, gbl_id, lcl_id, prags)
+mkABEnv exports = mkVarEnv [ (lcl_id, export) | export@(_, _, lcl_id, _) <- exports]
+
+mkArityEnv :: LHsBinds Id -> IdEnv Arity
+ -- Maps a local to the arity of its definition
+mkArityEnv binds = mkVarEnv (mapCatMaybes get_arity (bagToList binds))
+ where
+ get_arity (L _ (FunBind { fun_id = id, fun_matches = ms })) = Just (unLoc id, matchGroupArity ms)
+ get_arity _ = Nothing
+
+lookupArity :: IdEnv Arity -> Id -> Arity
+lookupArity ar_env id = lookupVarEnv ar_env id `orElse` 0
+
+addInline :: Id -> Arity -> CoreExpr -> [LPrag] -> Id
+addInline id arity rhs prags
+ = case [inl | L _ (InlinePrag inl) <- prags] of
+ [] -> id
+ (inl_spec : _) -> addInlineToId id arity rhs inl_spec
+
+addInlineToId :: Id -> Arity -> CoreExpr -> InlineSpec -> Id
+addInlineToId id inl_arity rhs (Inline phase is_inline)
+ = id `setInlinePragma` phase
+ `setIdUnfolding` inline_rule
+ where
+ inline_rule | is_inline = mkInlineRule rhs inl_arity
+ | otherwise = noUnfolding