Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
  • GHC GHC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 5,249
    • Issues 5,249
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 579
    • Merge requests 579
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Releases
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Glasgow Haskell CompilerGlasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #11047
Closed
Open
Issue created Nov 01, 2015 by Simon Marlow@simonmarDeveloper

Provide call stacks in GHCi

I want call stacks to be available in GHCi with no effort on the part of the user, or changes to the source code. The call stack will be available both programatically and via GHCi commands:

  • GHC.Stack.currentCallStack returns the current call stack as [String]. This can be used from error and copied into the exception string.
  • Debug.Trace.traceStack prints out the stack anywhere.
  • GHCi will have a new command :where to print out the stack when stopped at a breakpoint

The stack trace will be the accurate (i.e. not exposing details of lazy evaluation or tail calls) and detailed (including locations of calls, not just the enclosing function definition).

Implementation

Here's how it's going to work:

  • We make GHCi work with profiling (done: D1407)
  • We make breakpoint ticks behave like SCC annotations, and update the interpreter to implement the cost-centre-stack semantics.

Example

Here's an example from my prototype:

g :: Int -> [Int]
g n = traceStack "g" [n]

h :: Int -> Bool
h n = case g n of
         [] -> True
         (x:xs) -> False

map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x : map f xs

k n = map h [n]
[1 of 1] Compiling Main             ( /home/smarlow/scratch/dbg1.hs, interpreted )
Ok, modules loaded: Main.
*Main> k 1
[g
Stack trace:
  Main.g (/home/smarlow/scratch/dbg1.hs:13:7-24)
  Main.g (/home/smarlow/scratch/dbg1.hs:13:1-24)
  Main.h (/home/smarlow/scratch/dbg1.hs:16:12-14)
  Main.h (/home/smarlow/scratch/dbg1.hs:(16,7)-(18,24))
  Main.h (/home/smarlow/scratch/dbg1.hs:(16,1)-(18,24))
  Main.map (/home/smarlow/scratch/dbg1.hs:22:16-18)
  Main.map (/home/smarlow/scratch/dbg1.hs:22:16-29)
  Main.map (/home/smarlow/scratch/dbg1.hs:(21,1)-(22,29))
  Main.k (/home/smarlow/scratch/dbg1.hs:24:7-15)
  Main.k (/home/smarlow/scratch/dbg1.hs:24:1-15)
False]
*Main> 

We could trim some of the extra detail from the stack trace so that each function appears once; there are several choices here, currently I'm collecting and displaying the most detail.

Deployment

One disadvantage of this is that it requires GHCi to be built with profiling, and all the libraries have to be built with profiling too. There are two options for deployment:

  1. We deploy two versions of GHCi (profiled and non-profiled), or
  2. We expand on what GHCJS did, and make the interpreted code run in a separate process, thus separating the GHCi binary itself from the code being interpreted. This would allow the interpreted code to be run with the profiled RTS while GHCi itself is unprofiled.
Edited Mar 10, 2019 by Simon Marlow
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking