Defer for trivial cases
Этот коммит содержится в:
родитель
cd2a9d99a1
коммит
58b853bbef
3 изменённых файлов: 49 добавлений и 1 удалений
|
@ -47,12 +47,13 @@ Currently supported features:
|
||||||
features)
|
features)
|
||||||
* slices (partially)
|
* slices (partially)
|
||||||
* maps (very rough, unfinished)
|
* maps (very rough, unfinished)
|
||||||
|
* defer (only in trivial cases)
|
||||||
|
|
||||||
Not yet supported:
|
Not yet supported:
|
||||||
|
|
||||||
* complex numbers
|
* complex numbers
|
||||||
* garbage collection
|
* garbage collection
|
||||||
* defer
|
* recover
|
||||||
* closures
|
* closures
|
||||||
* channels
|
* channels
|
||||||
* introspection (if it ever gets implemented)
|
* introspection (if it ever gets implemented)
|
||||||
|
|
34
compiler.go
34
compiler.go
|
@ -61,6 +61,12 @@ type Frame struct {
|
||||||
taskHandle llvm.Value
|
taskHandle llvm.Value
|
||||||
cleanupBlock llvm.BasicBlock
|
cleanupBlock llvm.BasicBlock
|
||||||
suspendBlock llvm.BasicBlock
|
suspendBlock llvm.BasicBlock
|
||||||
|
deferred []*Defer
|
||||||
|
}
|
||||||
|
|
||||||
|
type Defer struct {
|
||||||
|
*ssa.Defer
|
||||||
|
Args []llvm.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
type Phi struct {
|
type Phi struct {
|
||||||
|
@ -1081,6 +1087,22 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) error {
|
||||||
return err
|
return err
|
||||||
case *ssa.DebugRef:
|
case *ssa.DebugRef:
|
||||||
return nil // ignore
|
return nil // ignore
|
||||||
|
case *ssa.Defer:
|
||||||
|
if instr.Block() == instr.Parent().Blocks[0] {
|
||||||
|
// Easy: evaluate the arguments now and run it at the end.
|
||||||
|
args := make([]llvm.Value, len(instr.Call.Args))
|
||||||
|
for i, arg := range instr.Call.Args {
|
||||||
|
val, err := c.parseExpr(frame, arg)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
args[i] = val
|
||||||
|
}
|
||||||
|
frame.deferred = append(frame.deferred, &Defer{instr, args})
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return errors.New("todo: defer in non-entry block")
|
||||||
|
}
|
||||||
case *ssa.Go:
|
case *ssa.Go:
|
||||||
if instr.Common().Method != nil {
|
if instr.Common().Method != nil {
|
||||||
return errors.New("todo: go on method receiver")
|
return errors.New("todo: go on method receiver")
|
||||||
|
@ -1203,6 +1225,18 @@ func (c *Compiler) parseInstr(frame *Frame, instr ssa.Instruction) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
case *ssa.RunDefers:
|
||||||
|
// Execute all deferred functions from the entry block, in reverse
|
||||||
|
// order.
|
||||||
|
for i := len(frame.deferred) - 1; i >= 0; i-- {
|
||||||
|
deferred := frame.deferred[i]
|
||||||
|
callee := deferred.Call.StaticCallee()
|
||||||
|
if callee == nil {
|
||||||
|
return errors.New("todo: non-static deferred functions")
|
||||||
|
}
|
||||||
|
c.builder.CreateCall(c.ir.GetFunction(callee).llvmFn, deferred.Args, "")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
case *ssa.Store:
|
case *ssa.Store:
|
||||||
llvmAddr, err := c.parseExpr(frame, instr.Addr)
|
llvmAddr, err := c.parseExpr(frame, instr.Addr)
|
||||||
if err == cgoWrapperError {
|
if err == cgoWrapperError {
|
||||||
|
|
|
@ -48,6 +48,7 @@ func main() {
|
||||||
println("Stringer.String():", s.String())
|
println("Stringer.String():", s.String())
|
||||||
|
|
||||||
runFunc(hello, 5) // must be indirect to avoid obvious inlining
|
runFunc(hello, 5) // must be indirect to avoid obvious inlining
|
||||||
|
testDefer()
|
||||||
|
|
||||||
// test library functions
|
// test library functions
|
||||||
println("lower to upper char:", 'h', "->", unicode.ToUpper('h'))
|
println("lower to upper char:", 'h', "->", unicode.ToUpper('h'))
|
||||||
|
@ -57,6 +58,18 @@ func runFunc(f func(int), arg int) {
|
||||||
f(arg)
|
f(arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func testDefer() {
|
||||||
|
i := 1
|
||||||
|
defer deferred("...run as defer", i)
|
||||||
|
i += 1
|
||||||
|
defer deferred("...run as defer", i)
|
||||||
|
println("deferring...")
|
||||||
|
}
|
||||||
|
|
||||||
|
func deferred(msg string, i int) {
|
||||||
|
println(msg, i)
|
||||||
|
}
|
||||||
|
|
||||||
func readMap(m map[string]int, key string) {
|
func readMap(m map[string]int, key string) {
|
||||||
println("map length:", len(m))
|
println("map length:", len(m))
|
||||||
println("map read:", key, "=", m[key])
|
println("map read:", key, "=", m[key])
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче