cmd/compile: export notinheap annotation to object file

In the rare case when a cgo type makes it into an object file, we need
the go:notinheap annotation to go with it.

Fixes #41761

Change-Id: I541500cb1a03de954881aef659f96fc0b7738848
Reviewed-on: https://go-review.googlesource.com/c/go/+/259297
Trust: Keith Randall <khr@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
diff --git a/misc/cgo/test/testdata/issue41761.go b/misc/cgo/test/testdata/issue41761.go
new file mode 100644
index 0000000..919c749
--- /dev/null
+++ b/misc/cgo/test/testdata/issue41761.go
@@ -0,0 +1,20 @@
+// Copyright 2020 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 cgotest
+
+/*
+   typedef struct S S;
+*/
+import "C"
+
+import (
+	"cgotest/issue41761a"
+	"testing"
+)
+
+func test41761(t *testing.T) {
+	var x issue41761a.T
+	_ = (*C.struct_S)(x.X)
+}
diff --git a/misc/cgo/test/testdata/issue41761a/a.go b/misc/cgo/test/testdata/issue41761a/a.go
new file mode 100644
index 0000000..ca5c181
--- /dev/null
+++ b/misc/cgo/test/testdata/issue41761a/a.go
@@ -0,0 +1,14 @@
+// Copyright 2020 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 issue41761a
+
+/*
+   typedef struct S S;
+*/
+import "C"
+
+type T struct {
+	X *C.S
+}
diff --git a/src/cmd/compile/internal/gc/iexport.go b/src/cmd/compile/internal/gc/iexport.go
index b3f50b6..3be3b0a 100644
--- a/src/cmd/compile/internal/gc/iexport.go
+++ b/src/cmd/compile/internal/gc/iexport.go
@@ -1017,6 +1017,8 @@
 }
 
 func (w *exportWriter) typeExt(t *types.Type) {
+	// Export whether this type is marked notinheap.
+	w.bool(t.NotInHeap())
 	// For type T, export the index of type descriptor symbols of T and *T.
 	if i, ok := typeSymIdx[t]; ok {
 		w.int64(i[0])
diff --git a/src/cmd/compile/internal/gc/iimport.go b/src/cmd/compile/internal/gc/iimport.go
index 4169222..0c5e469 100644
--- a/src/cmd/compile/internal/gc/iimport.go
+++ b/src/cmd/compile/internal/gc/iimport.go
@@ -596,7 +596,6 @@
 
 		// Ensure we expand the interface in the frontend (#25055).
 		checkwidth(t)
-
 		return t
 	}
 }
@@ -711,6 +710,7 @@
 }
 
 func (r *importReader) typeExt(t *types.Type) {
+	t.SetNotInHeap(r.bool())
 	i, pi := r.int64(), r.int64()
 	if i != -1 && pi != -1 {
 		typeSymIdx[t] = [2]int64{i, pi}
diff --git a/src/cmd/compile/internal/gc/lex.go b/src/cmd/compile/internal/gc/lex.go
index 1a344c6..25bc039 100644
--- a/src/cmd/compile/internal/gc/lex.go
+++ b/src/cmd/compile/internal/gc/lex.go
@@ -48,7 +48,7 @@
 	Nowritebarrierrec  // error on write barrier in this or recursive callees
 	Yeswritebarrierrec // cancels Nowritebarrierrec in this function and callees
 
-	// Runtime-only type pragmas
+	// Runtime and cgo type pragmas
 	NotInHeap // values of this type must not be heap allocated
 )