Skip to content

Commit a46b39b

Browse files
authored
Add support for Stack annotations with optional source locations (#333)
1 parent 732f93f commit a46b39b

10 files changed

Lines changed: 95 additions & 11 deletions

File tree

haskell-debugger/GHC/Debugger/Runtime/Eval/RemoteExpr/Builtin.hs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import GHC.Exts.Heap.Closures
2727
import GHC.Debugger.Runtime.Eval.RemoteExpr (RemoteExpr)
2828
import qualified GHC.Debugger.Runtime.Eval.RemoteExpr as Remote
2929
import GHC.Stack.Annotation.Experimental
30+
import GHC.Types.SrcLoc
3031

3132
-- | Remote 'GHC.Stack.CloneStack.cloneThreadStack'
3233
cloneThreadStack :: RemoteExpr ThreadId -> RemoteExpr (IO StackSnapshot)
@@ -88,5 +89,10 @@ f `compose` g = Remote.app (Remote.app composeVar f) g where
8889
composeVar = Remote.var (mkModuleName "GHC.Base") "." []
8990

9091
displayStackAnnotation :: RemoteExpr SomeStackAnnotation -> RemoteExpr String
91-
displayStackAnnotation = Remote.app $
92-
Remote.var (mkModuleName "GHC.Stack.Annotation.Experimental") "displayStackAnnotation" ["GHC.Stack.Annotation.Experimental.SomeStackAnnotation"]
92+
displayStackAnnotation = Remote.app $ Remote.var (mkModuleName "GHC.Internal.Stack.Annotation") "displayStackAnnotation" ["GHC.Stack.Annotation.Experimental.SomeStackAnnotation"]
93+
94+
displayStackAnnotationShort :: RemoteExpr SomeStackAnnotation -> RemoteExpr String
95+
displayStackAnnotationShort = Remote.app $ Remote.var (mkModuleName "GHC.Internal.Stack.Annotation") "displayStackAnnotationShort" ["GHC.Stack.Annotation.Experimental.SomeStackAnnotation"]
96+
97+
stackAnnotationSourceLocation :: RemoteExpr SomeStackAnnotation -> RemoteExpr (Maybe SrcLoc)
98+
stackAnnotationSourceLocation = Remote.app $ Remote.var (mkModuleName "GHC.Internal.Stack.Annotation") "stackAnnotationSourceLocation" ["SGHC.Stack.Annotation.Experimental.omeStackAnnotation"]

haskell-debugger/GHC/Debugger/Runtime/Interpreter/Custom.hs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ threadInfo threadId = do
140140
stackFrameInfo :: (StackFrame, Maybe InfoProv) -> IO (Maybe StackFrameInfo)
141141
stackFrameInfo (AnnFrame{annotation}, _)
142142
| let Box annVal = annotation
143-
, let stack_anno = displayStackAnnotation @SomeStackAnnotation (unsafeCoerce annVal)
144-
= pure $ Just $ StackFrameAnnotation Nothing{-No source locations yet-} stack_anno
143+
, let stack_frame = stackAnnoToStackFrameInfo (unsafeCoerce @_ @SomeStackAnnotation annVal)
144+
= pure $ Just stack_frame
145145
stackFrameInfo (_, Just ipe)
146146
= pure $ Just (StackFrameIPEInfo ipe)
147147
stackFrameInfo (RetBCO{bco}, _)
@@ -150,6 +150,14 @@ stackFrameInfo (RetBCO{bco}, _)
150150
stackFrameInfo _
151151
= pure Nothing
152152

153+
stackAnnoToStackFrameInfo :: SomeStackAnnotation -> StackFrameInfo
154+
stackAnnoToStackFrameInfo stack_anno =
155+
#if MIN_VERSION_ghc_experimental(9,1402,0)
156+
StackFrameAnnotation (stackAnnotationSourceLocation stack_anno) (displayStackAnnotationShort stack_anno)
157+
#else
158+
StackFrameAnnotation Nothing {-No source locations yet-} (displayStackAnnotation stack_anno)
159+
#endif
160+
153161
-- | Try to find a BRK_FUN breakpoint location at the start of a BCO heap closure
154162
lookupBCOBreakpoint :: Heap.GenClosure Box -> IO (Maybe InternalBreakpointId)
155163
lookupBCOBreakpoint Heap.BCOClosure{..}

haskell-debugger/GHC/Debugger/Runtime/Term/Parser.hs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,10 +287,16 @@ parseList item_parser =
287287
intParser :: TermParser Int
288288
intParser = fromIntegral <$> wordParser
289289

290+
intPrimParser :: TermParser Int
291+
intPrimParser = fromIntegral <$> primParser
292+
290293
-- | Parse a 'Word'
291294
wordParser :: TermParser Word
292295
wordParser = subtermWith 0 primParser
293296

297+
wordPrimParser :: TermParser Word
298+
wordPrimParser = primParser
299+
294300
-- | Parse a 'String' term
295301
stringParser :: TermParser String
296302
stringParser = do
@@ -392,4 +398,3 @@ programTermParser =
392398

393399
reifyBool :: Bool -> Debugger ForeignHValue
394400
reifyBool b = Comp.compileRaw (show b ++ ":: Bool")
395-

haskell-debugger/GHC/Debugger/Runtime/Thread/Stack.hs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,9 +148,15 @@ stackAnnoParser = do
148148
Just Term{val} -> do
149149
stack_anno <- liftDebugger $
150150
expectRight =<< Remote.evalString
151+
#if MIN_VERSION_ghc_experimental(9,1402,0)
152+
(Remote.displayStackAnnotationShort (Remote.ref (castForeignRef val)))
153+
#else
151154
(Remote.displayStackAnnotation (Remote.ref (castForeignRef val)))
155+
#endif
156+
157+
src_loc <- getOptionalStackAnnotationSrcLoc
152158

153-
pure $ Just (Nothing {- No source locations yet :( -}, stack_anno)
159+
pure $ Just (src_loc, stack_anno)
154160
_ ->
155161
pure Nothing
156162

@@ -170,6 +176,37 @@ bcoInternalBreakpointId = do
170176
, eb_info_index = fromIntegral $ brk_info_ix_hi .<<. 16 + brk_info_ix_lo
171177
}
172178

179+
getOptionalStackAnnotationSrcLoc :: TermParser (Maybe Stack.SrcLoc)
180+
#if MIN_VERSION_ghc_experimental(9,1402,0)
181+
getOptionalStackAnnotationSrcLoc = do
182+
src_loc_fv <- liftDebugger $
183+
expectRight =<< Remote.eval
184+
(Remote.stackAnnotationSourceLocation (Remote.ref (castForeignRef val)))
185+
186+
src_loc_either <- liftDebugger $
187+
obtainParsedTerm "Annotation SrcLoc" maxBound True anyTy (castForeignRef src_loc_fv) (maybeParser srcLocParser)
188+
189+
case src_loc_either of
190+
Left err -> fail (show err)
191+
Right t -> return t
192+
where
193+
-- | Parse a 'SrcLoc'.
194+
srcLocParser :: TermParser Stack.SrcLoc
195+
srcLocParser = do
196+
Stack.SrcLoc
197+
<$> subtermWith 0 stringParser -- srcLocPackage
198+
<*> subtermWith 1 stringParser -- srcLocModule
199+
<*> subtermWith 2 stringParser -- srcLocFile
200+
<*> subtermWith 3 intPrimParser -- unpacked srcLocStartLine
201+
<*> subtermWith 4 intPrimParser -- unpacked srcLocStartCol
202+
<*> subtermWith 5 intPrimParser -- unpacked srcLocEndLine
203+
<*> subtermWith 6 intPrimParser -- unpacked srcLocEndCol
204+
#else
205+
getOptionalStackAnnotationSrcLoc = do
206+
pure Nothing
207+
#endif
208+
209+
173210
-- | Parse a literal 'String' from a BCO given a valid index into the literals array
174211
bcoLiteralString :: Word -> TermParser String
175212
bcoLiteralString ix = do
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[1 of 2] Compiling Main ( <TEMPORARY-DIRECTORY>/T159.hs, <TEMPORARY-DIRECTORY>/.hdb-cache/<CACHE-ENTRY>/Main.gbc )[main]
22
(hdb) BreakFound {changed = True, breakId = [InternalBreakpointId Main 16], sourceSpan = SourceSpan {file = "<TEMPORARY-DIRECTORY>/T159.hs", startLine = 12, endLine = 12, startCol = 3, endCol = 47}}
33
(hdb) Stopped at breakpoint
4-
(hdb) [DbgStackFrame {name = "Main.foo", sourceSpan = SourceSpan {file = "<TEMPORARY-DIRECTORY>/T159.hs", startLine = 12, endLine = 12, startCol = 3, endCol = 47}, breakId = Just InternalBreakpointId Main 16},DbgStackFrame {name = "Lovely annotation, called at <TEMPORARY-DIRECTORY>/T159.hs:7:7 in main:Main", sourceSpan = SourceSpan {file = "", startLine = 0, endLine = 0, startCol = 0, endCol = 0}, breakId = Nothing},DbgStackFrame {name = "[1,2,3,4], called at <TEMPORARY-DIRECTORY>/T159.hs:6:5 in main:Main", sourceSpan = SourceSpan {file = "", startLine = 0, endLine = 0, startCol = 0, endCol = 0}, breakId = Nothing},DbgStackFrame {name = "annotateCallStackIO, called at <TEMPORARY-DIRECTORY>/T159.hs:5:3 in main:Main", sourceSpan = SourceSpan {file = "", startLine = 0, endLine = 0, startCol = 0, endCol = 0}, breakId = Nothing}]
4+
(hdb) [DbgStackFrame {name = "Main.foo", sourceSpan = SourceSpan {file = "<TEMPORARY-DIRECTORY>/T159.hs", startLine = 12, endLine = 12, startCol = 3, endCol = 47}, breakId = Just InternalBreakpointId Main 16},DbgStackFrame {name = "Lovely annotation", sourceSpan = SourceSpan {file = "<TEMPORARY-DIRECTORY>/T159.hs", startLine = 7, endLine = 7, startCol = 7, endCol = 28}, breakId = Nothing},DbgStackFrame {name = "[1,2,3,4]", sourceSpan = SourceSpan {file = "<TEMPORARY-DIRECTORY>/T159.hs", startLine = 6, endLine = 6, startCol = 5, endCol = 24}, breakId = Nothing},DbgStackFrame {name = "annotateCallStackIO", sourceSpan = SourceSpan {file = "<TEMPORARY-DIRECTORY>/T159.hs", startLine = 5, endLine = 5, startCol = 3, endCol = 22}, breakId = Nothing}]
55
(hdb) Exiting...
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[1 of 2] Compiling Main ( <TEMPORARY-DIRECTORY>/T159b.hs, <TEMPORARY-DIRECTORY>/.hdb-cache/<CACHE-ENTRY>/Main.gbc )[main]
22
(hdb) BreakFound {changed = True, breakId = [InternalBreakpointId Main 16], sourceSpan = SourceSpan {file = "<TEMPORARY-DIRECTORY>/T159b.hs", startLine = 12, endLine = 12, startCol = 3, endCol = 47}}
33
(hdb) Stopped at breakpoint
4-
(hdb) [DbgStackFrame {name = "Main.foo", sourceSpan = SourceSpan {file = "<TEMPORARY-DIRECTORY>/T159b.hs", startLine = 12, endLine = 12, startCol = 3, endCol = 47}, breakId = Just InternalBreakpointId Main 16},DbgStackFrame {name = "Lovely annotation, called at <TEMPORARY-DIRECTORY>/T159b.hs:7:7 in main:Main", sourceSpan = SourceSpan {file = "", startLine = 0, endLine = 0, startCol = 0, endCol = 0}, breakId = Nothing},DbgStackFrame {name = "[1,2,3,4], called at <TEMPORARY-DIRECTORY>/T159b.hs:6:5 in main:Main", sourceSpan = SourceSpan {file = "", startLine = 0, endLine = 0, startCol = 0, endCol = 0}, breakId = Nothing},DbgStackFrame {name = "annotateCallStackIO, called at <TEMPORARY-DIRECTORY>/T159b.hs:5:3 in main:Main", sourceSpan = SourceSpan {file = "", startLine = 0, endLine = 0, startCol = 0, endCol = 0}, breakId = Nothing}]
4+
(hdb) [DbgStackFrame {name = "Main.foo", sourceSpan = SourceSpan {file = "<TEMPORARY-DIRECTORY>/T159b.hs", startLine = 12, endLine = 12, startCol = 3, endCol = 47}, breakId = Just InternalBreakpointId Main 16},DbgStackFrame {name = "Lovely annotation", sourceSpan = SourceSpan {file = "<TEMPORARY-DIRECTORY>/T159b.hs", startLine = 7, endLine = 7, startCol = 7, endCol = 28}, breakId = Nothing},DbgStackFrame {name = "[1,2,3,4]", sourceSpan = SourceSpan {file = "<TEMPORARY-DIRECTORY>/T159b.hs", startLine = 6, endLine = 6, startCol = 5, endCol = 24}, breakId = Nothing},DbgStackFrame {name = "annotateCallStackIO", sourceSpan = SourceSpan {file = "<TEMPORARY-DIRECTORY>/T159b.hs", startLine = 5, endLine = 5, startCol = 3, endCol = 22}, breakId = Nothing}]
55
(hdb) Exiting...

test/golden/T239/T239.fails-239.ghc-1001.hdb-stdout

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
[1 of 3] Compiling GHC.Debugger.View.Class ( in-memory:GHC.Debugger.View.Class, interpreted )[haskell-debugger-view-in-memory]
2-
[2 of 3] Compiling Main ( <TEMPORARY-DIRECTORY>/Main.hs, interpreted )[main]
3-
(hdb) BreakFound {changed = True, breakId = [InternalBreakpointId Main 2], sourceSpan = SourceSpan {file = "<TEMPORARY-DIRECTORY>/Main.hs", startLine = 27, endLine = 27, startCol = 3, endCol = 28}}
1+
[1 of 2] Compiling Main ( <TEMPORARY-DIRECTORY>/Main.hs, <TEMPORARY-DIRECTORY>/.hdb-cache/<CACHE-ENTRY>/Main.gbc )[main]
2+
(hdb) BreakFound {changed = True, breakId = [InternalBreakpointId Main 5], sourceSpan = SourceSpan {file = "<TEMPORARY-DIRECTORY>/Main.hs", startLine = 27, endLine = 27, startCol = 3, endCol = 28}}
43
(hdb) Stopped at breakpoint
54
(hdb) _result : IO () = <fn> :: IO ()
65
container : Container = Container
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
cabal-version: 3.8
2+
name: T159
3+
version: 0.1.0.0
4+
build-type: Simple
5+
6+
executable T159
7+
main-is: Main.hs
8+
build-depends: base,
9+
ghc-experimental,
10+
hs-source-dirs: app,
11+
default-language: Haskell2010
12+
ghc-options: -finfo-table-map
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module Main (main) where
2+
3+
import GHC.Stack.Annotation.Experimental
4+
5+
main :: IO ()
6+
main = do
7+
annotateCallStackIO $ do
8+
annotateStackShowIO ([1..4] :: [Int]) $ do
9+
annotateStackStringIO "Lovely annotation" $ do
10+
foo 500
11+
12+
foo :: Int -> IO ()
13+
foo arg =
14+
putStrLn $ "foo: " <> show (arg * arg * arg)
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
packages: .
2+
3+
with-compiler: /home/hugin/Documents/haskell/ghc-more-annotations/_default/stage1/bin/ghc

0 commit comments

Comments
 (0)