@@ -7,6 +7,7 @@ function maybe_show_ir(ir::IRCode)
77 else
88 Core. show (ir)
99 end
10+ Core. println (Core. stdout )
1011end
1112
1213if ! isdefined (@__MODULE__ , Symbol (" @verify_error" ))
2526
2627is_toplevel_expr_head (head:: Symbol ) = head === :global || head === :method || head === :thunk
2728is_value_pos_expr_head (head:: Symbol ) = head === :static_parameter
28- function check_op (ir:: IRCode , domtree:: DomTree , @nospecialize (op), use_bb:: Int , use_idx:: Int , printed_use_idx:: Int , print:: Bool , isforeigncall:: Bool , arg_idx:: Int , allow_frontend_forms:: Bool )
29+ function check_op (ir:: IRCode , domtree:: DomTree , @nospecialize (op), use_bb:: Int , use_idx:: Int , printed_use_idx:: Int , print:: Bool , isforeigncall:: Bool , arg_idx:: Int ,
30+ allow_frontend_forms:: Bool , @nospecialize (raise_error))
2931 if isa (op, SSAValue)
3032 op. id > 0 || @verify_error " Def ($(op. id) ) is invalid in final IR"
3133 if op. id > length (ir. stmts)
@@ -39,14 +41,14 @@ function check_op(ir::IRCode, domtree::DomTree, @nospecialize(op), use_bb::Int,
3941 else
4042 if op. id >= use_idx
4143 @verify_error " Def ($(op. id) ) does not dominate use ($(use_idx) ) in same BB"
42- error ( " " )
44+ raise_error ( )
4345 end
4446 end
4547 else
4648 if ! dominates (domtree, def_bb, use_bb) && ! (bb_unreachable (domtree, def_bb) && bb_unreachable (domtree, use_bb))
4749 # At the moment, we allow GC preserve tokens outside the standard domination notion
4850 @verify_error " Basic Block $def_bb does not dominate block $use_bb (tried to use value %$(op. id) at %$(printed_use_idx) )"
49- error ( " " )
51+ raise_error ( )
5052 end
5153 end
5254
@@ -56,12 +58,12 @@ function check_op(ir::IRCode, domtree::DomTree, @nospecialize(op), use_bb::Int,
5658 # an earlier block got deleted, but for some reason we didn't figure
5759 # out yet that this entire block is dead also.
5860 @verify_error " At statement %$use_idx : Invalid use of value statement or terminator %$(op. id) "
59- error ( " " )
61+ raise_error ( )
6062 end
6163 elseif isa (op, GlobalRef)
6264 if ! isdefined (op. mod, op. name) || ! isconst (op. mod, op. name)
6365 @verify_error " Unbound GlobalRef not allowed in value position"
64- error ( " " )
66+ raise_error ( )
6567 end
6668 elseif isa (op, Expr)
6769 # Only Expr(:boundscheck) is allowed in value position
@@ -72,15 +74,15 @@ function check_op(ir::IRCode, domtree::DomTree, @nospecialize(op), use_bb::Int,
7274 elseif ! is_value_pos_expr_head (op. head)
7375 if ! allow_frontend_forms || op. head != = :opaque_closure_method
7476 @verify_error " Expr not allowed in value position"
75- error ( " " )
77+ raise_error ( )
7678 end
7779 end
7880 elseif isa (op, Union{OldSSAValue, NewSSAValue})
7981 @verify_error " At statement %$use_idx : Left over SSA marker ($op )"
80- error ( " " )
82+ raise_error ( )
8183 elseif isa (op, SlotNumber)
8284 @verify_error " Left over slot detected in converted IR"
83- error ( " " )
85+ raise_error ( )
8486 end
8587end
8688
9698
9799function verify_ir (ir:: IRCode , print:: Bool = true ,
98100 allow_frontend_forms:: Bool = false ,
99- 𝕃ₒ:: AbstractLattice = SimpleInferenceLattice. instance)
101+ 𝕃ₒ:: AbstractLattice = SimpleInferenceLattice. instance,
102+ mi:: Union{Nothing,MethodInstance} = nothing )
103+ function raise_error ()
104+ error_args = Any[" IR verification failed." ]
105+ if isdefined (Core, :Main ) && isdefined (Core. Main, :Base )
106+ # ensure we use I/O that does not yield, as this gets called during compilation
107+ firstline = invokelatest (Core. Main. Base. IRShow. debuginfo_firstline, ir. debuginfo)
108+ else
109+ firstline = nothing
110+ end
111+ if firstline != = nothing
112+ file, line = firstline
113+ push! (error_args, " \n " , " Code location: " , file, " :" , line)
114+ end
115+ if mi != = nothing
116+ push! (error_args, " \n " , " Method instance: " , mi)
117+ end
118+ error (error_args... )
119+ end
100120 # Verify CFG graph. Must be well formed to construct domtree
101121 if ! (length (ir. cfg. blocks) - 1 <= length (ir. cfg. index) <= length (ir. cfg. blocks))
102122 @verify_error " CFG index length ($(length (ir. cfg. index)) ) does not correspond to # of blocks $(length (ir. cfg. blocks)) "
103- error ( " " )
123+ raise_error ( )
104124 end
105125 if length (ir. stmts. stmt) != length (ir. stmts)
106126 @verify_error " IR stmt length is invalid $(length (ir. stmts. stmt)) / $(length (ir. stmts)) "
107- error ( " " )
127+ raise_error ( )
108128 end
109129 if length (ir. stmts. type) != length (ir. stmts)
110130 @verify_error " IR type length is invalid $(length (ir. stmts. type)) / $(length (ir. stmts)) "
111- error ( " " )
131+ raise_error ( )
112132 end
113133 if length (ir. stmts. info) != length (ir. stmts)
114134 @verify_error " IR info length is invalid $(length (ir. stmts. info)) / $(length (ir. stmts)) "
115- error ( " " )
135+ raise_error ( )
116136 end
117137 if length (ir. stmts. line) != length (ir. stmts) * 3
118138 @verify_error " IR line length is invalid $(length (ir. stmts. line)) / $(length (ir. stmts) * 3 ) "
119- error ( " " )
139+ raise_error ( )
120140 end
121141 if length (ir. stmts. flag) != length (ir. stmts)
122142 @verify_error " IR flag length is invalid $(length (ir. stmts. flag)) / $(length (ir. stmts)) "
123- error ( " " )
143+ raise_error ( )
124144 end
125145 # For now require compact IR
126146 # @assert isempty(ir.new_nodes)
@@ -132,43 +152,43 @@ function verify_ir(ir::IRCode, print::Bool=true,
132152 p == 0 && continue
133153 if ! (1 <= p <= length (ir. cfg. blocks))
134154 @verify_error " Predecessor $p of block $idx out of bounds for IR"
135- error ( " " )
155+ raise_error ( )
136156 end
137157 c = count_int (idx, ir. cfg. blocks[p]. succs)
138158 if c == 0
139159 @verify_error " Predecessor $p of block $idx not in successor list"
140- error ( " " )
160+ raise_error ( )
141161 elseif c == 2
142162 if count_int (p, block. preds) != 2
143163 @verify_error " Double edge from $p to $idx not correctly accounted"
144- error ( " " )
164+ raise_error ( )
145165 end
146166 end
147167 end
148168 for s in block. succs
149169 if ! (1 <= s <= length (ir. cfg. blocks))
150170 @verify_error " Successor $s of block $idx out of bounds for IR"
151- error ( " " )
171+ raise_error ( )
152172 end
153173 if ! (idx in ir. cfg. blocks[s]. preds)
154174 # Base.@show ir.cfg
155175 # Base.@show ir
156176 # Base.@show ir.argtypes
157177 @verify_error " Successor $s of block $idx not in predecessor list"
158- error ( " " )
178+ raise_error ( )
159179 end
160180 end
161181 if ! (1 <= first (block. stmts) <= length (ir. stmts))
162182 @verify_error " First statement of BB $idx ($(first (block. stmts)) ) out of bounds for IR (length=$(length (ir. stmts)) )"
163- error ( " " )
183+ raise_error ( )
164184 end
165185 if ! (1 <= last (block. stmts) <= length (ir. stmts))
166186 @verify_error " Last statement of BB $idx ($(last (block. stmts)) ) out of bounds for IR (length=$(length (ir. stmts)) )"
167- error ( " " )
187+ raise_error ( )
168188 end
169189 if idx <= length (ir. cfg. index) && last (block. stmts) + 1 != ir. cfg. index[idx]
170190 @verify_error " End of BB $idx ($(last (block. stmts)) ) is not one less than CFG index ($(ir. cfg. index[idx]) )"
171- error ( " " )
191+ raise_error ( )
172192 end
173193 end
174194 # Verify statements
@@ -177,7 +197,7 @@ function verify_ir(ir::IRCode, print::Bool=true,
177197 if first (block. stmts) != last_end + 1
178198 # ranges = [(idx,first(bb.stmts),last(bb.stmts)) for (idx, bb) in pairs(ir.cfg.blocks)]
179199 @verify_error " First statement of BB $idx ($(first (block. stmts)) ) does not match end of previous ($last_end )"
180- error ( " " )
200+ raise_error ( )
181201 end
182202 last_end = last (block. stmts)
183203 terminator = ir[SSAValue (last_end)][:stmt ]
@@ -186,32 +206,32 @@ function verify_ir(ir::IRCode, print::Bool=true,
186206 if isa (terminator, ReturnNode)
187207 if ! isempty (block. succs)
188208 @verify_error " Block $idx ends in return or unreachable, but has successors"
189- error ( " " )
209+ raise_error ( )
190210 end
191211 elseif isa (terminator, GotoNode)
192212 if length (block. succs) != 1 || block. succs[1 ] != terminator. label
193213 @verify_error " Block $idx successors ($(block. succs) ), does not match GotoNode terminator ($(terminator. label) )"
194- error ( " " )
214+ raise_error ( )
195215 end
196216 elseif isa (terminator, GotoIfNot)
197217 if terminator. dest == idx + 1
198218 @verify_error " Block $idx terminator forms a double edge to block $(idx+ 1 ) "
199- error ( " " )
219+ raise_error ( )
200220 end
201221 if length (block. succs) != 2 || (block. succs != [terminator. dest, idx+ 1 ] && block. succs != [idx+ 1 , terminator. dest])
202222 @verify_error " Block $idx successors ($(block. succs) ), does not match GotoIfNot terminator"
203- error ( " " )
223+ raise_error ( )
204224 end
205225 elseif isa (terminator, EnterNode)
206226 @label enter_check
207227 if length (block. succs) == 1
208228 if terminator. catch_dest != 0
209229 @verify_error " Block $idx successors ($(block. succs) ), does not match :enter terminator"
210- error ( " " )
230+ raise_error ( )
211231 end
212232 elseif (block. succs != Int[terminator. catch_dest, idx+ 1 ] && block. succs != Int[idx+ 1 , terminator. catch_dest])
213233 @verify_error " Block $idx successors ($(block. succs) ), does not match :enter terminator"
214- error ( " " )
234+ raise_error ( )
215235 end
216236 else
217237 if length (block. succs) != 1 || block. succs[1 ] != idx + 1
@@ -233,14 +253,14 @@ function verify_ir(ir::IRCode, print::Bool=true,
233253 # here, but that isn't always possible.
234254 else
235255 @verify_error " Block $idx successors ($(block. succs) ), does not match fall-through terminator %$termidx ($terminator )::$stmttyp "
236- error ( " " )
256+ raise_error ( )
237257 end
238258 end
239259 end
240260 end
241261 if length (ir. stmts) != last (ir. cfg. blocks[end ]. stmts)
242262 @verify_error " End of last BB $(last (ir. cfg. blocks[end ]. stmts)) does not match last IR statement $(length (ir. stmts)) "
243- error ( " " )
263+ raise_error ( )
244264 end
245265 lastbb = 0
246266 is_phinode_block = false
@@ -260,7 +280,7 @@ function verify_ir(ir::IRCode, print::Bool=true,
260280 if isa (stmt, PhiNode)
261281 if ! is_phinode_block
262282 @verify_error " φ node $idx is not at the beginning of the basic block $bb "
263- error ( " " )
283+ raise_error ( )
264284 end
265285 lastphi = idx
266286 @assert length (stmt. edges) == length (stmt. values)
@@ -271,20 +291,20 @@ function verify_ir(ir::IRCode, print::Bool=true,
271291 if edge == edge′
272292 # TODO : Move `unique` to Core.Compiler. For now we assume the predecessor list is always unique.
273293 @verify_error " Edge list φ node $idx in bb $bb not unique (double edge?)"
274- error ( " " )
294+ raise_error ( )
275295 end
276296 end
277297 if ! (edge == 0 && bb == 1 ) && ! (edge in ir. cfg. blocks[bb]. preds)
278298 # Base.@show ir.argtypes
279299 # Base.@show ir
280300 @verify_error " Edge $edge of φ node $idx not in predecessor list"
281- error ( " " )
301+ raise_error ( )
282302 end
283303 edge == 0 && continue
284304 if bb_unreachable (domtree, Int (edge))
285305 # TODO : Disallow?
286306 # @verify_error "Unreachable edge from #$edge should have been cleaned up at idx $idx"
287- # error("" )
307+ # raise_error( )
288308 continue
289309 end
290310 isassigned (stmt. values, i) || continue
@@ -297,10 +317,11 @@ function verify_ir(ir::IRCode, print::Bool=true,
297317 # PhiNode type was $phiT
298318 # Value type was $(ir.stmts[val.id][:type])
299319 # """
300- # error("" )
320+ # raise_error( )
301321 end
302322 end
303- check_op (ir, domtree, val, Int (edge), last (ir. cfg. blocks[stmt. edges[i]]. stmts)+ 1 , idx, print, false , i, allow_frontend_forms)
323+ check_op (ir, domtree, val, Int (edge), last (ir. cfg. blocks[stmt. edges[i]]. stmts)+ 1 , idx, print, false , i,
324+ allow_frontend_forms, raise_error)
304325 end
305326 continue
306327 end
@@ -311,7 +332,8 @@ function verify_ir(ir::IRCode, print::Bool=true,
311332 for validate_idx in firstidx: (lastphi- 1 )
312333 validate_stmt = ir[SSAValue (validate_idx)][:stmt ]
313334 isa (validate_stmt, PhiNode) && continue
314- check_op (ir, domtree, validate_stmt, bb, idx, idx, print, false , 0 , allow_frontend_forms)
335+ check_op (ir, domtree, validate_stmt, bb, idx, idx, print, false , 0 ,
336+ allow_frontend_forms, raise_error)
315337 end
316338 is_phinode_block = false
317339 end
@@ -321,29 +343,29 @@ function verify_ir(ir::IRCode, print::Bool=true,
321343 val = stmt. values[i]
322344 if ! isa (val, SSAValue)
323345 @verify_error " Operand $i of PhiC node $idx must be an SSA Value."
324- error ( " " )
346+ raise_error ( )
325347 end
326348 if ! isa (ir[val][:stmt ], UpsilonNode)
327349 @verify_error " Operand $i of PhiC node $idx must reference an Upsilon node."
328- error ( " " )
350+ raise_error ( )
329351 end
330352 end
331353 elseif isterminator (stmt)
332354 if idx != last (ir. cfg. blocks[bb]. stmts)
333355 @verify_error " Terminator $idx in bb $bb is not the last statement in the block"
334- error ( " " )
356+ raise_error ( )
335357 end
336358 if ! isa (stmt, ReturnNode) && ir[SSAValue (idx)][:type ] != = Any
337359 @verify_error " Explicit terminators (other than ReturnNode) must have `Any` type"
338- error ( " " )
360+ raise_error ( )
339361 end
340362 else
341363 isforeigncall = false
342364 if isa (stmt, Expr)
343365 if stmt. head === :(= )
344366 if stmt. args[1 ] isa SSAValue
345367 @verify_error " SSAValue as assignment LHS"
346- error ( " " )
368+ raise_error ( )
347369 end
348370 if stmt. args[2 ] isa GlobalRef
349371 # undefined GlobalRef as assignment RHS is OK
@@ -352,7 +374,7 @@ function verify_ir(ir::IRCode, print::Bool=true,
352374 elseif stmt. head === :isdefined
353375 if length (stmt. args) > 2 || (length (stmt. args) == 2 && ! isa (stmt. args[2 ], Bool))
354376 @verify_error " malformed isdefined"
355- error ( " " )
377+ raise_error ( )
356378 end
357379 if stmt. args[1 ] isa GlobalRef
358380 # undefined GlobalRef is OK in isdefined
@@ -380,12 +402,12 @@ function verify_ir(ir::IRCode, print::Bool=true,
380402 arg = stmt. args[i]
381403 if ! isa (arg, Union{Nothing, SSAValue})
382404 @verify_error " Malformed :leave - Expected `Nothing` or SSAValue"
383- error ()
405+ raise_error ()
384406 elseif isa (arg, SSAValue)
385407 enter_stmt = ir[arg:: SSAValue ][:stmt ]
386408 if ! isa (enter_stmt, Nothing) && ! isa (enter_stmt, EnterNode)
387409 @verify_error " Malformed :leave - argument ssavalue should point to `nothing` or :enter"
388- error ()
410+ raise_error ()
389411 end
390412 end
391413 end
@@ -394,7 +416,8 @@ function verify_ir(ir::IRCode, print::Bool=true,
394416 n = 1
395417 for op in userefs (stmt)
396418 op = op[]
397- check_op (ir, domtree, op, bb, idx, idx, print, isforeigncall, n, allow_frontend_forms)
419+ check_op (ir, domtree, op, bb, idx, idx, print, isforeigncall, n,
420+ allow_frontend_forms, raise_error)
398421 n += 1
399422 end
400423 end
0 commit comments