closure: MakeClosure/makeClosureCtx fix

This commit is contained in:
xushiwei
2024-05-05 23:32:54 +08:00
parent 8ab662b373
commit f17a4ca1de
5 changed files with 111 additions and 41 deletions

View File

@@ -131,9 +131,10 @@ type aFunction struct {
blks []BasicBlock
params []Type
base int // base = 1 if hasFreeVars; base = 0 otherwise
hasVArg bool
params []Type
freeVars Expr
base int // base = 1 if hasFreeVars; base = 0 otherwise
hasVArg bool
}
// Function represents a function or method.
@@ -145,7 +146,7 @@ func newFunction(fn llvm.Value, t Type, pkg Package, prog Program, hasFreeVars b
if hasFreeVars {
base = 1
}
return &aFunction{Expr{fn, t}, pkg, prog, nil, params, base, hasVArg}
return &aFunction{Expr{fn, t}, pkg, prog, nil, params, Expr{}, base, hasVArg}
}
func newParams(fn Type, prog Program) (params []Type, hasVArg bool) {
@@ -169,10 +170,21 @@ func (p Function) Param(i int) Expr {
return Expr{p.impl.Param(i), p.params[i]}
}
func (p Function) closureCtx(b Builder) Expr {
if p.freeVars.IsNil() {
if p.base == 0 {
panic("ssa: function has no free variables")
}
ptr := Expr{p.impl.Param(0), p.params[0]}
p.freeVars = b.Load(ptr)
}
return p.freeVars
}
// FreeVar returns the function's ith free variable.
func (p Function) FreeVar(b Builder, i int) Expr {
ctx := Expr{p.impl.Param(0), p.params[0]}
return b.Field(ctx, i)
ctx := p.closureCtx(b)
return b.getField(ctx, i)
}
// NewBuilder creates a new Builder for the function.

View File

@@ -541,7 +541,7 @@ func (b Builder) MakeClosure(fn Expr, bindings []Expr) Expr {
prog := b.Prog
tfn := fn.Type
sig := tfn.raw.Type.(*types.Signature)
tctx := sig.Params().At(0).Type().Underlying().(*types.Struct)
tctx := sig.Params().At(0).Type().Underlying().(*types.Pointer).Elem().(*types.Struct)
flds := llvmFields(bindings, tctx, b)
data := b.aggregateAlloc(prog.rawType(tctx), flds...)
return b.aggregateValue(prog.Closure(tfn), fn.impl, data)
@@ -576,6 +576,10 @@ func (b Builder) Field(x Expr, idx int) Expr {
if debugInstr {
log.Printf("Field %v, %d\n", x.impl, idx)
}
return b.getField(x, idx)
}
func (b Builder) getField(x Expr, idx int) Expr {
tfld := b.Prog.Field(x.Type, idx)
fld := llvm.CreateExtractValue(b.impl, x.impl, idx)
return Expr{fld, tfld}