FluxML / IRTools.jl

Mike's Little Intermediate Representation
MIT License
111 stars 36 forks source link

Segfault when trying to manually build a dynamo-like function #17

Open phipsgabler opened 5 years ago

phipsgabler commented 5 years ago

I tried to disassemble and understand the process of how dynamos are working, and reasoned about what would be equivalent the following dynamo:

IRTools.@dynamo function test_dynamo(a...) 
    ir = empty(IRTools.IR(a...))
    push!(ir, IRTools.xcall(Main, :println, "hi"))
    IRTools.return!(ir, nothing)
    return ir
end

Naively substituting the code pieces in dynamo.jl, I thought the following should work:

@generated function test1(f, args...)
    ir = IRTools.empty(IRTools.IR(f, args...))
    push!(ir, IRTools.xcall(Main, :println, "hi"))
    IRTools.return!(ir, nothing)

    m = ir.meta::IRTools.Meta
    ir = IRTools.varargs!(m, ir)
    IRTools.argnames!(m, :args)
    _self = IRTools.splicearg!(m, ir, Symbol("#self#"))
    IRTools.prewalk!(x -> x === IRTools.self ? _self : x, ir)
    @show result = IRTools.update!(m.code, ir)
    return result
end

But instead, it crashes:

julia> test1(identity, 1)
result = IRTools.update!(m.code, ir) = CodeInfo(
 1 ─      (Main.println)("hi")
 │   %2 = nothing
 └──      return %2
)
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),))
rec_backtrace at /buildworker/worker/package_linux64/build/src/stackwalk.c:94
record_backtrace at /buildworker/worker/package_linux64/build/src/task.c:246
jl_throw at /buildworker/worker/package_linux64/build/src/task.c:577
throw_boundserror at ./abstractarray.jl:484
checkbounds at ./abstractarray.jl:449 [inlined]
getindex at ./array.jl:737 [inlined]
scan_slot_def_use at ./compiler/ssair/slot2ssa.jl:51
just_construct_ssa at ./compiler/ssair/driver.jl:103
run_passes at ./compiler/ssair/driver.jl:114
optimize at ./compiler/optimize.jl:162
typeinf at ./compiler/typeinfer.jl:35
typeinf_ext at ./compiler/typeinfer.jl:567
typeinf_ext at ./compiler/typeinfer.jl:604
jfptr_typeinf_ext_1 at /usr/local/julia-1.0.0/lib/julia/sys.so (unknown line)
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2182
jl_apply at /buildworker/worker/package_linux64/build/src/julia.h:1536 [inlined]
jl_apply_with_saved_exception_state at /buildworker/worker/package_linux64/build/src/rtutils.c:257
jl_type_infer at /buildworker/worker/package_linux64/build/src/gf.c:275
jl_compile_method_internal at /buildworker/worker/package_linux64/build/src/gf.c:1784 [inlined]
jl_fptr_trampoline at /buildworker/worker/package_linux64/build/src/gf.c:1828
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2182
do_call at /buildworker/worker/package_linux64/build/src/interpreter.c:324
eval_value at /buildworker/worker/package_linux64/build/src/interpreter.c:428
eval_stmt_value at /buildworker/worker/package_linux64/build/src/interpreter.c:363 [inlined]
eval_body at /buildworker/worker/package_linux64/build/src/interpreter.c:686
jl_interpret_toplevel_thunk_callback at /buildworker/worker/package_linux64/build/src/interpreter.c:799
unknown function (ip: 0xfffffffffffffffe)
unknown function (ip: 0x7f69e453496f)
unknown function (ip: 0xffffffffffffffff)
jl_interpret_toplevel_thunk at /buildworker/worker/package_linux64/build/src/interpreter.c:808
jl_toplevel_eval_flex at /buildworker/worker/package_linux64/build/src/toplevel.c:787
jl_toplevel_eval_in at /buildworker/worker/package_linux64/build/src/builtins.c:622
eval at ./boot.jl:319
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2182
eval_user_input at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.0/REPL/src/REPL.jl:85
run_backend at /home/philipp/.julia/packages/Revise/agmgx/src/Revise.jl:949
#75 at ./task.jl:259
jl_fptr_trampoline at /buildworker/worker/package_linux64/build/src/gf.c:1829
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2182
jl_apply at /buildworker/worker/package_linux64/build/src/julia.h:1536 [inlined]
start_task at /buildworker/worker/package_linux64/build/src/task.c:268
unknown function (ip: 0xffffffffffffffff)
result = IRTools.update!(m.code, ir) = CodeInfo(
 1 ─      (Main.println)("hi")
 │   %2 = nothing
 └──      return %2
)

signal (11): Segmentation fault
in expression starting at no file:0
cast_or_null<llvm::Instruction, llvm::Instruction> at /buildworker/worker/package_linux64/build/usr/include/llvm/Support/Casting.h:298 [inlined]
emit_function at /buildworker/worker/package_linux64/build/src/codegen.cpp:6552
jl_compile_linfo at /buildworker/worker/package_linux64/build/src/codegen.cpp:1159
jl_generate_fptr at /buildworker/worker/package_linux64/build/src/codegen.cpp:1394
jl_compile_method_internal at /buildworker/worker/package_linux64/build/src/gf.c:1821 [inlined]
jl_fptr_trampoline at /buildworker/worker/package_linux64/build/src/gf.c:1828
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2182
do_call at /buildworker/worker/package_linux64/build/src/interpreter.c:324
eval_value at /buildworker/worker/package_linux64/build/src/interpreter.c:428
eval_stmt_value at /buildworker/worker/package_linux64/build/src/interpreter.c:363 [inlined]
eval_body at /buildworker/worker/package_linux64/build/src/interpreter.c:686
jl_interpret_toplevel_thunk_callback at /buildworker/worker/package_linux64/build/src/interpreter.c:799
unknown function (ip: 0xfffffffffffffffe)
unknown function (ip: 0x7f69e453496f)
unknown function (ip: 0xffffffffffffffff)
jl_interpret_toplevel_thunk at /buildworker/worker/package_linux64/build/src/interpreter.c:808
jl_toplevel_eval_flex at /buildworker/worker/package_linux64/build/src/toplevel.c:787
jl_toplevel_eval_in at /buildworker/worker/package_linux64/build/src/builtins.c:622
eval at ./boot.jl:319
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2182
eval_user_input at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.0/REPL/src/REPL.jl:85
run_backend at /home/philipp/.julia/packages/Revise/agmgx/src/Revise.jl:949
#75 at ./task.jl:259
jl_fptr_trampoline at /buildworker/worker/package_linux64/build/src/gf.c:1829
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2182
jl_apply at /buildworker/worker/package_linux64/build/src/julia.h:1536 [inlined]
start_task at /buildworker/worker/package_linux64/build/src/task.c:268
unknown function (ip: 0xffffffffffffffff)
Allocations: 21604532 (Pool: 21601220; Big: 3312); GC: 48
[1]    26428 segmentation fault (core dumped)  julia

No idea if that's a legitimate use case that should have worked. What I actually wanted to achieve was to get a dynamo that adds a new argument to the given method.

MikeInnes commented 5 years ago

This is possible, of course, but really fiddly. @dynamo exists because it's pretty much impossible to get this right first try (it always takes me multiple attempts as well).

We could dig into why this isn't working, but if you just want to add a new argument you probably don't need to, you can do this with @dynamo. You just need something like

@dynamo function foo(f, cx, args...)
  ir = IR(f, args...)
  cx = argument!(ir, at = 2)
  ...
end
phipsgabler commented 5 years ago

Hm. For some reason, just using argument! didn't work when I tried it, but now it does :) Thanks, that question is settled now.