Correctly add unwinding info in manifestSp and makeFixupBlocks
[ghc.git] / compiler / cmm / Debug.hs
1 {-# LANGUAGE GADTs #-}
2
3 -----------------------------------------------------------------------------
4 --
5 -- Debugging data
6 --
7 -- Association of debug data on the Cmm level, with methods to encode it in
8 -- event log format for later inclusion in profiling event logs.
9 --
10 -----------------------------------------------------------------------------
11
12 module Debug (
13
14 DebugBlock(..), dblIsEntry,
15 cmmDebugGen,
16 cmmDebugLabels,
17 cmmDebugLink,
18 debugToMap,
19
20 -- * Unwinding information
21 UnwindTable, UnwindPoint(..),
22 UnwindExpr(..), toUnwindExpr
23 ) where
24
25 import GhcPrelude
26
27 import BlockId
28 import CLabel
29 import Cmm
30 import CmmUtils
31 import CoreSyn
32 import FastString ( nilFS, mkFastString )
33 import Module
34 import Outputable
35 import PprCore ()
36 import PprCmmExpr ( pprExpr )
37 import SrcLoc
38 import Util ( seqList )
39
40 import Hoopl.Block
41 import Hoopl.Collections
42 import Hoopl.Graph
43 import Hoopl.Label
44
45 import Data.Maybe
46 import Data.List ( minimumBy, nubBy )
47 import Data.Ord ( comparing )
48 import qualified Data.Map as Map
49 import Data.Either ( partitionEithers )
50
51 -- | Debug information about a block of code. Ticks scope over nested
52 -- blocks.
53 data DebugBlock =
54 DebugBlock
55 { dblProcedure :: !Label -- ^ Entry label of containing proc
56 , dblLabel :: !Label -- ^ Hoopl label
57 , dblCLabel :: !CLabel -- ^ Output label
58 , dblHasInfoTbl :: !Bool -- ^ Has an info table?
59 , dblParent :: !(Maybe DebugBlock)
60 -- ^ The parent of this proc. See Note [Splitting DebugBlocks]
61 , dblTicks :: ![CmmTickish] -- ^ Ticks defined in this block
62 , dblSourceTick
63 :: !(Maybe CmmTickish) -- ^ Best source tick covering block
64 , dblPosition :: !(Maybe Int) -- ^ Output position relative to
65 -- other blocks. @Nothing@ means
66 -- the block was optimized out
67 , dblUnwind :: [UnwindPoint]
68 , dblBlocks :: ![DebugBlock] -- ^ Nested blocks
69 }
70
71 -- | Is this the entry block?
72 dblIsEntry :: DebugBlock -> Bool
73 dblIsEntry blk = dblProcedure blk == dblLabel blk
74
75 instance Outputable DebugBlock where
76 ppr blk = (if dblProcedure blk == dblLabel blk
77 then text "proc "
78 else if dblHasInfoTbl blk
79 then text "pp-blk "
80 else text "blk ") <>
81 ppr (dblLabel blk) <+> parens (ppr (dblCLabel blk)) <+>
82 (maybe empty ppr (dblSourceTick blk)) <+>
83 (maybe (text "removed") ((text "pos " <>) . ppr)
84 (dblPosition blk)) <+>
85 (ppr (dblUnwind blk)) <+>
86 (if null (dblBlocks blk) then empty else ppr (dblBlocks blk))
87
88 -- | Intermediate data structure holding debug-relevant context information
89 -- about a block.
90 type BlockContext = (CmmBlock, RawCmmDecl)
91
92 -- | Extract debug data from a group of procedures. We will prefer
93 -- source notes that come from the given module (presumably the module
94 -- that we are currently compiling).
95 cmmDebugGen :: ModLocation -> RawCmmGroup -> [DebugBlock]
96 cmmDebugGen modLoc decls = map (blocksForScope Nothing) topScopes
97 where
98 blockCtxs :: Map.Map CmmTickScope [BlockContext]
99 blockCtxs = blockContexts decls
100
101 -- Analyse tick scope structure: Each one is either a top-level
102 -- tick scope, or the child of another.
103 (topScopes, childScopes)
104 = partitionEithers $ map (\a -> findP a a) $ Map.keys blockCtxs
105 findP tsc GlobalScope = Left tsc -- top scope
106 findP tsc scp | scp' `Map.member` blockCtxs = Right (scp', tsc)
107 | otherwise = findP tsc scp'
108 where -- Note that we only following the left parent of
109 -- combined scopes. This loses us ticks, which we will
110 -- recover by copying ticks below.
111 scp' | SubScope _ scp' <- scp = scp'
112 | CombinedScope scp' _ <- scp = scp'
113 | otherwise = panic "findP impossible"
114
115 scopeMap = foldr (uncurry insertMulti) Map.empty childScopes
116
117 -- This allows us to recover ticks that we lost by flattening
118 -- the graph. Basically, if the parent is A but the child is
119 -- CBA, we know that there is no BA, because it would have taken
120 -- priority - but there might be a B scope, with ticks that
121 -- would not be associated with our child anymore. Note however
122 -- that there might be other childs (DB), which we have to
123 -- filter out.
124 --
125 -- We expect this to be called rarely, which is why we are not
126 -- trying too hard to be efficient here. In many cases we won't
127 -- have to construct blockCtxsU in the first place.
128 ticksToCopy :: CmmTickScope -> [CmmTickish]
129 ticksToCopy (CombinedScope scp s) = go s
130 where go s | scp `isTickSubScope` s = [] -- done
131 | SubScope _ s' <- s = ticks ++ go s'
132 | CombinedScope s1 s2 <- s = ticks ++ go s1 ++ go s2
133 | otherwise = panic "ticksToCopy impossible"
134 where ticks = bCtxsTicks $ fromMaybe [] $ Map.lookup s blockCtxs
135 ticksToCopy _ = []
136 bCtxsTicks = concatMap (blockTicks . fst)
137
138 -- Finding the "best" source tick is somewhat arbitrary -- we
139 -- select the first source span, while preferring source ticks
140 -- from the same source file. Furthermore, dumps take priority
141 -- (if we generated one, we probably want debug information to
142 -- refer to it).
143 bestSrcTick = minimumBy (comparing rangeRating)
144 rangeRating (SourceNote span _)
145 | srcSpanFile span == thisFile = 1
146 | otherwise = 2 :: Int
147 rangeRating note = pprPanic "rangeRating" (ppr note)
148 thisFile = maybe nilFS mkFastString $ ml_hs_file modLoc
149
150 -- Returns block tree for this scope as well as all nested
151 -- scopes. Note that if there are multiple blocks in the (exact)
152 -- same scope we elect one as the "branch" node and add the rest
153 -- as children.
154 blocksForScope :: Maybe CmmTickish -> CmmTickScope -> DebugBlock
155 blocksForScope cstick scope = mkBlock True (head bctxs)
156 where bctxs = fromJust $ Map.lookup scope blockCtxs
157 nested = fromMaybe [] $ Map.lookup scope scopeMap
158 childs = map (mkBlock False) (tail bctxs) ++
159 map (blocksForScope stick) nested
160
161 mkBlock :: Bool -> BlockContext -> DebugBlock
162 mkBlock top (block, prc)
163 = DebugBlock { dblProcedure = g_entry graph
164 , dblLabel = label
165 , dblCLabel = case info of
166 Just (Statics infoLbl _) -> infoLbl
167 Nothing
168 | g_entry graph == label -> entryLbl
169 | otherwise -> blockLbl label
170 , dblHasInfoTbl = isJust info
171 , dblParent = Nothing
172 , dblTicks = ticks
173 , dblPosition = Nothing -- see cmmDebugLink
174 , dblSourceTick = stick
175 , dblBlocks = blocks
176 , dblUnwind = []
177 }
178 where (CmmProc infos entryLbl _ graph) = prc
179 label = entryLabel block
180 info = mapLookup label infos
181 blocks | top = seqList childs childs
182 | otherwise = []
183
184 -- A source tick scopes over all nested blocks. However
185 -- their source ticks might take priority.
186 isSourceTick SourceNote {} = True
187 isSourceTick _ = False
188 -- Collect ticks from all blocks inside the tick scope.
189 -- We attempt to filter out duplicates while we're at it.
190 ticks = nubBy (flip tickishContains) $
191 bCtxsTicks bctxs ++ ticksToCopy scope
192 stick = case filter isSourceTick ticks of
193 [] -> cstick
194 sticks -> Just $! bestSrcTick (sticks ++ maybeToList cstick)
195
196 -- | Build a map of blocks sorted by their tick scopes
197 --
198 -- This involves a pre-order traversal, as we want blocks in rough
199 -- control flow order (so ticks have a chance to be sorted in the
200 -- right order).
201 blockContexts :: RawCmmGroup -> Map.Map CmmTickScope [BlockContext]
202 blockContexts decls = Map.map reverse $ foldr walkProc Map.empty decls
203 where walkProc :: RawCmmDecl
204 -> Map.Map CmmTickScope [BlockContext]
205 -> Map.Map CmmTickScope [BlockContext]
206 walkProc CmmData{} m = m
207 walkProc prc@(CmmProc _ _ _ graph) m
208 | mapNull blocks = m
209 | otherwise = snd $ walkBlock prc entry (emptyLbls, m)
210 where blocks = toBlockMap graph
211 entry = [mapFind (g_entry graph) blocks]
212 emptyLbls = setEmpty :: LabelSet
213
214 walkBlock :: RawCmmDecl -> [Block CmmNode C C]
215 -> (LabelSet, Map.Map CmmTickScope [BlockContext])
216 -> (LabelSet, Map.Map CmmTickScope [BlockContext])
217 walkBlock _ [] c = c
218 walkBlock prc (block:blocks) (visited, m)
219 | lbl `setMember` visited
220 = walkBlock prc blocks (visited, m)
221 | otherwise
222 = walkBlock prc blocks $
223 walkBlock prc succs
224 (lbl `setInsert` visited,
225 insertMulti scope (block, prc) m)
226 where CmmEntry lbl scope = firstNode block
227 (CmmProc _ _ _ graph) = prc
228 succs = map (flip mapFind (toBlockMap graph))
229 (successors (lastNode block))
230 mapFind = mapFindWithDefault (error "contextTree: block not found!")
231
232 insertMulti :: Ord k => k -> a -> Map.Map k [a] -> Map.Map k [a]
233 insertMulti k v = Map.insertWith (const (v:)) k [v]
234
235 cmmDebugLabels :: (i -> Bool) -> GenCmmGroup d g (ListGraph i) -> [Label]
236 cmmDebugLabels isMeta nats = seqList lbls lbls
237 where -- Find order in which procedures will be generated by the
238 -- back-end (that actually matters for DWARF generation).
239 --
240 -- Note that we might encounter blocks that are missing or only
241 -- consist of meta instructions -- we will declare them missing,
242 -- which will skip debug data generation without messing up the
243 -- block hierarchy.
244 lbls = map blockId $ filter (not . allMeta) $ concatMap getBlocks nats
245 getBlocks (CmmProc _ _ _ (ListGraph bs)) = bs
246 getBlocks _other = []
247 allMeta (BasicBlock _ instrs) = all isMeta instrs
248
249 -- | Sets position and unwind table fields in the debug block tree according to
250 -- native generated code.
251 cmmDebugLink :: [Label] -> LabelMap [UnwindPoint]
252 -> [DebugBlock] -> [DebugBlock]
253 cmmDebugLink labels unwindPts blocks = map link blocks
254 where blockPos :: LabelMap Int
255 blockPos = mapFromList $ flip zip [0..] labels
256 link block = block { dblPosition = mapLookup (dblLabel block) blockPos
257 , dblBlocks = map link (dblBlocks block)
258 , dblUnwind = fromMaybe mempty
259 $ mapLookup (dblLabel block) unwindPts
260 }
261
262 -- | Converts debug blocks into a label map for easier lookups
263 debugToMap :: [DebugBlock] -> LabelMap DebugBlock
264 debugToMap = mapUnions . map go
265 where go b = mapInsert (dblLabel b) b $ mapUnions $ map go (dblBlocks b)
266
267 {-
268 Note [What is this unwinding business?]
269 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
270
271 Unwinding tables are a variety of debugging information used by debugging tools
272 to reconstruct the execution history of a program at runtime. These tables
273 consist of sets of "instructions", one set for every instruction in the program,
274 which describe how to reconstruct the state of the machine at the point where
275 the current procedure was called. For instance, consider the following annotated
276 pseudo-code,
277
278 a_fun:
279 add rsp, 8 -- unwind: rsp = rsp - 8
280 mov rax, 1 -- unwind: rax = unknown
281 call another_block
282 sub rsp, 8 -- unwind: rsp = rsp
283
284 We see that attached to each instruction there is an "unwind" annotation, which
285 provides a relationship between each updated register and its value at the
286 time of entry to a_fun. This is the sort of information that allows gdb to give
287 you a stack backtrace given the execution state of your program. This
288 unwinding information is captured in various ways by various debug information
289 formats; in the case of DWARF (the only format supported by GHC) it is known as
290 Call Frame Information (CFI) and can be found in the .debug.frames section of
291 your object files.
292
293 Currently we only bother to produce unwinding information for registers which
294 are necessary to reconstruct flow-of-execution. On x86_64 this includes $rbp
295 (which is the STG stack pointer) and $rsp (the C stack pointer).
296
297 Let's consider how GHC would annotate a C-- program with unwinding information
298 with a typical C-- procedure as would come from the STG-to-Cmm code generator,
299
300 entry()
301 { c2fe:
302 v :: P64 = R2;
303 if ((Sp + 8) - 32 < SpLim) (likely: False) goto c2ff; else goto c2fg;
304 c2ff:
305 R2 = v :: P64;
306 R1 = test_closure;
307 call (stg_gc_fun)(R2, R1) args: 8, res: 0, upd: 8;
308 c2fg:
309 I64[Sp - 8] = c2dD;
310 R1 = v :: P64;
311 Sp = Sp - 8; // Sp updated here
312 if (R1 & 7 != 0) goto c2dD; else goto c2dE;
313 c2dE:
314 call (I64[R1])(R1) returns to c2dD, args: 8, res: 8, upd: 8;
315 c2dD:
316 w :: P64 = R1;
317 Hp = Hp + 48;
318 if (Hp > HpLim) (likely: False) goto c2fj; else goto c2fi;
319 ...
320 },
321
322 Let's consider how this procedure will be decorated with unwind information
323 (largely by CmmLayoutStack). Naturally, when we enter the procedure `entry` the
324 value of Sp is no different from what it was at its call site. Therefore we will
325 add an `unwind` statement saying this at the beginning of its unwind-annotated
326 code,
327
328 entry()
329 { c2fe:
330 unwind Sp = Just Sp + 0;
331 v :: P64 = R2;
332 if ((Sp + 8) - 32 < SpLim) (likely: False) goto c2ff; else goto c2fg;
333
334 After c2fe we may pass to either c2ff or c2fg; let's first consider the
335 former. In this case there is nothing in particular that we need to do other
336 than reiterate what we already know about Sp,
337
338 c2ff:
339 unwind Sp = Just Sp + 0;
340 R2 = v :: P64;
341 R1 = test_closure;
342 call (stg_gc_fun)(R2, R1) args: 8, res: 0, upd: 8;
343
344 In contrast, c2fg updates Sp midway through its body. To ensure that unwinding
345 can happen correctly after this point we must include an unwind statement there,
346 in addition to the usual beginning-of-block statement,
347
348 c2fg:
349 unwind Sp = Just Sp + 0;
350 I64[Sp - 8] = c2dD;
351 R1 = v :: P64;
352 Sp = Sp - 8;
353 unwind Sp = Just Sp + 8;
354 if (R1 & 7 != 0) goto c2dD; else goto c2dE;
355
356 The remaining blocks are simple,
357
358 c2dE:
359 unwind Sp = Just Sp + 8;
360 call (I64[R1])(R1) returns to c2dD, args: 8, res: 8, upd: 8;
361 c2dD:
362 unwind Sp = Just Sp + 8;
363 w :: P64 = R1;
364 Hp = Hp + 48;
365 if (Hp > HpLim) (likely: False) goto c2fj; else goto c2fi;
366 ...
367 },
368
369
370 The flow of unwinding information through the compiler is a bit convoluted:
371
372 * C-- begins life in StgCmm without any unwind information. This is because we
373 haven't actually done any register assignment or stack layout yet, so there
374 is no need for unwind information.
375
376 * CmmLayoutStack figures out how to layout each procedure's stack, and produces
377 appropriate unwinding nodes for each adjustment of the STG Sp register.
378
379 * The unwind nodes are carried through the sinking pass. Currently this is
380 guaranteed not to invalidate unwind information since it won't touch stores
381 to Sp, but this will need revisiting if CmmSink gets smarter in the future.
382
383 * Eventually we make it to the native code generator backend which can then
384 preserve the unwind nodes in its machine-specific instructions. In so doing
385 the backend can also modify or add unwinding information; this is necessary,
386 for instance, in the case of x86-64, where adjustment of $rsp may be
387 necessary during calls to native foreign code due to the native calling
388 convention.
389
390 * The NCG then retrieves the final unwinding table for each block from the
391 backend with extractUnwindPoints.
392
393 * This unwind information is converted to DebugBlocks by Debug.cmmDebugGen
394
395 * These DebugBlocks are then converted to, e.g., DWARF unwinding tables
396 (by the Dwarf module) and emitted in the final object.
397
398 See also:
399 Note [Unwinding information in the NCG] in AsmCodeGen,
400 Note [Unwind pseudo-instruction in Cmm],
401 Note [Debugging DWARF unwinding info].
402
403
404 Note [Debugging DWARF unwinding info]
405 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
406
407 For debugging generated unwinding info I've found it most useful to dump the
408 disassembled binary with objdump -D and dump the debug info with
409 readelf --debug-dump=frames-interp.
410
411 You should get something like this:
412
413 0000000000000010 <stg_catch_frame_info>:
414 10: 48 83 c5 18 add $0x18,%rbp
415 14: ff 65 00 jmpq *0x0(%rbp)
416
417 and:
418
419 Contents of the .debug_frame section:
420
421 00000000 0000000000000014 ffffffff CIE "" cf=1 df=-8 ra=16
422 LOC CFA rbp rsp ra
423 0000000000000000 rbp+0 v+0 s c+0
424
425 00000018 0000000000000024 00000000 FDE cie=00000000 pc=000000000000000f..0000000000000017
426 LOC CFA rbp rsp ra
427 000000000000000f rbp+0 v+0 s c+0
428 000000000000000f rbp+24 v+0 s c+0
429
430 To read it http://www.dwarfstd.org/doc/dwarf-2.0.0.pdf has a nice example in
431 Appendix 5 (page 101 of the pdf) and more details in the relevant section.
432
433 The key thing to keep in mind is that the value at LOC is the value from
434 *before* the instruction at LOC executes. In other words it answers the
435 question: if my $rip is at LOC, how do I get the relevant values given the
436 values obtained through unwinding so far.
437
438 If the readelf --debug-dump=frames-interp output looks wrong, it may also be
439 useful to look at readelf --debug-dump=frames, which is closer to the
440 information that GHC generated.
441
442 It's also useful to dump the relevant Cmm with -ddump-cmm -ddump-opt-cmm
443 -ddump-cmm-proc -ddump-cmm-verbose. Note [Unwind pseudo-instruction in Cmm]
444 explains how to interpret it.
445
446 Inside gdb there are a couple useful commands for inspecting frames.
447 For example:
448
449 gdb> info frame <num>
450
451 It shows the values of registers obtained through unwinding.
452
453 Another useful thing to try when debugging the DWARF unwinding is to enable
454 extra debugging output in GDB:
455
456 gdb> set debug frame 1
457
458 This makes GDB produce a trace of its internal workings. Having gone this far,
459 it's just a tiny step to run GDB in GDB. Make sure you install debugging
460 symbols for gdb if you obtain it through a package manager.
461
462 Keep in mind that the current release of GDB has an instruction pointer handling
463 heuristic that works well for C-like languages, but doesn't always work for
464 Haskell. See Note [Info Offset] in Dwarf.Types for more details.
465
466 Note [Unwind pseudo-instruction in Cmm]
467 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
468
469 One of the possible CmmNodes is a CmmUnwind pseudo-instruction. It doesn't
470 generate any assembly, but controls what DWARF unwinding information gets
471 generated.
472
473 It's important to understand what ranges of code the unwind pseudo-instruction
474 refers to.
475 For a sequence of CmmNodes like:
476
477 A // starts at addr X and ends at addr Y-1
478 unwind Sp = Just Sp + 16;
479 B // starts at addr Y and ends at addr Z
480
481 the unwind statement reflects the state after A has executed, but before B
482 has executed. If you consult the Note [Debugging DWARF unwinding info], the
483 LOC this information will end up in is Y.
484 -}
485
486 -- | A label associated with an 'UnwindTable'
487 data UnwindPoint = UnwindPoint !CLabel !UnwindTable
488
489 instance Outputable UnwindPoint where
490 ppr (UnwindPoint lbl uws) =
491 braces $ ppr lbl<>colon
492 <+> hsep (punctuate comma $ map pprUw $ Map.toList uws)
493 where
494 pprUw (g, expr) = ppr g <> char '=' <> ppr expr
495
496 -- | Maps registers to expressions that yield their "old" values
497 -- further up the stack. Most interesting for the stack pointer @Sp@,
498 -- but might be useful to document saved registers, too. Note that a
499 -- register's value will be 'Nothing' when the register's previous
500 -- value cannot be reconstructed.
501 type UnwindTable = Map.Map GlobalReg (Maybe UnwindExpr)
502
503 -- | Expressions, used for unwind information
504 data UnwindExpr = UwConst !Int -- ^ literal value
505 | UwReg !GlobalReg !Int -- ^ register plus offset
506 | UwDeref UnwindExpr -- ^ pointer dereferencing
507 | UwLabel CLabel
508 | UwPlus UnwindExpr UnwindExpr
509 | UwMinus UnwindExpr UnwindExpr
510 | UwTimes UnwindExpr UnwindExpr
511 deriving (Eq)
512
513 instance Outputable UnwindExpr where
514 pprPrec _ (UwConst i) = ppr i
515 pprPrec _ (UwReg g 0) = ppr g
516 pprPrec p (UwReg g x) = pprPrec p (UwPlus (UwReg g 0) (UwConst x))
517 pprPrec _ (UwDeref e) = char '*' <> pprPrec 3 e
518 pprPrec _ (UwLabel l) = pprPrec 3 l
519 pprPrec p (UwPlus e0 e1) | p <= 0
520 = pprPrec 0 e0 <> char '+' <> pprPrec 0 e1
521 pprPrec p (UwMinus e0 e1) | p <= 0
522 = pprPrec 1 e0 <> char '-' <> pprPrec 1 e1
523 pprPrec p (UwTimes e0 e1) | p <= 1
524 = pprPrec 2 e0 <> char '*' <> pprPrec 2 e1
525 pprPrec _ other = parens (pprPrec 0 other)
526
527 -- | Conversion of Cmm expressions to unwind expressions. We check for
528 -- unsupported operator usages and simplify the expression as far as
529 -- possible.
530 toUnwindExpr :: CmmExpr -> UnwindExpr
531 toUnwindExpr (CmmLit (CmmInt i _)) = UwConst (fromIntegral i)
532 toUnwindExpr (CmmLit (CmmLabel l)) = UwLabel l
533 toUnwindExpr (CmmRegOff (CmmGlobal g) i) = UwReg g i
534 toUnwindExpr (CmmReg (CmmGlobal g)) = UwReg g 0
535 toUnwindExpr (CmmLoad e _) = UwDeref (toUnwindExpr e)
536 toUnwindExpr e@(CmmMachOp op [e1, e2]) =
537 case (op, toUnwindExpr e1, toUnwindExpr e2) of
538 (MO_Add{}, UwReg r x, UwConst y) -> UwReg r (x + y)
539 (MO_Sub{}, UwReg r x, UwConst y) -> UwReg r (x - y)
540 (MO_Add{}, UwConst x, UwReg r y) -> UwReg r (x + y)
541 (MO_Add{}, UwConst x, UwConst y) -> UwConst (x + y)
542 (MO_Sub{}, UwConst x, UwConst y) -> UwConst (x - y)
543 (MO_Mul{}, UwConst x, UwConst y) -> UwConst (x * y)
544 (MO_Add{}, u1, u2 ) -> UwPlus u1 u2
545 (MO_Sub{}, u1, u2 ) -> UwMinus u1 u2
546 (MO_Mul{}, u1, u2 ) -> UwTimes u1 u2
547 _otherwise -> pprPanic "Unsupported operator in unwind expression!"
548 (pprExpr e)
549 toUnwindExpr e
550 = pprPanic "Unsupported unwind expression!" (ppr e)