@@ -221,34 +221,50 @@ function InferenceState(result::InferenceResult, cached::Symbol, interp::GPUInte
221221 src === nothing && return nothing
222222 validate_code_in_debug_mode (result. linfo, src, " lowered" )
223223 validate_globalrefs (interp, result. linfo, src)
224+ validate_code_in_debug_mode (result. linfo, src, " validated" )
225+ errors = Core. Compiler. validate_code (result. linfo, src)
226+ @safe_info " errors" errors src. code
224227 return InferenceState (result, src, cached, interp)
225228end
226229
227230function validate_globalrefs (interp, mi, src)
228- function validate (x)
231+ # pseudo (single-frame) backtrace pointing to a source code location
232+ function backtrace (i)
233+ loc = src. linetable[i]
234+ [StackTraces. StackFrame (loc. method, loc. file, loc. line, mi, false , false , C_NULL )]
235+ end
236+
237+ function validate (i, x, errors:: Vector{IRError} )
229238 if x isa Expr
230- return Expr (x. head, validate .(x. args))
239+ for y in x. args
240+ validate (i, y, errors)
241+ end
231242 elseif x isa GlobalRef
232243 Base. isbindingresolved (x. mod, x. name) || return
233244 # XXX : when does this happen? do we miss any cases by bailing out early?
234245 # why doesn't calling `Base.resolve(x, force=true)` work?
235246 if ! Base. isdefined (x. mod, x. name)
236- throw ( KernelError (interp . job, " using undefined global: $(x. mod) .$(x. name) " ))
247+ push! (errors, ( " using undefined global: $(x. mod) .$(x. name) " , backtrace (i), nothing ))
237248 end
238249 if ! Base. isconst (x. mod, x. name)
239- throw ( KernelError (interp . job, " using mutable global: $(x. mod) .$(x. name) " ))
250+ push! (errors, ( " using mutable global: $(x. mod) .$(x. name) " , backtrace (i), nothing ))
240251 end
241- # XXX : can we use KernelError? and make the validation conditional? both are
242- # complicated by the fact that we don't have the CompilerJob here,
243- # and that inference results can be cached across jobs.
252+
253+ # TODO : make the validation conditional, but make sure we don't cache invalid IR
244254
245255 # TODO : perform more validation? e.g. disallow Arrays and other CPU values?
246- # probably requires an interface, so again access to the CompilerJob
247- # (as a CPU-back-end would still support such values).
248256 end
257+
258+ return
249259 end
250260
251- validate .(src. code)
261+ errors = IRError[]
262+ for (i, x) in enumerate (src. code)
263+ validate (i, x, errors)
264+ end
265+ if ! isempty (errors)
266+ throw (InvalidIRError (interp. job, errors))
267+ end
252268
253269 return
254270end
0 commit comments