[LLVMdev] OCaml bindings

Gordon Henriksen gordonhenriksen at mac.com
Sun Nov 25 12:01:53 PST 2007


On Nov 25, 2007, at 11:49, Jon Harrop wrote:

> On Sunday 25 November 2007 12:23, Gordon Henriksen wrote:
>
>> If ocamlc is on your path, then 'configure; make; make install'  
>> should install the bindings in your ocaml lib.
>
> Right. I hadn't noticed they were already installed after llvm "make  
> install" in:
>
>  /usr/local/lib/ocaml/


Right. They're installed in 'if $stdlib is beneath $prefix then  
$stdlib else $prefix/lib/ocaml'. :) You can force the matter with

     ./configure --with-ocaml-libdir=`ocamlc -where`

>> On 2007-11-24, at 21:58, Jon Harrop wrote:
>>
>>
>>> - Some interface to LLVM from OCaml
>>> What is the easiest way to interface a front-end written in OCaml  
>>> with an LLVM backend?
>>
>> The C and Ocaml bindings in the source tree are intended to cover  
>> precisely this scenario, and I would recommend them over .ll  
>> emission. Jan's remark is a bit out of date; the bindings are  
>> sufficient for code generation now. A few corners of the IR are  
>> still not fully covered, but extending the bindings to new methods  
>> is quite straightforward.
>>
>>> I just rediscovered the OCaml bindings in bindings/ocaml (...).  
>>> They do indeed look quite complete but I can't find any examples  
>>> using them.
>>
>> See an example here, which an Ocaml program to emit the bitcode for  
>> a "hello world" program:
>>
>>     http://lists.cs.uiuc.edu/pipermail/llvmdev/2007-October/010996.html
>>
>
> Wow, this is just great!
>
> I had to tweak your example to get it to compile. Some of the  
> function names and signatures have changed (I'm using CVS LLVM) so  
> I've updated them and just thrown away the booleans you were passing  
> (no idea what they were for but it works ;-).

Ah, right; I'd forgotten about those changes or I would've updated it  
for you. The booleans in particular were used for null-terminating  
strings and creating varargs function types, among others, but weren't  
self-documenting, so I introduced variant names instead. For instance:

> Also, I think const_string maybe should null terminate the given  
> string so I changed your example to pass it a null terminated string  
> instead (nasty hack).

const_stringz null-terminates the string. But adding \000 in the  
literal as you did is equivalent.

> My code is:
>
> [...]
>
> To use it I just do:
>
> $ ocamlopt -dtypes -cc g++ -I /usr/local/lib/ocaml/ llvm.cmxa  
> llvm_bitwriter.cmxa hellow.ml -o hellow
> $ ./hellow run.bc
>
> How do I compile straight to native code without going via C?

-march=c invokes a very unusual LLVM target which emits C code instead  
of assembly. Read http://llvm.org/cmds/llc.html and llc --help. Here:

> $ llc -f -march=c run.bc -o run.c

Simply run 'llc run.bc -o run.s' to generate native assembly code.  
 From there, you can use 'as' and 'ld' to assemble and link.

In my example, I had used the gcc driver to succinctly invoke 'as' and  
'ld' in the proper platform-specific manner, including linking with  
the C standard library (for printf). Since the input was already  
compiled to assembly code, 'gcc' did not invoke the C compiler.

> $ gcc run.c -o run
> run.c:114: warning: conflicting types for built-in function ‘malloc’
> run.c: In function ‘main’:
> run.c:143: warning: return type of ‘main’ is not ‘int’
> $ ./run
> Hello, world!
>
> Can we use pipes to avoid generating intermediate files?

For the llvm tools, yes. For instance:

     # optimize bitcode and disassemble to LLVM assembly
     opt -std-compile-opts < run.bc | llvm-dis

     # optimize bitcode, compile to native assembly, and assemble to  
native object
     opt -std-compile-opts < run.bc | llc | as -o run.o

However, writing the bitcode presently requires a temp file. This is a  
problem with the libraries at both ends:

  1. Standard C++ doesn't provide file-descriptor streams at all.  
(LLVM uses C++ iostreams.)
  2. Ocaml doesn't allow extracting the file descriptor from an  
Output_channel.

There are a variety of workarounds available for the bindings, but I  
have not yet pursued them. The simplest is a "write_bitcode_to_stdout"  
function which uses the std::cout stream internally.

>> I think a translation of the tutorial would be most welcome and  
>> about 10x shorter. ;-)
>
> Shall we port the tutorial to OCaml?

By all means! I think you'd also stumble across some areas that are  
not bound yet, such as building pipelines to run optimizations in- 
process. I'd be happy to fill in any gaps you find. It would be a very  
useful exercise in that it would generate that feedback, improving  
both the C and Ocaml bindings.

You'll find that the LLVM community openly welcomes not only users and  
their contributions, so please jump in and get your hands dirty. The  
#llvm IRC channel on irc.oftc.net is also a great resource.

— Gordon





More information about the llvm-dev mailing list