mirror of
https://github.com/golang/go
synced 2024-11-25 20:47:58 -07:00
cmd/cgo: add and use runtime/cgo.Incomplete instead of //go:notinheap
Updates #46731 Change-Id: Ia83f27c177cc2f57e240cb5c6708d4552423f5be Reviewed-on: https://go-review.googlesource.com/c/go/+/421879 Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-by: David Chase <drchase@google.com> TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
parent
a6219737e3
commit
846c378b8c
14
api/next/46731.txt
Normal file
14
api/next/46731.txt
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
pkg runtime/cgo (darwin-amd64-cgo), type Incomplete struct #46731
|
||||||
|
pkg runtime/cgo (freebsd-386-cgo), type Incomplete struct #46731
|
||||||
|
pkg runtime/cgo (freebsd-amd64-cgo), type Incomplete struct #46731
|
||||||
|
pkg runtime/cgo (freebsd-arm-cgo), type Incomplete struct #46731
|
||||||
|
pkg runtime/cgo (linux-386-cgo), type Incomplete struct #46731
|
||||||
|
pkg runtime/cgo (linux-amd64-cgo), type Incomplete struct #46731
|
||||||
|
pkg runtime/cgo (linux-arm-cgo), type Incomplete struct #46731
|
||||||
|
pkg runtime/cgo (netbsd-386-cgo), type Incomplete struct #46731
|
||||||
|
pkg runtime/cgo (netbsd-amd64-cgo), type Incomplete struct #46731
|
||||||
|
pkg runtime/cgo (netbsd-arm-cgo), type Incomplete struct #46731
|
||||||
|
pkg runtime/cgo (netbsd-arm64-cgo), type Incomplete struct #46731
|
||||||
|
pkg runtime/cgo (openbsd-386-cgo), type Incomplete struct #46731
|
||||||
|
pkg runtime/cgo (openbsd-amd64-cgo), type Incomplete struct #46731
|
||||||
|
pkg runtime/cgo, type Incomplete struct #46731
|
@ -2154,8 +2154,8 @@ type typeConv struct {
|
|||||||
// Type names X for which there exists an XGetTypeID function with type func() CFTypeID.
|
// Type names X for which there exists an XGetTypeID function with type func() CFTypeID.
|
||||||
getTypeIDs map[string]bool
|
getTypeIDs map[string]bool
|
||||||
|
|
||||||
// badStructs contains C structs that should be marked NotInHeap.
|
// incompleteStructs contains C structs that should be marked Incomplete.
|
||||||
notInHeapStructs map[string]bool
|
incompleteStructs map[string]bool
|
||||||
|
|
||||||
// Predeclared types.
|
// Predeclared types.
|
||||||
bool ast.Expr
|
bool ast.Expr
|
||||||
@ -2168,7 +2168,6 @@ type typeConv struct {
|
|||||||
string ast.Expr
|
string ast.Expr
|
||||||
goVoid ast.Expr // _Ctype_void, denotes C's void
|
goVoid ast.Expr // _Ctype_void, denotes C's void
|
||||||
goVoidPtr ast.Expr // unsafe.Pointer or *byte
|
goVoidPtr ast.Expr // unsafe.Pointer or *byte
|
||||||
goVoidPtrNoHeap ast.Expr // *_Ctype_void_notinheap, like goVoidPtr but marked NotInHeap
|
|
||||||
|
|
||||||
ptrSize int64
|
ptrSize int64
|
||||||
intSize int64
|
intSize int64
|
||||||
@ -2192,7 +2191,7 @@ func (c *typeConv) Init(ptrSize, intSize int64) {
|
|||||||
c.m = make(map[string]*Type)
|
c.m = make(map[string]*Type)
|
||||||
c.ptrs = make(map[string][]*Type)
|
c.ptrs = make(map[string][]*Type)
|
||||||
c.getTypeIDs = make(map[string]bool)
|
c.getTypeIDs = make(map[string]bool)
|
||||||
c.notInHeapStructs = make(map[string]bool)
|
c.incompleteStructs = make(map[string]bool)
|
||||||
c.bool = c.Ident("bool")
|
c.bool = c.Ident("bool")
|
||||||
c.byte = c.Ident("byte")
|
c.byte = c.Ident("byte")
|
||||||
c.int8 = c.Ident("int8")
|
c.int8 = c.Ident("int8")
|
||||||
@ -2211,7 +2210,6 @@ func (c *typeConv) Init(ptrSize, intSize int64) {
|
|||||||
c.void = c.Ident("void")
|
c.void = c.Ident("void")
|
||||||
c.string = c.Ident("string")
|
c.string = c.Ident("string")
|
||||||
c.goVoid = c.Ident("_Ctype_void")
|
c.goVoid = c.Ident("_Ctype_void")
|
||||||
c.goVoidPtrNoHeap = c.Ident("*_Ctype_void_notinheap")
|
|
||||||
|
|
||||||
// Normally cgo translates void* to unsafe.Pointer,
|
// Normally cgo translates void* to unsafe.Pointer,
|
||||||
// but for historical reasons -godefs uses *byte instead.
|
// but for historical reasons -godefs uses *byte instead.
|
||||||
@ -2561,19 +2559,13 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
|
|||||||
// other than try to determine a Go representation.
|
// other than try to determine a Go representation.
|
||||||
tt := *t
|
tt := *t
|
||||||
tt.C = &TypeRepr{"%s %s", []interface{}{dt.Kind, tag}}
|
tt.C = &TypeRepr{"%s %s", []interface{}{dt.Kind, tag}}
|
||||||
tt.Go = c.Ident("struct{}")
|
// We don't know what the representation of this struct is, so don't let
|
||||||
if dt.Kind == "struct" {
|
// anyone allocate one on the Go side. As a side effect of this annotation,
|
||||||
// We don't know what the representation of this struct is, so don't let
|
// pointers to this type will not be considered pointers in Go. They won't
|
||||||
// anyone allocate one on the Go side. As a side effect of this annotation,
|
// get writebarrier-ed or adjusted during a stack copy. This should handle
|
||||||
// pointers to this type will not be considered pointers in Go. They won't
|
// all the cases badPointerTypedef used to handle, but hopefully will
|
||||||
// get writebarrier-ed or adjusted during a stack copy. This should handle
|
// continue to work going forward without any more need for cgo changes.
|
||||||
// all the cases badPointerTypedef used to handle, but hopefully will
|
tt.Go = c.Ident("_cgopackage.Incomplete")
|
||||||
// continue to work going forward without any more need for cgo changes.
|
|
||||||
tt.NotInHeap = true
|
|
||||||
// TODO: we should probably do the same for unions. Unions can't live
|
|
||||||
// on the Go heap, right? It currently doesn't work for unions because
|
|
||||||
// they are defined as a type alias for struct{}, not a defined type.
|
|
||||||
}
|
|
||||||
typedef[name.Name] = &tt
|
typedef[name.Name] = &tt
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -2599,7 +2591,9 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
|
|||||||
tt.C = &TypeRepr{"struct %s", []interface{}{tag}}
|
tt.C = &TypeRepr{"struct %s", []interface{}{tag}}
|
||||||
}
|
}
|
||||||
tt.Go = g
|
tt.Go = g
|
||||||
tt.NotInHeap = c.notInHeapStructs[tag]
|
if c.incompleteStructs[tag] {
|
||||||
|
tt.Go = c.Ident("_cgopackage.Incomplete")
|
||||||
|
}
|
||||||
typedef[name.Name] = &tt
|
typedef[name.Name] = &tt
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2644,9 +2638,9 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if c.badVoidPointerTypedef(dt) {
|
if c.badVoidPointerTypedef(dt) {
|
||||||
// Treat this typedef as a pointer to a NotInHeap void.
|
// Treat this typedef as a pointer to a _cgopackage.Incomplete.
|
||||||
s := *sub
|
s := *sub
|
||||||
s.Go = c.goVoidPtrNoHeap
|
s.Go = c.Ident("*_cgopackage.Incomplete")
|
||||||
sub = &s
|
sub = &s
|
||||||
// Make sure we update any previously computed type.
|
// Make sure we update any previously computed type.
|
||||||
if oldType := typedef[name.Name]; oldType != nil {
|
if oldType := typedef[name.Name]; oldType != nil {
|
||||||
@ -2654,22 +2648,21 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check for non-pointer "struct <tag>{...}; typedef struct <tag> *<name>"
|
// Check for non-pointer "struct <tag>{...}; typedef struct <tag> *<name>"
|
||||||
// typedefs that should be marked NotInHeap.
|
// typedefs that should be marked Incomplete.
|
||||||
if ptr, ok := dt.Type.(*dwarf.PtrType); ok {
|
if ptr, ok := dt.Type.(*dwarf.PtrType); ok {
|
||||||
if strct, ok := ptr.Type.(*dwarf.StructType); ok {
|
if strct, ok := ptr.Type.(*dwarf.StructType); ok {
|
||||||
if c.badStructPointerTypedef(dt.Name, strct) {
|
if c.badStructPointerTypedef(dt.Name, strct) {
|
||||||
c.notInHeapStructs[strct.StructName] = true
|
c.incompleteStructs[strct.StructName] = true
|
||||||
// Make sure we update any previously computed type.
|
// Make sure we update any previously computed type.
|
||||||
name := "_Ctype_struct_" + strct.StructName
|
name := "_Ctype_struct_" + strct.StructName
|
||||||
if oldType := typedef[name]; oldType != nil {
|
if oldType := typedef[name]; oldType != nil {
|
||||||
oldType.NotInHeap = true
|
oldType.Go = c.Ident("_cgopackage.Incomplete")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
t.Go = name
|
t.Go = name
|
||||||
t.BadPointer = sub.BadPointer
|
t.BadPointer = sub.BadPointer
|
||||||
t.NotInHeap = sub.NotInHeap
|
|
||||||
if unionWithPointer[sub.Go] {
|
if unionWithPointer[sub.Go] {
|
||||||
unionWithPointer[t.Go] = true
|
unionWithPointer[t.Go] = true
|
||||||
}
|
}
|
||||||
@ -2680,7 +2673,6 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
|
|||||||
tt := *t
|
tt := *t
|
||||||
tt.Go = sub.Go
|
tt.Go = sub.Go
|
||||||
tt.BadPointer = sub.BadPointer
|
tt.BadPointer = sub.BadPointer
|
||||||
tt.NotInHeap = sub.NotInHeap
|
|
||||||
typedef[name.Name] = &tt
|
typedef[name.Name] = &tt
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3204,7 +3196,7 @@ func (c *typeConv) anonymousStructTypedef(dt *dwarf.TypedefType) bool {
|
|||||||
// non-pointers in this type.
|
// non-pointers in this type.
|
||||||
// TODO: Currently our best solution is to find these manually and list them as
|
// TODO: Currently our best solution is to find these manually and list them as
|
||||||
// they come up. A better solution is desired.
|
// they come up. A better solution is desired.
|
||||||
// Note: DEPRECATED. There is now a better solution. Search for NotInHeap in this file.
|
// Note: DEPRECATED. There is now a better solution. Search for _cgopackage.Incomplete in this file.
|
||||||
func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool {
|
func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool {
|
||||||
if c.badCFType(dt) {
|
if c.badCFType(dt) {
|
||||||
return true
|
return true
|
||||||
@ -3218,7 +3210,7 @@ func (c *typeConv) badPointerTypedef(dt *dwarf.TypedefType) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// badVoidPointerTypedef is like badPointerTypeDef, but for "void *" typedefs that should be NotInHeap.
|
// badVoidPointerTypedef is like badPointerTypeDef, but for "void *" typedefs that should be _cgopackage.Incomplete.
|
||||||
func (c *typeConv) badVoidPointerTypedef(dt *dwarf.TypedefType) bool {
|
func (c *typeConv) badVoidPointerTypedef(dt *dwarf.TypedefType) bool {
|
||||||
// Match the Windows HANDLE type (#42018).
|
// Match the Windows HANDLE type (#42018).
|
||||||
if goos != "windows" || dt.Name != "HANDLE" {
|
if goos != "windows" || dt.Name != "HANDLE" {
|
||||||
|
@ -153,7 +153,6 @@ type Type struct {
|
|||||||
EnumValues map[string]int64
|
EnumValues map[string]int64
|
||||||
Typedef string
|
Typedef string
|
||||||
BadPointer bool // this pointer type should be represented as a uintptr (deprecated)
|
BadPointer bool // this pointer type should be represented as a uintptr (deprecated)
|
||||||
NotInHeap bool // this type should have a go:notinheap annotation
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// A FuncType collects information about a function type in both the C and Go worlds.
|
// A FuncType collects information about a function type in both the C and Go worlds.
|
||||||
|
@ -81,11 +81,14 @@ func (p *Package) writeDefs() {
|
|||||||
fmt.Fprintf(fgo2, "// Code generated by cmd/cgo; DO NOT EDIT.\n\n")
|
fmt.Fprintf(fgo2, "// Code generated by cmd/cgo; DO NOT EDIT.\n\n")
|
||||||
fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName)
|
fmt.Fprintf(fgo2, "package %s\n\n", p.PackageName)
|
||||||
fmt.Fprintf(fgo2, "import \"unsafe\"\n\n")
|
fmt.Fprintf(fgo2, "import \"unsafe\"\n\n")
|
||||||
if !*gccgo && *importRuntimeCgo {
|
|
||||||
fmt.Fprintf(fgo2, "import _ \"runtime/cgo\"\n\n")
|
|
||||||
}
|
|
||||||
if *importSyscall {
|
if *importSyscall {
|
||||||
fmt.Fprintf(fgo2, "import \"syscall\"\n\n")
|
fmt.Fprintf(fgo2, "import \"syscall\"\n\n")
|
||||||
|
}
|
||||||
|
if *importRuntimeCgo {
|
||||||
|
fmt.Fprintf(fgo2, "import _cgopackage \"runtime/cgo\"\n\n")
|
||||||
|
fmt.Fprintf(fgo2, "type _ _cgopackage.Incomplete\n") // prevent import-not-used error
|
||||||
|
}
|
||||||
|
if *importSyscall {
|
||||||
fmt.Fprintf(fgo2, "var _ syscall.Errno\n")
|
fmt.Fprintf(fgo2, "var _ syscall.Errno\n")
|
||||||
}
|
}
|
||||||
fmt.Fprintf(fgo2, "func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }\n\n")
|
fmt.Fprintf(fgo2, "func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { return ptr }\n\n")
|
||||||
@ -109,9 +112,6 @@ func (p *Package) writeDefs() {
|
|||||||
sort.Strings(typedefNames)
|
sort.Strings(typedefNames)
|
||||||
for _, name := range typedefNames {
|
for _, name := range typedefNames {
|
||||||
def := typedef[name]
|
def := typedef[name]
|
||||||
if def.NotInHeap {
|
|
||||||
fmt.Fprintf(fgo2, "//go:notinheap\n")
|
|
||||||
}
|
|
||||||
fmt.Fprintf(fgo2, "type %s ", name)
|
fmt.Fprintf(fgo2, "type %s ", name)
|
||||||
// We don't have source info for these types, so write them out without source info.
|
// We don't have source info for these types, so write them out without source info.
|
||||||
// Otherwise types would look like:
|
// Otherwise types would look like:
|
||||||
@ -136,7 +136,6 @@ func (p *Package) writeDefs() {
|
|||||||
fmt.Fprintf(fgo2, "%s", buf.Bytes())
|
fmt.Fprintf(fgo2, "%s", buf.Bytes())
|
||||||
fmt.Fprintf(fgo2, "\n\n")
|
fmt.Fprintf(fgo2, "\n\n")
|
||||||
}
|
}
|
||||||
fmt.Fprintf(fgo2, "//go:notinheap\ntype _Ctype_void_notinheap struct{}\n\n")
|
|
||||||
if *gccgo {
|
if *gccgo {
|
||||||
fmt.Fprintf(fgo2, "type _Ctype_void byte\n")
|
fmt.Fprintf(fgo2, "type _Ctype_void byte\n")
|
||||||
} else {
|
} else {
|
||||||
|
@ -31,3 +31,10 @@ package cgo
|
|||||||
|
|
||||||
*/
|
*/
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
|
import "runtime/internal/sys"
|
||||||
|
|
||||||
|
// Incomplete is used specifically for the semantics of incomplete C types.
|
||||||
|
type Incomplete struct {
|
||||||
|
_ sys.NotInHeap
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user