Anything changng assembly?

175 views
Skip to first unread message

andrew cooke

unread,
Mar 22, 2015, 1:04:36 PM3/22/15
to julia...@googlegroups.com

I'm aware of https://groups.google.com/forum/#!searchin/julia-users/calling$20assembly/julia-users/fJHZCAJkrgo/VV7ZskAjqzMJ - I'm wondering if anything has changed in the last few years?  Is calling C still the best way to call inline assembly?

I ask because for a general library, I am not sure how portable this is.  How does one bundle C code so that it is compiled on all platforms Julia runs on?

Thanks, Andrew

PS That thread refers to "PAPI C's interface[1]", but I can't see what [1] refers to, and my attepts at googling for PAPI have been unproductive.  So any info on that, too, would be appreciated.

Isaiah Norton

unread,
Mar 22, 2015, 3:13:43 PM3/22/15
to julia...@googlegroups.com
(The PAPI thing was related to the perf counters, so not directly relevant to the inline assembly question. but, see here: http://icl.cs.utk.edu/projectsdev/papi/)

The big change is that `Base.llvmcall` is now merged, so you can write LLVM IR directly. There are two examples in test/llvmcall.jl, and I believe Simon Byrne has been testing the use of this for some math intrinsics if you want to google around (or maybe he will see this and comment if so).

However, the LLVM+JIT combo in the downloadable Julia versions (LLVM 3.3) does not support inline assembly, so you will need to compile Julia yourself against LLVM version 3.6 [1].

Once that is done, here are some basic examples I cobbled together -- if you know assembly and LLVM IR better than I do, hopefully it will be easier for you.

Add some ints:

 f(x::Int64,y::Int64) = Base.llvmcall("""%3 = add i64 %0, %1
                                                       ret i64 %3""", (Int64), (Int64,Int64), x, y)

julia> f(1,2)
3

Read the RTDSC counter:

 f() = Base.llvmcall("""%1 = call i64 asm sideeffect "rdtsc", "=A,~{dirflag},~{fpsr},~{flags}"()
                                ret i64 %1""", (Int64), ())
julia> f()
3643079421
 

A helpful trick here is to use clang to tell you what the IR should look like. Write a C file with the inline assembly you want, then compile it with `clang -emit-llvm -o test.ll test.c`, then try to translate that into the form expected by Base.llvmcall.

I should note that llvmcall is not documented yet, so here are the basics (I guess I should put this in the docs now that I've grok'd it myself...):

- first arg is the IR string
- second arg is the return type. Note that contrary to ccall, if you want to return i64 you should use `(Int64)` rather than `(Int64,)` (comma added) because otherwise the ret type will be interpreted as `<1 x i64>`.
- third arg is the argument types
- then the actual arguments

Hope that helps to get started.

[1] Create a file at the base of the source tree called `Make.user` with contents:

LLVM_VER = 3.6.0

and then proceed with the standard build instructions.

Stefan Karpinski

unread,
Mar 22, 2015, 4:37:49 PM3/22/15
to Julia Users
2015-03-22 20:13 GMT+01:00 Isaiah Norton <isaiah...@gmail.com>:
Note that contrary to ccall, if you want to return i64 you should use `(Int64)` rather than `(Int64,)` (comma added) because otherwise the ret type will be interpreted as `<1 x i64>`.

Isn't that the same as ccall since the return type arg to ccall is is not a tuple?

andrew cooke

unread,
Mar 22, 2015, 9:01:04 PM3/22/15
to julia...@googlegroups.com

awesome!

that gives me something to do for the next few months :o)

thank-you,
andrew

Simon Byrne

unread,
Mar 23, 2015, 4:32:11 AM3/23/15
to julia...@googlegroups.com
On Sunday, 22 March 2015 20:13:43 UTC+1, Isaiah wrote:
The big change is that `Base.llvmcall` is now merged, so you can write LLVM IR directly. There are two examples in test/llvmcall.jl, and I believe Simon Byrne has been testing the use of this for some math intrinsics if you want to google around (or maybe he will see this and comment if so).

Kind of. I don't really speak assembly (or LLVM IR for that matter), I actually used the same "clang -emit-llvm" process. All I managed was accessing one of the more useless instructions:

Some instructions are also available via LLVM intrinsics, which can be slightly easier to use. See for example here:

Unfortunately, these aren't really documented, but you can find some by grepping the LLVM tests directory. However to make this useful, we really need a fix to #8308.

simon

Isaiah Norton

unread,
Mar 23, 2015, 10:03:22 AM3/23/15
to julia...@googlegroups.com
Note that contrary to ccall, if you want to return i64 you should use `(Int64)` rather than `(Int64,)` (comma added) because otherwise the ret type will be interpreted as `<1 x i64>`.

Isn't that the same as ccall since the return type arg to ccall is is not a tuple?

Right, thanks for the correction. I had tried `(Int64,)` as a return type first (not realizing what the argument order was), and got LLVM errors about mismatched return type `<1 x i64>`.


Reply all
Reply to author
Forward
0 new messages