LLVM-OCaml Bindings Tutorial (2.6-2.7)

Attached are updated LLVM-OCaml Bindings Tutorial from Chris Wailes.
(http://lists.cs.uiuc.edu/pipermail/llvmdev/2009-April/021804.html)
We changed them to work with the latest APIs(LLVM2.6 and the latest
LLVM from SVN).

Does anyone know if there is any realistic project using LLVM-OCaml
Bindings? How is the performance?

Jianzhou

LLVMOCamlBindingsTutorial.tgz (34 KB)

Does anyone know if there is any realistic project using LLVM-OCaml
Bindings?

I've written a VM in OCaml built upon LLVM using LLVM's OCaml bindings:

  http://www.ffconsultancy.com/ocaml/hlvm/

There are at least two other significant users of LLVM's OCaml bindings,
AFAIK.

How is the performance?

Performance of the bindings? Fine.

My only gripe with LLVM's OCaml bindings is the way an error caught on the
LLVM side causes my program to die in a way that the stack trace is
unobtainable. So I resort to massively verbose debug logs. I'd much rather
the bindings reraised errors as exceptions on the OCaml side.

There are at least two other significant users of LLVM's OCaml bindings,
AFAIK.

I'm writing an llvm backend/repl for felix, but it's pretty early.

My only gripe with LLVM's OCaml bindings is the way an error caught on the
LLVM side causes my program to die in a way that the stack trace is
unobtainable. So I resort to massively verbose debug logs. I'd much rather
the bindings reraised errors as exceptions on the OCaml side.

Unfortunately most errors are assertions, which we can't hook into.
Perhaps though we can recover some type safety. Hypothetically, I can
imagine using polymorphic variants just like lablgtk, and

type llvalue = [`Value]
type lluser = [value | `User]
type llconstant = [user | `Constant]
type llfunction = [llconstant | `Function]

val value_name : [> llvalue] -> string
val is_tail_call : [>llfunction] -> bool

Would something like this be worthwhile? If we do it right, I think we
could be mostly source compatible.

Does anyone know if there is any realistic project using LLVM-OCaml
Bindings?

I've written a VM in OCaml built upon LLVM using LLVM's OCaml bindings:

http://www.ffconsultancy.com/ocaml/hlvm/

There are at least two other significant users of LLVM's OCaml bindings,
AFAIK.

How is the performance?

Performance of the bindings? Fine.

My only gripe with LLVM's OCaml bindings is the way an error caught on the
LLVM side causes my program to die in a way that the stack trace is
unobtainable. So I resort to massively verbose debug logs. I'd much rather
the bindings reraised errors as exceptions on the OCaml side.

I met the same issue about how to debug assertion failures from C.
But I found the latest LLVM fixed the problem I met. So I am fine
temporarily. :slight_smile:

HLVM is an interesting project to support multi-language programming
in a higher level. In this project, have you designed a compiler optimization
pass with OCaml bindings?

I looked into the OCaml bindings codes.
It provides some OCaml interfaces to call an existing LLVM pass, such
as constant propagation, simplification of CFG, but it has not wrapped
enough interfaces to design a pass in OCaml from sketch yet. For example,
to implement a simple constant propagation (which is defined in
lib/Transforms/scalar in C++)
in OCaml, we need some functions in lib/Analysis which have not been
ported into OCaml. Was there any difficult to port those C++ code into
OCaml?

How does LLVM team expect users to use these OCaml bindings?
Is the implementation of a pass in OCaml an expected requirement? or
this bindings are only used to drive the LLVM compilations from OCaml.

Thanks
Jianzhou

There are at least two other significant users of LLVM's OCaml bindings,
AFAIK.

I'm writing an llvm backend/repl for felix, but it's pretty early.

My only gripe with LLVM's OCaml bindings is the way an error caught on the
LLVM side causes my program to die in a way that the stack trace is
unobtainable. So I resort to massively verbose debug logs. I'd much rather
the bindings reraised errors as exceptions on the OCaml side.

Unfortunately most errors are assertions, which we can't hook into.
Perhaps though we can recover some type safety. Hypothetically, I can
imagine using polymorphic variants just like lablgtk, and

type llvalue = [`Value]
type lluser = [value | `User]
type llconstant = [user | `Constant]
type llfunction = [llconstant | `Function]

val value_name : [> llvalue] -> string
val is_tail_call : [>llfunction] -> bool

Would something like this be worthwhile? If we do it right, I think we
could be mostly source compatible.

It sounds attractive if this works. But I did not quite get this idea.
Would you like to point out an example, or a reference
to elaborate this idea? Thanks.

Jianzhou

> I've written a VM in OCaml built upon LLVM using LLVM's OCaml bindings:
>
> http://www.ffconsultancy.com/ocaml/hlvm/

HLVM is an interesting project to support multi-language programming
in a higher level. In this project, have you designed a compiler
optimization pass with OCaml bindings?

HLVM is designed as a completely separate layer on top of LLVM with loose
bindings. LLVM code never calls back into HLVM, so no LLVM compiler passes
are written in OCaml. However, HLVM is compiling its own declarative
intermediate representation down to LLVM IR and, therefore, implements its
own internal compiler optimization passes that act upon HLVM's own IR and are
written entirely in OCaml. This is, of course, far simpler and safer than
trying to write LLVM passes in OCaml.

I looked into the OCaml bindings codes.
It provides some OCaml interfaces to call an existing LLVM pass, such
as constant propagation, simplification of CFG, but it has not wrapped
enough interfaces to design a pass in OCaml from sketch yet. For example,
to implement a simple constant propagation (which is defined in
lib/Transforms/scalar in C++)
in OCaml, we need some functions in lib/Analysis which have not been
ported into OCaml. Was there any difficult to port those C++ code into
OCaml?

How does LLVM team expect users to use these OCaml bindings?
Is the implementation of a pass in OCaml an expected requirement? or
this bindings are only used to drive the LLVM compilations from OCaml.

I believe the OCaml bindings are only intended to let OCaml programs drive
LLVM by conveying IR to it.

For me, the quality of LLVM's code gen is extremely important but its
optimization passes are irrelevant. HLVM generates very efficient LLVM IR
directly so LLVM's optimization passes rarely provide significant performance
improvements. Any productive optimizations that HLVM might do cannot be
expressed as LLVM passes because they would require higher-level information
that has been removed by that stage.

I thought about this before but I don't think it is worth doing. I read a blog
post describing how one set of Haskell bindings go to great lengths to convey
such type information but the errors it catches aren't the important ones in
practice and the added obfuscation actually drove that user away because they
couldn't get their code to compile and couldn't understand the type error.

I think it would be infinitely more valuable in practice to catch LLVM when it
dies with an error and have that raised on the OCaml side as an exception so
you get a useful stack trace telling you what your compiler was doing when
LLVM barfed.