From cec8c00ddc2527478da838df88c8911fe0296ed2 Mon Sep 17 00:00:00 2001
From: Peter Wortmann <scpmw@leeds.ac.uk>
Date: Wed, 8 Aug 2012 16:52:15 +0100
Subject: [PATCH] Annotate code in {-# LINE #-} pragmas as well
I suppose this was a good idea for HPC, as it assumed that source code
annotations coming from a source file could only talk about the same
source file (by how Mix files are saved).
I don't see a reason why cost-centres or source annotations would want
that kind of behaviour. I introduced a flag for toggling the behaviour
per tickish.
(plus some minor refactoring, as well as making sure that the same check
applies to binary tick boxes, where they had apparently been forgotten.)
---
compiler/deSugar/Coverage.lhs | 90 +++++++++++++++++++++++++++--------------
1 files changed, 59 insertions(+), 31 deletions(-)
diff --git a/compiler/deSugar/Coverage.lhs b/compiler/deSugar/Coverage.lhs
index d3fbe4c..2f5ef71 100644
|
a
|
b
|
|
| 89 | 89 | | tyCon <- tyCons ] |
| 90 | 90 | , density = mkDensity dflags |
| 91 | 91 | , this_mod = mod |
| | 92 | , tickishType = case hscTarget dflags of |
| | 93 | HscInterpreted -> Breakpoints |
| | 94 | _ | opt_Hpc -> HpcTicks |
| | 95 | | dopt Opt_SccProfilingOn dflags |
| | 96 | -> ProfNotes |
| | 97 | | otherwise -> error "addTicksToBinds: No way to annotate!" |
| 92 | 98 | }) |
| 93 | 99 | (TT |
| 94 | 100 | { tickBoxCount = 0 |
| … |
… |
|
| 910 | 916 | , inScope :: VarSet |
| 911 | 917 | , blackList :: Map SrcSpan () |
| 912 | 918 | , this_mod :: Module |
| | 919 | , tickishType :: TickishType |
| 913 | 920 | } |
| 914 | 921 | |
| 915 | 922 | -- deriving Show |
| 916 | 923 | |
| | 924 | data TickishType = ProfNotes | HpcTicks | Breakpoints |
| | 925 | |
| | 926 | |
| | 927 | -- | Tickishs that only make sense when their source code location |
| | 928 | -- refers to the current file. This might not always be true due to |
| | 929 | -- LINE pragmas in the code - which would confuse at least HPC. |
| | 930 | tickSameFileOnly :: TickishType -> Bool |
| | 931 | tickSameFileOnly HpcTicks = True |
| | 932 | tickSameFileOnly _other = False |
| | 933 | |
| 917 | 934 | type FreeVars = OccEnv Id |
| 918 | 935 | noFVs :: FreeVars |
| 919 | 936 | noFVs = emptyOccEnv |
| … |
… |
|
| 982 | 999 | getFileName :: TM FastString |
| 983 | 1000 | getFileName = fileName `liftM` getEnv |
| 984 | 1001 | |
| 985 | | sameFileName :: SrcSpan -> TM a -> TM a -> TM a |
| 986 | | sameFileName pos out_of_scope in_scope = do |
| | 1002 | isGoodSrcSpan' :: SrcSpan -> Bool |
| | 1003 | isGoodSrcSpan' pos@(RealSrcSpan _) = srcSpanStart pos /= srcSpanEnd pos |
| | 1004 | isGoodSrcSpan' (UnhelpfulSpan _) = False |
| | 1005 | |
| | 1006 | isGoodTickSrcSpan :: SrcSpan -> TM Bool |
| | 1007 | isGoodTickSrcSpan pos = do |
| 987 | 1008 | file_name <- getFileName |
| 988 | | case srcSpanFileName_maybe pos of |
| 989 | | Just file_name2 |
| 990 | | | file_name == file_name2 -> in_scope |
| 991 | | _ -> out_of_scope |
| | 1009 | tickish <- tickishType `liftM` getEnv |
| | 1010 | let need_same_file = tickSameFileOnly tickish |
| | 1011 | same_file = Just file_name == srcSpanFileName_maybe pos |
| | 1012 | return (isGoodSrcSpan' pos && (not need_same_file || same_file)) |
| | 1013 | |
| | 1014 | ifGoodTickSrcSpan :: SrcSpan -> TM a -> TM a -> TM a |
| | 1015 | ifGoodTickSrcSpan pos then_code else_code = do |
| | 1016 | good <- isGoodTickSrcSpan pos |
| | 1017 | if good then then_code else else_code |
| 992 | 1018 | |
| 993 | 1019 | bindLocals :: [Id] -> TM a -> TM a |
| 994 | 1020 | bindLocals new_ids (TM m) |
| … |
… |
|
| 1007 | 1033 | -- expression argument to support nested box allocations |
| 1008 | 1034 | allocTickBox :: BoxLabel -> Bool -> Bool -> SrcSpan -> TM (HsExpr Id) |
| 1009 | 1035 | -> TM (LHsExpr Id) |
| 1010 | | allocTickBox boxLabel countEntries topOnly pos m | isGoodSrcSpan' pos = |
| 1011 | | sameFileName pos (do e <- m; return (L pos e)) $ do |
| | 1036 | allocTickBox boxLabel countEntries topOnly pos m = |
| | 1037 | ifGoodTickSrcSpan pos (do |
| 1012 | 1038 | (fvs, e) <- getFreeVars m |
| 1013 | 1039 | env <- getEnv |
| 1014 | 1040 | tickish <- mkTickish boxLabel countEntries topOnly pos fvs (declPath env) |
| 1015 | 1041 | return (L pos (HsTick tickish (L pos e))) |
| 1016 | | allocTickBox _boxLabel _countEntries _topOnly pos m = do |
| 1017 | | e <- m |
| 1018 | | return (L pos e) |
| 1019 | | |
| | 1042 | ) (do |
| | 1043 | e <- m |
| | 1044 | return (L pos e) |
| | 1045 | ) |
| 1020 | 1046 | |
| 1021 | 1047 | -- the tick application inherits the source position of its |
| 1022 | 1048 | -- expression argument to support nested box allocations |
| 1023 | 1049 | allocATickBox :: BoxLabel -> Bool -> Bool -> SrcSpan -> FreeVars |
| 1024 | 1050 | -> TM (Maybe (Tickish Id)) |
| 1025 | | allocATickBox boxLabel countEntries topOnly pos fvs | isGoodSrcSpan' pos = |
| 1026 | | sameFileName pos (return Nothing) $ do |
| | 1051 | allocATickBox boxLabel countEntries topOnly pos fvs = |
| | 1052 | ifGoodTickSrcSpan pos (do |
| 1027 | 1053 | let |
| 1028 | 1054 | mydecl_path = case boxLabel of |
| 1029 | 1055 | TopLevelBox x -> x |
| … |
… |
|
| 1031 | 1057 | _ -> panic "allocATickBox" |
| 1032 | 1058 | tickish <- mkTickish boxLabel countEntries topOnly pos fvs mydecl_path |
| 1033 | 1059 | return (Just tickish) |
| 1034 | | allocATickBox _boxLabel _countEntries _topOnly _pos _fvs = |
| 1035 | | return Nothing |
| | 1060 | ) (return Nothing) |
| 1036 | 1061 | |
| 1037 | 1062 | |
| 1038 | 1063 | mkTickish :: BoxLabel -> Bool -> Bool -> SrcSpan -> OccEnv Id -> [String] |
| … |
… |
|
| 1059 | 1084 | |
| 1060 | 1085 | count = countEntries && dopt Opt_ProfCountEntries dflags |
| 1061 | 1086 | |
| 1062 | | tickish |
| 1063 | | | opt_Hpc = HpcTick (this_mod env) c |
| 1064 | | | dopt Opt_SccProfilingOn dflags = ProfNote cc count True{-scopes-} |
| 1065 | | | otherwise = Breakpoint c ids |
| | 1087 | tickish = case tickishType env of |
| | 1088 | HpcTicks -> HpcTick (this_mod env) c |
| | 1089 | ProfNotes -> ProfNote cc count True{-scopes-} |
| | 1090 | Breakpoints -> Breakpoint c ids |
| | 1091 | _otherwise -> panic "mkTickish: bad source span!" |
| 1066 | 1092 | in |
| 1067 | 1093 | ( tickish |
| 1068 | 1094 | , fvs |
| … |
… |
|
| 1072 | 1098 | |
| 1073 | 1099 | allocBinTickBox :: (Bool -> BoxLabel) -> SrcSpan -> TM (HsExpr Id) |
| 1074 | 1100 | -> TM (LHsExpr Id) |
| 1075 | | allocBinTickBox boxLabel pos m |
| 1076 | | | not opt_Hpc = allocTickBox (ExpBox False) False False pos m |
| 1077 | | | isGoodSrcSpan' pos = |
| 1078 | | do |
| 1079 | | e <- m |
| | 1101 | allocBinTickBox boxLabel pos m = do |
| | 1102 | env <- getEnv |
| | 1103 | case tickishType env of |
| | 1104 | HpcTicks -> do e <- liftM (L pos) m |
| | 1105 | ifGoodTickSrcSpan pos |
| | 1106 | (mkBinTickBoxHpc boxLabel pos e) |
| | 1107 | (return e) |
| | 1108 | _other -> allocTickBox (ExpBox False) False False pos m |
| | 1109 | |
| | 1110 | mkBinTickBoxHpc :: (Bool -> BoxLabel) -> SrcSpan -> LHsExpr Id |
| | 1111 | -> TM (LHsExpr Id) |
| | 1112 | mkBinTickBoxHpc boxLabel pos e = |
| 1080 | 1113 | TM $ \ env st -> |
| 1081 | 1114 | let meT = (pos,declPath env, [],boxLabel True) |
| 1082 | 1115 | meF = (pos,declPath env, [],boxLabel False) |
| … |
… |
|
| 1084 | 1117 | c = tickBoxCount st |
| 1085 | 1118 | mes = mixEntries st |
| 1086 | 1119 | in |
| 1087 | | ( L pos $ HsTick (HpcTick (this_mod env) c) $ L pos $ HsBinTick (c+1) (c+2) (L pos e) |
| | 1120 | ( L pos $ HsTick (HpcTick (this_mod env) c) $ L pos $ HsBinTick (c+1) (c+2) e |
| 1088 | 1121 | -- notice that F and T are reversed, |
| 1089 | 1122 | -- because we are building the list in |
| 1090 | 1123 | -- reverse... |
| 1091 | 1124 | , noFVs |
| 1092 | 1125 | , st {tickBoxCount=c+3 , mixEntries=meF:meT:meE:mes} |
| 1093 | 1126 | ) |
| 1094 | | allocBinTickBox _boxLabel pos m = do e <- m; return (L pos e) |
| 1095 | | |
| 1096 | | isGoodSrcSpan' :: SrcSpan -> Bool |
| 1097 | | isGoodSrcSpan' pos@(RealSrcSpan _) = srcSpanStart pos /= srcSpanEnd pos |
| 1098 | | isGoodSrcSpan' (UnhelpfulSpan _) = False |
| 1099 | 1127 | |
| 1100 | 1128 | mkHpcPos :: SrcSpan -> HpcPos |
| 1101 | 1129 | mkHpcPos pos@(RealSrcSpan s) |