From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail2-relais-roc.national.inria.fr (mail2-relais-roc.national.inria.fr [192.134.164.83]) by sympa.inria.fr (Postfix) with ESMTPS id D36427EE57 for ; Wed, 6 Nov 2013 08:54:28 +0100 (CET) Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of nanaki@gmail.com) identity=pra; client-ip=209.85.128.181; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="nanaki@gmail.com"; x-sender="nanaki@gmail.com"; x-conformance=sidf_compatible Received-SPF: Pass (mail2-smtp-roc.national.inria.fr: domain of nanaki@gmail.com designates 209.85.128.181 as permitted sender) identity=mailfrom; client-ip=209.85.128.181; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="nanaki@gmail.com"; x-sender="nanaki@gmail.com"; x-conformance=sidf_compatible; x-record-type="v=spf1" Received-SPF: None (mail2-smtp-roc.national.inria.fr: no sender authenticity information available from domain of postmaster@mail-ve0-f181.google.com) identity=helo; client-ip=209.85.128.181; receiver=mail2-smtp-roc.national.inria.fr; envelope-from="nanaki@gmail.com"; x-sender="postmaster@mail-ve0-f181.google.com"; x-conformance=sidf_compatible X-IronPort-Anti-Spam-Filtered: true X-IronPort-Anti-Spam-Result: AlwPADn1eVLRVYC1lGdsb2JhbABZgz9TgwiFbaN1ihuIQ4EbCBYOAQEBAQcLCwkSKoIlAQEEASADHQEbEgQHAQMBCwYDAgsDFx0CAiIBEQEFAQoSBhMSCYdTAQMJBg2QIo9ai3kIA1ODCYQqChknAwpkiQEBBQyPSQQHgmkCgUUDiUCJUIR8gS+ObxgpgmaCDBs X-IPAS-Result: AlwPADn1eVLRVYC1lGdsb2JhbABZgz9TgwiFbaN1ihuIQ4EbCBYOAQEBAQcLCwkSKoIlAQEEASADHQEbEgQHAQMBCwYDAgsDFx0CAiIBEQEFAQoSBhMSCYdTAQMJBg2QIo9ai3kIA1ODCYQqChknAwpkiQEBBQyPSQQHgmkCgUUDiUCJUIR8gS+ObxgpgmaCDBs X-IronPort-AV: E=Sophos;i="4.93,644,1378850400"; d="scan'208";a="41176999" Received: from mail-ve0-f181.google.com ([209.85.128.181]) by mail2-smtp-roc.national.inria.fr with ESMTP/TLS/RC4-SHA; 06 Nov 2013 08:53:52 +0100 Received: by mail-ve0-f181.google.com with SMTP id jz11so3267094veb.40 for ; Tue, 05 Nov 2013 23:54:26 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=8Tq99EHglfIgDcfcEdlMjvgLEVTZdT0utWYNtuSmBks=; b=DKKTt3waHtoAntFqQCUU2hUsZsjqSRI/EyiQ+mKLxvWyvIclLBvLvCm0ZQnBAR759a fscDfJ+k5BR0tLPrblszFYwfdBrSbR1WvyzazJZzx84gd590HOqehitYB6miiG9ggxxA r4c/NHW+FqOB8RViu78LRKhK7xEkABEpr0p+qr6g0QlT6vVafmlcG2p7oOIHNFxFa3tO f/JzMhSk2TZ/kPhMzXdGOl89RliNjvlBWqAqM9WmcCq3dG5/fax5p8OrI7n9kJ/66l/U UdxVt5SEzHiSLRnNstg9IeAebXEriqgW/gclyl3kMu4fTnAWocP96Xwfvjsi9Tdyxh/v Fmnw== MIME-Version: 1.0 X-Received: by 10.58.144.168 with SMTP id sn8mr1278342veb.33.1383724466752; Tue, 05 Nov 2013 23:54:26 -0800 (PST) Received: by 10.58.220.135 with HTTP; Tue, 5 Nov 2013 23:54:26 -0800 (PST) In-Reply-To: References: <5278D1D1.4060009@gmail.com> <523e06f6b965a40b16bc8fe69a88e339@whitequark.org> Date: Tue, 5 Nov 2013 23:54:26 -0800 Message-ID: From: Jeff Meister To: Peter Zotov Cc: Caml List Content-Type: multipart/alternative; boundary=047d7b5da93b4ed30b04ea7d756b Subject: Re: [Caml-list] LLVM OCaml bindings --047d7b5da93b4ed30b04ea7d756b Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: quoted-printable On Tue, Nov 5, 2013 at 11:19 PM, Peter Zotov wro= te: > Jeff Meister =D0=BF=D0=B8=D1=81=D0=B0=D0=BB 06.11.2013 01:00: > > I can call const_int to get an llvalue representing an integer, then >> pass this llvalue as the first argument to build_call, which expects a >> function. Since both have type llvalue, the OCaml type checker will >> not complain, but a segfault or other undefined behavior will likely >> result at runtime. >> > > As mentioned elsewhere, it's defined in Asserts build. Personally, > I'm going to ship my compiler with LLVM built in Release+Asserts mode. > Sure, but those are runtime assertions, not compile time type errors. In my opinion, if the correct types can be expressed in OCaml, we should use them. Collapsing LLVM's complex subtype hierarchies into types like llvalue and lltype is not acceptable to me as an OCaml programmer. I might as well program in C. > What I did to fix this was reintroduce the inheritance hierarchy >> present in the C++ code. Using some module system tricks to make >> OCaml's structural subtyping act like nominal subtyping, I refactored >> everything into classes. In my version, const_int would return a >> ConstInt.t, which is a subtype of Value.t, but not compatible with the >> Function.t required by build_call. >> > > One thing to consider is that the C++ API does not use subtyping for > this kind of safety, either. Consider the prototype of > IRBuilder::CreateCall: > CallInst *CreateCall (Value *Callee, ArrayRef< Value * > Args, const Twine > &Name=3D"") > > This means that there is no guarantee you can convert the API to use > the subtyping safety measure you devised. Indeed, there are several > functions which do not have an equivalent type in hierarchy. > Llvm.set_volatile expects a [load] or [store], where Llvm.set_alignment > expects a [load], [store] or a global value, and Llvm.set_atomic_ordering > expects a [load], [store], [atomicrmw], [fence], or [cmpxchg]. > LLVM itself represents this by trying to explicitly cast the instruction > to each supported one, and then calling the corresponding method. > > Interestingly, this kind of relationship can be expressed better by OCaml= 's > structural OO system than C++'s nominative one. I think that a project > to wrap either LLVM's C or C++ API into OCaml's classes and objects may > be a good solution to at least part of the problem. I don't have time > to develop this myself, though. > That's a very interesting point! In my implementation, I simply duplicated the C++ method types, so if a parameter had type Value in C++, the same was reflected in the OCaml interface, even if the actual type is more complex as you described. My goal was simply to get the OCaml bindings on par with the C++ types to prevent undefined behavior (or runtime assertion failures) from mistaken casts that can easily be detected statically in OCaml. If we could use the OCaml type system to go even further than C++, that would be excellent! > I will try to find my code and put it up on GitHub if it would be useful >> to you. >> > > I would be interested to look into it, but I probably will not integrate > it into the bindings. > > > -- > WBR, Peter Zotov. > > -- > Caml-list mailing list. Subscription management and archives: > https://sympa.inria.fr/sympa/arc/caml-list > Beginner's list: http://groups.yahoo.com/group/ocaml_beginners > Bug reports: http://caml.inria.fr/bin/caml-bugs > --047d7b5da93b4ed30b04ea7d756b Content-Type: text/html; charset=KOI8-R Content-Transfer-Encoding: quoted-printable
On T= ue, Nov 5, 2013 at 11:19 PM, Peter Zotov <whitequark@whitequark.or= g> wrote:
Jeff Meister =D0=C9=D3=C1=CC 06.11.2013 01:0= 0:

I can call const_int to get an llvalue representing an integer, then
pass this llvalue as the first argument to build_call, which expects a
function. Since both have type llvalue, the OCaml type checker will
not complain, but a segfault or other undefined behavior will likely
result at runtime.

As mentioned elsewhere, it's defined in Asserts build. Personally,
I'm going to ship my compiler with LLVM built in Release+Asserts mode.<= br>

Sure, but those are runtime assertions, no= t compile time type errors. In my opinion, if the correct types can be expr= essed in OCaml, we should use them. Collapsing LLVM's complex subtype h= ierarchies into types like llvalue and lltype is not acceptable to me as an= OCaml programmer. I might as well program in C.
=9A
What I did to fix this was reintroduce the inheritance hierarchy
present in the C++ code. Using some module system tricks to make
OCaml's structural subtyping act like nominal subtyping, I refactored everything into classes. In my version, const_int would return a
ConstInt.t, which is a subtype of Value.t, but not compatible with the
Function.t required by build_call.

One thing to consider is that the C++ API does not use subtyping for
this kind of safety, either. Consider the prototype of
IRBuilder::CreateCall:
CallInst *CreateCall (Value *Callee, ArrayRef< Value * > Args, const = Twine &Name=3D"")

This means that there is no guarantee you can convert the API to use
the subtyping safety measure you devised. Indeed, there are several
functions which do not have an equivalent type in hierarchy.
Llvm.set_volatile expects a [load] or [store], where Llvm.set_alignment
expects a [load], [store] or a global value, and Llvm.set_atomic_ordering expects a [load], [store], [atomicrmw], [fence], or [cmpxchg].
LLVM itself represents this by trying to explicitly cast the instruction
to each supported one, and then calling the corresponding method.

Interestingly, this kind of relationship can be expressed better by OCaml&#= 39;s
structural OO system than C++'s nominative one. I think that a project<= br> to wrap either LLVM's C or C++ API into OCaml's classes and objects= may
be a good solution to at least part of the problem. I don't have time to develop this myself, though.

That's a very = interesting point! In my implementation, I simply duplicated the C++ method= types, so if a parameter had type Value in C++, the same was reflected in = the OCaml interface, even if the actual type is more complex as you describ= ed. My goal was simply to get the OCaml bindings on par with the C++ types = to prevent undefined behavior (or runtime assertion failures) from mistaken= casts that can easily be detected statically in OCaml. If we could use the= OCaml type system to go even further than C++, that would be excellent!
=9A
I will try to find my code and put it up on GitHub if it would be useful to= you.

I would be interested to look into it, but I probably will not integrate
it into the bindings.


--
=9A WBR, Peter Zotov.

--
Caml-list mailing list. =9ASubscription management and archives:
ht= tps://sympa.inria.fr/sympa/arc/caml-list
Beginner's list: http://groups.yahoo.com/group/ocaml_beginners<= /a>
Bug reports:
http://caml.inria.fr/bin/caml-bugs

--047d7b5da93b4ed30b04ea7d756b--