@@ -21,13 +21,15 @@ function Base.show(io::IO, cfg::CFG)
21
21
end
22
22
23
23
function print_stmt (io:: IO , idx:: Int , @nospecialize (stmt), used:: BitSet , maxlength_idx:: Int , color:: Bool , show_type:: Bool )
24
- indent = maxlength_idx + 4
25
24
if idx in used
26
- pad = " " ^ (maxlength_idx - length (string (idx)) + 1 )
27
- print (io, " %" , idx, pad, " = " )
25
+ idx_s = string (idx)
26
+ pad = " " ^ (maxlength_idx - length (idx_s) + 1 )
27
+ print (io, " %" , idx_s, pad, " = " )
28
28
else
29
- print (io, " " ^ indent )
29
+ print (io, " " ^ (maxlength_idx + 4 ) )
30
30
end
31
+ # TODO : `indent` is supposed to be the full width of the leader for correct alignment
32
+ indent = 16
31
33
if ! color && stmt isa PiNode
32
34
# when the outer context is already colored (yellow, for pending nodes), don't use the usual coloring printer
33
35
print (io, " π (" )
@@ -314,6 +316,145 @@ end
314
316
315
317
Base. show (io:: IO , code:: IRCode ) = show_ir (io, code)
316
318
319
+
320
+ lineinfo_disabled (io:: IO , linestart:: String , lineidx:: Int32 ) = " "
321
+
322
+ function DILineInfoPrinter (linetable:: Vector )
323
+ context = LineInfoNode[]
324
+ context_depth = Ref (0 )
325
+ indent (s:: String ) = s^ (max (context_depth[], 1 ) - 1 )
326
+ function emit_lineinfo_update (io:: IO , linestart:: String , lineidx:: Int32 )
327
+ # internal configuration options:
328
+ collapse = true
329
+ indent_all = true
330
+ # convert lineidx to a vector
331
+ lineidx == 0 && return indent_all ? indent (" │" ) : " " # just skip over lines with no debug info at all
332
+ DI = LineInfoNode[]
333
+ while lineidx != 0
334
+ entry = linetable[lineidx]:: LineInfoNode
335
+ push! (DI, entry)
336
+ lineidx = entry. inlined_at
337
+ end
338
+ nframes = length (DI)
339
+ nctx = 0
340
+ pop_skips = 0
341
+ # compute the size of the matching prefix in the inlining information stack
342
+ for i = 1 : min (length (context), nframes)
343
+ CtxLine = context[i]
344
+ FrameLine = DI[nframes - i + 1 ]
345
+ CtxLine === FrameLine || break
346
+ nctx = i
347
+ end
348
+ update_line_only = false
349
+ if collapse && 0 < nctx
350
+ # check if we're adding more frames with the same method name,
351
+ # if so, drop all existing calls to it from the top of the context
352
+ # AND check if instead the context was previously printed that way
353
+ # but now has removed the recursive frames
354
+ let method = context[nctx]. method
355
+ if (nctx < nframes && DI[nframes - nctx]. method === method) ||
356
+ (nctx < length (context) && context[nctx + 1 ]. method === method)
357
+ update_line_only = true
358
+ while nctx > 0 && context[nctx]. method === method
359
+ nctx -= 1
360
+ end
361
+ end
362
+ end
363
+ end
364
+ # examine what frames we're returning from
365
+ if nctx < length (context)
366
+ # compute the new inlining depth
367
+ if collapse
368
+ npops = 1
369
+ let Prev = context[nctx + 1 ]. method
370
+ for i = (nctx + 2 ): length (context)
371
+ Next = context[i]. method
372
+ Prev === Next || (npops += 1 )
373
+ Prev = Next
374
+ end
375
+ end
376
+ else
377
+ npops = length (context) - nctx
378
+ end
379
+ # look at the first non-matching element to see if we are only changing the line number
380
+ if ! update_line_only && nctx < nframes
381
+ let CtxLine = context[nctx + 1 ],
382
+ FrameLine = DI[nframes - nctx]
383
+ if CtxLine. file == FrameLine. file &&
384
+ CtxLine. method == FrameLine. method &&
385
+ CtxLine. mod == FrameLine. mod
386
+ update_line_only = true
387
+ end
388
+ end
389
+ end
390
+ resize! (context, nctx)
391
+ update_line_only && (npops -= 1 )
392
+ if npops > 0
393
+ context_depth[] -= npops
394
+ print (io, linestart, indent (" │" ), " ┘" ^ npops, " \n " )
395
+ end
396
+ end
397
+ # see what change we made to the outermost line number
398
+ if update_line_only
399
+ frame = DI[nframes - nctx]
400
+ nctx += 1
401
+ push! (context, frame)
402
+ if frame. line != typemax (frame. line) && frame. line != 0
403
+ print (io, linestart, indent (" │" ), " @ " , frame. file, " :" , frame. line, " within `" , frame. method, " '" )
404
+ if collapse
405
+ method = frame. method
406
+ while nctx < nframes
407
+ frame = DI[nframes - nctx]
408
+ frame. method === method || break
409
+ nctx += 1
410
+ push! (context, frame)
411
+ print (io, " @ " , frame. file, " :" , frame. line)
412
+ end
413
+ end
414
+ print (io, " \n " )
415
+ end
416
+ end
417
+ # now print the rest of the new frames
418
+ while nctx < nframes
419
+ frame = DI[nframes - nctx]
420
+ print (io, linestart, indent (" │" ))
421
+ nctx += 1
422
+ push! (context, frame)
423
+ context_depth[] += 1
424
+ nctx != 1 && print (io, " ┌" )
425
+ print (io, " @ " , frame. file)
426
+ if frame. line != typemax (frame. line) && frame. line != 0
427
+ print (io, " :" , frame. line)
428
+ end
429
+ print (io, " within `" , frame. method, " '" )
430
+ if collapse
431
+ method = frame. method
432
+ while nctx < nframes
433
+ frame = DI[nframes - nctx]
434
+ frame. method === method || break
435
+ nctx += 1
436
+ push! (context, frame)
437
+ print (io, " @ " , frame. file, " :" , frame. line)
438
+ end
439
+ end
440
+ print (io, " \n " )
441
+ end
442
+ # FOR DEBUGGING `collapse`:
443
+ # let Prev = context[1].method,
444
+ # depth2 = 1
445
+ # for i = 2:nctx
446
+ # Next = context[i].method
447
+ # (collapse && Prev === Next) || (depth2 += 1)
448
+ # Prev = Next
449
+ # end
450
+ # @assert context_depth[] == depth2
451
+ # end
452
+ return indent_all ? indent (" │" ) : " "
453
+ end
454
+ return emit_lineinfo_update
455
+ end
456
+
457
+
317
458
function show_ir (io:: IO , code:: IRCode , expr_type_printer= default_expr_type_printer; verbose_linetable= false )
318
459
cols = displaysize (io)[2 ]
319
460
used = BitSet ()
@@ -465,7 +606,7 @@ function show_ir(io::IO, code::IRCode, expr_type_printer=default_expr_type_print
465
606
end
466
607
end
467
608
468
- function show_ir (io:: IO , code:: CodeInfo , expr_type_printer = default_expr_type_printer; verbose_linetable = false )
609
+ function show_ir (io:: IO , code:: CodeInfo , line_info_preprinter = DILineInfoPrinter (code . linetable), line_info_postprinter = default_expr_type_printer )
469
610
cols = displaysize (io)[2 ]
470
611
used = BitSet ()
471
612
stmts = code. code
@@ -483,14 +624,6 @@ function show_ir(io::IO, code::CodeInfo, expr_type_printer=default_expr_type_pri
483
624
maxused = maximum (used)
484
625
maxlength_idx = length (string (maxused))
485
626
end
486
- if ! verbose_linetable
487
- (loc_annotations, loc_methods, loc_lineno) = compute_ir_line_annotations (code)
488
- max_loc_width = maximum (length (str) for str in loc_annotations)
489
- max_lineno_width = maximum (length (str) for str in loc_lineno)
490
- max_method_width = maximum (length (str) for str in loc_methods)
491
- end
492
- max_depth = maximum (compute_inlining_depth (code. linetable, line) for line in code. codelocs)
493
- last_stack = []
494
627
for idx in eachindex (stmts)
495
628
if ! isassigned (stmts, idx)
496
629
# This is invalid, but do something useful rather
@@ -499,63 +632,24 @@ function show_ir(io::IO, code::CodeInfo, expr_type_printer=default_expr_type_pri
499
632
continue
500
633
end
501
634
stmt = stmts[idx]
502
- # Compute BB guard rail
503
635
bbrange = cfg. blocks[bb_idx]. stmts
504
636
bbrange = bbrange. first: bbrange. last
505
- bb_idx_str = string (bb_idx)
506
- bb_pad = max_bb_idx_size - length (bb_idx_str )
507
- bb_type = length (cfg . blocks[bb_idx] . preds) <= 1 ? " ─ " : " ┄ "
508
- bb_start_str = string (bb_idx_str, " " , bb_type, " ─ " ^ bb_pad, " " )
509
- bb_guard_rail_cont = string ( " │ " , " " ^ max_bb_idx_size)
637
+ # Print line info update
638
+ linestart = idx == first (bbrange) ? " " : sprint (io -> printstyled (io, " │ " , color = :light_black ), context = io )
639
+ linestart *= " " ^ max_bb_idx_size
640
+ inlining_indent = line_info_preprinter (io, linestart, code . codelocs[idx] )
641
+ # Compute BB guard rail
510
642
if idx == first (bbrange)
511
- bb_guard_rail = bb_start_str
512
- else
513
- bb_guard_rail = bb_guard_rail_cont
514
- end
515
- # Print linetable information
516
- if verbose_linetable
517
- stack = compute_loc_stack (code. linetable, code. codelocs[idx])
518
- # We need to print any stack frames that did not exist in the last stack
519
- ndepth = max (1 , length (stack))
520
- rail = string (" " ^ (max_depth+ 1 - ndepth), " │" ^ ndepth)
521
- start_column = cols - max_depth - 10
522
- for (i, x) in enumerate (stack)
523
- if i > length (last_stack) || last_stack[i] != x
524
- entry = code. linetable[x]
525
- printstyled (io, " \e [$(start_column) G$(rail) \e [1G" , color = :light_black )
526
- print (io, bb_guard_rail)
527
- ssa_guard = " " ^ (maxlength_idx + 4 + (i - 1 ))
528
- entry_label = " $(ssa_guard)$(entry. method) at $(entry. file) :$(entry. line) "
529
- hline = string (" ─" ^ (start_column- length (entry_label)- length (bb_guard_rail)+ max_depth- i), " ┐" )
530
- printstyled (io, string (entry_label, hline), " \n " ; color= :light_black )
531
- bb_guard_rail = bb_guard_rail_cont
532
- end
533
- end
534
- printstyled (io, " \e [$(start_column) G$(rail) \e [1G" , color = :light_black )
535
- last_stack = stack
643
+ bb_idx_str = string (bb_idx)
644
+ bb_pad = max_bb_idx_size - length (bb_idx_str)
645
+ bb_type = length (cfg. blocks[bb_idx]. preds) <= 1 ? " ─" : " ┄"
646
+ printstyled (io, bb_idx_str, " " , bb_type, " ─" ^ bb_pad, color= :light_black )
647
+ elseif idx == last (bbrange) # print separator
648
+ printstyled (io, " └" , " ─" ^ (1 + max_bb_idx_size), color= :light_black )
536
649
else
537
- annotation = loc_annotations[idx]
538
- loc_method = loc_methods[idx]
539
- lineno = loc_lineno[idx]
540
- # Print location information right aligned. If the line below is too long, it'll overwrite this,
541
- # but that's what we want.
542
- if get (io, :color , false )
543
- method_start_column = cols - max_method_width - max_loc_width - 2
544
- filler = " " ^ (max_loc_width- length (annotation))
545
- printstyled (io, " \e [$(method_start_column) G$(annotation)$(filler)$(loc_method) \e [1G" , color = :light_black )
546
- end
547
- printstyled (io, lineno, " " ^ (max_lineno_width- length (lineno)+ 1 ); color = :light_black )
548
- end
549
- idx != last (bbrange) && print (io, bb_guard_rail)
550
- if idx == last (bbrange) # print separator
551
- if idx == first (bbrange)
552
- print (io, bb_start_str)
553
- elseif idx == last (bbrange)
554
- print (io, " └" , " ─" ^ (1 + max_bb_idx_size), " " )
555
- else
556
- print (io, " │ " , " " ^ max_bb_idx_size)
557
- end
650
+ printstyled (io, " │ " , " " ^ max_bb_idx_size, color= :light_black )
558
651
end
652
+ print (io, inlining_indent, " " )
559
653
if idx == last (bbrange)
560
654
bb_idx += 1
561
655
end
@@ -582,7 +676,7 @@ function show_ir(io::IO, code::CodeInfo, expr_type_printer=default_expr_type_pri
582
676
printstyled (io, " ::#UNDEF" , color= :red )
583
677
elseif show_type
584
678
typ = types[idx]
585
- expr_type_printer (io, typ, idx in used)
679
+ line_info_postprinter (io, typ, idx in used)
586
680
end
587
681
end
588
682
println (io)
0 commit comments