<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On 15 September 2015 at 01:09, Rodney M. Bates <span dir="ltr"><<a href="mailto:rodney_bates@lcwb.coop" target="_blank">rodney_bates@lcwb.coop</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class=""><br>
<br>
On 09/13/2015 04:41 PM, mats petersson wrote:<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
So, my code builds a closure structure, which contains pointers to the variables shared between the nested function and the outer function.<br>
<br>
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.<br>
<br>
</blockquote>
<br></span>
Actually, we do already use something named a "closure", but it's not the usual closure.  I find<br>
it rather strange, and will resist boring people with the details, (it starts to get rather OT),<br>
but it does handle mixtures of nested functions, top-level functions, and functions from other<br>
languages, e.g., C.  My issue is not how get an environment into a nested procedure, it's how<br>
can it be used from there when the outer variables to be accessed are independent alloca values<br>
in their own scope.<br></blockquote><div><br></div><div>In essence: <br></div><div>Store the value of the alloca (in other words, the local address) into a structure (what I call a closure). <br>Then re-introduce those variables as references in the inner function context. <br><br><br></div><div>There is no real magic to it.<br><br></div><div>Some of my code:<br><br>Create a closure structure, and store the address of the variable:<br><a href="https://github.com/Leporacanthicus/lacsap/blob/master/expr.cpp#L3294">https://github.com/Leporacanthicus/lacsap/blob/master/expr.cpp#L3294</a><br><br></div><div>Unpack (re-introduce) the closure argument in the new context:<br><a href="https://github.com/Leporacanthicus/lacsap/blob/master/expr.cpp#L1358">https://github.com/Leporacanthicus/lacsap/blob/master/expr.cpp#L1358</a><br><br></div><div>Create data structure for the closure:<br><a href="https://github.com/Leporacanthicus/lacsap/blob/master/expr.cpp#L1665">https://github.com/Leporacanthicus/lacsap/blob/master/expr.cpp#L1665</a><br><br></div><div>I hope this is answering your question, and of at least some help... <br><br>--<br></div><div>Mats<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
<blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><span class="">
But if you want something that in C would look something like this:<br>
<br>
void func1(void (*fptr)(int), int x)<br>
{<br>
     fptr(x);<br>
}<br>
<br>
void func2(int a)<br>
{<br>
     int y = a;<br>
<br>
     void foo(int x)<br>
     {<br>
         printf("x=%d, y=%d\n", x, y);<br>
     }<br>
<br>
     func1(foo, 42);<br>
}<br>
<br>
void bar(int x);<br>
<br>
int main()<br>
{<br>
     func1(bar);<br>
     func2(17);<br>
     return 0;<br>
}<br>
<br>
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.<br>
<br>
[This is almost identical to the function in the Pascal conformance test that I had to implement trampolines for]<br>
<br>
--<br>
Mats<br>
<br></span><span class="">
On 13 September 2015 at 22:03, Rodney M. Bates via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a> <mailto:<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>>> wrote:<br>
<br>
    I want to avoid trampolines for two reasons.  They have to be built in memory that is<br>
    both writable and executable, which has already been a problem on some targets.  Also,<br>
    a debugger needs to both construct and interpret them, which creates difficult target<br>
    dependencies and compiler code-generation dependencies.<br>
<br>
    I intend to pass some kind of environment pointer, like a static link.  The real question<br>
    is, what does it point to?  As I understand, llvm locals can not be used outside the<br>
    function they are created in, so using a static link from outside can't access the<br>
    alloca values.  I am thinking the best way is to wrap at least up-level referenceable<br>
    formals and locals  in a struct, and have the static link point to that.  This would<br>
    include the next outer static link.<br>
<br>
    On 09/13/2015 04:39 AM, David Chisnall wrote:<br>
<br></span><span class="">
        On 13 Sep 2015, at 01:18, Rodney M. Bates via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a> <mailto:<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>>> wrote:<br>
<br>
<br>
            Does Clang have an option that allows C nested functions, as in gcc?<br>
            So far, I can't find it.  I just want to look at generated llvm IR, for<br>
            ideas on the best way to produce it from another front end.<br>
<br>
<br>
        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.<br>
<br>
        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.<br>
<br>
        David<br>
<br>
<br>
<br>
    --<br>
    Rodney Bates<br></span>
    <a href="mailto:rodney.m.bates@acm.org" target="_blank">rodney.m.bates@acm.org</a> <mailto:<a href="mailto:rodney.m.bates@acm.org" target="_blank">rodney.m.bates@acm.org</a>><br>
<br>
    _______________________________________________<br>
    cfe-dev mailing list<br>
    <a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a> <mailto:<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>><br>
    <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev</a><br>
<br>
<br><span class=""><font color="#888888">
</font></span></blockquote><span class=""><font color="#888888">
<br>
-- <br>
Rodney Bates<br>
<a href="mailto:rodney.m.bates@acm.org" target="_blank">rodney.m.bates@acm.org</a><br>
</font></span></blockquote></div><br></div></div>