Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segfault with llvmcall and @eval #33689

Closed
thomasfaingnaert opened this issue Oct 26, 2019 · 1 comment
Closed

Segfault with llvmcall and @eval #33689

thomasfaingnaert opened this issue Oct 26, 2019 · 1 comment

Comments

@thomasfaingnaert
Copy link
Contributor

I'm wrapping a series of related LLVM IR snippets using llvmcall and @eval, and stumbled upon a segmentation fault if llvmcall is invoked with a list of declarations.

As an illustrative example, suppose we want to wrap addition and substraction:

for func in (:add, :sub)
    func_name = Symbol("do_", func)
    llvm_inst = string(func)

    @eval $func_name(x, y) = Base.llvmcall(
        "%res = $($(llvm_inst)) i64 %0, %1
         ret i64 %res", Int64, Tuple{Int64, Int64}, x, y)
end

Now, do_add(1, 2) and do_sub(1, 2) return 3 and -1, as expected.

However, I need the second form of llvmcall, which includes declarations (just an empty string for this example to not complicate matters):

for func in (:add, :sub)
    func_name = Symbol("do_", func)
    llvm_inst = string(func)

    @eval $func_name(x, y) = Base.llvmcall(("",
        "%res = $($(llvm_inst)) i64 %0, %1
         ret i64 %res"), Int64, Tuple{Int64, Int64}, x, y)
end

Executing do_add(1, 2) now results in a segfault:

signal (11): Segmentation fault
in expression starting at REPL[2]:1
eval_value at /buildworker/worker/package_linux64/build/src/interpreter.c:374
do_call at /buildworker/worker/package_linux64/build/src/interpreter.c:322
eval_value at /buildworker/worker/package_linux64/build/src/interpreter.c:411
unknown function (ip: 0xfffffffffffffffe)
unknown function (ip: 0x7fdb04b1310f)
unknown function (ip: 0x3100000005)
jl_interpret_toplevel_expr_in at /buildworker/worker/package_linux64/build/src/interpreter.c:927
try_eval at /buildworker/worker/package_linux64/build/src/ccall.cpp:637
emit_llvmcall at /buildworker/worker/package_linux64/build/src/ccall.cpp:861
emit_intrinsic at /buildworker/worker/package_linux64/build/src/intrinsics.cpp:875
emit_call at /buildworker/worker/package_linux64/build/src/codegen.cpp:3243
emit_expr at /buildworker/worker/package_linux64/build/src/codegen.cpp:4029
emit_ssaval_assign at /buildworker/worker/package_linux64/build/src/codegen.cpp:3734
emit_stmtpos at /buildworker/worker/package_linux64/build/src/codegen.cpp:3926 [inlined]
emit_function at /buildworker/worker/package_linux64/build/src/codegen.cpp:6404
jl_compile_linfo at /buildworker/worker/package_linux64/build/src/codegen.cpp:1196
jl_compile_method_internal at /buildworker/worker/package_linux64/build/src/gf.c:1775
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2196
do_call at /buildworker/worker/package_linux64/build/src/interpreter.c:323
eval_value at /buildworker/worker/package_linux64/build/src/interpreter.c:411
eval_stmt_value at /buildworker/worker/package_linux64/build/src/interpreter.c:362 [inlined]
eval_body at /buildworker/worker/package_linux64/build/src/interpreter.c:772
jl_interpret_toplevel_thunk_callback at /buildworker/worker/package_linux64/build/src/interpreter.c:884
unknown function (ip: 0xfffffffffffffffe)
unknown function (ip: 0x7fdb04b1308f)
unknown function (ip: 0xffffffffffffffff)
jl_interpret_toplevel_thunk at /buildworker/worker/package_linux64/build/src/interpreter.c:893
jl_toplevel_eval_flex at /buildworker/worker/package_linux64/build/src/toplevel.c:815
jl_toplevel_eval_flex at /buildworker/worker/package_linux64/build/src/toplevel.c:764
jl_toplevel_eval_in at /buildworker/worker/package_linux64/build/src/toplevel.c:844
eval at ./boot.jl:330
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2191
eval_user_input at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.2/REPL/src/REPL.jl:86
run_backend at /home/thomas/.julia/packages/Revise/cbX7Q/src/Revise.jl:973
#79 at ./task.jl:268
jl_apply_generic at /buildworker/worker/package_linux64/build/src/gf.c:2197
jl_apply at /buildworker/worker/package_linux64/build/src/julia.h:1614 [inlined]
start_task at /buildworker/worker/package_linux64/build/src/task.c:596
unknown function (ip: 0xffffffffffffffff)
Allocations: 4831791 (Pool: 4830554; Big: 1237); GC: 10
Segmentation fault (core dumped)

However, explicitly declaring do_add and do_sub works:

do_add(x, y) = Base.llvmcall(("", "%res = add i64 %0, %1
                                   ret i64 %res"), Int64, Tuple{Int64, Int64}, x, y)
do_sub(x, y) = Base.llvmcall(("", "%res = sub i64 %0, %1
                                   ret i64 %res"), Int64, Tuple{Int64, Int64}, x, y)

do_add(1, 2) returns 3, as expected.

Is this a bug or am I doing something wrong here?

Output of versioninfo():

Julia Version 1.2.0
Commit c6da87ff4b (2019-08-20 00:03 UTC)
Platform Info:
  OS: Linux (x86_64-pc-linux-gnu)
  CPU: Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-6.0.1 (ORCJIT, skylake)
Environment:
  JULIA_EDITOR = gvim --remote-silent
@maleadt
Copy link
Member

maleadt commented Oct 27, 2019

#25041, arguments to llvmcall need to be literals.

julia> for func in (:add, :sub)
           func_name = Symbol("do_", func)
           llvm_inst = string(func)

           x = ("",
                "%res = $llvm_inst i64 %0, %1
                 ret i64 %res")
           @eval $func_name(x, y) = Base.llvmcall($x, Int64, Tuple{Int64, Int64}, x, y)
       end

julia> do_add(1, 2)
3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants