goplus / llgo

A Go compiler based on LLVM in order to better integrate Go with the C ecosystem including Python
Apache License 2.0
216 stars 15 forks source link

Autoretain & autorelease #372

Closed cpunion closed 1 week ago

cpunion commented 1 week ago

Add autoptr directives:

// llgo:autorelease (*Object).DecRef
// llgo:link (*Object).DecRef C.Py_DecRef
func (o *Object) DecRef() {}

// llgo:autoretain (*Object).IncRef
// llgo:link (*Object).IncRef C.Py_IncRef
func (o *Object) IncRef() {}

Rewrite SSA to add IncRef() and defer DecRef():

func returnObj() *py.Object {
    x := py.Float(3)
    // DON'T INSERT x.IncRef() because escaped by returning       | implemented
    return x
}

func testInnerClosure() {
    var x *py.Object
    // INSERT func() { x.DecRef() }()                                                        | not implemented
    func() {
        x = py.Float(3)
        // DONT INSERT x.IncRef() because escaped by free vars      | implemented
    }
}

func returnMulti() (*py.Object, error) {
    x := py.Float(3)
    return x, nil
}

func testReturnMultiple() {
    a, b := returnMulti()
    // INSERT defer a.DecRef()             | not implemented

    c, _ := returnMulti()
    // INSERT defer c.DecRef()             | not implemented

    _, d := returnMulti()
    // INSERT defer x.DecRef()             | not implemented

    returnMulti()
    // INSERT defer x.DecRef()             | not implemented
}

func main() {
    a := py.Float(1.0)
    // INSERT defer a.DecRef()             | implemented
    b := returnObj()
    // INSERT defer b.DecRef()             | implemented
    var c *py.Object
    if a.Float64() < b.Float64() {
        c = a
    } else {
        d := math.Sqrt(b)
        c = d
    }
    // INSERT phi(a, d).IncRef()           | implemented
    // INSERT defer c.DecRef()             | implemented

    testInnerClosure()
    testReturnMultiple()
}