I tried this for a C closure library I was toying with, where all
closures conformed to "void fn(val_t env, val_t arg, val_t* ret_val)". I
found that under-application, over-application and full application all
seem to have elaborations into inline case statements, as long as you
have alloca that can take a dynamic parameter.
I believe the OCaml ZAM uses a similar calling convention, although it
doesn't concern itself with stack allocating return values since it uses
efficient bump pointer allocation. I can provide a simple overview if
there's interest, since the code isn't publicly linkable at this time.
Problems I ran into might only be C limitations:
1. While intermediate closures in over-applications can be
stack-allocated, any such intermediate closures remain on the stack
throughout the whole application, even after they're no longer used. You
*might* be able to solve this with tail calls, but this generally isn't
a huge deal since the space used is small.
2. Consider a function that accepts two pointers, x and y: the
function could write x.foo = y, or y.foo = x, or x's and y's lifetime
may have no bearing at all. You need some kind of region analysis to
enforce proper lifetime nesting if you don't want heap allocation and
GC. x and y could be closures after all, so it's not strictly true that
closures can always be stack allocated, except in the trivial case where
all of your program's data structures can be stack allocated, or none of
your heap structures hold closure values.
Sandro
On 11/02/2015 11:53 AM, Keean Schupke wrote:
I have an idea that closures can (always?) be stack allocated, a key
idea is that of move semantics for return values. You can reserve the
space for the closure in the callers stack and pass this in by
reference to the function that would create the closure. Maybe this is
something well known, i'm not sure?
_______________________________________________
bitc-dev mailing list
[email protected]
http://www.coyotos.org/mailman/listinfo/bitc-dev