1 -----------------------------------------------------------------------------
3 -- Support code for instrumentation and expansion of the breakpoint combinator
5 -- Pepe Iborra (supported by Google SoC) 2006
7 -----------------------------------------------------------------------------
11 dsAndThenMaybeInsertBreakpoint
12 , maybeInsertBreakpoint
48 import {-#SOURCE#-}DsExpr ( dsLExpr )
51 import Foreign.StablePtr
55 mkBreakpointExpr :: SrcSpan -> Id -> DsM (LHsExpr Id)
56 mkBreakpointExpr loc bkptFuncId = do
57 scope' <- getLocalBindsDs
59 let scope = filter (isValidType .idType ) scope'
60 mod_name = moduleNameFS$ moduleName mod
61 if null scope && instrumenting
62 -- need to return some expresion, hence lazy is used here as a noop (hopefully)
63 then return (l$ HsVar lazyId)
65 when (not instrumenting) $
66 warnDs (text "Extracted ids:" <+> (ppr scope $$
67 ppr (map idType scope)))
68 stablePtr <- ioToIOEnv $ newStablePtr scope
69 site <- if instrumenting
70 then recordBkpt (srcSpanStart loc)
72 ATyCon opaqueTyCon <- dsLookupGlobal opaqueTyConName
73 jumpFuncId <- mkJumpFunc bkptFuncId
74 let [opaqueDataCon] = tyConDataCons opaqueTyCon
75 opaqueId = dataConWrapId opaqueDataCon
76 opaqueTy = mkTyConApp opaqueTyCon []
78 l(HsApp (l(HsWrap (WpTyApp (idType id)) (HsVar opaqueId)))
80 -- Yes, I know... I'm gonna burn in hell.
81 Ptr addr# = castStablePtrToPtr stablePtr
82 hvals = ExplicitList opaqueTy (map wrapInOpaque scope)
83 locInfo = nlTuple [ HsLit (HsString (packageIdFS$ modulePackageId mod))
84 , HsLit (HsString mod_name)
85 , HsLit (HsInt (fromIntegral site))]
87 funE = l$ HsVar jumpFuncId
88 ptrE = l (HsLit (HsInt (fromIntegral (I# (addr2Int# addr#)))))
91 msgE = l (srcSpanLit loc)
92 return$ l(l(l(l(funE `HsApp` ptrE) `HsApp` hvalE) `HsApp` locE) `HsApp` msgE)
94 nlTuple exps = ExplicitTuple (map noLoc exps) Boxed
95 -- isValidType (PredTy p `FunTy` ty ) = False -- TODO: Too restrictive ?
96 isValidType (FunTy a b) = isValidType a && isValidType b
97 isValidType (NoteTy _ t) = isValidType t
98 isValidType (AppTy a b) = isValidType a && isValidType b
99 isValidType (TyConApp con ts) = not (isUnLiftedTyCon con) && all isValidType ts
101 srcSpanLit :: SrcSpan -> HsExpr Id
102 srcSpanLit span = HsLit (HsString (mkFastString (showSDoc (ppr span))))
103 instrumenting = idName bkptFuncId == breakpointAutoName
105 mkBreakpointExpr = undefined -- A stage1 ghc doesn't care about breakpoints
108 debug_enabled :: DsM Bool
109 #if defined(GHCI) && defined(DEBUGGER)
111 debugging <- doptDs Opt_Debugging
112 b_enabled <- breakpoints_enabled
113 return (debugging && b_enabled)
115 debug_enabled = return False
118 isInstrumentationSpot (L loc e) = do
119 ghcmode <- getGhcModeDs
120 instrumenting <- debug_enabled
121 return$ instrumenting
122 && isGoodSrcSpan loc -- Avoids 'derived' code
123 && (not$ isRedundant e)
125 isRedundant HsLet {} = True
126 isRedundant HsDo {} = True
127 isRedundant HsCase {} = False
128 isRedundant _ = False
130 dynBreakpoint :: SrcSpan -> DsM (LHsExpr Id)
131 dynBreakpoint loc | not (isGoodSrcSpan loc) =
132 pprPanic "dynBreakpoint" (ppr loc)
133 dynBreakpoint loc = do
134 let autoBreakpoint = Id.mkGlobalId VanillaGlobal breakpointAutoName
135 breakpointAutoTy vanillaIdInfo
137 ioToIOEnv$ debugTraceMsg dflags 3 (text "Breakpoint inserted at " <> ppr loc)
138 return$ L loc (HsVar autoBreakpoint)
139 where breakpointAutoTy = (ForAllTy alphaTyVar
140 (FunTy (TyVarTy alphaTyVar)
141 (TyVarTy alphaTyVar)))
143 -- Records a breakpoint site and returns the site number
144 recordBkpt :: SrcLoc -> DsM (Int)
146 sites_var <- getBkptSitesDs
147 sites <- ioToIOEnv$ readIORef sites_var
148 let site = length sites + 1
149 let coords = (srcLocLine loc, srcLocCol loc)
150 ioToIOEnv$ writeIORef sites_var ((site, coords) : sites)
153 mkJumpFunc :: Id -> DsM Id
154 mkJumpFunc bkptFuncId
155 | idName bkptFuncId == breakpointName
156 = build breakpointJumpName id
157 | idName bkptFuncId == breakpointCondName
158 = build breakpointCondJumpName (FunTy boolTy)
159 | idName bkptFuncId == breakpointAutoName
160 = build breakpointAutoJumpName id
163 basicType extra opaqueTy =
165 (FunTy (mkListTy opaqueTy)
166 (FunTy (mkTupleType [stringTy, stringTy, intTy])
170 (FunTy (TyVarTy tyvar)
171 (TyVarTy tyvar))))))))
172 build name extra = do
173 ATyCon opaqueTyCon <- dsLookupGlobal opaqueTyConName
174 return$ Id.mkGlobalId VanillaGlobal name
175 (basicType extra (mkTyConApp opaqueTyCon [])) vanillaIdInfo
176 mkTupleType tys = mkTupleTy Boxed (length tys) tys
178 breakpoints_enabled :: DsM Bool
179 dsAndThenMaybeInsertBreakpoint :: LHsExpr Id -> DsM CoreExpr
180 -- | Takes an expression and its type
181 maybeInsertBreakpoint :: LHsExpr Id -> Type -> DsM (LHsExpr Id)
184 maybeInsertBreakpoint lhsexpr@(L loc _) ty = do
185 instrumenting <- isInstrumentationSpot lhsexpr
187 then do L _ dynBkpt <- dynBreakpoint loc
188 return$ l(HsApp (l$ HsWrap (WpTyApp ty) dynBkpt) lhsexpr)
192 dsAndThenMaybeInsertBreakpoint expr@(L loc _) = do
193 coreExpr <- dsLExpr expr
194 instrumenting <- isInstrumentationSpot expr
196 then do L _ dynBkpt<- dynBreakpoint loc
197 bkptCore <- dsLExpr (l$ HsWrap (WpTyApp (exprType coreExpr)) dynBkpt)
198 return (bkptCore `App` coreExpr)
202 breakpoints_enabled = do
203 ghcMode <- getGhcModeDs
204 currentModule <- getModuleDs
205 ignore_breakpoints <- doptDs Opt_IgnoreBreakpoints
206 return ( not ignore_breakpoints
207 && ghcMode == Interactive
208 && currentModule /= iNTERACTIVE )
210 maybeInsertBreakpoint expr _ = return expr
211 dsAndThenMaybeInsertBreakpoint coreExpr = dsLExpr coreExpr
212 breakpoints_enabled = return False