merge up to ghc HEAD 16-Apr-2011
[ghc-hetmet.git] / compiler / deSugar / Coverage.lhs
1 %
2 % (c) Galois, 2006
3 % (c) University of Glasgow, 2007
4 %
5 \section[Coverage]{@coverage@: the main function}
6
7 \begin{code}
8 module Coverage (addCoverageTicksToBinds, hpcInitCode) where
9
10 import HsSyn
11 import Module
12 import Outputable
13 import DynFlags
14 import Control.Monad
15 import SrcLoc
16 import ErrUtils
17 import Name
18 import Bag
19 import Id
20 import VarSet
21 import Data.List
22 import FastString
23 import HscTypes 
24 import StaticFlags
25 import TyCon
26 import MonadUtils
27 import Maybes
28 import CLabel
29 import Util
30
31 import Data.Array
32 import System.Directory ( createDirectoryIfMissing )
33
34 import Trace.Hpc.Mix
35 import Trace.Hpc.Util
36
37 import BreakArray 
38 import Data.HashTable   ( hashString )
39 import Data.Map (Map)
40 import qualified Data.Map as Map
41 \end{code}
42
43
44 %************************************************************************
45 %*                                                                      *
46 %*              The main function: addCoverageTicksToBinds
47 %*                                                                      *
48 %************************************************************************
49
50 \begin{code}
51 addCoverageTicksToBinds
52         :: DynFlags
53         -> Module
54         -> ModLocation          -- of the current module
55         -> [TyCon]              -- type constructor in this module
56         -> LHsBinds Id
57         -> IO (LHsBinds Id, HpcInfo, ModBreaks)
58
59 addCoverageTicksToBinds dflags mod mod_loc tyCons binds = 
60  case ml_hs_file mod_loc of
61  Nothing -> return (binds, emptyHpcInfo False, emptyModBreaks)
62  Just orig_file -> do
63
64   if "boot" `isSuffixOf` orig_file then return (binds, emptyHpcInfo False, emptyModBreaks) else do
65
66   -- Now, we try look for a file generated from a .hsc file to a .hs file, by peeking ahead.
67
68   let top_pos = catMaybes $ foldrBag (\ (L pos _) rest -> srcSpanFileName_maybe pos : rest) [] binds
69   let orig_file2 = case top_pos of
70                      (file_name:_) 
71                        | ".hsc" `isSuffixOf` unpackFS file_name -> unpackFS file_name
72                      _ -> orig_file
73
74   let mod_name = moduleNameString (moduleName mod)
75
76   let (binds1,_,st)
77                  = unTM (addTickLHsBinds binds) 
78                    (TTE
79                        { fileName    = mkFastString orig_file2
80                       , declPath     = []
81                       , inScope      = emptyVarSet
82                       , blackList    = Map.fromList [ (getSrcSpan (tyConName tyCon),()) 
83                                                     | tyCon <- tyCons ]
84                        })
85                    (TT 
86                       { tickBoxCount = 0
87                       , mixEntries   = []
88                       })
89
90   let entries = reverse $ mixEntries st
91
92   -- write the mix entries for this module
93   hashNo <- if opt_Hpc then do
94      let hpc_dir = hpcDir dflags
95
96      let hpc_mod_dir = if modulePackageId mod == mainPackageId 
97                        then hpc_dir
98                        else hpc_dir ++ "/" ++ packageIdString (modulePackageId mod)
99
100      let tabStop = 1 -- <tab> counts as a normal char in GHC's location ranges.
101      createDirectoryIfMissing True hpc_mod_dir
102      modTime <- getModificationTime orig_file2
103      let entries' = [ (hpcPos, box) 
104                     | (span,_,_,box) <- entries, hpcPos <- [mkHpcPos span] ]
105      when (length entries' /= tickBoxCount st) $ do
106        panic "the number of .mix entries are inconsistent"
107      let hashNo = mixHash orig_file2 modTime tabStop entries'
108      mixCreate hpc_mod_dir mod_name 
109                $ Mix orig_file2 modTime (toHash hashNo) tabStop entries'
110      return $ hashNo 
111    else do
112      return $ 0
113
114   -- Todo: use proper src span type
115   breakArray <- newBreakArray $ length entries
116
117   let locsTicks = listArray (0,tickBoxCount st-1) 
118                      [ span | (span,_,_,_) <- entries ]
119       varsTicks = listArray (0,tickBoxCount st-1) 
120                      [ vars | (_,_,vars,_) <- entries ]
121       declsTicks= listArray (0,tickBoxCount st-1) 
122                      [ decls | (_,decls,_,_) <- entries ]
123       modBreaks = emptyModBreaks 
124                   { modBreaks_flags = breakArray 
125                   , modBreaks_locs  = locsTicks 
126                   , modBreaks_vars  = varsTicks
127                   , modBreaks_decls = declsTicks
128                   } 
129
130   doIfSet_dyn dflags  Opt_D_dump_hpc $ do
131           printDump (pprLHsBinds binds1)
132
133   return (binds1, HpcInfo (tickBoxCount st) hashNo, modBreaks)
134 \end{code}
135
136
137 \begin{code}
138 liftL :: (Monad m) => (a -> m a) -> Located a -> m (Located a)
139 liftL f (L loc a) = do
140   a' <- f a
141   return $ L loc a'
142
143 addTickLHsBinds :: LHsBinds Id -> TM (LHsBinds Id)
144 addTickLHsBinds binds = mapBagM addTickLHsBind binds
145
146 addTickLHsBind :: LHsBind Id -> TM (LHsBind Id)
147 addTickLHsBind (L pos bind@(AbsBinds { abs_binds = binds })) = do
148   binds' <- addTickLHsBinds binds
149   return $ L pos $ bind { abs_binds = binds' }
150 addTickLHsBind (L pos (funBind@(FunBind { fun_id = (L _ id)  }))) = do 
151   let name = getOccString id
152   decl_path <- getPathEntry
153
154   (fvs, (MatchGroup matches' ty)) <- 
155         getFreeVars $
156         addPathEntry name $
157         addTickMatchGroup (fun_matches funBind)
158
159   blackListed <- isBlackListed pos
160
161   -- Todo: we don't want redundant ticks on simple pattern bindings
162   -- We don't want to generate code for blacklisted positions
163   if blackListed || (not opt_Hpc && isSimplePatBind funBind)
164      then 
165         return $ L pos $ funBind { fun_matches = MatchGroup matches' ty 
166                                  , fun_tick = Nothing 
167                                  }
168      else do
169         tick_no <- allocATickBox (if null decl_path
170                                      then TopLevelBox [name]
171                                      else LocalBox (decl_path ++ [name])) 
172                                 pos fvs
173
174         return $ L pos $ funBind { fun_matches = MatchGroup matches' ty 
175                                  , fun_tick = tick_no
176                                  }
177    where
178    -- a binding is a simple pattern binding if it is a funbind with zero patterns
179    isSimplePatBind :: HsBind a -> Bool
180    isSimplePatBind funBind = matchGroupArity (fun_matches funBind) == 0
181
182 -- TODO: Revisit this
183 addTickLHsBind (L pos (pat@(PatBind { pat_rhs = rhs }))) = do
184   let name = "(...)"
185   rhs' <- addPathEntry name $ addTickGRHSs False rhs
186 {-
187   decl_path <- getPathEntry
188   tick_me <- allocTickBox (if null decl_path
189                            then TopLevelBox [name]
190                            else LocalBox (name : decl_path))
191 -}                         
192   return $ L pos $ pat { pat_rhs = rhs' }
193
194 -- Only internal stuff, not from source, uses VarBind, so we ignore it.
195 addTickLHsBind var_bind@(L _ (VarBind {})) = return var_bind
196
197 -- Add a tick to the expression no matter what it is.  There is one exception:
198 -- for the debugger, if the expression is a 'let', then we don't want to add
199 -- a tick here because there will definititely be a tick on the body anyway.
200 addTickLHsExprAlways :: LHsExpr Id -> TM (LHsExpr Id)
201 addTickLHsExprAlways (L pos e0)
202   | not opt_Hpc, HsLet _ _ <- e0 = addTickLHsExprNever (L pos e0)
203   | otherwise = allocTickBox (ExpBox False) pos $ addTickHsExpr e0
204
205 addTickLHsExprNeverOrAlways :: LHsExpr Id -> TM (LHsExpr Id)
206 addTickLHsExprNeverOrAlways e
207     | opt_Hpc   = addTickLHsExprNever e
208     | otherwise = addTickLHsExprAlways e
209
210 addTickLHsExprNeverOrMaybe :: LHsExpr Id -> TM (LHsExpr Id)
211 addTickLHsExprNeverOrMaybe e
212     | opt_Hpc   = addTickLHsExprNever e
213     | otherwise = addTickLHsExpr e
214
215 -- version of addTick that does not actually add a tick,
216 -- because the scope of this tick is completely subsumed by 
217 -- another.
218 addTickLHsExprNever :: LHsExpr Id -> TM (LHsExpr Id)
219 addTickLHsExprNever (L pos e0) = do
220     e1 <- addTickHsExpr e0
221     return $ L pos e1
222
223 -- selectively add ticks to interesting expressions
224 addTickLHsExpr :: LHsExpr Id -> TM (LHsExpr Id)
225 addTickLHsExpr (L pos e0) = do
226     if opt_Hpc || isGoodBreakExpr e0
227        then do
228           allocTickBox (ExpBox False) pos $ addTickHsExpr e0
229        else do
230           e1 <- addTickHsExpr e0
231           return $ L pos e1 
232
233 -- general heuristic: expressions which do not denote values are good break points
234 isGoodBreakExpr :: HsExpr Id -> Bool
235 isGoodBreakExpr (HsApp {})     = True
236 isGoodBreakExpr (OpApp {})     = True
237 isGoodBreakExpr (NegApp {})    = True
238 isGoodBreakExpr (HsCase {})    = True
239 isGoodBreakExpr (HsIf {})      = True
240 isGoodBreakExpr (RecordCon {}) = True
241 isGoodBreakExpr (RecordUpd {}) = True
242 isGoodBreakExpr (ArithSeq {})  = True
243 isGoodBreakExpr (PArrSeq {})   = True
244 isGoodBreakExpr _other         = False 
245
246 addTickLHsExprOptAlt :: Bool -> LHsExpr Id -> TM (LHsExpr Id)
247 addTickLHsExprOptAlt oneOfMany (L pos e0)
248   | not opt_Hpc = addTickLHsExpr (L pos e0)
249   | otherwise =
250     allocTickBox (ExpBox oneOfMany) pos $ 
251         addTickHsExpr e0
252
253 addBinTickLHsExpr :: (Bool -> BoxLabel) -> LHsExpr Id -> TM (LHsExpr Id)
254 addBinTickLHsExpr boxLabel (L pos e0) =
255     allocBinTickBox boxLabel pos $
256         addTickHsExpr e0
257
258 addTickHsExpr :: HsExpr Id -> TM (HsExpr Id)
259 addTickHsExpr e@(HsVar id) = do freeVar id; return e
260 addTickHsExpr e@(HsIPVar _) = return e
261 addTickHsExpr e@(HsOverLit _) = return e
262 addTickHsExpr e@(HsLit _) = return e
263 addTickHsExpr (HsLam matchgroup) =
264         liftM HsLam (addTickMatchGroup matchgroup)
265 addTickHsExpr (HsApp e1 e2) = 
266         liftM2 HsApp (addTickLHsExprNever e1) (addTickLHsExpr e2)
267 addTickHsExpr (OpApp e1 e2 fix e3) = 
268         liftM4 OpApp 
269                 (addTickLHsExpr e1) 
270                 (addTickLHsExprNever e2)
271                 (return fix)
272                 (addTickLHsExpr e3)
273 addTickHsExpr (NegApp e neg) =
274         liftM2 NegApp
275                 (addTickLHsExpr e) 
276                 (addTickSyntaxExpr hpcSrcSpan neg)
277 addTickHsExpr (HsPar e) = liftM HsPar (addTickLHsExprNeverOrMaybe e)
278 addTickHsExpr (SectionL e1 e2) = 
279         liftM2 SectionL
280                 (addTickLHsExpr e1)
281                 (addTickLHsExpr e2)
282 addTickHsExpr (SectionR e1 e2) = 
283         liftM2 SectionR
284                 (addTickLHsExpr e1)
285                 (addTickLHsExpr e2)
286 addTickHsExpr (ExplicitTuple es boxity) =
287         liftM2 ExplicitTuple
288                 (mapM addTickTupArg es)
289                 (return boxity)
290 addTickHsExpr (HsCase e mgs) = 
291         liftM2 HsCase
292                 (addTickLHsExpr e) 
293                 (addTickMatchGroup mgs)
294 addTickHsExpr (HsIf cnd e1 e2 e3) = 
295         liftM3 (HsIf cnd)
296                 (addBinTickLHsExpr (BinBox CondBinBox) e1)
297                 (addTickLHsExprOptAlt True e2)
298                 (addTickLHsExprOptAlt True e3)
299 addTickHsExpr (HsLet binds e) =
300         bindLocals (collectLocalBinders binds) $
301         liftM2 HsLet
302                 (addTickHsLocalBinds binds) -- to think about: !patterns.
303                 (addTickLHsExprNeverOrAlways e)
304 addTickHsExpr (HsDo cxt stmts last_exp srcloc) = do
305         (stmts', last_exp') <- addTickLStmts' forQual stmts 
306                                      (addTickLHsExpr last_exp)
307         return (HsDo cxt stmts' last_exp' srcloc)
308   where
309         forQual = case cxt of
310                     ListComp -> Just $ BinBox QualBinBox
311                     _        -> Nothing
312 addTickHsExpr (ExplicitList ty es) = 
313         liftM2 ExplicitList
314                 (return ty)
315                 (mapM (addTickLHsExpr) es)
316 addTickHsExpr (ExplicitPArr ty es) =
317         liftM2 ExplicitPArr
318                 (return ty)
319                 (mapM (addTickLHsExpr) es)
320 addTickHsExpr (RecordCon id ty rec_binds) = 
321         liftM3 RecordCon
322                 (return id)
323                 (return ty)
324                 (addTickHsRecordBinds rec_binds)
325 addTickHsExpr (RecordUpd e rec_binds cons tys1 tys2) =
326         liftM5 RecordUpd
327                 (addTickLHsExpr e)
328                 (addTickHsRecordBinds rec_binds)
329                 (return cons) (return tys1) (return tys2)
330
331 addTickHsExpr (ExprWithTySigOut e ty) =
332         liftM2 ExprWithTySigOut
333                 (addTickLHsExprNever e) -- No need to tick the inner expression
334                                     -- for expressions with signatures
335                 (return ty)
336 addTickHsExpr (ArithSeq  ty arith_seq) =
337         liftM2 ArithSeq 
338                 (return ty)
339                 (addTickArithSeqInfo arith_seq)
340 addTickHsExpr (HsTickPragma _ (L pos e0)) = do
341     e2 <- allocTickBox (ExpBox False) pos $
342                 addTickHsExpr e0
343     return $ unLoc e2
344 addTickHsExpr (PArrSeq   ty arith_seq) =
345         liftM2 PArrSeq  
346                 (return ty)
347                 (addTickArithSeqInfo arith_seq)
348 addTickHsExpr (HsSCC nm e) =
349         liftM2 HsSCC 
350                 (return nm)
351                 (addTickLHsExpr e)
352 addTickHsExpr (HsCoreAnn nm e) = 
353         liftM2 HsCoreAnn 
354                 (return nm)
355                 (addTickLHsExpr e)
356 addTickHsExpr e@(HsBracket     {}) = return e
357 addTickHsExpr e@(HsBracketOut  {}) = return e
358 addTickHsExpr e@(HsSpliceE  {}) = return e
359 addTickHsExpr (HsProc pat cmdtop) =
360         liftM2 HsProc
361                 (addTickLPat pat)
362                 (liftL (addTickHsCmdTop) cmdtop)
363 addTickHsExpr (HsWrap w e) = 
364         liftM2 HsWrap
365                 (return w)
366                 (addTickHsExpr e)       -- explicitly no tick on inside
367
368 addTickHsExpr e@(HsType _) = return e
369
370 -- Others dhould never happen in expression content.
371 addTickHsExpr e  = pprPanic "addTickHsExpr" (ppr e)
372
373 addTickTupArg :: HsTupArg Id -> TM (HsTupArg Id)
374 addTickTupArg (Present e)  = do { e' <- addTickLHsExpr e; return (Present e') }
375 addTickTupArg (Missing ty) = return (Missing ty)
376
377 addTickMatchGroup :: MatchGroup Id -> TM (MatchGroup Id)
378 addTickMatchGroup (MatchGroup matches ty) = do
379   let isOneOfMany = matchesOneOfMany matches
380   matches' <- mapM (liftL (addTickMatch isOneOfMany)) matches
381   return $ MatchGroup matches' ty
382
383 addTickMatch :: Bool -> Match Id -> TM (Match Id)
384 addTickMatch isOneOfMany (Match pats opSig gRHSs) =
385   bindLocals (collectPatsBinders pats) $ do
386     gRHSs' <- addTickGRHSs isOneOfMany gRHSs
387     return $ Match pats opSig gRHSs'
388
389 addTickGRHSs :: Bool -> GRHSs Id -> TM (GRHSs Id)
390 addTickGRHSs isOneOfMany (GRHSs guarded local_binds) = do
391   bindLocals binders $ do
392     local_binds' <- addTickHsLocalBinds local_binds
393     guarded' <- mapM (liftL (addTickGRHS isOneOfMany)) guarded
394     return $ GRHSs guarded' local_binds'
395   where
396     binders = collectLocalBinders local_binds
397
398 addTickGRHS :: Bool -> GRHS Id -> TM (GRHS Id)
399 addTickGRHS isOneOfMany (GRHS stmts expr) = do
400   (stmts',expr') <- addTickLStmts' (Just $ BinBox $ GuardBinBox) stmts
401                         (if opt_Hpc then addTickLHsExprOptAlt isOneOfMany expr
402                                     else addTickLHsExprAlways expr)
403   return $ GRHS stmts' expr'
404
405 addTickLStmts :: (Maybe (Bool -> BoxLabel)) -> [LStmt Id] -> TM [LStmt Id]
406 addTickLStmts isGuard stmts = do
407   (stmts, _) <- addTickLStmts' isGuard stmts (return ())
408   return stmts
409
410 addTickLStmts' :: (Maybe (Bool -> BoxLabel)) -> [LStmt Id] -> TM a 
411                -> TM ([LStmt Id], a)
412 addTickLStmts' isGuard lstmts res
413   = bindLocals binders $ do
414         lstmts' <- mapM (liftL (addTickStmt isGuard)) lstmts
415         a <- res
416         return (lstmts', a)
417   where
418         binders = collectLStmtsBinders lstmts
419
420 addTickStmt :: (Maybe (Bool -> BoxLabel)) -> Stmt Id -> TM (Stmt Id)
421 addTickStmt _isGuard (BindStmt pat e bind fail) = do
422         liftM4 BindStmt
423                 (addTickLPat pat)
424                 (addTickLHsExprAlways e)
425                 (addTickSyntaxExpr hpcSrcSpan bind)
426                 (addTickSyntaxExpr hpcSrcSpan fail)
427 addTickStmt isGuard (ExprStmt e bind' ty) = do
428         liftM3 ExprStmt
429                 (addTick isGuard e)
430                 (addTickSyntaxExpr hpcSrcSpan bind')
431                 (return ty)
432 addTickStmt _isGuard (LetStmt binds) = do
433         liftM LetStmt
434                 (addTickHsLocalBinds binds)
435 addTickStmt isGuard (ParStmt pairs) = do
436     liftM ParStmt 
437         (mapM (addTickStmtAndBinders isGuard) pairs)
438
439 addTickStmt isGuard (TransformStmt stmts ids usingExpr maybeByExpr) = do
440     liftM4 TransformStmt 
441         (addTickLStmts isGuard stmts)
442         (return ids)
443         (addTickLHsExprAlways usingExpr)
444         (addTickMaybeByLHsExpr maybeByExpr)
445
446 addTickStmt isGuard (GroupStmt stmts binderMap by using) = do
447     liftM4 GroupStmt 
448         (addTickLStmts isGuard stmts)
449         (return binderMap)
450         (fmapMaybeM  addTickLHsExprAlways by)
451         (fmapEitherM addTickLHsExprAlways (addTickSyntaxExpr hpcSrcSpan) using)
452
453 addTickStmt isGuard stmt@(RecStmt {})
454   = do { stmts' <- addTickLStmts isGuard (recS_stmts stmt)
455        ; ret'   <- addTickSyntaxExpr hpcSrcSpan (recS_ret_fn stmt)
456        ; mfix'  <- addTickSyntaxExpr hpcSrcSpan (recS_mfix_fn stmt)
457        ; bind'  <- addTickSyntaxExpr hpcSrcSpan (recS_bind_fn stmt)
458        ; return (stmt { recS_stmts = stmts', recS_ret_fn = ret'
459                       , recS_mfix_fn = mfix', recS_bind_fn = bind' }) }
460
461 addTick :: Maybe (Bool -> BoxLabel) -> LHsExpr Id -> TM (LHsExpr Id)
462 addTick isGuard e | Just fn <- isGuard = addBinTickLHsExpr fn e
463                   | otherwise          = addTickLHsExprAlways e
464
465 addTickStmtAndBinders :: Maybe (Bool -> BoxLabel) -> ([LStmt Id], a) 
466                       -> TM ([LStmt Id], a)
467 addTickStmtAndBinders isGuard (stmts, ids) = 
468     liftM2 (,) 
469         (addTickLStmts isGuard stmts)
470         (return ids)
471
472 addTickMaybeByLHsExpr :: Maybe (LHsExpr Id) -> TM (Maybe (LHsExpr Id))
473 addTickMaybeByLHsExpr maybeByExpr = 
474     case maybeByExpr of
475         Nothing -> return Nothing
476         Just byExpr -> addTickLHsExprAlways byExpr >>= (return . Just)
477
478 addTickHsLocalBinds :: HsLocalBinds Id -> TM (HsLocalBinds Id)
479 addTickHsLocalBinds (HsValBinds binds) = 
480         liftM HsValBinds 
481                 (addTickHsValBinds binds)
482 addTickHsLocalBinds (HsIPBinds binds)  = 
483         liftM HsIPBinds 
484                 (addTickHsIPBinds binds)
485 addTickHsLocalBinds (EmptyLocalBinds)  = return EmptyLocalBinds
486
487 addTickHsValBinds :: HsValBindsLR Id a -> TM (HsValBindsLR Id b)
488 addTickHsValBinds (ValBindsOut binds sigs) =
489         liftM2 ValBindsOut
490                 (mapM (\ (rec,binds') -> 
491                                 liftM2 (,)
492                                         (return rec)
493                                         (addTickLHsBinds binds'))
494                         binds)
495                 (return sigs)
496 addTickHsValBinds _ = panic "addTickHsValBinds"
497
498 addTickHsIPBinds :: HsIPBinds Id -> TM (HsIPBinds Id)
499 addTickHsIPBinds (IPBinds ipbinds dictbinds) =
500         liftM2 IPBinds
501                 (mapM (liftL (addTickIPBind)) ipbinds)
502                 (return dictbinds)
503
504 addTickIPBind :: IPBind Id -> TM (IPBind Id)
505 addTickIPBind (IPBind nm e) =
506         liftM2 IPBind
507                 (return nm)
508                 (addTickLHsExpr e)
509
510 -- There is no location here, so we might need to use a context location??
511 addTickSyntaxExpr :: SrcSpan -> SyntaxExpr Id -> TM (SyntaxExpr Id)
512 addTickSyntaxExpr pos x = do
513         L _ x' <- addTickLHsExpr (L pos x)
514         return $ x'
515 -- we do not walk into patterns.
516 addTickLPat :: LPat Id -> TM (LPat Id)
517 addTickLPat pat = return pat
518
519 addTickHsCmdTop :: HsCmdTop Id -> TM (HsCmdTop Id)
520 addTickHsCmdTop (HsCmdTop cmd tys ty syntaxtable) =
521         liftM4 HsCmdTop
522                 (addTickLHsCmd cmd)
523                 (return tys)
524                 (return ty)
525                 (return syntaxtable)
526
527 addTickLHsCmd ::  LHsCmd Id -> TM (LHsCmd Id)
528 addTickLHsCmd (L pos c0) = do
529         c1 <- addTickHsCmd c0
530         return $ L pos c1 
531
532 addTickHsCmd :: HsCmd Id -> TM (HsCmd Id)
533 addTickHsCmd (HsLam matchgroup) =
534         liftM HsLam (addTickCmdMatchGroup matchgroup)
535 addTickHsCmd (HsApp e1 e2) = 
536         liftM2 HsApp (addTickLHsExprNever e1) (addTickLHsExpr e2)
537 addTickHsCmd (OpApp e1 c2 fix c3) = 
538         liftM4 OpApp 
539                 (addTickLHsExpr e1) 
540                 (addTickLHsCmd c2)
541                 (return fix)
542                 (addTickLHsCmd c3)
543 addTickHsCmd (HsPar e) = liftM HsPar (addTickLHsCmd e)
544 addTickHsCmd (HsCase e mgs) = 
545         liftM2 HsCase
546                 (addTickLHsExpr e) 
547                 (addTickCmdMatchGroup mgs)
548 addTickHsCmd (HsIf cnd e1 c2 c3) = 
549         liftM3 (HsIf cnd)
550                 (addBinTickLHsExpr (BinBox CondBinBox) e1)
551                 (addTickLHsCmd c2)
552                 (addTickLHsCmd c3)
553 addTickHsCmd (HsLet binds c) =
554         bindLocals (collectLocalBinders binds) $
555         liftM2 HsLet
556                 (addTickHsLocalBinds binds) -- to think about: !patterns.
557                 (addTickLHsCmd c)
558 addTickHsCmd (HsDo cxt stmts last_exp srcloc) = do
559         (stmts', last_exp') <- addTickLCmdStmts' stmts (addTickLHsCmd last_exp)
560         return (HsDo cxt stmts' last_exp' srcloc)
561   where
562 addTickHsCmd (HsArrApp   e1 e2 ty1 arr_ty lr) = 
563         liftM5 HsArrApp
564                (addTickLHsExpr e1)
565                (addTickLHsExpr e2)
566                (return ty1)
567                (return arr_ty)
568                (return lr)
569 addTickHsCmd (HsArrForm e fix cmdtop) = 
570         liftM3 HsArrForm
571                (addTickLHsExpr e)
572                (return fix)
573                (mapM (liftL (addTickHsCmdTop)) cmdtop)
574
575 -- Others should never happen in a command context.
576 addTickHsCmd e  = pprPanic "addTickHsCmd" (ppr e)
577
578 addTickCmdMatchGroup :: MatchGroup Id -> TM (MatchGroup Id)
579 addTickCmdMatchGroup (MatchGroup matches ty) = do
580   matches' <- mapM (liftL addTickCmdMatch) matches
581   return $ MatchGroup matches' ty
582
583 addTickCmdMatch :: Match Id -> TM (Match Id)
584 addTickCmdMatch (Match pats opSig gRHSs) =
585   bindLocals (collectPatsBinders pats) $ do
586     gRHSs' <- addTickCmdGRHSs gRHSs
587     return $ Match pats opSig gRHSs'
588
589 addTickCmdGRHSs :: GRHSs Id -> TM (GRHSs Id)
590 addTickCmdGRHSs (GRHSs guarded local_binds) = do
591   bindLocals binders $ do
592     local_binds' <- addTickHsLocalBinds local_binds
593     guarded' <- mapM (liftL addTickCmdGRHS) guarded
594     return $ GRHSs guarded' local_binds'
595   where
596     binders = collectLocalBinders local_binds
597
598 addTickCmdGRHS :: GRHS Id -> TM (GRHS Id)
599 addTickCmdGRHS (GRHS stmts cmd) = do
600   (stmts',expr') <- addTickLCmdStmts' stmts (addTickLHsCmd cmd)
601   return $ GRHS stmts' expr'
602
603 addTickLCmdStmts :: [LStmt Id] -> TM [LStmt Id]
604 addTickLCmdStmts stmts = do
605   (stmts, _) <- addTickLCmdStmts' stmts (return ())
606   return stmts
607
608 addTickLCmdStmts' :: [LStmt Id] -> TM a -> TM ([LStmt Id], a)
609 addTickLCmdStmts' lstmts res
610   = bindLocals binders $ do
611         lstmts' <- mapM (liftL addTickCmdStmt) lstmts
612         a <- res
613         return (lstmts', a)
614   where
615         binders = collectLStmtsBinders lstmts
616
617 addTickCmdStmt :: Stmt Id -> TM (Stmt Id)
618 addTickCmdStmt (BindStmt pat c bind fail) = do
619         liftM4 BindStmt
620                 (addTickLPat pat)
621                 (addTickLHsCmd c)
622                 (return bind)
623                 (return fail)
624 addTickCmdStmt (ExprStmt c bind' ty) = do
625         liftM3 ExprStmt
626                 (addTickLHsCmd c)
627                 (return bind')
628                 (return ty)
629 addTickCmdStmt (LetStmt binds) = do
630         liftM LetStmt
631                 (addTickHsLocalBinds binds)
632 addTickCmdStmt stmt@(RecStmt {})
633   = do { stmts' <- addTickLCmdStmts (recS_stmts stmt)
634        ; ret'   <- addTickSyntaxExpr hpcSrcSpan (recS_ret_fn stmt)
635        ; mfix'  <- addTickSyntaxExpr hpcSrcSpan (recS_mfix_fn stmt)
636        ; bind'  <- addTickSyntaxExpr hpcSrcSpan (recS_bind_fn stmt)
637        ; return (stmt { recS_stmts = stmts', recS_ret_fn = ret'
638                       , recS_mfix_fn = mfix', recS_bind_fn = bind' }) }
639
640 -- Others should never happen in a command context.
641 addTickCmdStmt stmt  = pprPanic "addTickHsCmd" (ppr stmt)
642
643 addTickHsRecordBinds :: HsRecordBinds Id -> TM (HsRecordBinds Id)
644 addTickHsRecordBinds (HsRecFields fields dd) 
645   = do  { fields' <- mapM process fields
646         ; return (HsRecFields fields' dd) }
647   where
648     process (HsRecField ids expr doc)
649         = do { expr' <- addTickLHsExpr expr
650              ; return (HsRecField ids expr' doc) }
651
652 addTickArithSeqInfo :: ArithSeqInfo Id -> TM (ArithSeqInfo Id)
653 addTickArithSeqInfo (From e1) =
654         liftM From
655                 (addTickLHsExpr e1)
656 addTickArithSeqInfo (FromThen e1 e2) =
657         liftM2 FromThen
658                 (addTickLHsExpr e1)
659                 (addTickLHsExpr e2)
660 addTickArithSeqInfo (FromTo e1 e2) =
661         liftM2 FromTo
662                 (addTickLHsExpr e1)
663                 (addTickLHsExpr e2)
664 addTickArithSeqInfo (FromThenTo e1 e2 e3) =
665         liftM3 FromThenTo
666                 (addTickLHsExpr e1)
667                 (addTickLHsExpr e2)
668                 (addTickLHsExpr e3)
669 \end{code}
670
671 \begin{code}
672 data TickTransState = TT { tickBoxCount:: Int
673                          , mixEntries  :: [MixEntry_]
674                          }                        
675
676 data TickTransEnv = TTE { fileName      :: FastString
677                         , declPath     :: [String]
678                         , inScope      :: VarSet
679                         , blackList   :: Map SrcSpan ()
680                         }
681
682 --      deriving Show
683
684 type FreeVars = OccEnv Id
685 noFVs :: FreeVars
686 noFVs = emptyOccEnv
687
688 -- Note [freevars]
689 --   For breakpoints we want to collect the free variables of an
690 --   expression for pinning on the HsTick.  We don't want to collect
691 --   *all* free variables though: in particular there's no point pinning
692 --   on free variables that are will otherwise be in scope at the GHCi
693 --   prompt, which means all top-level bindings.  Unfortunately detecting
694 --   top-level bindings isn't easy (collectHsBindsBinders on the top-level
695 --   bindings doesn't do it), so we keep track of a set of "in-scope"
696 --   variables in addition to the free variables, and the former is used
697 --   to filter additions to the latter.  This gives us complete control
698 --   over what free variables we track.
699
700 data TM a = TM { unTM :: TickTransEnv -> TickTransState -> (a,FreeVars,TickTransState) }
701         -- a combination of a state monad (TickTransState) and a writer
702         -- monad (FreeVars).
703
704 instance Monad TM where
705   return a = TM $ \ _env st -> (a,noFVs,st)
706   (TM m) >>= k = TM $ \ env st -> 
707                                 case m env st of
708                                   (r1,fv1,st1) -> 
709                                      case unTM (k r1) env st1 of
710                                        (r2,fv2,st2) -> 
711                                           (r2, fv1 `plusOccEnv` fv2, st2)
712
713 -- getState :: TM TickTransState
714 -- getState = TM $ \ env st -> (st, noFVs, st)
715
716 -- setState :: (TickTransState -> TickTransState) -> TM ()
717 -- setState f = TM $ \ env st -> ((), noFVs, f st)
718
719 getEnv :: TM TickTransEnv
720 getEnv = TM $ \ env st -> (env, noFVs, st)
721
722 withEnv :: (TickTransEnv -> TickTransEnv) -> TM a -> TM a
723 withEnv f (TM m) = TM $ \ env st -> 
724                                  case m (f env) st of
725                                    (a, fvs, st') -> (a, fvs, st')
726
727 getFreeVars :: TM a -> TM (FreeVars, a)
728 getFreeVars (TM m) 
729   = TM $ \ env st -> case m env st of (a, fv, st') -> ((fv,a), fv, st')
730
731 freeVar :: Id -> TM ()
732 freeVar id = TM $ \ env st -> 
733                 if id `elemVarSet` inScope env
734                    then ((), unitOccEnv (nameOccName (idName id)) id, st)
735                    else ((), noFVs, st)
736
737 addPathEntry :: String -> TM a -> TM a
738 addPathEntry nm = withEnv (\ env -> env { declPath = declPath env ++ [nm] })
739
740 getPathEntry :: TM [String]
741 getPathEntry = declPath `liftM` getEnv
742
743 getFileName :: TM FastString
744 getFileName = fileName `liftM` getEnv
745
746 sameFileName :: SrcSpan -> TM a -> TM a -> TM a
747 sameFileName pos out_of_scope in_scope = do
748   file_name <- getFileName
749   case srcSpanFileName_maybe pos of 
750     Just file_name2 
751       | file_name == file_name2 -> in_scope
752     _ -> out_of_scope
753
754 bindLocals :: [Id] -> TM a -> TM a
755 bindLocals new_ids (TM m)
756   = TM $ \ env st -> 
757                  case m env{ inScope = inScope env `extendVarSetList` new_ids } st of
758                    (r, fv, st') -> (r, fv `delListFromOccEnv` occs, st')
759   where occs = [ nameOccName (idName id) | id <- new_ids ] 
760
761 isBlackListed :: SrcSpan -> TM Bool
762 isBlackListed pos = TM $ \ env st -> 
763               case Map.lookup pos (blackList env) of
764                 Nothing -> (False,noFVs,st)
765                 Just () -> (True,noFVs,st)
766
767 -- the tick application inherits the source position of its
768 -- expression argument to support nested box allocations 
769 allocTickBox :: BoxLabel -> SrcSpan -> TM (HsExpr Id) -> TM (LHsExpr Id)
770 allocTickBox boxLabel pos m | isGoodSrcSpan' pos = 
771   sameFileName pos 
772     (do e <- m; return (L pos e)) $ do
773   (fvs, e) <- getFreeVars m
774   TM $ \ env st ->
775     let c = tickBoxCount st
776         ids = occEnvElts fvs
777         mes = mixEntries st
778         me = (pos, declPath env, map (nameOccName.idName) ids, boxLabel)
779     in
780     ( L pos (HsTick c ids (L pos e))
781     , fvs
782     , st {tickBoxCount=c+1,mixEntries=me:mes}
783     )
784 allocTickBox _boxLabel pos m = do e <- m; return (L pos e)
785
786 -- the tick application inherits the source position of its
787 -- expression argument to support nested box allocations 
788 allocATickBox :: BoxLabel -> SrcSpan -> FreeVars -> TM (Maybe (Int,[Id]))
789 allocATickBox boxLabel pos fvs | isGoodSrcSpan' pos = 
790   sameFileName pos 
791     (return Nothing) $ TM $ \ env st ->
792   let mydecl_path
793         | null (declPath env), TopLevelBox x <- boxLabel = x
794         | otherwise = declPath env
795       me = (pos, mydecl_path, map (nameOccName.idName) ids, boxLabel)
796       c = tickBoxCount st
797       mes = mixEntries st
798       ids = occEnvElts fvs
799   in ( Just (c, ids)
800      , noFVs
801      , st {tickBoxCount=c+1, mixEntries=me:mes}
802      )
803 allocATickBox _boxLabel _pos _fvs = return Nothing
804
805 allocBinTickBox :: (Bool -> BoxLabel) -> SrcSpan -> TM (HsExpr Id)
806                 -> TM (LHsExpr Id)
807 allocBinTickBox boxLabel pos m
808  | not opt_Hpc = allocTickBox (ExpBox False) pos m
809  | isGoodSrcSpan' pos =
810  do
811  e <- m
812  TM $ \ env st ->
813   let meT = (pos,declPath env, [],boxLabel True)
814       meF = (pos,declPath env, [],boxLabel False)
815       meE = (pos,declPath env, [],ExpBox False)
816       c = tickBoxCount st
817       mes = mixEntries st
818   in 
819              ( L pos $ HsTick c [] $ L pos $ HsBinTick (c+1) (c+2) (L pos e)
820            -- notice that F and T are reversed,
821            -- because we are building the list in
822            -- reverse...
823              , noFVs
824              , st {tickBoxCount=c+3 , mixEntries=meF:meT:meE:mes}
825              )
826 allocBinTickBox _boxLabel pos m = do e <- m; return (L pos e)
827
828 isGoodSrcSpan' :: SrcSpan -> Bool
829 isGoodSrcSpan' pos
830    | not (isGoodSrcSpan pos) = False
831    | start == end            = False
832    | otherwise               = True
833   where
834    start = srcSpanStart pos
835    end   = srcSpanEnd pos
836
837 mkHpcPos :: SrcSpan -> HpcPos
838 mkHpcPos pos 
839    | not (isGoodSrcSpan' pos) = panic "bad source span; expected such spans to be filtered out"
840    | otherwise                = hpcPos
841   where
842    start = srcSpanStart pos
843    end   = srcSpanEnd pos
844    hpcPos = toHpcPos ( srcLocLine start
845                      , srcLocCol start
846                      , srcLocLine end
847                      , srcLocCol end - 1
848                      )
849
850 hpcSrcSpan :: SrcSpan
851 hpcSrcSpan = mkGeneralSrcSpan (fsLit "Haskell Program Coverage internals")
852 \end{code}
853
854
855 \begin{code}
856 matchesOneOfMany :: [LMatch Id] -> Bool
857 matchesOneOfMany lmatches = sum (map matchCount lmatches) > 1
858   where
859         matchCount (L _ (Match _pats _ty (GRHSs grhss _binds))) = length grhss
860 \end{code}
861
862
863 \begin{code}
864 type MixEntry_ = (SrcSpan, [String], [OccName], BoxLabel)
865
866 -- For the hash value, we hash everything: the file name, 
867 --  the timestamp of the original source file, the tab stop,
868 --  and the mix entries. We cheat, and hash the show'd string.
869 -- This hash only has to be hashed at Mix creation time,
870 -- and is for sanity checking only.
871
872 mixHash :: FilePath -> Integer -> Int -> [MixEntry] -> Int
873 mixHash file tm tabstop entries = fromIntegral $ hashString
874         (show $ Mix file tm 0 tabstop entries)
875 \end{code}
876
877 %************************************************************************
878 %*                                                                      *
879 %*              initialisation
880 %*                                                                      *
881 %************************************************************************
882
883 Each module compiled with -fhpc declares an initialisation function of
884 the form `hpc_init_<module>()`, which is emitted into the _stub.c file
885 and annotated with __attribute__((constructor)) so that it gets
886 executed at startup time.
887
888 The function's purpose is to call hs_hpc_module to register this
889 module with the RTS, and it looks something like this:
890
891 static void hpc_init_Main(void) __attribute__((constructor));
892 static void hpc_init_Main(void)
893 {extern StgWord64 _hpc_tickboxes_Main_hpc[];
894  hs_hpc_module("Main",8,1150288664,_hpc_tickboxes_Main_hpc);}
895
896 \begin{code}
897 hpcInitCode :: Module -> HpcInfo -> SDoc
898 hpcInitCode _ (NoHpcInfo {}) = empty
899 hpcInitCode this_mod (HpcInfo tickCount hashNo)
900  = vcat
901     [ text "static void hpc_init_" <> ppr this_mod
902          <> text "(void) __attribute__((constructor));"
903     , text "static void hpc_init_" <> ppr this_mod <> text "(void)"
904     , braces (vcat [
905         ptext (sLit "extern StgWord64 ") <> tickboxes <>
906                ptext (sLit "[]") <> semi,
907         ptext (sLit "hs_hpc_module") <>
908           parens (hcat (punctuate comma [
909               doubleQuotes full_name_str,
910               int tickCount, -- really StgWord32
911               int hashNo,    -- really StgWord32
912               tickboxes
913             ])) <> semi
914        ])
915     ]
916   where
917     tickboxes = pprCLabel (mkHpcTicksLabel $ this_mod)
918
919     module_name  = hcat (map (text.charToC) $
920                          bytesFS (moduleNameFS (Module.moduleName this_mod)))
921     package_name = hcat (map (text.charToC) $
922                          bytesFS (packageIdFS  (modulePackageId this_mod)))
923     full_name_str
924        | modulePackageId this_mod == mainPackageId
925        = module_name
926        | otherwise
927        = package_name <> char '/' <> module_name
928 \end{code}