[dev.link] cmd/internal: convert basic types to builtin symbols

The Go compiler includes special treatment for a small set of very
commonly used type symbols (26 to be exact); for these types it
doesn't bother to emit type descriptors for "normal" compilations, and
instead only generates them for the runtime package, so as to reduce
object file bloat.

This patch moves the set of type symbols in question from the
PkgIdxNone index space (in the object file) to the PkgIdxBuiltin
space, which saves some work in the compiler and loader (reduces each
package's index space slightly).

Change-Id: I039c805e05c1aef26f035e52760fd0a0af40f7a5
Reviewed-on: https://go-review.googlesource.com/c/go/+/239658
Run-TryBot: Than McIntosh <thanm@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
diff --git a/src/cmd/internal/goobj2/builtinlist.go b/src/cmd/internal/goobj2/builtinlist.go
index 8fbbe45..171f57f 100644
--- a/src/cmd/internal/goobj2/builtinlist.go
+++ b/src/cmd/internal/goobj2/builtinlist.go
@@ -7,6 +7,7 @@
 	abi  int
 }{
 	{"runtime.newobject", 1},
+	{"runtime.mallocgc", 1},
 	{"runtime.panicdivide", 1},
 	{"runtime.panicshift", 1},
 	{"runtime.panicmakeslicelen", 1},
@@ -127,6 +128,7 @@
 	{"runtime.block", 1},
 	{"runtime.makeslice", 1},
 	{"runtime.makeslice64", 1},
+	{"runtime.makeslicecopy", 1},
 	{"runtime.growslice", 1},
 	{"runtime.memmove", 1},
 	{"runtime.memclrNoHeapPointers", 1},
@@ -204,4 +206,40 @@
 	{"runtime.morestack", 0},
 	{"runtime.morestackc", 0},
 	{"runtime.morestack_noctxt", 0},
+	{"type.int8", 0},
+	{"type.*int8", 0},
+	{"type.uint8", 0},
+	{"type.*uint8", 0},
+	{"type.int16", 0},
+	{"type.*int16", 0},
+	{"type.uint16", 0},
+	{"type.*uint16", 0},
+	{"type.int32", 0},
+	{"type.*int32", 0},
+	{"type.uint32", 0},
+	{"type.*uint32", 0},
+	{"type.int64", 0},
+	{"type.*int64", 0},
+	{"type.uint64", 0},
+	{"type.*uint64", 0},
+	{"type.float32", 0},
+	{"type.*float32", 0},
+	{"type.float64", 0},
+	{"type.*float64", 0},
+	{"type.complex64", 0},
+	{"type.*complex64", 0},
+	{"type.complex128", 0},
+	{"type.*complex128", 0},
+	{"type.unsafe.Pointer", 0},
+	{"type.*unsafe.Pointer", 0},
+	{"type.uintptr", 0},
+	{"type.*uintptr", 0},
+	{"type.bool", 0},
+	{"type.*bool", 0},
+	{"type.string", 0},
+	{"type.*string", 0},
+	{"type.error", 0},
+	{"type.*error", 0},
+	{"type.func(error) string", 0},
+	{"type.*func(error) string", 0},
 }
diff --git a/src/cmd/internal/goobj2/mkbuiltin.go b/src/cmd/internal/goobj2/mkbuiltin.go
index d773e53..4838fa2 100644
--- a/src/cmd/internal/goobj2/mkbuiltin.go
+++ b/src/cmd/internal/goobj2/mkbuiltin.go
@@ -21,6 +21,7 @@
 	"log"
 	"os"
 	"path/filepath"
+	"strings"
 )
 
 var stdout = flag.Bool("stdout", false, "write to stdout instead of builtinlist.go")
@@ -98,9 +99,15 @@
 
 	// The list above only contains ones that are used by the frontend.
 	// The backend may create more references of builtin functions.
+	// We also want to include predefined types.
 	// Add them.
-	for _, b := range extra {
-		name := pkg + "." + b.name
+	extras := append(fextras[:], enumerateBasicTypes()...)
+	for _, b := range extras {
+		prefix := ""
+		if !strings.HasPrefix(b.name, "type.") {
+			prefix = pkg + "."
+		}
+		name := prefix + b.name
 		if decls[name] {
 			log.Fatalf("%q already added -- mkbuiltin.go out of sync?", name)
 		}
@@ -109,10 +116,31 @@
 	fmt.Fprintln(w, "}")
 }
 
-var extra = [...]struct {
+// addBasicTypes returns the symbol names for basic types that are
+// defined in the runtime and referenced in other packages.
+// Needs to be kept in sync with reflect.go:dumpbasictypes() and
+// reflect.go:dtypesym() in the compiler.
+func enumerateBasicTypes() []extra {
+	names := [...]string{
+		"int8", "uint8", "int16", "uint16",
+		"int32", "uint32", "int64", "uint64",
+		"float32", "float64", "complex64", "complex128",
+		"unsafe.Pointer", "uintptr", "bool", "string", "error",
+		"func(error) string"}
+	result := []extra{}
+	for _, n := range names {
+		result = append(result, extra{"type." + n, 0})
+		result = append(result, extra{"type.*" + n, 0})
+	}
+	return result
+}
+
+type extra struct {
 	name string
 	abi  int
-}{
+}
+
+var fextras = [...]extra{
 	// compiler frontend inserted calls (sysfunc)
 	{"deferproc", 1},
 	{"deferprocStack", 1},
diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go
index 7cebe23..8bc5fe2 100644
--- a/src/cmd/link/internal/loader/loader.go
+++ b/src/cmd/link/internal/loader/loader.go
@@ -1980,6 +1980,7 @@
 	}
 	l.growAttrBitmaps(len(l.objSyms) + int(end-start))
 	needNameExpansion := r.NeedNameExpansion()
+	loadingRuntimePkg := r.unit.Lib.Pkg == "runtime"
 	for i := start; i < end; i++ {
 		osym := r.Sym(i)
 		name := osym.Name(r.Reader)
@@ -2005,7 +2006,8 @@
 		if strings.HasPrefix(name, "go.itablink.") {
 			l.itablink[gi] = struct{}{}
 		}
-		if strings.HasPrefix(name, "runtime.") {
+		if strings.HasPrefix(name, "runtime.") ||
+			(loadingRuntimePkg && strings.HasPrefix(name, "type.")) {
 			if bi := goobj2.BuiltinIdx(name, v); bi != -1 {
 				// This is a definition of a builtin symbol. Record where it is.
 				l.builtinSyms[bi] = gi