[LLVMdev] Perfect forwarding?

OvermindDL1 overminddl1 at gmail.com
Mon Aug 31 22:57:38 PDT 2009


Blast!  LLVM mailing server *still* has the headers broken...

On Mon, Aug 31, 2009 at 11:03 PM, Talin<viridia at gmail.com> wrote:
> OvermindDL1 wrote:
>>
>> BLAST!  LLVM mailing list headers are still royally screwed up...
>> My message is below...
>>
>> On Sun, Aug 30, 2009 at 2:20 PM, Talin<viridia at gmail.com> wrote:
>>
>>>
>>> Hey all, it's been a while since I have posted on this list, but I've
>>> been continuing my work with LLVM and getting lots done :)
>>>
>>> One question I wanted to ask is whether anyone had any advice on how to
>>> implement "perfect forwarding" in a runtime (as opposed to compile-time)
>>> context with LLVM. The general idea is that you have a bunch of methods
>>> that have different call signatures, and you want to have some generic
>>> handler function that can intercept these calls and then forward each
>>> call to another method that has the same signature as the original call.
>>>
>>> A typical example of how this would be used is something like Mockito or
>>> EasyMock - you have some interface, and you dynamically create an
>>> implementation of that interface which is able to intercept all of the
>>> method calls and record the order in which they are called and the value
>>> of the arguments. The unit test code then performs some validation on
>>> the recording to ensure that the invocations match what was expected.
>>>
>>> The key point is that the handler method doesn't know at compile-time
>>> the call signature of the various methods that are going to be
>>> intercepted. In the case of Java and C#, the VM is able to box all of
>>> the arguments that are primitive types, and pass to the handler method
>>> an array of type Object[]. Similarly, one can call method.invoke() on a
>>> method, passing in that same array of objects, and the VM will unbox the
>>> primitive types and then call the actual method with the right argument
>>> types.
>>>
>>> One obvious way to do this is to generate two stub functions for every
>>> function emitted by the compiler, one that takes the original argument
>>> signature and creates a list of boxed objects, and one that takes a list
>>> of boxed objects, unboxes them and then calls the function. However,
>>> that's a lot of extra code to generate, and I am concerned about the
>>> amount of code bloat that would create.
>>>
>>> What would be better is if there was some way for the generic handler
>>> function to be able to dynamically get a picture of the layout of the
>>> call frame. On the receiving end, this would be something similar to a
>>> varargs call, where the called function unpacks the argument list based
>>> on a runtime-provided schema. One problem with the varargs approach is
>>> that I wouldn't want every method call to have to use the varargs
>>> calling convention.
>>>
>>> On the calling side, I'm not sure that any language has a means to
>>> dynamically construct an argument list for a call. If such a thing did
>>> exist, what I suppose it would do is given a description of a function's
>>> calling signature, figure out which arguments should be put in which
>>> registers and which should be pushed on the stack. In other words, to do
>>> at runtime what LLVM currently does at compile time.
>>>
>>
>> Actually many languages have such means to do that, Python is probably
>> the most easy.  You can even do so for C++ using Boost.Fusion
>> (Boost.Fusion has an invoke method that can call any arbitrary
>> function/functor with a vector of parameters, it also has a lot more
>> stuff, Boost.Fusion also has thing that allow C++ get the closest to
>> perfect forwarding then C++ has ever got before).  Although
>> Boost.Fusion is not usable in the LLVM world, the way it works is.  I
>> have even used it to implement a C++ network RPC system that
>> serializes up the arguments, handles pointers/references/const'ness
>> correctly, handles sync of network objects, and is used like any
>> normal C++ function.  It let me create this syntax:
>>
>
> I should have been more specific - I'm aware of Python's abilities in this
> regard, and I've used it a number of times before. What I should have said
> was that I wasn't aware of any statically compiled language that can
> dynamically construct a call frame.
>
> What C++ does is something different - it pre-generates at compile time a
> stub function for each permutation of statically typed arguments. These stub
> functions box/unbox the arguments. That is a powerful feature, but I don't
> think it is as powerful as, say, Java's "Proxy" capability which can operate
> on whole classes rather than individual methods. C++ templates have no way
> to iterate over all of the members of a class, however if the stub function
> generator was built into the compiler to begin with then you wouldn't need
> to - once you have the ability to intercept any method call generically, you
> can do at runtime what you would normally use templates to do at compile
> time. (I've noticed that metaprogramming and reflection tend to get used for
> similar things.) Which approach (runtime or compile time) is better is
> really just a time vs. space tradeoff.
>
> One approach that I have been considering is rather than generating a pair
> of stub functions for each normal function, instead generate a pair of stub
> functions for each unique type signature - the idea being that two methods
> that have the same calling signature can use the same argument
> boxing/unboxing logic. The number of permutations could be reduced further
> by weakening the type signature - i.e. convert all pointer arguments to
> void* and so on.
>
> Each stub function would have a function name which is generated from the
> type signature of the arguments, and then these functions would be given
> "linkonce" linkage, so that duplicates would get coalesced at link time.
>
> What's missing from this picture is a scheme for encoding a set of LLVM
> argument types as a string function name. In particular, I'd need some way
> to accomodate "structs as first class data types" arguments.

Boost.Fusion has adapters to convert structs/classes into
tuples/kwtuples.  You have to write the short and simple adapter for
your classes, but it would allow you to iterate over
everything/anything in it.  I have done this exact thing.  Not quite
fully what you want, but Boost.Fusion and other bits of other boost
metalibraries seem to do most of what you want.  Might be interesting
to look at?



More information about the llvm-dev mailing list