Skip to content

Commit 6caabc9

Browse files
StefanKarpinskiKristofferC
authored andcommitted
Revert "RFC: prettier IR-show for line number and inlining information" (#29118)
1 parent 3b428c9 commit 6caabc9

File tree

7 files changed

+163
-371
lines changed

7 files changed

+163
-371
lines changed

base/compiler/ssair/ir.jl

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,11 @@ function basic_blocks_starts(stmts::Vector{Any})
8585
push!(jump_dests, idx)
8686
push!(jump_dests, idx+1)
8787
# The catch block is a jump dest
88-
push!(jump_dests, stmt.args[1]::Int)
88+
push!(jump_dests, stmt.args[1])
8989
elseif stmt.head === :gotoifnot
9090
# also tolerate expr form of IR
9191
push!(jump_dests, idx+1)
92-
push!(jump_dests, stmt.args[2]::Int)
92+
push!(jump_dests, stmt.args[2])
9393
elseif stmt.head === :return
9494
# also tolerate expr form of IR
9595
# This is a fake dest to force the next stmt to start a bb
@@ -130,7 +130,7 @@ function compute_basic_blocks(stmts::Vector{Any})
130130
# Compute successors/predecessors
131131
for (num, b) in enumerate(blocks)
132132
terminator = stmts[last(b.stmts)]
133-
if isa(terminator, ReturnNode) || isexpr(terminator, :return)
133+
if isa(terminator, ReturnNode)
134134
# return never has any successors
135135
continue
136136
end
@@ -150,28 +150,17 @@ function compute_basic_blocks(stmts::Vector{Any})
150150
push!(blocks[block′].preds, num)
151151
push!(b.succs, block′)
152152
end
153-
elseif isa(terminator, Expr)
154-
if terminator.head == :enter
155-
# :enter gets a virtual edge to the exception handler and
156-
# the exception handler gets a virtual edge from outside
157-
# the function.
158-
# See the devdocs on exception handling in SSA form (or
159-
# bug Keno to write them, if you're reading this and they
160-
# don't exist)
161-
block′ = block_for_inst(basic_block_index, terminator.args[1]::Int)
162-
push!(blocks[block′].preds, num)
163-
push!(blocks[block′].preds, 0)
164-
push!(b.succs, block′)
165-
elseif terminator.head == :gotoifnot
166-
block′ = block_for_inst(basic_block_index, terminator.args[2]::Int)
167-
if block′ == num + 1
168-
# This GotoIfNot acts like a noop - treat it as such.
169-
# We will drop it during SSA renaming
170-
else
171-
push!(blocks[block′].preds, num)
172-
push!(b.succs, block′)
173-
end
174-
end
153+
elseif isa(terminator, Expr) && terminator.head == :enter
154+
# :enter gets a virtual edge to the exception handler and
155+
# the exception handler gets a virtual edge from outside
156+
# the function.
157+
# See the devdocs on exception handling in SSA form (or
158+
# bug Keno to write them, if you're reading this and they
159+
# don't exist)
160+
block′ = block_for_inst(basic_block_index, terminator.args[1])
161+
push!(blocks[block′].preds, num)
162+
push!(blocks[block′].preds, 0)
163+
push!(b.succs, block′)
175164
end
176165
# statement fall-through
177166
if num + 1 <= length(blocks)

base/compiler/ssair/show.jl

Lines changed: 66 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,13 @@ function Base.show(io::IO, cfg::CFG)
2121
end
2222

2323
function print_stmt(io::IO, idx::Int, @nospecialize(stmt), used::BitSet, maxlength_idx::Int, color::Bool, show_type::Bool)
24+
indent = maxlength_idx + 4
2425
if idx in used
25-
idx_s = string(idx)
26-
pad = " "^(maxlength_idx - length(idx_s) + 1)
27-
print(io, "%", idx_s, pad, "= ")
26+
pad = " "^(maxlength_idx - length(string(idx)) + 1)
27+
print(io, "%", idx, pad, "= ")
2828
else
29-
print(io, " "^(maxlength_idx + 4))
29+
print(io, " "^indent)
3030
end
31-
# TODO: `indent` is supposed to be the full width of the leader for correct alignment
32-
indent = 16
3331
if !color && stmt isa PiNode
3432
# when the outer context is already colored (yellow, for pending nodes), don't use the usual coloring printer
3533
print(io, "π (")
@@ -316,145 +314,6 @@ end
316314

317315
Base.show(io::IO, code::IRCode) = show_ir(io, code)
318316

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-
458317
function show_ir(io::IO, code::IRCode, expr_type_printer=default_expr_type_printer; verbose_linetable=false)
459318
cols = displaysize(io)[2]
460319
used = BitSet()
@@ -606,7 +465,7 @@ function show_ir(io::IO, code::IRCode, expr_type_printer=default_expr_type_print
606465
end
607466
end
608467

609-
function show_ir(io::IO, code::CodeInfo, line_info_preprinter=DILineInfoPrinter(code.linetable), line_info_postprinter=default_expr_type_printer)
468+
function show_ir(io::IO, code::CodeInfo, expr_type_printer=default_expr_type_printer; verbose_linetable=false)
610469
cols = displaysize(io)[2]
611470
used = BitSet()
612471
stmts = code.code
@@ -624,6 +483,14 @@ function show_ir(io::IO, code::CodeInfo, line_info_preprinter=DILineInfoPrinter(
624483
maxused = maximum(used)
625484
maxlength_idx = length(string(maxused))
626485
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 = []
627494
for idx in eachindex(stmts)
628495
if !isassigned(stmts, idx)
629496
# This is invalid, but do something useful rather
@@ -632,24 +499,63 @@ function show_ir(io::IO, code::CodeInfo, line_info_preprinter=DILineInfoPrinter(
632499
continue
633500
end
634501
stmt = stmts[idx]
502+
# Compute BB guard rail
635503
bbrange = cfg.blocks[bb_idx].stmts
636504
bbrange = bbrange.first:bbrange.last
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
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)
642510
if idx == first(bbrange)
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)
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
649536
else
650-
printstyled(io, "", " "^max_bb_idx_size, color=:light_black)
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
651558
end
652-
print(io, inlining_indent, " ")
653559
if idx == last(bbrange)
654560
bb_idx += 1
655561
end
@@ -676,7 +582,7 @@ function show_ir(io::IO, code::CodeInfo, line_info_preprinter=DILineInfoPrinter(
676582
printstyled(io, "::#UNDEF", color=:red)
677583
elseif show_type
678584
typ = types[idx]
679-
line_info_postprinter(io, typ, idx in used)
585+
expr_type_printer(io, typ, idx in used)
680586
end
681587
end
682588
println(io)

doc/src/devdocs/reflection.md

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,12 @@ particular interest for understanding how language constructs map to primitive o
9494
as assignments, branches, and calls:
9595

9696
```jldoctest
97-
julia> Meta.lower(@__MODULE__, :( [1+2, sin(0.5)] ))
97+
julia> Meta.lower(@__MODULE__, :([1+2, sin(0.5)]) )
9898
:($(Expr(:thunk, CodeInfo(
99-
@ none within `top-level scope'
100-
1 ─ %1 = 1 + 2
101-
│ %2 = sin(0.5)
102-
│ %3 = (Base.vect)(%1, %2)
103-
└── return %3
99+
1 ─ %1 = 1 + 2
100+
│ %2 = sin(0.5)
101+
│ %3 = (Base.vect)(%1, %2)
102+
└── return %3
104103
))))
105104
```
106105

@@ -123,11 +122,11 @@ calls and expand argument types automatically:
123122
```julia-repl
124123
julia> @code_llvm +(1,1)
125124
126-
; @ int.jl:53 within `+'
127-
define i64 @"julia_+_130862"(i64, i64) {
125+
; Function Attrs: sspreq
126+
define i64 @"julia_+_130862"(i64, i64) #0 {
128127
top:
129-
%2 = add i64 %1, %0
130-
ret i64 %2
128+
%2 = add i64 %1, %0, !dbg !8
129+
ret i64 %2, !dbg !8
131130
}
132131
```
133132

0 commit comments

Comments
 (0)