forked from go-llvm/llgo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
closures.go
31 lines (28 loc) · 1.18 KB
/
closures.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// Copyright 2011 The llgo Authors.
// Use of this source code is governed by an MIT-style
// license that can be found in the LICENSE file.
package llgo
import (
"github.com/axw/gollvm/llvm"
)
// makeClosure creates a closure from a function pointer and
// a set of bindings. The bindings are addresses of captured
// variables.
func (c *compiler) makeClosure(fn *LLVMValue, bindings []*LLVMValue) *LLVMValue {
types := make([]llvm.Type, len(bindings))
for i, binding := range bindings {
types[i] = c.types.ToLLVM(binding.Type())
}
block := c.createTypeMalloc(llvm.StructType(types, false))
for i, binding := range bindings {
addressPtr := c.builder.CreateStructGEP(block, i, "")
c.builder.CreateStore(binding.LLVMValue(), addressPtr)
}
block = c.builder.CreateBitCast(block, llvm.PointerType(llvm.Int8Type(), 0), "")
// fn is a raw function pointer; ToLLVM yields {*fn, *uint8}.
closure := llvm.Undef(c.types.ToLLVM(fn.Type()))
fnptr := c.builder.CreateBitCast(fn.LLVMValue(), closure.Type().StructElementTypes()[0], "")
closure = c.builder.CreateInsertValue(closure, fnptr, 0, "")
closure = c.builder.CreateInsertValue(closure, block, 1, "")
return c.NewValue(closure, fn.Type())
}