Этот коммит содержится в:
Ayke van Laethem 2018-09-01 17:09:56 +02:00
родитель cd2a9d99a1
коммит 58b853bbef
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E97FF5335DFDFDED
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)

Просмотреть файл

@ -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])