[LLVMdev] Closures, newbie question

David Given dg at cowlark.com
Sat Jan 26 14:37:12 PST 2013


On 26/01/13 20:03, David Given wrote:
[...]
> There are numerous ways to pass the stack frames into the inner
> functions. The naive approach is to simply have each stack frame contain
> a pointer to the enclosing frame, but that means that level4 has to
> evaluate f.level3.level2.level1.i. Optimising this is easy, and that's
> what I've done in the past, but I'm actually wondering whether it may
> not be easiest just to pass each frame in as a separate parameter and
> then let LLVM take care of the details:

I am reminded that in an implementation such as this, closures are *not*
first-class values --- you can't pass them around and they can only be
called statically. D'oh.

In order to produce first-class closures you need to bake all the
information described above statically into an object, and then pass
that object around.

My original implementation of this did this by having a special
pointer-to-closure representation which was two pointers; one to the
code, and one to the stack frame needed to call the code. An equally
valid alternative is to allocate a heap object with the same information
in it. In this case you're basically creating a object with a virtual
method; calling the method calls the closure.

There is another aspect to be wary of: depending on your implementation,
it's possible for two different closures of compatible types have
different calling conventions. Therefore anyone who has a simple
pointer-to-closure object doesn't know how to call the object. e.g.:

function level1()
{
  var i;
  function level2()
  {
    return i;
  }
}

From the point of view of the language, level1 and level2 have the same
type signature --- but as level2 is taking a hidden pointer to level1's
stack frame, and level1 doesn't, it's possible that the implementations
won't.

The easiest way around this is to arrange your implementation so that
the two functions above *do* have the same calling convention which can
be determined from the type signature. This requires a fixed number of
hidden parameters (usually one). The
multiple-stack-frames-passed-as-parameters implementation I described
above isn't suitable here, so I can't recommend it.

(My compiler could tell statically whether you were calling the closure
directly or via a pointer, and so would generate different code. This
made static calls much more efficient but it made calls via a pointer
less efficient, and I'm not sure whether it was worth it or not. It was
certainly much more complex.)

-- 
┌─── dg@cowlark.com ───── http://www.cowlark.com ─────
│ "Of course, on a sufficiently small planet, 40 km/hr is, in fact,
│ sufficient to punt the elastic spherical cow into low orbit." ---
│ Brooks Moses on r.a.sf.c

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 262 bytes
Desc: OpenPGP digital signature
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20130126/9439fc6b/attachment.sig>


More information about the llvm-dev mailing list