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)
I'm trying to do the equivalent of IRTools.func
without needing IRTools but I don't understand why it's not working.
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
?
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).
Takafumi Arakaki (tkf) said:
Don't you need
@generated function foo(x)
instead offoo(_, x)
? Or, if you want to change the arity (i.e., create a ci for 2-arg functionfoo(f, x)
from 1-arg functionf(x)
), I guess you can do it by mutatingci
?
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
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.
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
e.g.
julia> ci = code_lowered(f, (Any,))[1];
julia> ci.slotnames
2-element Vector{Symbol}:
Symbol("#self#")
:x
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
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
Again, I did not want to add slots! Your first suggestion was correct. All I needed to do was remove that extra argument
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: Dec 28 2024 at 04:38 UTC