March 23, 2013
Moritz Maxeiner wrote:
> On Saturday, 23 March 2013 at 10:31:30 UTC, Jens Mueller wrote:
> >Moritz Maxeiner wrote:
> >>On Saturday, 23 March 2013 at 09:30:07 UTC, Jens Mueller wrote:
> >>>Moritz Maxeiner wrote:
> >>>>A couple of more things I forgot to mention:
> >>>>
> >>>>- You will need to additionally add bindings for all the >>LLVMInitialize"TARGET_NAME"{TargetInfo,Target,TargetMC,AsmParser,AsmPrinter,Disassembler}
> >>>>functions. They reside inside the target libraries and not
> >>>>inside
> >>>>llvm-c, which is why only translating the C API won't get you
> >>>>them.
> >>>>The LLVMInitializeNativeTarget function , which is necessary
> >>>>to
> >>>>use
> >>>>LLVM for jitting - otherwise you'll only have access to
> >>>>interpreting, which is horribly slow - uses them, but it is a
> >>>>static
> >>>>inline function and as such does not get exposed because LLVM
> >>>>builds
> >>>>with the option to hide all inline functions. That is not a
> >>>>problem
> >>>>for C, as this function gets defined in the header, but for
> >>>>D it
> >>>>is
> >>>>a big problem, because you cannot access
> >>>>LLVMInitializeNativeTarget.
> >>>>You need to recreate it in D by using all the functions it
> >>>>references. Of course, you'll also have to accomodate the
> >>>>fact
> >>>>that
> >>>>these referenced functions may or may not be compiled in
> >>>>depending
> >>>>on which target where selected when compiling LLVM.
> >>>
> >>>Do you happen to know why these functions are not declared in
> >>>the
> >>>header
> >>>files. I mean when using the C interface in C I wouldn't even
> >>>know
> >>>that
> >>>these functions exist.
> >>
> >>I suspect it is because of LLVM's internal structure. Each
> >>supported
> >>target is presented by its own directory and they are afaict
> >>mutually independent from one another, "so their initialiation
> >>routines should be part of them themselves" I would guess, but I
> >>don't know, sorry.
> >>Also, when using the C interface in C there is little need to
> >>know
> >>them because they get encapsulated in LLVMInitializeAllTargets
> >>and
> >>LLVMInitializeNativeTarget.
> >
> >Not sure whether this fixes the problem completely. Can you check
> >https://github.com/jkm/deimos-llvm/blob/master/deimos/llvm/c/target.d#L157
> >I came up with this solution to replace the macros in the C
> >binding.
> 
> It looks mostly okay to me with one problem: Afaict the code
> enforces the presence of the initialization routines of all targets,
> e.g. if one target is missing LLVMInitializeAllTargets will not
> link, as there are undefined references for that missing target, but
> LLVM may or may not be compiled with that target so you cannot
> enforce its presence in the bindings. For runtime loading the
> solution I used was to check the function pointer for null; for
> linking you have this problem: When using linking, knowing which
> targets are available happens at link time (when the LLVM libraries
> are linked in), which means you cannot use any compile time tricks
> for automatic detection of which targets are available.
> The only solution for that problem I can think of would be to use
> runtime reflection and check at runtime for each initialiation
> routine if it is a callable function, but afaik D only has compile
> time reflection.

I wonder how they do it in C. Don't you have to set a macro? I could add some version identifiers.

> PS: All your recent posts seem to create new threads, I don't know why, though, just mentioning it because some people not interested in this might get annoyed.

Don't know either. I'm using the mail interface.

Jens
March 23, 2013
On Saturday, 23 March 2013 at 16:37:35 UTC, Jens Mueller wrote:
> Moritz Maxeiner wrote:
>> On Saturday, 23 March 2013 at 10:31:30 UTC, Jens Mueller wrote:
>> >Moritz Maxeiner wrote:
>> >>On Saturday, 23 March 2013 at 09:30:07 UTC, Jens Mueller wrote:
>> >>>Moritz Maxeiner wrote:
>> >>>>A couple of more things I forgot to mention:
>> >>>>
>> >>>>- You will need to additionally add bindings for all the
>> >>>>>>LLVMInitialize"TARGET_NAME"{TargetInfo,Target,TargetMC,AsmParser,AsmPrinter,Disassembler}
>> >>>>functions. They reside inside the target libraries and not
>> >>>>inside
>> >>>>llvm-c, which is why only translating the C API won't get you
>> >>>>them.
>> >>>>The LLVMInitializeNativeTarget function , which is necessary
>> >>>>to
>> >>>>use
>> >>>>LLVM for jitting - otherwise you'll only have access to
>> >>>>interpreting, which is horribly slow - uses them, but it is a
>> >>>>static
>> >>>>inline function and as such does not get exposed because LLVM
>> >>>>builds
>> >>>>with the option to hide all inline functions. That is not a
>> >>>>problem
>> >>>>for C, as this function gets defined in the header, but for
>> >>>>D it
>> >>>>is
>> >>>>a big problem, because you cannot access
>> >>>>LLVMInitializeNativeTarget.
>> >>>>You need to recreate it in D by using all the functions it
>> >>>>references. Of course, you'll also have to accomodate the
>> >>>>fact
>> >>>>that
>> >>>>these referenced functions may or may not be compiled in
>> >>>>depending
>> >>>>on which target where selected when compiling LLVM.
>> >>>
>> >>>Do you happen to know why these functions are not declared in
>> >>>the
>> >>>header
>> >>>files. I mean when using the C interface in C I wouldn't even
>> >>>know
>> >>>that
>> >>>these functions exist.
>> >>
>> >>I suspect it is because of LLVM's internal structure. Each
>> >>supported
>> >>target is presented by its own directory and they are afaict
>> >>mutually independent from one another, "so their initialiation
>> >>routines should be part of them themselves" I would guess, but I
>> >>don't know, sorry.
>> >>Also, when using the C interface in C there is little need to
>> >>know
>> >>them because they get encapsulated in LLVMInitializeAllTargets
>> >>and
>> >>LLVMInitializeNativeTarget.
>> >
>> >Not sure whether this fixes the problem completely. Can you check
>> >https://github.com/jkm/deimos-llvm/blob/master/deimos/llvm/c/target.d#L157
>> >I came up with this solution to replace the macros in the C
>> >binding.
>> 
>> It looks mostly okay to me with one problem: Afaict the code
>> enforces the presence of the initialization routines of all targets,
>> e.g. if one target is missing LLVMInitializeAllTargets will not
>> link, as there are undefined references for that missing target, but
>> LLVM may or may not be compiled with that target so you cannot
>> enforce its presence in the bindings. For runtime loading the
>> solution I used was to check the function pointer for null; for
>> linking you have this problem: When using linking, knowing which
>> targets are available happens at link time (when the LLVM libraries
>> are linked in), which means you cannot use any compile time tricks
>> for automatic detection of which targets are available.
>> The only solution for that problem I can think of would be to use
>> runtime reflection and check at runtime for each initialiation
>> routine if it is a callable function, but afaik D only has compile
>> time reflection.
>
> I wonder how they do it in C. Don't you have to set a macro?

Afaict they rely on the fact that when you install llvm on your system you get the {/usr/include/}llvm/Config/Targets.def file, in which is set what targets LLVM was compiled with (it gets generated at LLVM compile-time). Then the Target.h, in which the LLVMInitializeAllTargets function rests, includes that file and does some of that macro-voodoo that makes C/C++ so "lovable" to only create calls for the targets enabled in the Targets.def file when LLVMInitalizeAllTargets gets inlined. Of course, that solution isn't viable because afaik you cannot access filesystem IO functions in D CTFE, meaning the Targets.def file is useless to you. <rant>Hooray for the C/C++ preprocessor, may it die, die, die!</rant>

>  I could add
> some version identifiers.

That would be one solution, but you'd have to create one version identifier for each target.

- Moritz