mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.typeparams] cmd/compile: remove special escape analysis tags
This CL removes the special escape analysis tags added to support //go:uintptrescapes and calls to external functions. Instead, these are kept as function pragmas. This CL by itself isn't very interesting, but I expect will help with subsequent cleanups I have planned here. Change-Id: Ifb960289a27e0a6295ce2d2f5ec233cac590522b Reviewed-on: https://go-review.googlesource.com/c/go/+/329969 Run-TryBot: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com> Trust: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
859d903b06
commit
077100dfcd
3 changed files with 48 additions and 44 deletions
|
|
@ -1132,7 +1132,7 @@ func (e *escape) tagHole(ks []hole, fn *ir.Name, param *types.Field) hole {
|
||||||
|
|
||||||
// Call to previously tagged function.
|
// Call to previously tagged function.
|
||||||
|
|
||||||
if param.Note == UintptrEscapesNote {
|
if fn.Func != nil && fn.Func.Pragma&ir.UintptrEscapes != 0 && (param.Type.IsUintptr() || param.IsDDD() && param.Type.Elem().IsUintptr()) {
|
||||||
k := e.heapHole()
|
k := e.heapHole()
|
||||||
k.uintptrEscapesHack = true
|
k.uintptrEscapesHack = true
|
||||||
return k
|
return k
|
||||||
|
|
@ -2048,15 +2048,6 @@ func HeapAllocReason(n ir.Node) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// This special tag is applied to uintptr variables
|
|
||||||
// that we believe may hold unsafe.Pointers for
|
|
||||||
// calls into assembly functions.
|
|
||||||
const UnsafeUintptrNote = "unsafe-uintptr"
|
|
||||||
|
|
||||||
// This special tag is applied to uintptr parameters of functions
|
|
||||||
// marked go:uintptrescapes.
|
|
||||||
const UintptrEscapesNote = "uintptr-escapes"
|
|
||||||
|
|
||||||
func (b *batch) paramTag(fn *ir.Func, narg int, f *types.Field) string {
|
func (b *batch) paramTag(fn *ir.Func, narg int, f *types.Field) string {
|
||||||
name := func() string {
|
name := func() string {
|
||||||
if f.Sym != nil {
|
if f.Sym != nil {
|
||||||
|
|
@ -2072,11 +2063,13 @@ func (b *batch) paramTag(fn *ir.Func, narg int, f *types.Field) string {
|
||||||
// This really doesn't have much to do with escape analysis per se,
|
// This really doesn't have much to do with escape analysis per se,
|
||||||
// but we are reusing the ability to annotate an individual function
|
// but we are reusing the ability to annotate an individual function
|
||||||
// argument and pass those annotations along to importing code.
|
// argument and pass those annotations along to importing code.
|
||||||
|
fn.Pragma |= ir.UintptrKeepAlive
|
||||||
|
|
||||||
if f.Type.IsUintptr() {
|
if f.Type.IsUintptr() {
|
||||||
if base.Flag.LowerM != 0 {
|
if base.Flag.LowerM != 0 {
|
||||||
base.WarnfAt(f.Pos, "assuming %v is unsafe uintptr", name())
|
base.WarnfAt(f.Pos, "assuming %v is unsafe uintptr", name())
|
||||||
}
|
}
|
||||||
return UnsafeUintptrNote
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
if !f.Type.HasPointers() { // don't bother tagging for scalars
|
if !f.Type.HasPointers() { // don't bother tagging for scalars
|
||||||
|
|
@ -2102,18 +2095,20 @@ func (b *batch) paramTag(fn *ir.Func, narg int, f *types.Field) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
if fn.Pragma&ir.UintptrEscapes != 0 {
|
if fn.Pragma&ir.UintptrEscapes != 0 {
|
||||||
|
fn.Pragma |= ir.UintptrKeepAlive
|
||||||
|
|
||||||
if f.Type.IsUintptr() {
|
if f.Type.IsUintptr() {
|
||||||
if base.Flag.LowerM != 0 {
|
if base.Flag.LowerM != 0 {
|
||||||
base.WarnfAt(f.Pos, "marking %v as escaping uintptr", name())
|
base.WarnfAt(f.Pos, "marking %v as escaping uintptr", name())
|
||||||
}
|
}
|
||||||
return UintptrEscapesNote
|
return ""
|
||||||
}
|
}
|
||||||
if f.IsDDD() && f.Type.Elem().IsUintptr() {
|
if f.IsDDD() && f.Type.Elem().IsUintptr() {
|
||||||
// final argument is ...uintptr.
|
// final argument is ...uintptr.
|
||||||
if base.Flag.LowerM != 0 {
|
if base.Flag.LowerM != 0 {
|
||||||
base.WarnfAt(f.Pos, "marking %v as escaping ...uintptr", name())
|
base.WarnfAt(f.Pos, "marking %v as escaping ...uintptr", name())
|
||||||
}
|
}
|
||||||
return UintptrEscapesNote
|
return ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -436,18 +436,19 @@ func (s NameSet) Sorted(less func(*Name, *Name) bool) []*Name {
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
type PragmaFlag int16
|
type PragmaFlag uint16
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// Func pragmas.
|
// Func pragmas.
|
||||||
Nointerface PragmaFlag = 1 << iota
|
Nointerface PragmaFlag = 1 << iota
|
||||||
Noescape // func parameters don't escape
|
Noescape // func parameters don't escape
|
||||||
Norace // func must not have race detector annotations
|
Norace // func must not have race detector annotations
|
||||||
Nosplit // func should not execute on separate stack
|
Nosplit // func should not execute on separate stack
|
||||||
Noinline // func should not be inlined
|
Noinline // func should not be inlined
|
||||||
NoCheckPtr // func should not be instrumented by checkptr
|
NoCheckPtr // func should not be instrumented by checkptr
|
||||||
CgoUnsafeArgs // treat a pointer to one arg as a pointer to them all
|
CgoUnsafeArgs // treat a pointer to one arg as a pointer to them all
|
||||||
UintptrEscapes // pointers converted to uintptr escape
|
UintptrKeepAlive // pointers converted to uintptr must be kept alive (compiler internal only)
|
||||||
|
UintptrEscapes // pointers converted to uintptr escape
|
||||||
|
|
||||||
// Runtime-only func pragmas.
|
// Runtime-only func pragmas.
|
||||||
// See ../../../../runtime/README.md for detailed descriptions.
|
// See ../../../../runtime/README.md for detailed descriptions.
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ import (
|
||||||
"go/constant"
|
"go/constant"
|
||||||
|
|
||||||
"cmd/compile/internal/base"
|
"cmd/compile/internal/base"
|
||||||
"cmd/compile/internal/escape"
|
|
||||||
"cmd/compile/internal/ir"
|
"cmd/compile/internal/ir"
|
||||||
"cmd/compile/internal/reflectdata"
|
"cmd/compile/internal/reflectdata"
|
||||||
"cmd/compile/internal/staticinit"
|
"cmd/compile/internal/staticinit"
|
||||||
|
|
@ -554,37 +553,46 @@ func (o *orderState) call(nn ir.Node) {
|
||||||
n.X = o.expr(n.X, nil)
|
n.X = o.expr(n.X, nil)
|
||||||
o.exprList(n.Args)
|
o.exprList(n.Args)
|
||||||
|
|
||||||
if n.Op() == ir.OCALLINTER {
|
// Pick out the function callee, if statically known.
|
||||||
|
// TODO(mdempsky): De-duplicate with similar code in escape analysis.
|
||||||
|
var callee *ir.Func
|
||||||
|
switch n.Op() {
|
||||||
|
case ir.OCALLFUNC:
|
||||||
|
if fn, ok := n.X.(*ir.Name); ok && fn.Op() == ir.ONAME && fn.Class == ir.PFUNC {
|
||||||
|
callee = fn.Func
|
||||||
|
}
|
||||||
|
case ir.OCALLMETH:
|
||||||
|
callee = ir.MethodExprName(n.X).Func
|
||||||
|
}
|
||||||
|
|
||||||
|
if callee == nil || callee.Pragma&ir.UintptrKeepAlive == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
keepAlive := func(arg ir.Node) {
|
|
||||||
|
keepAlive := func(args []ir.Node) {
|
||||||
// If the argument is really a pointer being converted to uintptr,
|
// If the argument is really a pointer being converted to uintptr,
|
||||||
// arrange for the pointer to be kept alive until the call returns,
|
// arrange for the pointer to be kept alive until the call returns,
|
||||||
// by copying it into a temp and marking that temp
|
// by copying it into a temp and marking that temp
|
||||||
// still alive when we pop the temp stack.
|
// still alive when we pop the temp stack.
|
||||||
if arg.Op() == ir.OCONVNOP {
|
for _, arg := range args {
|
||||||
arg := arg.(*ir.ConvExpr)
|
if arg.Op() == ir.OCONVNOP && arg.Type().IsUintptr() {
|
||||||
if arg.X.Type().IsUnsafePtr() {
|
arg := arg.(*ir.ConvExpr)
|
||||||
x := o.copyExpr(arg.X)
|
if arg.X.Type().IsUnsafePtr() {
|
||||||
arg.X = x
|
x := o.copyExpr(arg.X)
|
||||||
x.SetAddrtaken(true) // ensure SSA keeps the x variable
|
arg.X = x
|
||||||
n.KeepAlive = append(n.KeepAlive, x)
|
x.SetAddrtaken(true) // ensure SSA keeps the x variable
|
||||||
|
n.KeepAlive = append(n.KeepAlive, x)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for "unsafe-uintptr" tag provided by escape analysis.
|
last := len(n.Args) - 1
|
||||||
for i, param := range n.X.Type().Params().FieldSlice() {
|
if n.IsDDD && n.Args[last].Op() == ir.OSLICELIT {
|
||||||
if param.Note == escape.UnsafeUintptrNote || param.Note == escape.UintptrEscapesNote {
|
keepAlive(n.Args[:last])
|
||||||
if arg := n.Args[i]; arg.Op() == ir.OSLICELIT {
|
keepAlive(n.Args[last].(*ir.CompLitExpr).List)
|
||||||
arg := arg.(*ir.CompLitExpr)
|
} else {
|
||||||
for _, elt := range arg.List {
|
keepAlive(n.Args)
|
||||||
keepAlive(elt)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
keepAlive(arg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue