mirror of
https://github.com/golang/go
synced 2024-11-16 20:44:52 -07:00
342b495301
This CL exports the existing ir.UintptrKeepAlive via the new directive //go:uintptrkeepalive. This makes the compiler insert KeepAlives for pointers converted to uintptr in calls, keeping them alive for the duration of the call. //go:uintptrkeepalive requires //go:nosplit, as stack growth can't handle these arguments (it cannot know which are pointers). We currently check this on the immediate function, but the actual restriction applies to all transitive calls. The existing //go:uintptrescapes is an extension of //go:uintptrkeepalive which forces pointers to escape to the heap, thus eliminating the stack growth issue. This pragma is limited to the standard library. For #51087 Change-Id: If9a19d484d3561b4219e5539b70c11a3cc09391e Reviewed-on: https://go-review.googlesource.com/c/go/+/388095 Run-TryBot: Michael Pratt <mpratt@google.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
64 lines
2.0 KiB
Go
64 lines
2.0 KiB
Go
// errorcheck -0 -m -live -std
|
|
|
|
// +build !windows,!js
|
|
|
|
// Copyright 2015 The Go Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
// Test escape analysis and liveness inferred for uintptrkeepalive functions.
|
|
//
|
|
// This behavior is enabled automatically for function declarations with no
|
|
// bodies (assembly, linkname), as well as explicitly on complete functions
|
|
// with //go:uintptrkeepalive.
|
|
//
|
|
// This is most important for syscall.Syscall (and similiar functions), so we
|
|
// test it explicitly.
|
|
|
|
package p
|
|
|
|
import (
|
|
"syscall"
|
|
"unsafe"
|
|
)
|
|
|
|
func implicit(uintptr) // ERROR "assuming arg#1 is unsafe uintptr"
|
|
|
|
//go:uintptrkeepalive
|
|
//go:nosplit
|
|
func explicit(uintptr) {
|
|
}
|
|
|
|
func autotmpImplicit() { // ERROR "can inline autotmpImplicit"
|
|
var t int
|
|
implicit(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to implicit: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
|
|
}
|
|
|
|
func autotmpExplicit() { // ERROR "can inline autotmpExplicit"
|
|
var t int
|
|
explicit(uintptr(unsafe.Pointer(&t))) // ERROR "live at call to explicit: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
|
|
}
|
|
|
|
func autotmpSyscall() { // ERROR "can inline autotmpSyscall"
|
|
var v int
|
|
syscall.Syscall(0, 1, uintptr(unsafe.Pointer(&v)), 2) // ERROR "live at call to Syscall: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
|
|
}
|
|
|
|
func localImplicit() { // ERROR "can inline localImplicit"
|
|
var t int
|
|
p := unsafe.Pointer(&t)
|
|
implicit(uintptr(p)) // ERROR "live at call to implicit: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
|
|
}
|
|
|
|
func localExplicit() { // ERROR "can inline localExplicit"
|
|
var t int
|
|
p := unsafe.Pointer(&t)
|
|
explicit(uintptr(p)) // ERROR "live at call to explicit: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
|
|
}
|
|
|
|
func localSyscall() { // ERROR "can inline localSyscall"
|
|
var v int
|
|
p := unsafe.Pointer(&v)
|
|
syscall.Syscall(0, 1, uintptr(p), 2) // ERROR "live at call to Syscall: .?autotmp" "stack object .autotmp_[0-9]+ unsafe.Pointer$"
|
|
}
|