]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: do not emit a few more basic types from every compilation
authorRuss Cox <rsc@golang.org>
Sat, 12 Nov 2022 17:27:33 +0000 (12:27 -0500)
committerGopher Robot <gobot@golang.org>
Wed, 16 Nov 2022 02:02:26 +0000 (02:02 +0000)
We already emit types for any and func(error) string in runtime.a
but unlike the other pre-emitted types, we don't then exclude them
from being emitted in other packages. Fix that.

Also add slices of non-func types that we already emit.

Saves 0.3% of .a files in std cmd deps, computed by adding sizes from:

ls -l $(go list -export -f '{{.Export}}' -deps std cmd

The effect is small and not worth doing on its own.
The real improvement is making “what to write always in runtime”
and “what not to write in other packages” more obviously aligned.

Change-Id: Ie5cb5fd7e5a3025d2776d9b4cece775fdf92d3b6
Reviewed-on: https://go-review.googlesource.com/c/go/+/450135
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Russ Cox <rsc@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Keith Randall <khr@google.com>
src/cmd/compile/internal/reflectdata/reflect.go
src/cmd/link/internal/ld/dwarf.go

index f4996668b6c8533408997d8bd3da2dea818948ae..9dcc0a0e046a6558cd9a154d28a180adbbf55c37 100644 (file)
@@ -1395,6 +1395,35 @@ func WriteImportStrings() {
        }
 }
 
+// writtenByWriteBasicTypes reports whether typ is written by WriteBasicTypes.
+// WriteBasicTypes always writes pointer types; any pointer has been stripped off typ already.
+func writtenByWriteBasicTypes(typ *types.Type) bool {
+       if typ.Sym() == nil && typ.Kind() == types.TFUNC {
+               f := typ.FuncType()
+               // func(error) string
+               if f.Receiver.NumFields() == 0 && f.TParams.NumFields() == 0 &&
+                       f.Params.NumFields() == 1 && f.Results.NumFields() == 1 &&
+                       f.Params.FieldType(0) == types.ErrorType &&
+                       f.Results.FieldType(0) == types.Types[types.TSTRING] {
+                       return true
+               }
+       }
+
+       // Now we have left the basic types plus any and error, plus slices of them.
+       // Strip the slice.
+       if typ.Sym() == nil && typ.IsSlice() {
+               typ = typ.Elem()
+       }
+
+       // Basic types.
+       sym := typ.Sym()
+       if sym != nil && (sym.Pkg == types.BuiltinPkg || sym.Pkg == types.UnsafePkg) {
+               return true
+       }
+       // any or error
+       return (sym == nil && typ.IsEmptyInterface()) || typ == types.ErrorType
+}
+
 func WriteBasicTypes() {
        // do basic types if compiling package runtime.
        // they have to be in at least one package,
@@ -1402,23 +1431,30 @@ func WriteBasicTypes() {
        // so this is as good as any.
        // another possible choice would be package main,
        // but using runtime means fewer copies in object files.
+       // The code here needs to be in sync with writtenByWriteBasicTypes above.
        if base.Ctxt.Pkgpath == "runtime" {
+               // Note: always write NewPtr(t) because NeedEmit's caller strips the pointer.
+               var list []*types.Type
                for i := types.Kind(1); i <= types.TBOOL; i++ {
-                       writeType(types.NewPtr(types.Types[i]))
+                       list = append(list, types.Types[i])
+               }
+               list = append(list,
+                       types.Types[types.TSTRING],
+                       types.Types[types.TUNSAFEPTR],
+                       types.AnyType,
+                       types.ErrorType)
+               for _, t := range list {
+                       writeType(types.NewPtr(t))
+                       writeType(types.NewPtr(types.NewSlice(t)))
                }
-               writeType(types.NewPtr(types.Types[types.TSTRING]))
-               writeType(types.NewPtr(types.Types[types.TUNSAFEPTR]))
-               writeType(types.AnyType)
-
-               // emit type structs for error and func(error) string.
-               // The latter is the type of an auto-generated wrapper.
-               writeType(types.NewPtr(types.ErrorType))
 
-               writeType(types.NewSignature(types.NoPkg, nil, nil, []*types.Field{
+               // emit type for func(error) string,
+               // which is the type of an auto-generated wrapper.
+               writeType(types.NewPtr(types.NewSignature(types.NoPkg, nil, nil, []*types.Field{
                        types.NewField(base.Pos, nil, types.ErrorType),
                }, []*types.Field{
                        types.NewField(base.Pos, nil, types.Types[types.TSTRING]),
-               }))
+               })))
 
                // add paths for runtime and main, which 6l imports implicitly.
                dimportpath(ir.Pkgs.Runtime)
@@ -1759,6 +1795,9 @@ func NeedEmit(typ *types.Type) bool {
        // instantiated generic functions too.
 
        switch sym := typ.Sym(); {
+       case writtenByWriteBasicTypes(typ):
+               return base.Ctxt.Pkgpath == "runtime"
+
        case sym == nil:
                // Anonymous type; possibly never seen before or ever again.
                // Need to emit to be safe (however, see TODO above).
@@ -1768,11 +1807,6 @@ func NeedEmit(typ *types.Type) bool {
                // Local defined type; our responsibility.
                return true
 
-       case base.Ctxt.Pkgpath == "runtime" && (sym.Pkg == types.BuiltinPkg || sym.Pkg == types.UnsafePkg):
-               // Package runtime is responsible for including code for builtin
-               // types (predeclared and package unsafe).
-               return true
-
        case typ.IsFullyInstantiated():
                // Instantiated type; possibly instantiated with unique type arguments.
                // Need to emit to be safe (however, see TODO above).
index 75fabb4bd8c5101bdd626d0bdfca24488e914a08..feea8640d6bc8f196d96026eefa33ec01b98e693 100644 (file)
@@ -539,6 +539,9 @@ func (d *dwctxt) newtype(gotype loader.Sym) *dwarf.DWDie {
        sn := d.ldr.SymName(gotype)
        name := sn[5:] // could also decode from Type.string
        tdata := d.ldr.Data(gotype)
+       if len(tdata) == 0 {
+               d.linkctxt.Errorf(gotype, "missing type")
+       }
        kind := decodetypeKind(d.arch, tdata)
        bytesize := decodetypeSize(d.arch, tdata)