Skip to content

Commit 0efa8cc

Browse files
committed
Reuse existing IRError infrastructure.
1 parent c8d4aec commit 0efa8cc

File tree

2 files changed

+28
-10
lines changed

2 files changed

+28
-10
lines changed

src/jlgen.jl

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -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)
225228
end
226229

227230
function 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
254270
end

src/validation.jl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ end
9595

9696
## IR validation
9797

98+
# TODO: generalize for Julia and LLVM IR
99+
98100
const IRError = Tuple{String, StackTraces.StackTrace, Any} # kind, bt, meta
99101

100102
struct InvalidIRError <: Exception

0 commit comments

Comments
 (0)