Skip to content

Commit

Permalink
IRVerify: Check IR stmt + metadata vector ranges
Browse files Browse the repository at this point in the history
These checks are important to make sure that `verify_ir` does not end up
triggering out-of-bounds errors as it checks IR.

It also fills out some of the verification:
  - Confirms that cfg.index is correct
  - Confirms that cfg.blocks[i].stmts cover the complete IR
  • Loading branch information
topolarity committed Aug 15, 2023
1 parent 6a81943 commit 5c0b04a
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 3 deletions.
47 changes: 44 additions & 3 deletions base/compiler/ssair/verify.jl
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,31 @@ end
function verify_ir(ir::IRCode, print::Bool=true,
allow_frontend_forms::Bool=false,
𝕃ₒ::AbstractLattice = SimpleInferenceLattice.instance)
# Verify CFG graph. Must be well formed to construct domtree
if !(length(ir.cfg.blocks) - 1 <= length(ir.cfg.index) <= length(ir.cfg.blocks))
@verify_error "CFG index length ($(length(ir.cfg.index))) does not correspond to # of blocks $(length(ir.cfg.blocks))"
error("")
end
if length(ir.stmts.stmt) != length(ir.stmts)
@verify_error "IR stmt length is invalid $(length(ir.stmts.stmt)) / $(length(ir.stmts))"
error("")
end
if length(ir.stmts.type) != length(ir.stmts)
@verify_error "IR type length is invalid $(length(ir.stmts.type)) / $(length(ir.stmts))"
error("")
end
if length(ir.stmts.info) != length(ir.stmts)
@verify_error "IR info length is invalid $(length(ir.stmts.info)) / $(length(ir.stmts))"
error("")
end
if length(ir.stmts.line) != length(ir.stmts)
@verify_error "IR line length is invalid $(length(ir.stmts.line)) / $(length(ir.stmts))"
error("")
end
if length(ir.stmts.flag) != length(ir.stmts)
@verify_error "IR flag length is invalid $(length(ir.stmts.flag)) / $(length(ir.stmts))"
error("")
end
# For now require compact IR
# @assert isempty(ir.new_nodes)
# Verify CFG
Expand Down Expand Up @@ -125,6 +150,18 @@ function verify_ir(ir::IRCode, print::Bool=true,
error("")
end
end
if !(1 <= first(block.stmts) <= length(ir.stmts))
@verify_error "First statement of BB $idx ($(first(block.stmts))) out of bounds for IR (length=$(length(ir.stmts)))"
error("")
end
if !(1 <= last(block.stmts) <= length(ir.stmts))
@verify_error "Last statement of BB $idx ($(last(block.stmts))) out of bounds for IR (length=$(length(ir.stmts)))"
error("")
end
if idx <= length(ir.cfg.index) && last(block.stmts) + 1 != ir.cfg.index[idx]
@verify_error "End of BB $idx ($(last(block.stmts))) is not one less than CFG index ($(ir.cfg.index[idx]))"
error("")
end
end
# Verify statements
domtree = construct_domtree(ir.cfg.blocks)
Expand All @@ -145,7 +182,7 @@ function verify_ir(ir::IRCode, print::Bool=true,
end
elseif isa(terminator, GotoNode)
if length(block.succs) != 1 || block.succs[1] != terminator.label
@verify_error "Block $idx successors ($(block.succs)), does not match GotoNode terminator"
@verify_error "Block $idx successors ($(block.succs)), does not match GotoNode terminator ($(terminator.label))"
error("")
end
elseif isa(terminator, GotoIfNot)
Expand All @@ -167,8 +204,8 @@ function verify_ir(ir::IRCode, print::Bool=true,
if length(block.succs) != 1 || block.succs[1] != idx + 1
# As a special case, we allow extra statements in the BB of an :enter
# statement, until we can do proper CFG manipulations during compaction.
for idx in first(block.stmts):last(block.stmts)
stmt = ir[SSAValue(idx)][:stmt]
for stmt_idx in first(block.stmts):last(block.stmts)
stmt = ir[SSAValue(stmt_idx)][:stmt]
if isexpr(stmt, :enter)
terminator = stmt
@goto enter_check
Expand All @@ -188,6 +225,10 @@ function verify_ir(ir::IRCode, print::Bool=true,
end
end
end
if length(ir.stmts) != last(ir.cfg.blocks[end].stmts)
@verify_error "End of last BB $(last(ir.cfg.blocks[end].stmts)) does not match last IR statement $(length(ir.stmts))"
error("")
end
lastbb = 0
is_phinode_block = false
firstidx = 1
Expand Down
3 changes: 3 additions & 0 deletions test/compiler/interpreter_exec.jl
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ let m = Meta.@lower 1 + 1
]
nstmts = length(src.code)
src.ssavaluetypes = Any[ Any for _ = 1:nstmts ]
src.ssaflags = fill(UInt8(0x00), nstmts)
src.codelocs = fill(Int32(1), nstmts)
src.inferred = true
Core.Compiler.verify_ir(Core.Compiler.inflate_ir(src))
Expand Down Expand Up @@ -61,6 +62,7 @@ let m = Meta.@lower 1 + 1
]
nstmts = length(src.code)
src.ssavaluetypes = Any[ Any for _ = 1:nstmts ]
src.ssaflags = fill(UInt8(0x00), nstmts)
src.codelocs = fill(Int32(1), nstmts)
src.inferred = true
Core.Compiler.verify_ir(Core.Compiler.inflate_ir(src))
Expand Down Expand Up @@ -98,6 +100,7 @@ let m = Meta.@lower 1 + 1
]
nstmts = length(src.code)
src.ssavaluetypes = Any[ Any for _ = 1:nstmts ]
src.ssaflags = fill(UInt8(0x00), nstmts)
src.codelocs = fill(Int32(1), nstmts)
src.inferred = true
Core.Compiler.verify_ir(Core.Compiler.inflate_ir(src))
Expand Down
1 change: 1 addition & 0 deletions test/compiler/irpasses.jl
Original file line number Diff line number Diff line change
Expand Up @@ -849,6 +849,7 @@ function each_stmt_a_bb(stmts, preds, succs)
empty!(ir.stmts.line); append!(ir.stmts.line, [Int32(0) for _ = 1:length(stmts)])
empty!(ir.stmts.info); append!(ir.stmts.info, [NoCallInfo() for _ = 1:length(stmts)])
empty!(ir.cfg.blocks); append!(ir.cfg.blocks, [BasicBlock(StmtRange(i, i), preds[i], succs[i]) for i = 1:length(stmts)])
empty!(ir.cfg.index); append!(ir.cfg.index, [i for i = 2:length(stmts)])
Core.Compiler.verify_ir(ir)
return ir
end
Expand Down

0 comments on commit 5c0b04a

Please sign in to comment.