[cfe-dev] Nested functions in Clang?

mats petersson via cfe-dev cfe-dev at lists.llvm.org
Tue Sep 15 01:28:53 PDT 2015


On 15 September 2015 at 01:09, Rodney M. Bates <rodney_bates at lcwb.coop>
wrote:

>
>
> On 09/13/2015 04:41 PM, mats petersson wrote:
>
>> So, my code builds a closure structure, which contains pointers to the
>> variables shared between the nested function and the outer function.
>>
>> As long as you don't need function pointers that are compatible with
>> function pointers without local variable usage, you don't need trampolines,
>> just the closure structure to pass the arguments. Or you can just pass
>> extra arguments with those local variables as references.
>>
>>
> Actually, we do already use something named a "closure", but it's not the
> usual closure.  I find
> it rather strange, and will resist boring people with the details, (it
> starts to get rather OT),
> but it does handle mixtures of nested functions, top-level functions, and
> functions from other
> languages, e.g., C.  My issue is not how get an environment into a nested
> procedure, it's how
> can it be used from there when the outer variables to be accessed are
> independent alloca values
> in their own scope.
>

In essence:
Store the value of the alloca (in other words, the local address) into a
structure (what I call a closure).
Then re-introduce those variables as references in the inner function
context.


There is no real magic to it.

Some of my code:

Create a closure structure, and store the address of the variable:
https://github.com/Leporacanthicus/lacsap/blob/master/expr.cpp#L3294

Unpack (re-introduce) the closure argument in the new context:
https://github.com/Leporacanthicus/lacsap/blob/master/expr.cpp#L1358

Create data structure for the closure:
https://github.com/Leporacanthicus/lacsap/blob/master/expr.cpp#L1665

I hope this is answering your question, and of at least some help...

--
Mats

>
> But if you want something that in C would look something like this:
>>
>> void func1(void (*fptr)(int), int x)
>> {
>>      fptr(x);
>> }
>>
>> void func2(int a)
>> {
>>      int y = a;
>>
>>      void foo(int x)
>>      {
>>          printf("x=%d, y=%d\n", x, y);
>>      }
>>
>>      func1(foo, 42);
>> }
>>
>> void bar(int x);
>>
>> int main()
>> {
>>      func1(bar);
>>      func2(17);
>>      return 0;
>> }
>>
>> For the foo function to be compatible with bar, you need a trampoline. If
>> you don't have this use-case, then you just need some way to pass y into
>> foo.
>>
>> [This is almost identical to the function in the Pascal conformance test
>> that I had to implement trampolines for]
>>
>> --
>> Mats
>>
>> On 13 September 2015 at 22:03, Rodney M. Bates via cfe-dev <
>> cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>> wrote:
>>
>>     I want to avoid trampolines for two reasons.  They have to be built
>> in memory that is
>>     both writable and executable, which has already been a problem on
>> some targets.  Also,
>>     a debugger needs to both construct and interpret them, which creates
>> difficult target
>>     dependencies and compiler code-generation dependencies.
>>
>>     I intend to pass some kind of environment pointer, like a static
>> link.  The real question
>>     is, what does it point to?  As I understand, llvm locals can not be
>> used outside the
>>     function they are created in, so using a static link from outside
>> can't access the
>>     alloca values.  I am thinking the best way is to wrap at least
>> up-level referenceable
>>     formals and locals  in a struct, and have the static link point to
>> that.  This would
>>     include the next outer static link.
>>
>>     On 09/13/2015 04:39 AM, David Chisnall wrote:
>>
>>         On 13 Sep 2015, at 01:18, Rodney M. Bates via cfe-dev <
>> cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>> wrote:
>>
>>
>>             Does Clang have an option that allows C nested functions, as
>> in gcc?
>>             So far, I can't find it.  I just want to look at generated
>> llvm IR, for
>>             ideas on the best way to produce it from another front end.
>>
>>
>>         Clang doesn’t support it, but llvm-gcc did (and DragonEgg,
>> possibly?), and this is what the trampoline intrinsics are for.  The way
>> that GCC implements it is very dangerous - it requires having an executable
>> stack, which makes various attacks significantly easier.
>>
>>         The nested function approach is *only* required if you need the
>> ability for unmodified C code (or code using a C FFI) to be able to call
>> the generated functions.  If you do not have this requirement, then using
>> an explicit argument in the LLVM IR to contain the state for the closure
>> (as [Objective-]C blocks and C++ lambdas do) is probably a better option.
>>
>>         David
>>
>>
>>
>>     --
>>     Rodney Bates
>>     rodney.m.bates at acm.org <mailto:rodney.m.bates at acm.org>
>>
>>     _______________________________________________
>>     cfe-dev mailing list
>>     cfe-dev at lists.llvm.org <mailto:cfe-dev at lists.llvm.org>
>>     http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev
>>
>>
>>
> --
> Rodney Bates
> rodney.m.bates at acm.org
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20150915/523e147f/attachment.html>


More information about the cfe-dev mailing list