Stream: helpdesk (published)

Topic: Why does this generated function segfault?


view this post on Zulip Mason Protter (Feb 18 2021 at 03:56):

I'm sure I'm just doing something stupid, but I'd appreciate some pointers as to what's going wrong here.

julia> f(x) = x + 1
f (generic function with 1 method)

julia> @generated function foo(_, x)
           ci_orig = ci = code_lowered(f, (Any,))[1]
           ci = ccall(:jl_copy_code_info, Ref{Core.CodeInfo}, (Any,), ci_orig)
           return ci
       end
foo (generic function with 1 method)

julia> foo(f, 1)
Internal error: encountered unexpected error in runtime:
BoundsError(a=Array{Core.Compiler.SlotInfo, (2,)}[
  Core.Compiler.SlotInfo(defs=Array{Int64, (0,)}[], uses=Array{Int64, (0,)}[], any_newvar=false),
  Core.Compiler.SlotInfo(defs=Array{Int64, (0,)}[], uses=Array{Int64, (0,)}[], any_newvar=false)], i=(Core.Compiler.UnitRange{Int64}(start=1, stop=3),))
throw_boundserror at ./abstractarray.jl:645
checkbounds at ./abstractarray.jl:610 [inlined]
getindex at ./array.jl:807 [inlined]
scan_slot_def_use at ./compiler/ssair/slot2ssa.jl:50
slot2reg at ./compiler/ssair/driver.jl:116 [inlined]
run_passes at ./compiler/ssair/driver.jl:124
optimize at ./compiler/optimize.jl:272 [inlined]
_typeinf at ./compiler/typeinfer.jl:244
typeinf at ./compiler/typeinfer.jl:209
typeinf_ext at ./compiler/typeinfer.jl:892
typeinf_ext_toplevel at ./compiler/typeinfer.jl:925
typeinf_ext_toplevel at ./compiler/typeinfer.jl:921
jfptr_typeinf_ext_toplevel_11349 at /home/mason/julia/usr/lib/julia/sys.so (unknown line)
jl_apply at /home/mason/julia/src/julia.h:1703 [inlined]
jl_type_infer at /home/mason/julia/src/gf.c:298
jl_generate_fptr at /home/mason/julia/src/jitlayers.cpp:340
jl_compile_method_internal at /home/mason/julia/src/gf.c:1971
jl_compile_method_internal at /home/mason/julia/src/gf.c:1925 [inlined]
_jl_invoke at /home/mason/julia/src/gf.c:2230 [inlined]
jl_apply_generic at /home/mason/julia/src/gf.c:2420
jl_apply at /home/mason/julia/src/julia.h:1703 [inlined]
do_call at /home/mason/julia/src/interpreter.c:115
eval_value at /home/mason/julia/src/interpreter.c:204
eval_stmt_value at /home/mason/julia/src/interpreter.c:155 [inlined]
eval_body at /home/mason/julia/src/interpreter.c:561
jl_interpret_toplevel_thunk at /home/mason/julia/src/interpreter.c:669
top-level scope at REPL[3]:1
jl_toplevel_eval_flex at /home/mason/julia/src/toplevel.c:879
jl_toplevel_eval_flex at /home/mason/julia/src/toplevel.c:827
jl_toplevel_eval_flex at /home/mason/julia/src/toplevel.c:827
jl_toplevel_eval_in at /home/mason/julia/src/toplevel.c:931
eval at ./boot.jl:360
eval_user_input at /home/mason/julia/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:139
repl_backend_loop at /home/mason/julia/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:200
start_repl_backend at /home/mason/julia/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:185
#run_repl#42 at /home/mason/julia/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:317
run_repl at /home/mason/julia/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:305
#878 at ./client.jl:387
jfptr_YY.878_41186 at /home/mason/julia/usr/lib/julia/sys.so (unknown line)
jl_apply at /home/mason/julia/src/julia.h:1703 [inlined]
do_apply at /home/mason/julia/src/builtins.c:672
jl_f__apply_latest at /home/mason/julia/src/builtins.c:722
#invokelatest#2 at ./essentials.jl:707 [inlined]
invokelatest at ./essentials.jl:706 [inlined]
run_main_repl at ./client.jl:372
exec_options at ./client.jl:302
_start at ./client.jl:485
jfptr__start_38985 at /home/mason/julia/usr/lib/julia/sys.so (unknown line)
jl_apply at /home/mason/julia/src/julia.h:1703 [inlined]
true_main at /home/mason/julia/src/jlapi.c:557
repl_entrypoint at /home/mason/julia/src/jlapi.c:699
main at /home/mason/julia/cli/loader_exe.c:51
__libc_start_main at /usr/lib/libc.so.6 (unknown line)
_start at /home/mason/julia/./julia (unknown line)
julia: /home/mason/julia/src/julia.h:923: jl_value_t* jl_array_ptr_ref(void*, size_t): Assertion `i < jl_array_len(a)' failed.

signal (6): Aborted
in expression starting at REPL[3]:1
gsignal at /usr/lib/libc.so.6 (unknown line)
abort at /usr/lib/libc.so.6 (unknown line)
__assert_fail_base.cold at /usr/lib/libc.so.6 (unknown line)
__assert_fail at /usr/lib/libc.so.6 (unknown line)
jl_array_ptr_ref at /home/mason/julia/src/julia.h:923 [inlined]
jl_array_ptr_ref at /home/mason/julia/src/julia.h:920 [inlined]
emit_function at /home/mason/julia/src/codegen.cpp:5833
jl_emit_code at /home/mason/julia/src/codegen.cpp:7185
jl_emit_codeinst at /home/mason/julia/src/codegen.cpp:7230
_jl_compile_codeinst at /home/mason/julia/src/jitlayers.cpp:124
jl_generate_fptr_for_unspecialized at /home/mason/julia/src/jitlayers.cpp:396
jl_compile_method_internal at /home/mason/julia/src/gf.c:1977
jl_compile_method_internal at /home/mason/julia/src/gf.c:1925 [inlined]
_jl_invoke at /home/mason/julia/src/gf.c:2230 [inlined]
jl_apply_generic at /home/mason/julia/src/gf.c:2420
jl_apply at /home/mason/julia/src/julia.h:1703 [inlined]
do_call at /home/mason/julia/src/interpreter.c:115
eval_value at /home/mason/julia/src/interpreter.c:204
eval_stmt_value at /home/mason/julia/src/interpreter.c:155 [inlined]
eval_body at /home/mason/julia/src/interpreter.c:561
jl_interpret_toplevel_thunk at /home/mason/julia/src/interpreter.c:669
jl_toplevel_eval_flex at /home/mason/julia/src/toplevel.c:879
jl_toplevel_eval_flex at /home/mason/julia/src/toplevel.c:827
jl_toplevel_eval_flex at /home/mason/julia/src/toplevel.c:827
jl_toplevel_eval_in at /home/mason/julia/src/toplevel.c:931
eval at ./boot.jl:360
eval_user_input at /home/mason/julia/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:139
repl_backend_loop at /home/mason/julia/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:200
start_repl_backend at /home/mason/julia/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:185
#run_repl#42 at /home/mason/julia/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:317
run_repl at /home/mason/julia/usr/share/julia/stdlib/v1.6/REPL/src/REPL.jl:305
#878 at ./client.jl:387
jfptr_YY.878_41186 at /home/mason/julia/usr/lib/julia/sys.so (unknown line)
jl_apply at /home/mason/julia/src/julia.h:1703 [inlined]
do_apply at /home/mason/julia/src/builtins.c:672
jl_f__apply_latest at /home/mason/julia/src/builtins.c:722
#invokelatest#2 at ./essentials.jl:707 [inlined]
invokelatest at ./essentials.jl:706 [inlined]
run_main_repl at ./client.jl:372
exec_options at ./client.jl:302
_start at ./client.jl:485
jfptr__start_38985 at /home/mason/julia/usr/lib/julia/sys.so (unknown line)
jl_apply at /home/mason/julia/src/julia.h:1703 [inlined]
true_main at /home/mason/julia/src/jlapi.c:557
repl_entrypoint at /home/mason/julia/src/jlapi.c:699
main at /home/mason/julia/cli/loader_exe.c:51
__libc_start_main at /usr/lib/libc.so.6 (unknown line)
_start at /home/mason/julia/./julia (unknown line)
Allocations: 2062789 (Pool: 2061837; Big: 952); GC: 3
Aborted (core dumped)

view this post on Zulip Mason Protter (Feb 18 2021 at 03:58):

I'm trying to do the equivalent of IRTools.func without needing IRTools but I don't understand why it's not working.

view this post on Zulip Takafumi Arakaki (tkf) (Feb 18 2021 at 06:59):

Don't you need @generated function foo(x) instead of foo(_, x)? Or, if you want to change the arity (i.e., create a ci for 2-arg function foo(f, x) from 1-arg function f(x)), I guess you can do it by mutating ci?

view this post on Zulip Eric Forgy (Feb 18 2021 at 07:01):

I have no idea and could unsurprisingly be wrong, but it looks like ci and ci_orig are not only initialized to the same value, they are the same objects so modifying one will modify the other (ignore me if that is intended).

view this post on Zulip Mason Protter (Feb 18 2021 at 17:32):

Takafumi Arakaki (tkf) said:

Don't you need @generated function foo(x) instead of foo(_, x)? Or, if you want to change the arity (i.e., create a ci for 2-arg function foo(f, x) from 1-arg function f(x)), I guess you can do it by mutating ci?

Ohh, I didn't even think about this. In IRTools.jl you need to add an extra argument for the self slot if you do something similar. I guess Julia is smart enough with it's own CodeInfo object that this isn't necessary

view this post on Zulip Simeon Schaub (Feb 18 2021 at 20:58):

You can also manually add slots to CodeInfo, but if you just copy it, it will of course give you the same number of slots as the function you copy it from.

view this post on Zulip Mason Protter (Feb 18 2021 at 21:07):

I didn't want to add slots, I thought I needed to add an argument to foo in order to account for the internal #self# slot in the CodeInfo, but I was mistaken

view this post on Zulip Mason Protter (Feb 18 2021 at 21:09):

e.g.

julia> ci = code_lowered(f, (Any,))[1];

julia> ci.slotnames
2-element Vector{Symbol}:
 Symbol("#self#")
 :x

view this post on Zulip Mason Protter (Feb 18 2021 at 21:16):

I was just thrown off because it's different from IRTools.func

julia> using IRTools

julia> ir = IRTools.@code_ir f(1)
1: (%1, %2)
  %3 = %2 + 1
  return %3

julia> g = IRTools.func(ir)
##280 (generic function with 1 method)

julia> methods(g)
# 1 method for generic function "##280":
[1] var"##280"(arg1, arg2) in IRTools.Inner at /home/mason/.julia/packages/IRTools/aSVI5/src/eval.jl:18

julia> g(g, 1)
2

view this post on Zulip Takafumi Arakaki (tkf) (Feb 18 2021 at 22:43):

Maybe a MWE for the OP is something like this (though it's incomplete)

@generated function foo(f, x)
    ci, = code_lowered(f.instance, (x,))
    ci = ccall(:jl_copy_code_info, Ref{Core.CodeInfo}, (Any,), ci)
    for c in ci.code
        c isa Expr || continue
        for (i, a) in pairs(c.args)
            if a isa Core.SlotNumber && a.id > 1
                c.args[i] = Core.SlotNumber(a.id + 1)
            end
        end
    end
    insert!(ci.slotnames, 2, Symbol("#f#"))
    insert!(ci.slotflags, 2, 0x00)
    return ci
end

view this post on Zulip Mason Protter (Feb 18 2021 at 22:52):

Again, I did not want to add slots! Your first suggestion was correct. All I needed to do was remove that extra argument

view this post on Zulip Mason Protter (Feb 18 2021 at 22:53):

julia> f(x) = x + 1
f (generic function with 1 method)

julia> @generated function foo(x)
           ci_orig = ci = code_lowered(f, (Any,))[1]
           ci = ccall(:jl_copy_code_info, Ref{Core.CodeInfo}, (Any,), ci_orig)
           return ci
       end
foo (generic function with 1 method)

julia> foo(1)
2

is exactly what I wanted to do


Last updated: Oct 02 2023 at 04:34 UTC