[llvm-dev] JIT compiler and calls to existing functions
Philip Reames via llvm-dev
llvm-dev at lists.llvm.org
Wed Mar 30 08:08:21 PDT 2016
We use an explicit relocation step to deal with this. We generate code
into a temporary memory location, then relocate it into a reserved area
of memory which is always within a small relative offset of other
interesting code. This allows us to get pc relative calls.
Philip
On 03/30/2016 05:53 AM, Matt Godbolt wrote:
> For what it's worth we did a similar thing, but
> overrode RTDyldMemoryManager directly This allowed us to control where
> the RAM was allocated too (e.g. guarantee it was in the low 4GB so we
> could use small memory model and avoid the mov rax, xxxxxxx; call rax
> code generated for x86)*, and also override findSymbol() to have the
> same behaviour as described in 4).
>
> --matt
>
> * later issues in not always being able to allocate low ram caused us
> to drop this feature. I wish we could fix the "call rax"es :)
>
> On Tue, Mar 29, 2016 at 6:51 PM Philip Reames via llvm-dev
> <llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>> wrote:
>
> There is no documentation I know of. Rough sketch:
> 1) Create a subclass of SectionMemoryManager
> 2) Create an instance of this class and add it the EngineBuilder
> via setMCJITMemoryManager
> (Make sure everything runs without changes)
> 3) Override the getSymbolAddress method, have your implementation
> call the base classes impl
> (Make sure everything runs without changes)
> 4) Add handling to map name->address for any custom functions you
> want.
>
>
>
> On 03/28/2016 09:18 PM, Russell Wallace wrote:
>> True, I care more about how fast the code runs than how long it
>> takes to compile it. So if the symbolic approach enables better
>> code generation, that is a very significant advantage from my
>> perspective.
>>
>> Is there any example code or documentation you can point to for
>> details about how to implement the symbolic approach? Is it
>> similar to any of the versions of Kaleidoscope or any other
>> extant tutorial?
>>
>> On Tue, Mar 29, 2016 at 5:07 AM, Philip Reames
>> <listmail at philipreames.com <mailto:listmail at philipreames.com>> wrote:
>>
>> Other advantages of keeping things symbolic:
>> 1) You can use function attributes to provide optimization or
>> semantic information.
>> 2) Linking modules works as expected when one of them
>> contains the definition.
>> 3) You can get better code generation (i.e. pc relative
>> addressing for local symbols, etc..)
>>
>> If the inttoptr scheme makes you happy, go for it. I'm not
>> telling you its wrong, merely that there's another approach
>> you should consider which has it's own advantages.
>>
>> Philip
>>
>> p.s. Your point about compiling faster is off base. Not
>> because you're wrong, but because if you're trying to
>> optimize for compile speed at that granularity, you really
>> don't want to be using LLVM (or just about any framework.)
>> LLVM does not make a good first tier JIT. It's makes a great
>> high tier JIT, but if you really really care about compile
>> time, it is not the appropriate answer.
>>
>> On 03/28/2016 08:57 PM, Russell Wallace wrote:
>>> Ah! Okay then, so you are saying something substantive that
>>> I think I disagree with, but that could be because there are
>>> relevant issues I don't understand.
>>>
>>> My reasoning is, I've already got a pointer to the function
>>> I want the generated code to call, so I just supply that
>>> pointer, it looks ugly on a microscopic scale because there
>>> are a couple of lines of casts to shepherd it through the
>>> type system, but on an even slightly larger scale it's as
>>> simple and elegant as it gets: I supply a 64-bit machine
>>> word that gets compiled into the object code, there are no
>>> extra layers of machinery to go wrong, no nonlocal effects
>>> to understand, no having to wonder about whether anything
>>> depends on symbol information that might vary between debug
>>> and release builds or between the vendor compiler and clang
>>> or between Windows and Linux; if it works once, it will work
>>> the same way every time. As a bonus, it will compile
>>> slightly faster.
>>>
>>> Keeping things symbolic - you're saying the advantage is the
>>> intermediate code is easier to debug because a dump will say
>>> 'call print' instead of 'call function at 123456'? I can see
>>> that being a real advantage but as of right now it doesn't
>>> jump out at me as necessarily outweighing the advantages of
>>> the direct pointer method.
>>>
>>>
>>>
>>> On Tue, Mar 29, 2016 at 4:37 AM, Philip Reames
>>> <listmail at philipreames.com
>>> <mailto:listmail at philipreames.com>> wrote:
>>>
>>> I think our use cases are actually quite similar. Part
>>> of generating the in memory executable code is resolving
>>> all the symbolic symbols and relocations. The details of
>>> this are mostly hidden from you by the MCJIT interface,
>>> but it's this step I was referring to as "link time".
>>>
>>> The way to think of MCJIT: generate object file,
>>> incrementally link, run dynamic loader, but do it all in
>>> memory without round tripping through disk or explicit
>>> files.
>>>
>>> Philip
>>>
>>>
>>>
>>> On Mar 28, 2016, at 7:25 PM, Russell Wallace
>>> <russell.wallace at gmail.com
>>> <mailto:russell.wallace at gmail.com>> wrote:
>>>
>>>> Right, but when you say link time, the JIT compiler I'm
>>>> writing works the way openJDK or v8 do, it reads a
>>>> script, JIT compiles it into memory and runs the code
>>>> in memory without ever writing anything to disk (an
>>>> option for ahead of time compilation may come later,
>>>> but that will be a while down the road), so we might be
>>>> doing different things?
>>>>
>>>> On Tue, Mar 29, 2016 at 2:59 AM, Philip Reames
>>>> <listmail at philipreames.com
>>>> <mailto:listmail at philipreames.com>> wrote:
>>>>
>>>> The option we use is to have a custom memory
>>>> manager, override the getPointerToNamedFunction
>>>> function, and provide the pointer to the external
>>>> function at link time. The inttoptr scheme works
>>>> fairly well, but it does make for some pretty ugly
>>>> and sometimes hard to analyze IR. I recommend
>>>> leaving everything symbolic until link time if you can.
>>>>
>>>> Philip
>>>>
>>>>
>>>> On 03/28/2016 06:33 PM, Russell Wallace via
>>>> llvm-dev wrote:
>>>>> That seems to work, thanks! The specific code I
>>>>> ended up with to call int64_t print(int64_t) looks
>>>>> like:
>>>>>
>>>>> auto f = builder.CreateIntToPtr(
>>>>> ConstantInt::get(builder.getInt64Ty(),
>>>>> uintptr_t(print)),
>>>>> PointerType::getUnqual(FunctionType::get(
>>>>> builder.getInt64Ty(), {builder.getInt64Ty()},
>>>>> false)));
>>>>> return builder.CreateCall(f, args);
>>>>>
>>>>>
>>>>> On Mon, Mar 28, 2016 at 1:40 PM, Caldarale,
>>>>> Charles R <Chuck.Caldarale at unisys.com
>>>>> <mailto:Chuck.Caldarale at unisys.com>> wrote:
>>>>>
>>>>> > From: llvm-dev
>>>>> [mailto:llvm-dev-bounces at lists.llvm.org
>>>>> <mailto:llvm-dev-bounces at lists.llvm.org>]
>>>>> > On Behalf Of Russell Wallace via llvm-dev
>>>>> > Subject: [llvm-dev] JIT compiler and calls
>>>>> to existing functions
>>>>>
>>>>> > In the context of a JIT compiler, what's the
>>>>> recommended way to generate a call to an
>>>>> > existing function, that is, not one that you
>>>>> are generating on-the-fly with LLVM, but
>>>>> > one that's already linked into your program?
>>>>> For example the cosine function (from the
>>>>> > standard math library); the Kaleidoscope
>>>>> tutorial recommends looking it up by name with
>>>>> > dlsym("cos"), but it seems to me that it
>>>>> should be possible to use a more efficient and
>>>>> > portable solution that takes advantage of
>>>>> the fact that you already have an actual pointer
>>>>> > to cos, even if you haven't linked with
>>>>> debugging symbols.
>>>>>
>>>>> Perhaps not the most elegant, but we simply
>>>>> use the IRBuilder.CreateIntToPtr() method to
>>>>> construct the Callee argument for
>>>>> IRBuilder.CreateCall(). The first argument for
>>>>> CreateIntToPtr() comes from
>>>>> ConstantInt::get(I64, uintptr_t(ptr)), while
>>>>> the second is a function type pointer defined
>>>>> by using PointerType::get() on the result of
>>>>> FunctionType::get() with the appropriate
>>>>> function signature.
>>>>>
>>>>> - Chuck
>>>>>
>>>>>
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> LLVM Developers mailing list
>>>>> llvm-dev at lists.llvm.org
>>>>> <mailto:llvm-dev at lists.llvm.org>
>>>>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>>>>
>>>>
>>>
>>
>>
>
> _______________________________________________
> LLVM Developers mailing list
> llvm-dev at lists.llvm.org <mailto:llvm-dev at lists.llvm.org>
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20160330/f3e14394/attachment-0001.html>
More information about the llvm-dev
mailing list