<html><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; "><div><div><div><div>Hi all,</div><div><br class="webkit-block-placeholder"></div><div>I'm authoring a C interface to the LLVM IR type system. Since this is Really Quite Tedious, I would like to solicit opinions before I get too far down any paths that seem offensive. I've attached the header, where I've mapped a portion of <font class="Apple-style-span" face="Courier">Module</font> and most of <font class="Apple-style-span" face="Courier">Type</font> and its subclasses. This is working, and I've built ocaml bindings on top of it.[1] My intent is to extend this work (only) far enough to author a language front-end. The C bindings should help other languages which want to have self-hosting front-ends, and probably a C interface to the JIT would be well-received.</div><div><br class="webkit-block-placeholder"></div><div>My naming conventions are similar to the Carbon interfaces in OS X. (Should I prefer a Unixy flavor instead?) Naming prefix is LLVM, which may be a bit long. (Would LL be better?) Pointers are opaque, obviously. I find myself copying enums, which is mildly scary.</div><div><br class="webkit-block-placeholder"></div><div>I'm using C strings instead of <font class="Apple-style-span" face="Courier"><font class="Apple-style-span" color="#004080">const char*, size_t</font></font> tuples. This avoids having to write things like <font class="Apple-style-span" face="Courier"><font class="Apple-style-span" color="#004080">"tmp", strlen("tmp")</font></font> in C, and is well-supported for language bindings. Nevertheless, most languages other than C have binary-safe string types, so I'm certainly willing to have my mind changed if we want to prefer correctness over inconvenience to the C programmer. (Providing overloads is silly, though.)</div><div><br class="webkit-block-placeholder"></div><div>I'm putting the headers in <font class="Apple-style-span" face="Courier">include/llvm-c</font>. I created a new library called <font class="Apple-style-span" face="Courier">Interop</font> to house the C bindings—but it might make more sense to implement the C bindings in each library instead. They're just glue which the linker will trivially DCE, so that approach may have merit.</div><div><br class="webkit-block-placeholder"></div><div>— Gordon</div><br></div><div><br class="webkit-block-placeholder"></div><div>[1]</div><div><div><font class="Apple-style-span" face="Courier"><b>$ cat emit_bc.ml</b></font></div><div><font class="Apple-style-span" face="Courier"><font class="Apple-style-span" color="#0000FF">open</font> Llvm</font></div><div><font class="Apple-style-span" face="Courier"><br class="webkit-block-placeholder"></font></div><div><font class="Apple-style-span" face="Courier"><font class="Apple-style-span" color="#0000FF">let</font> emit_bc filename =</font></div><div><font class="Apple-style-span" face="Courier">  <font class="Apple-style-span" color="#0000FF">let</font> m = create_module filename <font class="Apple-style-span" color="#0000FF">in</font></font></div><div><font class="Apple-style-span" face="Courier"><br class="webkit-block-placeholder"></font></div><div><font class="Apple-style-span" face="Courier">  <font class="Apple-style-span" color="#0000FF">let</font> big_fn_ty = make_pointer_type</font></div><div><font class="Apple-style-span" face="Courier">    (make_function_type (void_type ())</font></div><div><font class="Apple-style-span" face="Courier">                        [| make_vector_type (float_type ()) 4;</font></div><div><font class="Apple-style-span" face="Courier">                           make_pointer_type</font></div><div><font class="Apple-style-span" face="Courier">                             (make_struct_type [| double_type ();</font></div><div><font class="Apple-style-span" face="Courier">                                                  x86fp80_type ();</font></div><div><font class="Apple-style-span" face="Courier">                                                  fp128_type ();</font></div><div><font class="Apple-style-span" face="Courier">                                                  ppc_fp128_type () |] <font class="Apple-style-span" color="#0000FF">true</font>);</font></div><div><font class="Apple-style-span" face="Courier">                           make_pointer_type</font></div><div><font class="Apple-style-span" face="Courier">                             (make_struct_type [| make_integer_type 1;</font></div><div><font class="Apple-style-span" face="Courier">                                                  make_integer_type 3;</font></div><div><font class="Apple-style-span" face="Courier">                                                  i8_type ();</font></div><div><font class="Apple-style-span" face="Courier">                                                  i32_type () |] <font class="Apple-style-span" color="#0000FF">false</font>);</font></div><div><font class="Apple-style-span" face="Courier">                           make_pointer_type</font></div><div><font class="Apple-style-span" face="Courier">                             (make_array_type (make_opaque_type ()) 4) |]</font></div><div><font class="Apple-style-span" face="Courier">                        <font class="Apple-style-span" color="#0000FF">false</font>) <font class="Apple-style-span" color="#0000FF">in</font></font></div><div><font class="Apple-style-span" face="Courier"><br class="webkit-block-placeholder"></font></div><div><font class="Apple-style-span" face="Courier"><font class="Apple-style-span" color="#008040">  (* string_of_lltype is implemented in ocaml, so the info on stdout</font></font></div><div><font class="Apple-style-span" face="Courier"><font class="Apple-style-span" color="#008040">     shows that make_*_type isn't a write-once/read-never interface. *)</font></font></div><div><font class="Apple-style-span" face="Courier">  print_endline (<font class="Apple-style-span" color="#800000">"big_fn_ty = "</font> ^ (string_of_lltype big_fn_ty));</font></div><div><font class="Apple-style-span" face="Courier">  </font></div><div><font class="Apple-style-span" face="Courier">  <font class="Apple-style-span" color="#0000FF">ignore</font>(add_type_name m <font class="Apple-style-span" color="#800000">"big_fn_ty"</font> big_fn_ty);</font></div><div><font class="Apple-style-span" face="Courier">  </font></div><div><font class="Apple-style-span" face="Courier">  <font class="Apple-style-span" color="#0000FF">if not</font> (write_bitcode_file m filename)</font></div><div><font class="Apple-style-span" face="Courier">    <font class="Apple-style-span" color="#0000FF">then</font> print_endline (<font class="Apple-style-span" color="#800000">"write failed: "</font> ^ filename);</font></div><div><font class="Apple-style-span" face="Courier">  </font></div><div><font class="Apple-style-span" face="Courier">  dispose_module m</font></div><div><font class="Apple-style-span" face="Courier"><br class="webkit-block-placeholder"></font></div><div><font class="Apple-style-span" face="Courier"><font class="Apple-style-span" color="#0000FF">let</font> _ = </font></div><div><font class="Apple-style-span" face="Courier">  <font class="Apple-style-span" color="#0000FF">if</font> 2 = <i>Array.</i>length <i>Sys.</i>argv</font></div><div><font class="Apple-style-span" face="Courier">    <font class="Apple-style-span" color="#0000FF">then</font> emit_bc <i>Sys.</i>argv.(1)</font></div><div><font class="Apple-style-span" face="Courier">    <font class="Apple-style-span" color="#0000FF">else</font> print_endline <font class="Apple-style-span" color="#800000">"Usage: emit_bc FILE"</font></font></div><div><font class="Apple-style-span" face="Courier"><br class="webkit-block-placeholder"></font></div><div><font class="Apple-style-span" face="Courier"><b>$ make emit_bc</b></font></div><div><font class="Apple-style-span" face="Courier">ocamlc -cc g++ -I ../llvm/Release/lib/ocaml llvm_ml.cma -o emit_bc emit_bc.ml</font></div><div><font class="Apple-style-span" face="Courier"><b>$ ./emit_bc test.bc</b></font></div><div><font class="Apple-style-span" face="Courier">big_fn_ty = void (< 4 x float >, { double, x86fp80, fp128, ppc_fp128 }*, { i1, i3, i8, i32 }*, [ 4 x opaque ]*)*</font></div><div><font class="Apple-style-span" face="Courier"><b>$ llvm-dis -o - test.bc</b></font></div><div><font class="Apple-style-span" face="Courier">; ModuleID = 'test.bc'</font></div><div><font class="Apple-style-span" face="Courier">        %big_fn_ty = type void (<4 x float>, <{ double, x86_fp80, fp128, ppc_fp128 }>*, { i1, i3, i8, i32 }*, [4 x opaque]*)*</font></div><font class="Apple-style-span" face="Courier"></font></div><span><div><br class="webkit-block-placeholder"></div><span><div><br class="webkit-block-placeholder"></div></span></span></div></div></body></html>