From patchwork Thu Sep 22 13:28:29 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Lance Taylor X-Patchwork-Id: 1368 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:a5d:5044:0:0:0:0:0 with SMTP id h4csp197919wrt; Thu, 22 Sep 2022 06:29:26 -0700 (PDT) X-Google-Smtp-Source: AMsMyM6UhJToy0l1PtLyImOYKcaTM7AwZtriHJQrNulQb1ZM7aX0r4WG5Qs4zgnLQom2/THbsa21 X-Received: by 2002:a17:906:ee89:b0:73d:70c5:1a4e with SMTP id wt9-20020a170906ee8900b0073d70c51a4emr2701054ejb.683.1663853366317; Thu, 22 Sep 2022 06:29:26 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1663853366; cv=none; d=google.com; s=arc-20160816; b=lEQCIh0J/RIIAGshv4pk6EeEodSpjhReH9mM5wclm0X/Y+GnCO2rOEyT9TFKoYFEO4 MDEr+w2165t27BV9Pl5vdewiTFUEBcyGiV3bC586JjT/yDjHsCz6DPWOsOKKYzYHReMR Oh4hYcGE82+a+oP5Bk6DcDuNE/KAZ/CR3+o9AFNb1Ox2oGraSxxUrGV/SAuIFHMbq51D H+HU0je4Zj3q/9+l4avtqeYi1dse0nIaTgXZKhdd0qiF4b9IfAkQndjYU+DnvUrOYv/x /73n2tX+HSQaD9nkt0YPCngOYFs9u66BHGpm/EUQmrsb2ZeTFZc2Kz3s2FVtuAgPApmn wYGA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:reply-to:from:list-subscribe:list-help:list-post :list-archive:list-unsubscribe:list-id:precedence:to:subject :message-id:date:mime-version:dmarc-filter:delivered-to :dkim-signature:dkim-filter; bh=AGj3XC2qR2acjaUwPZ1ZQ+MpYbphCPYKIPKji5qH338=; b=buE/PweVbGYij9a9haAv96dMzAayTB70lNNmG8vYN4Sd/fzLdqYyg2FSd4fDaHSTgh CgHIlDwg+PjTDb68c3/Aphy1d6f965mhXeVKSZvJiMq9SNB2ygLEwZhbdwimBXvlqDdh nszVI5VOW6BM2iBGWmDVrVy8YHldkYD8IMKk/NSlVUb5VTD3KtCaK5flgAHwl5cfcQes gZVqPPvUoCaANDARUUjw7zkPY7Pb5yVQom+YiO/deB9xtRjidETWn1mEreBtzifpzD2v iXF8MPansU65YZXtihujPHCD7E6w+mGF4Axks4bkfQMgd+GzMSMBmTZkaBG2rjyfZ6fN R9OA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=n+oFFvbh; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from sourceware.org (ip-8-43-85-97.sourceware.org. [8.43.85.97]) by mx.google.com with ESMTPS id dd22-20020a1709069b9600b007825409d0a4si2152539ejc.59.2022.09.22.06.29.26 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 22 Sep 2022 06:29:26 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) client-ip=8.43.85.97; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=n+oFFvbh; spf=pass (google.com: domain of gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org designates 8.43.85.97 as permitted sender) smtp.mailfrom="gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=gnu.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3687B385801C for ; Thu, 22 Sep 2022 13:29:25 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3687B385801C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1663853365; bh=AGj3XC2qR2acjaUwPZ1ZQ+MpYbphCPYKIPKji5qH338=; h=Date:Subject:To:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=n+oFFvbhOA0Srw30CYiWUrk65/HrV75O9L2Eng7yPohllL3SyQr3tahCtF3PojMpI PGHNEUmtBC/to2KQUtHGx2cPfHM9osnH1f/gn7XWNb8qNJsHNRpJhgUdfef1GsYU49 lgl5a3leodM6M5hTyTHlWQjBlveIdPwt32BR1Qqs= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-oo1-xc32.google.com (mail-oo1-xc32.google.com [IPv6:2607:f8b0:4864:20::c32]) by sourceware.org (Postfix) with ESMTPS id E4B98385829D for ; Thu, 22 Sep 2022 13:28:40 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org E4B98385829D Received: by mail-oo1-xc32.google.com with SMTP id r136-20020a4a378e000000b004755953bc6cso1404971oor.13 for ; Thu, 22 Sep 2022 06:28:40 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=to:subject:message-id:date:from:mime-version:x-gm-message-state :from:to:cc:subject:date; bh=AGj3XC2qR2acjaUwPZ1ZQ+MpYbphCPYKIPKji5qH338=; b=o2TjlG850+I+qQUipIe7K04aKTd8RzTgvB2ZkVVVSCNEcnr9An59i+DKPOBEqcQG8D DMqDIvAoCd5lodQIT00uKfEYCjPEtJWgzsCyrr9gkwVxw8iM+zr7F0sv3KvJ1Z5dAAoT VITxNgRmchgaYwx8y4wvsmJTSoMvDkDoDo5mVemHjEk+A6jwjtb+1pPoQVebI7NnE+au nIfxUw1U8qrlclcR3zUlzQpA9+BvYzqejIWxK+nIhJ5fAQ4C94b3fp7fnuwL8tqmzGmE N0fWuzBQE+mSEEdOUY5epnv/Ahc+hCE6eqHN2ov/XXHs2PNn3ujvYWwWCgIH9CmP6f8K JGrA== X-Gm-Message-State: ACrzQf07zUlertkBp0LsQxlI9CZx+oL41wUECgjKA4P6MgHKaB85mkhh fAe5Fv4cKJNpjwjPDjzFtUg7q6im4RXA5A2im+ntBbkMZGOGDg== X-Received: by 2002:a4a:d4c1:0:b0:476:42e3:b45e with SMTP id r1-20020a4ad4c1000000b0047642e3b45emr1119042oos.89.1663853319790; Thu, 22 Sep 2022 06:28:39 -0700 (PDT) MIME-Version: 1.0 Date: Thu, 22 Sep 2022 06:28:29 -0700 Message-ID: Subject: libgo patch committed: Add cgo.Incomplete To: gcc-patches , gofrontend-dev X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Ian Lance Taylor via Gcc-patches From: Ian Lance Taylor Reply-To: Ian Lance Taylor Errors-To: gcc-patches-bounces+ouuuleilei=gmail.com@gcc.gnu.org Sender: "Gcc-patches" X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1744676707479753693?= X-GMAIL-MSGID: =?utf-8?q?1744676707479753693?= 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 {...}; typedef struct *" - // 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{} } +}