This libgo patch changes the cgo command to use runtime/cgo.Incomplete
instead of //go:notinheap, and to define the new type in the
runtime/cgo package.  This ports https://go.dev/cl/421879 to libgo.
This is a quick port to update libgo to work with the version of cgo
in gc mainline.  A more complete port will follow, changing the gc
version of cmd/cgo to choose an approach based on feature testing the
gccgo in use.  Bootstrapped and tested on x86_64-pc-linux-gnu.
Committed to mainline.

Ian
c69b87678d3c4e9b995b8ccb51fb38c75a134323
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index dce38e727a7..f7a7985287d 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-6543b7fc6da533eb976b37649a925e7fd5a521fa
+42efec8c126cf3787bc7c89d9c7f224eff7c5a21
 
 The first line of this file holds the git revision number of the last
 merge done from the gofrontend repository.
diff --git a/libgo/go/cmd/cgo/gcc.go b/libgo/go/cmd/cgo/gcc.go
index 02391495bbe..e786aeaafa9 100644
--- a/libgo/go/cmd/cgo/gcc.go
+++ b/libgo/go/cmd/cgo/gcc.go
@@ -132,12 +132,11 @@ func (p *Package) addToFlag(flag string, args []string) {
 //
 // For example, the following string:
 //
-//     `a b:"c d" 'e''f'  "g\""`
+//     `a b:"c d" 'e''f'  "g\""`
 //
 // Would be parsed as:
 //
-//     []string{"a", "b:c d", "ef", `g"`}
-//
+//     []string{"a", "b:c d", "ef", `g"`}
 func splitQuoted(s string) (r []string, err error) {
        var args []string
        arg := make([]rune, len(s))
@@ -1156,13 +1155,19 @@ func (p *Package) mangle(f *File, arg *ast.Expr, 
addPosition bool) (ast.Expr, bo
 
 // checkIndex checks whether arg has the form &a[i], possibly inside
 // type conversions. If so, then in the general case it writes
-//    _cgoIndexNN := a
-//    _cgoNN := &cgoIndexNN[i] // with type conversions, if any
+//
+//     _cgoIndexNN := a
+//     _cgoNN := &cgoIndexNN[i] // with type conversions, if any
+//
 // to sb, and writes
-//    _cgoCheckPointer(_cgoNN, _cgoIndexNN)
+//
+//     _cgoCheckPointer(_cgoNN, _cgoIndexNN)
+//
 // to sbCheck, and returns true. If a is a simple variable or field reference,
 // it writes
-//    _cgoIndexNN := &a
+//
+//     _cgoIndexNN := &a
+//
 // and dereferences the uses of _cgoIndexNN. Taking the address avoids
 // making a copy of an array.
 //
@@ -1210,10 +1215,14 @@ func (p *Package) checkIndex(sb, sbCheck *bytes.Buffer, 
arg ast.Expr, i int) boo
 
 // checkAddr checks whether arg has the form &x, possibly inside type
 // conversions. If so, it writes
-//    _cgoBaseNN := &x
-//    _cgoNN := _cgoBaseNN // with type conversions, if any
+//
+//     _cgoBaseNN := &x
+//     _cgoNN := _cgoBaseNN // with type conversions, if any
+//
 // to sb, and writes
-//    _cgoCheckPointer(_cgoBaseNN, true)
+//
+//     _cgoCheckPointer(_cgoBaseNN, true)
+//
 // to sbCheck, and returns true. This tells _cgoCheckPointer to check
 // just the contents of the pointer being passed, not any other part
 // of the memory allocation. This is run after checkIndex, which looks
@@ -2131,8 +2140,8 @@ type typeConv struct {
        // Type names X for which there exists an XGetTypeID function with type 
func() CFTypeID.
        getTypeIDs map[string]bool
 
-       // badStructs contains C structs that should be marked NotInHeap.
-       notInHeapStructs map[string]bool
+       // incompleteStructs contains C structs that should be marked 
Incomplete.
+       incompleteStructs map[string]bool
 
        // Predeclared types.
        bool                                   ast.Expr
@@ -2145,7 +2154,6 @@ type typeConv struct {
        string                                 ast.Expr
        goVoid                                 ast.Expr // _Ctype_void, denotes 
C's void
        goVoidPtr                              ast.Expr // unsafe.Pointer or 
*byte
-       goVoidPtrNoHeap                        ast.Expr // 
*_Ctype_void_notinheap, like goVoidPtr but marked NotInHeap
 
        ptrSize int64
        intSize int64
@@ -2169,7 +2177,7 @@ func (c *typeConv) Init(ptrSize, intSize int64) {
        c.m = make(map[string]*Type)
        c.ptrs = make(map[string][]*Type)
        c.getTypeIDs = make(map[string]bool)
-       c.notInHeapStructs = make(map[string]bool)
+       c.incompleteStructs = make(map[string]bool)
        c.bool = c.Ident("bool")
        c.byte = c.Ident("byte")
        c.int8 = c.Ident("int8")
@@ -2188,7 +2196,6 @@ func (c *typeConv) Init(ptrSize, intSize int64) {
        c.void = c.Ident("void")
        c.string = c.Ident("string")
        c.goVoid = c.Ident("_Ctype_void")
-       c.goVoidPtrNoHeap = c.Ident("*_Ctype_void_notinheap")
 
        // Normally cgo translates void* to unsafe.Pointer,
        // but for historical reasons -godefs uses *byte instead.
@@ -2531,19 +2538,13 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos 
token.Pos, parent string) *Typ
                        // other than try to determine a Go representation.
                        tt := *t
                        tt.C = &TypeRepr{"%s %s", []interface{}{dt.Kind, tag}}
-                       tt.Go = c.Ident("struct{}")
-                       if dt.Kind == "struct" {
-                               // We don't know what the representation of 
this struct is, so don't let
-                               // anyone allocate one on the Go side. As a 
side effect of this annotation,
-                               // pointers to this type will not be considered 
pointers in Go. They won't
-                               // get writebarrier-ed or adjusted during a 
stack copy. This should handle
-                               // all the cases badPointerTypedef used to 
handle, but hopefully will
-                               // 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.
-                       }
+                       // We don't know what the representation of this struct 
is, so don't let
+                       // anyone allocate one on the Go side. As a side effect 
of this annotation,
+                       // pointers to this type will not be considered 
pointers in Go. They won't
+                       // get writebarrier-ed or adjusted during a stack copy. 
This should handle
+                       // all the cases badPointerTypedef used to handle, but 
hopefully will
+                       // continue to work going forward without any more need 
for cgo changes.
+                       tt.Go = c.Ident("_cgopackage.Incomplete")
                        typedef[name.Name] = &tt
                        break
                }
@@ -2569,7 +2570,9 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos 
token.Pos, parent string) *Typ
                                tt.C = &TypeRepr{"struct %s", 
[]interface{}{tag}}
                        }
                        tt.Go = g
-                       tt.NotInHeap = c.notInHeapStructs[tag]
+                       if c.incompleteStructs[tag] {
+                               tt.Go = c.Ident("_cgopackage.Incomplete")
+                       }
                        typedef[name.Name] = &tt
                }
 
@@ -2614,9 +2617,9 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos 
token.Pos, parent string) *Typ
                        }
                }
                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.Go = c.goVoidPtrNoHeap
+                       s.Go = c.Ident("*_cgopackage.Incomplete")
                        sub = &s
                        // Make sure we update any previously computed type.
                        if oldType := typedef[name.Name]; oldType != nil {
@@ -2624,22 +2627,21 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos 
token.Pos, parent string) *Typ
                        }
                }
                // 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 strct, ok := ptr.Type.(*dwarf.StructType); ok {
                                if c.badStructPointerTypedef(dt.Name, strct) {
-                                       c.notInHeapStructs[strct.StructName] = 
true
+                                       c.incompleteStructs[strct.StructName] = 
true
                                        // Make sure we update any previously 
computed type.
                                        name := "_Ctype_struct_" + 
strct.StructName
                                        if oldType := typedef[name]; oldType != 
nil {
-                                               oldType.NotInHeap = true
+                                               oldType.Go = 
c.Ident("_cgopackage.Incomplete")
                                        }
                                }
                        }
                }
                t.Go = name
                t.BadPointer = sub.BadPointer
-               t.NotInHeap = sub.NotInHeap
                if unionWithPointer[sub.Go] {
                        unionWithPointer[t.Go] = true
                }
@@ -2650,7 +2652,6 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos 
token.Pos, parent string) *Typ
                        tt := *t
                        tt.Go = sub.Go
                        tt.BadPointer = sub.BadPointer
-                       tt.NotInHeap = sub.NotInHeap
                        typedef[name.Name] = &tt
                }
 
@@ -3174,7 +3175,7 @@ func (c *typeConv) anonymousStructTypedef(dt 
*dwarf.TypedefType) bool {
 // non-pointers in this type.
 // TODO: Currently our best solution is to find these manually and list them as
 // 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 {
        if c.badCFType(dt) {
                return true
@@ -3188,7 +3189,7 @@ func (c *typeConv) badPointerTypedef(dt 
*dwarf.TypedefType) bool {
        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 {
        // Match the Windows HANDLE type (#42018).
        if goos != "windows" || dt.Name != "HANDLE" {
diff --git a/libgo/go/cmd/cgo/main.go b/libgo/go/cmd/cgo/main.go
index 58477e47045..186aef06c08 100644
--- a/libgo/go/cmd/cgo/main.go
+++ b/libgo/go/cmd/cgo/main.go
@@ -153,7 +153,6 @@ type Type struct {
        EnumValues map[string]int64
        Typedef    string
        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.
diff --git a/libgo/go/cmd/cgo/out.go b/libgo/go/cmd/cgo/out.go
index 8d1eb5b6a96..9ed88b84974 100644
--- a/libgo/go/cmd/cgo/out.go
+++ b/libgo/go/cmd/cgo/out.go
@@ -85,11 +85,14 @@ func (p *Package) writeDefs() {
        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, "import \"unsafe\"\n\n")
-       if !*gccgo && *importRuntimeCgo {
-               fmt.Fprintf(fgo2, "import _ \"runtime/cgo\"\n\n")
-       }
        if *importSyscall {
                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, "func _Cgo_ptr(ptr unsafe.Pointer) unsafe.Pointer { 
return ptr }\n\n")
@@ -113,9 +116,6 @@ func (p *Package) writeDefs() {
        sort.Strings(typedefNames)
        for _, name := range typedefNames {
                def := typedef[name]
-               if def.NotInHeap {
-                       fmt.Fprintf(fgo2, "//go:notinheap\n")
-               }
                fmt.Fprintf(fgo2, "type %s ", name)
                // We don't have source info for these types, so write them out 
without source info.
                // Otherwise types would look like:
@@ -140,7 +140,6 @@ func (p *Package) writeDefs() {
                fmt.Fprintf(fgo2, "%s", buf.Bytes())
                fmt.Fprintf(fgo2, "\n\n")
        }
-       fmt.Fprintf(fgo2, "//go:notinheap\ntype _Ctype_void_notinheap 
struct{}\n\n")
        if *gccgo {
                fmt.Fprintf(fgo2, "type _Ctype_void byte\n")
        } else {
diff --git a/libgo/go/cmd/go/internal/load/pkg.go 
b/libgo/go/cmd/go/internal/load/pkg.go
index 44bd61caea7..9c5c0a1ce26 100644
--- a/libgo/go/cmd/go/internal/load/pkg.go
+++ b/libgo/go/cmd/go/internal/load/pkg.go
@@ -1818,7 +1818,7 @@ func (p *Package) load(ctx context.Context, opts 
PackageOpts, path string, stk *
                if p.UsesCgo() {
                        addImport("unsafe", true)
                }
-               if p.UsesCgo() && (!p.Standard || !cgoExclude[p.ImportPath]) && 
cfg.BuildContext.Compiler != "gccgo" {
+               if p.UsesCgo() && (!p.Standard || !cgoExclude[p.ImportPath]) {
                        addImport("runtime/cgo", true)
                }
                if p.UsesCgo() && (!p.Standard || 
!cgoSyscallExclude[p.ImportPath]) {
@@ -1828,9 +1828,7 @@ func (p *Package) load(ctx context.Context, opts 
PackageOpts, path string, stk *
                // SWIG adds imports of some standard packages.
                if p.UsesSwig() {
                        addImport("unsafe", true)
-                       if cfg.BuildContext.Compiler != "gccgo" {
-                               addImport("runtime/cgo", true)
-                       }
+                       addImport("runtime/cgo", true)
                        addImport("syscall", true)
                        addImport("sync", true)
 
@@ -2455,7 +2453,7 @@ func LinkerDeps(p *Package) []string {
        deps := []string{"runtime"}
 
        // External linking mode forces an import of runtime/cgo.
-       if externalLinkingForced(p) && cfg.BuildContext.Compiler != "gccgo" {
+       if externalLinkingForced(p) {
                deps = append(deps, "runtime/cgo")
        }
        // On ARM with GOARM=5, it forces an import of math, for soft floating 
point.
diff --git a/libgo/go/runtime/cgo/cgo.go b/libgo/go/runtime/cgo/cgo.go
new file mode 100644
index 00000000000..5921435696b
--- /dev/null
+++ b/libgo/go/runtime/cgo/cgo.go
@@ -0,0 +1,18 @@
+// Copyright 2010 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.
+
+/*
+Package cgo contains runtime support for code generated
+by the cgo tool.  See the documentation for the cgo command
+for details on using cgo.
+*/
+package cgo
+
+// Incomplete is used specifically for the semantics of incomplete C types.
+//
+//go:notinheap
+type Incomplete struct {
+       //      _ sys.NotInHeap
+       _ struct{ _ struct{} }
+}

Reply via email to