]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile: move Type, Sym printing to package types [generated]
authorRuss Cox <rsc@golang.org>
Sun, 6 Dec 2020 18:54:50 +0000 (13:54 -0500)
committerRuss Cox <rsc@golang.org>
Mon, 7 Dec 2020 20:41:11 +0000 (20:41 +0000)
Move the printing of types.Type and types.Sym out of ir
into package types, where it properly belongs. This wasn't
done originally (when the code was in gc) because the Type
and Sym printing was a bit tangled up with the Node printing.
But now they are untangled and can move into the correct
package.

This CL is automatically generated.
A followup CL will clean up a little bit more by hand.

Passes buildall w/ toolstash -cmp.

[git-generate]
cd src/cmd/compile/internal/ir
rf '
mv FmtMode fmtMode
mv FErr fmtGo
mv FDbg fmtDebug
mv FTypeId fmtTypeID
mv FTypeIdName fmtTypeIDName
mv methodSymName SymMethodName

mv BuiltinPkg LocalPkg BlankSym OrigSym NumImport \
fmtMode fmtGo symFormat sconv sconv2 symfmt SymMethodName \
BasicTypeNames fmtBufferPool InstallTypeFormats typeFormat tconv tconv2 fldconv FmtConst \
typefmt.go

mv typefmt.go cmd/compile/internal/types
'
cd ../types
mv typefmt.go fmt.go

Change-Id: I6f3fd818323733ab8446f00594937c1628760b27
Reviewed-on: https://go-review.googlesource.com/c/go/+/275779
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
27 files changed:
src/cmd/compile/internal/gc/align.go
src/cmd/compile/internal/gc/bimport.go
src/cmd/compile/internal/gc/const.go
src/cmd/compile/internal/gc/dcl.go
src/cmd/compile/internal/gc/embed.go
src/cmd/compile/internal/gc/export.go
src/cmd/compile/internal/gc/gen.go
src/cmd/compile/internal/gc/go.go
src/cmd/compile/internal/gc/iexport.go
src/cmd/compile/internal/gc/iimport.go
src/cmd/compile/internal/gc/init.go
src/cmd/compile/internal/gc/inl.go
src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/gc/noder.go
src/cmd/compile/internal/gc/obj.go
src/cmd/compile/internal/gc/reflect.go
src/cmd/compile/internal/gc/sinit.go
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/gc/subr.go
src/cmd/compile/internal/gc/typecheck.go
src/cmd/compile/internal/gc/universe.go
src/cmd/compile/internal/gc/walk.go
src/cmd/compile/internal/ir/fmt.go
src/cmd/compile/internal/ir/ir.go
src/cmd/compile/internal/ir/node.go
src/cmd/compile/internal/ssa/export_test.go
src/cmd/compile/internal/types/fmt.go [new file with mode: 0644]

index af426f5b245deb2d68d5674ce0bad02a8026671b..212e4c46aea802581cece43377451a861158864e 100644 (file)
@@ -193,7 +193,7 @@ func findTypeLoop(t *types.Type, path *[]*types.Type) bool {
                // Type imported from package, so it can't be part of
                // a type loop (otherwise that package should have
                // failed to compile).
-               if t.Sym().Pkg != ir.LocalPkg {
+               if t.Sym().Pkg != types.LocalPkg {
                        return false
                }
 
index c0c18e728e6311c6525ffbbff15ddf0582c7c326..5a7018d8e618711a9e05021582c1a58a2d1eaf3d 100644 (file)
@@ -6,6 +6,7 @@ package gc
 
 import (
        "cmd/compile/internal/ir"
+       "cmd/compile/internal/types"
        "cmd/internal/src"
 )
 
@@ -15,5 +16,5 @@ func npos(pos src.XPos, n ir.Node) ir.Node {
 }
 
 func builtinCall(op ir.Op) ir.Node {
-       return ir.Nod(ir.OCALL, mkname(ir.BuiltinPkg.Lookup(ir.OpNames[op])), nil)
+       return ir.Nod(ir.OCALL, mkname(types.BuiltinPkg.Lookup(ir.OpNames[op])), nil)
 }
index 304c9aa2c3174324631ec6f331104cae3aa49a5b..80799580c6d1f6ba8f2d50f84d1d91ba1a3370e6 100644 (file)
@@ -384,7 +384,7 @@ func overflow(v constant.Value, t *types.Type) bool {
                return true
        }
        if doesoverflow(v, t) {
-               base.Errorf("constant %v overflows %v", ir.FmtConst(v, false), t)
+               base.Errorf("constant %v overflows %v", types.FmtConst(v, false), t)
                return true
        }
        return false
index a77c1aed455546f60a11798942a9882ff660c199..1c23c5a92f635efa0523728b7a5347784adbcb55 100644 (file)
@@ -66,7 +66,7 @@ func declare(n *ir.Name, ctxt ir.Class) {
        s := n.Sym()
 
        // kludgy: typecheckok means we're past parsing. Eg genwrapper may declare out of package names later.
-       if !inimport && !typecheckok && s.Pkg != ir.LocalPkg {
+       if !inimport && !typecheckok && s.Pkg != types.LocalPkg {
                base.ErrorfAt(n.Pos(), "cannot declare name %v", s)
        }
 
@@ -253,7 +253,7 @@ func oldname(s *types.Sym) ir.Node {
 // but it reports an error if sym is from another package and not exported.
 func importName(sym *types.Sym) ir.Node {
        n := oldname(sym)
-       if !types.IsExported(sym.Name) && sym.Pkg != ir.LocalPkg {
+       if !types.IsExported(sym.Name) && sym.Pkg != types.LocalPkg {
                n.SetDiag(true)
                base.Errorf("cannot refer to unexported name %s.%s", sym.Pkg.Name, sym.Name)
        }
@@ -512,7 +512,7 @@ func tostruct(l []*ir.Field) *types.Type {
        checkdupfields("field", fields)
 
        base.Pos = lno
-       return types.NewStruct(ir.LocalPkg, fields)
+       return types.NewStruct(types.LocalPkg, fields)
 }
 
 func tointerface(nmethods []*ir.Field) *types.Type {
@@ -533,7 +533,7 @@ func tointerface(nmethods []*ir.Field) *types.Type {
        }
 
        base.Pos = lno
-       return types.NewInterface(ir.LocalPkg, methods)
+       return types.NewInterface(types.LocalPkg, methods)
 }
 
 func fakeRecv() *ir.Field {
@@ -585,14 +585,14 @@ func functype(nrecv *ir.Field, nparams, nresults []*ir.Field) *types.Type {
                recv = funarg(nrecv)
        }
 
-       t := types.NewSignature(ir.LocalPkg, recv, funargs(nparams), funargs(nresults))
+       t := types.NewSignature(types.LocalPkg, recv, funargs(nparams), funargs(nresults))
        checkdupfields("argument", t.Recvs().FieldSlice(), t.Params().FieldSlice(), t.Results().FieldSlice())
        return t
 }
 
 func hasNamedResults(fn *ir.Func) bool {
        typ := fn.Type()
-       return typ.NumResults() > 0 && ir.OrigSym(typ.Results().Field(0).Sym) != nil
+       return typ.NumResults() > 0 && types.OrigSym(typ.Results().Field(0).Sym) != nil
 }
 
 // methodSym returns the method symbol representing a method name
@@ -703,7 +703,7 @@ func addmethod(n *ir.Func, msym *types.Sym, t *types.Type, local, nointerface bo
                return nil
        }
 
-       if local && mt.Sym().Pkg != ir.LocalPkg {
+       if local && mt.Sym().Pkg != types.LocalPkg {
                base.Errorf("cannot define new methods on non-local type %v", mt)
                return nil
        }
index d6e42e4f03edf3153610d8b544d785ed66b05043..7664bde1c5878f4ef02290409527e9f4721a8c70 100644 (file)
@@ -131,18 +131,18 @@ func varEmbed(p *noder, names []ir.Node, typ ir.Ntype, exprs []ir.Node, embeds [
 // can't tell whether "string" and "byte" really mean "string" and "byte".
 // The result must be confirmed later, after type checking, using embedKind.
 func embedKindApprox(typ ir.Node) int {
-       if typ.Sym() != nil && typ.Sym().Name == "FS" && (typ.Sym().Pkg.Path == "embed" || (typ.Sym().Pkg == ir.LocalPkg && base.Ctxt.Pkgpath == "embed")) {
+       if typ.Sym() != nil && typ.Sym().Name == "FS" && (typ.Sym().Pkg.Path == "embed" || (typ.Sym().Pkg == types.LocalPkg && base.Ctxt.Pkgpath == "embed")) {
                return embedFiles
        }
        // These are not guaranteed to match only string and []byte -
        // maybe the local package has redefined one of those words.
        // But it's the best we can do now during the noder.
        // The stricter check happens later, in initEmbed calling embedKind.
-       if typ.Sym() != nil && typ.Sym().Name == "string" && typ.Sym().Pkg == ir.LocalPkg {
+       if typ.Sym() != nil && typ.Sym().Name == "string" && typ.Sym().Pkg == types.LocalPkg {
                return embedString
        }
        if typ, ok := typ.(*ir.SliceType); ok {
-               if sym := typ.Elem.Sym(); sym != nil && sym.Name == "byte" && sym.Pkg == ir.LocalPkg {
+               if sym := typ.Elem.Sym(); sym != nil && sym.Name == "byte" && sym.Pkg == types.LocalPkg {
                        return embedBytes
                }
        }
@@ -151,7 +151,7 @@ func embedKindApprox(typ ir.Node) int {
 
 // embedKind determines the kind of embedding variable.
 func embedKind(typ *types.Type) int {
-       if typ.Sym() != nil && typ.Sym().Name == "FS" && (typ.Sym().Pkg.Path == "embed" || (typ.Sym().Pkg == ir.LocalPkg && base.Ctxt.Pkgpath == "embed")) {
+       if typ.Sym() != nil && typ.Sym().Name == "FS" && (typ.Sym().Pkg.Path == "embed" || (typ.Sym().Pkg == types.LocalPkg && base.Ctxt.Pkgpath == "embed")) {
                return embedFiles
        }
        if typ == types.Types[types.TSTRING] {
index b632a15865d0a82442989295b1409f7fb67462b7..593dd3b2f83c7e17669deec2c9cb3bf0fa25de5d 100644 (file)
@@ -42,7 +42,7 @@ func initname(s string) bool {
 }
 
 func autoexport(n *ir.Name, ctxt ir.Class) {
-       if n.Sym().Pkg != ir.LocalPkg {
+       if n.Sym().Pkg != types.LocalPkg {
                return
        }
        if (ctxt != ir.PEXTERN && ctxt != ir.PFUNC) || dclcontext != ir.PEXTERN {
@@ -202,7 +202,7 @@ func dumpasmhdr() {
        if err != nil {
                base.Fatalf("%v", err)
        }
-       fmt.Fprintf(b, "// generated by compile -asmhdr from package %s\n\n", ir.LocalPkg.Name)
+       fmt.Fprintf(b, "// generated by compile -asmhdr from package %s\n\n", types.LocalPkg.Name)
        for _, n := range asmlist {
                if n.Sym().IsBlank() {
                        continue
index 0d3f9392fbc0e02d590504179592cc94f9dd202a..39e94259786bdc0c252f9c74ecc6d8ef55bb0471 100644 (file)
@@ -66,7 +66,7 @@ func tempAt(pos src.XPos, curfn *ir.Func, t *types.Type) *ir.Name {
 
        s := &types.Sym{
                Name: autotmpname(len(curfn.Dcl)),
-               Pkg:  ir.LocalPkg,
+               Pkg:  types.LocalPkg,
        }
        n := ir.NewNameAt(pos, s)
        s.Def = n
index c4b9c185dcb377c22c682780c0156cd3954c21f5..041073f1173a932b1a14fa684681052cd064433c 100644 (file)
@@ -37,7 +37,7 @@ var (
 
 // isRuntimePkg reports whether p is package runtime.
 func isRuntimePkg(p *types.Pkg) bool {
-       if base.Flag.CompilingRuntime && p == ir.LocalPkg {
+       if base.Flag.CompilingRuntime && p == types.LocalPkg {
                return true
        }
        return p.Path == "runtime"
@@ -45,7 +45,7 @@ func isRuntimePkg(p *types.Pkg) bool {
 
 // isReflectPkg reports whether p is package reflect.
 func isReflectPkg(p *types.Pkg) bool {
-       if p == ir.LocalPkg {
+       if p == types.LocalPkg {
                return base.Ctxt.Pkgpath == "reflect"
        }
        return p.Path == "reflect"
index 003cf3b446d185f509ea4663478c600c9be40c3b..b1cc9a3dd97e81b448cf81cc402733ea78954dc8 100644 (file)
@@ -322,7 +322,7 @@ func (w *exportWriter) writeIndex(index map[*types.Sym]uint64, mainIndex bool) {
        // we reference, even if we're not exporting (or reexporting)
        // any symbols from it.
        if mainIndex {
-               pkgSyms[ir.LocalPkg] = nil
+               pkgSyms[types.LocalPkg] = nil
                for pkg := range w.p.allPkgs {
                        pkgSyms[pkg] = nil
                }
@@ -402,7 +402,7 @@ func (p *iexporter) pushDecl(n *ir.Name) {
        }
 
        // Don't export predeclared declarations.
-       if n.Sym().Pkg == ir.BuiltinPkg || n.Sym().Pkg == unsafepkg {
+       if n.Sym().Pkg == types.BuiltinPkg || n.Sym().Pkg == unsafepkg {
                return
        }
 
@@ -596,7 +596,7 @@ func (w *exportWriter) selector(s *types.Sym) {
        } else {
                pkg := w.currPkg
                if types.IsExported(name) {
-                       pkg = ir.LocalPkg
+                       pkg = types.LocalPkg
                }
                if s.Pkg != pkg {
                        base.Fatalf("package mismatch in selector: %v in package %q, but want %q", s, s.Pkg.Path, pkg.Path)
@@ -637,7 +637,7 @@ func (w *exportWriter) startType(k itag) {
 
 func (w *exportWriter) doTyp(t *types.Type) {
        if t.Sym() != nil {
-               if t.Sym().Pkg == ir.BuiltinPkg || t.Sym().Pkg == unsafepkg {
+               if t.Sym().Pkg == types.BuiltinPkg || t.Sym().Pkg == unsafepkg {
                        base.Fatalf("builtin type missing from typIndex: %v", t)
                }
 
@@ -748,7 +748,7 @@ func (w *exportWriter) paramList(fs []*types.Field) {
 
 func (w *exportWriter) param(f *types.Field) {
        w.pos(f.Pos)
-       w.localIdent(ir.OrigSym(f.Sym), 0)
+       w.localIdent(types.OrigSym(f.Sym), 0)
        w.typ(f.Type)
 }
 
index 1d9baed5ad81267b156d77757fb5562e6a0a92db..859263c83f33786c4015cb0700fa413d56f8efe0 100644 (file)
@@ -148,7 +148,7 @@ func iimport(pkg *types.Pkg, in *bio.Reader) (fingerprint goobj.FingerprintType)
                if pkg.Name == "" {
                        pkg.Name = pkgName
                        pkg.Height = pkgHeight
-                       ir.NumImport[pkgName]++
+                       types.NumImport[pkgName]++
 
                        // TODO(mdempsky): This belongs somewhere else.
                        pkg.Lookup("_").Def = ir.BlankNode
@@ -437,7 +437,7 @@ func (r *importReader) ident() *types.Sym {
        }
        pkg := r.currPkg
        if types.IsExported(name) {
-               pkg = ir.LocalPkg
+               pkg = types.LocalPkg
        }
        return pkg.Lookup(name)
 }
index dc825b24218a3d25ba41649ebb90811f567e8034..e0907f952cdf20632ccf9d40eb3c00660792fba2 100644 (file)
@@ -96,7 +96,7 @@ func fninit(n []ir.Node) {
                fns = append(fns, s.Linksym())
        }
 
-       if len(deps) == 0 && len(fns) == 0 && ir.LocalPkg.Name != "main" && ir.LocalPkg.Name != "runtime" {
+       if len(deps) == 0 && len(fns) == 0 && types.LocalPkg.Name != "main" && types.LocalPkg.Name != "runtime" {
                return // nothing to initialize
        }
 
index 840285242404c5f2b20be11d3e4f75d5353d1dc8..77fbf7c80270078f9e74ee51fc2b4443a7931fa3 100644 (file)
@@ -85,7 +85,7 @@ func typecheckinl(fn *ir.Func) {
        // the ->inl of a local function has been typechecked before caninl copied it.
        pkg := fnpkg(fn.Nname)
 
-       if pkg == ir.LocalPkg || pkg == nil {
+       if pkg == types.LocalPkg || pkg == nil {
                return // typecheckinl on local function
        }
 
index a40671bccf818e82d30ec90df1f541864caa8857..15659dc7fd2f8ad8ce564375a54541c81e406b7a 100644 (file)
@@ -77,17 +77,17 @@ func Main(archInit func(*Arch)) {
        // See bugs 31188 and 21945 (CLs 170638, 98075, 72371).
        base.Ctxt.UseBASEntries = base.Ctxt.Headtype != objabi.Hdarwin
 
-       ir.LocalPkg = types.NewPkg("", "")
-       ir.LocalPkg.Prefix = "\"\""
+       types.LocalPkg = types.NewPkg("", "")
+       types.LocalPkg.Prefix = "\"\""
 
        // We won't know localpkg's height until after import
        // processing. In the mean time, set to MaxPkgHeight to ensure
        // height comparisons at least work until then.
-       ir.LocalPkg.Height = types.MaxPkgHeight
+       types.LocalPkg.Height = types.MaxPkgHeight
 
        // pseudo-package, for scoping
-       ir.BuiltinPkg = types.NewPkg("go.builtin", "") // TODO(gri) name this package go.builtin?
-       ir.BuiltinPkg.Prefix = "go.builtin"            // not go%2ebuiltin
+       types.BuiltinPkg = types.NewPkg("go.builtin", "") // TODO(gri) name this package go.builtin?
+       types.BuiltinPkg.Prefix = "go.builtin"            // not go%2ebuiltin
 
        // pseudo-package, accessed by import "unsafe"
        unsafepkg = types.NewPkg("unsafe", "unsafe")
@@ -212,7 +212,7 @@ func Main(archInit func(*Arch)) {
        // would lead to import cycles)
        types.Widthptr = Widthptr
        types.Dowidth = dowidth
-       ir.InstallTypeFormats()
+       types.InstallTypeFormats()
        types.TypeLinkSym = func(t *types.Type) *obj.LSym {
                return typenamesym(t).Linksym()
        }
@@ -922,14 +922,14 @@ func pkgnotused(lineno src.XPos, path string, name string) {
 }
 
 func mkpackage(pkgname string) {
-       if ir.LocalPkg.Name == "" {
+       if types.LocalPkg.Name == "" {
                if pkgname == "_" {
                        base.Errorf("invalid package name _")
                }
-               ir.LocalPkg.Name = pkgname
+               types.LocalPkg.Name = pkgname
        } else {
-               if pkgname != ir.LocalPkg.Name {
-                       base.Errorf("package %s; expected %s", pkgname, ir.LocalPkg.Name)
+               if pkgname != types.LocalPkg.Name {
+                       base.Errorf("package %s; expected %s", pkgname, types.LocalPkg.Name)
                }
        }
 }
@@ -942,7 +942,7 @@ func clearImports() {
        }
        var unused []importedPkg
 
-       for _, s := range ir.LocalPkg.Syms {
+       for _, s := range types.LocalPkg.Syms {
                n := ir.AsNode(s.Def)
                if n == nil {
                        continue
@@ -1046,7 +1046,7 @@ func recordPackageName() {
        // together two package main archives. So allow dups.
        s.Set(obj.AttrDuplicateOK, true)
        base.Ctxt.Data = append(base.Ctxt.Data, s)
-       s.P = []byte(ir.LocalPkg.Name)
+       s.P = []byte(types.LocalPkg.Name)
 }
 
 // currentLang returns the current language version.
@@ -1073,9 +1073,9 @@ var langWant lang
 func langSupported(major, minor int, pkg *types.Pkg) bool {
        if pkg == nil {
                // TODO(mdempsky): Set Pkg for local types earlier.
-               pkg = ir.LocalPkg
+               pkg = types.LocalPkg
        }
-       if pkg != ir.LocalPkg {
+       if pkg != types.LocalPkg {
                // Assume imported packages passed type-checking.
                return true
        }
index 1cd83756773b7192ac6d65c50edb6f6411aaab7d..f39bf2ff3c4764d87445b1b485625d895648af37 100644 (file)
@@ -79,7 +79,7 @@ func parseFiles(filenames []string) uint {
                p.processPragmas()
        }
 
-       ir.LocalPkg.Height = myheight
+       types.LocalPkg.Height = myheight
 
        return lines
 }
@@ -501,7 +501,7 @@ func (p *noder) typeDecl(decl *syntax.TypeDecl) ir.Node {
        }
 
        nod := p.nod(decl, ir.ODCLTYPE, n, nil)
-       if n.Alias() && !langSupported(1, 9, ir.LocalPkg) {
+       if n.Alias() && !langSupported(1, 9, types.LocalPkg) {
                base.ErrorfAt(nod.Pos(), "type aliases only supported as of -lang=go1.9")
        }
        return nod
@@ -532,7 +532,7 @@ func (p *noder) funcDecl(fun *syntax.FuncDecl) ir.Node {
                        }
                }
 
-               if ir.LocalPkg.Name == "main" && name.Name == "main" {
+               if types.LocalPkg.Name == "main" && name.Name == "main" {
                        if t.List().Len() > 0 || t.Rlist().Len() > 0 {
                                base.ErrorfAt(f.Pos(), "func main must have no arguments and no return values")
                        }
@@ -931,7 +931,7 @@ func (p *noder) packname(expr syntax.Expr) *types.Sym {
                var pkg *types.Pkg
                if def.Op() != ir.OPACK {
                        base.Errorf("%v is not a package", name)
-                       pkg = ir.LocalPkg
+                       pkg = types.LocalPkg
                } else {
                        def := def.(*ir.PkgName)
                        def.Used = true
@@ -1387,7 +1387,7 @@ func (p *noder) binOp(op syntax.Operator) ir.Op {
 // literal is not compatible with the current language version.
 func checkLangCompat(lit *syntax.BasicLit) {
        s := lit.Value
-       if len(s) <= 2 || langSupported(1, 13, ir.LocalPkg) {
+       if len(s) <= 2 || langSupported(1, 13, types.LocalPkg) {
                return
        }
        // len(s) > 2
index b1701b30a12868fed233dd7c7fda4da43818e027..c34a86d4ebe9f13cc4551b975a138992f9c62dc9 100644 (file)
@@ -84,7 +84,7 @@ func printObjHeader(bout *bio.Writer) {
        if base.Flag.BuildID != "" {
                fmt.Fprintf(bout, "build id %q\n", base.Flag.BuildID)
        }
-       if ir.LocalPkg.Name == "main" {
+       if types.LocalPkg.Name == "main" {
                fmt.Fprintf(bout, "main\n")
        }
        fmt.Fprintf(bout, "\n") // header ends with blank line
@@ -200,7 +200,7 @@ func dumpLinkerObj(bout *bio.Writer) {
 }
 
 func addptabs() {
-       if !base.Ctxt.Flag_dynlink || ir.LocalPkg.Name != "main" {
+       if !base.Ctxt.Flag_dynlink || types.LocalPkg.Name != "main" {
                return
        }
        for _, exportn := range exportlist {
@@ -235,7 +235,7 @@ func dumpGlobal(n ir.Node) {
        if n.Class() == ir.PFUNC {
                return
        }
-       if n.Sym().Pkg != ir.LocalPkg {
+       if n.Sym().Pkg != types.LocalPkg {
                return
        }
        dowidth(n.Type())
@@ -248,7 +248,7 @@ func dumpGlobalConst(n ir.Node) {
        if t == nil {
                return
        }
-       if n.Sym().Pkg != ir.LocalPkg {
+       if n.Sym().Pkg != types.LocalPkg {
                return
        }
        // only export integer constants for now
@@ -478,7 +478,7 @@ var slicedataGen int
 func slicedata(pos src.XPos, s string) ir.Node {
        slicedataGen++
        symname := fmt.Sprintf(".gobytes.%d", slicedataGen)
-       sym := ir.LocalPkg.Lookup(symname)
+       sym := types.LocalPkg.Lookup(symname)
        symnode := NewName(sym)
        sym.Def = symnode
 
index 42139b71359807fcf4d5ca38aba3a9c8be20f579..9b8f26a84ba5523b193bb8f1987b5351941d4a34 100644 (file)
@@ -301,7 +301,7 @@ func deferstruct(stksize int64) *types.Type {
                // Unlike the global makefield function, this one needs to set Pkg
                // because these types might be compared (in SSA CSE sorting).
                // TODO: unify this makefield and the global one above.
-               sym := &types.Sym{Name: name, Pkg: ir.LocalPkg}
+               sym := &types.Sym{Name: name, Pkg: types.LocalPkg}
                return types.NewField(src.NoXPos, sym, typ)
        }
        argtype := types.NewArray(types.Types[types.TUINT8], stksize)
@@ -491,7 +491,7 @@ func dimportpath(p *types.Pkg) {
        }
 
        str := p.Path
-       if p == ir.LocalPkg {
+       if p == types.LocalPkg {
                // Note: myimportpath != "", or else dgopkgpath won't call dimportpath.
                str = base.Ctxt.Pkgpath
        }
@@ -508,7 +508,7 @@ func dgopkgpath(s *obj.LSym, ot int, pkg *types.Pkg) int {
                return duintptr(s, ot, 0)
        }
 
-       if pkg == ir.LocalPkg && base.Ctxt.Pkgpath == "" {
+       if pkg == types.LocalPkg && base.Ctxt.Pkgpath == "" {
                // If we don't know the full import path of the package being compiled
                // (i.e. -p was not passed on the compiler command line), emit a reference to
                // type..importpath.""., which the linker will rewrite using the correct import path.
@@ -527,7 +527,7 @@ func dgopkgpathOff(s *obj.LSym, ot int, pkg *types.Pkg) int {
        if pkg == nil {
                return duint32(s, ot, 0)
        }
-       if pkg == ir.LocalPkg && base.Ctxt.Pkgpath == "" {
+       if pkg == types.LocalPkg && base.Ctxt.Pkgpath == "" {
                // If we don't know the full import path of the package being compiled
                // (i.e. -p was not passed on the compiler command line), emit a reference to
                // type..importpath.""., which the linker will rewrite using the correct import path.
@@ -1158,7 +1158,7 @@ func dtypesym(t *types.Type) *obj.LSym {
 
        if base.Ctxt.Pkgpath != "runtime" || (tbase != types.Types[tbase.Kind()] && tbase != types.ByteType && tbase != types.RuneType && tbase != types.ErrorType) { // int, float, etc
                // named types from other files are defined only by those files
-               if tbase.Sym() != nil && tbase.Sym().Pkg != ir.LocalPkg {
+               if tbase.Sym() != nil && tbase.Sym().Pkg != types.LocalPkg {
                        if i, ok := typeSymIdx[tbase]; ok {
                                lsym.Pkg = tbase.Sym().Pkg.Prefix
                                if t != tbase {
@@ -1568,7 +1568,7 @@ func dumptabs() {
        }
 
        // process ptabs
-       if ir.LocalPkg.Name == "main" && len(ptabs) > 0 {
+       if types.LocalPkg.Name == "main" && len(ptabs) > 0 {
                ot := 0
                s := base.Ctxt.Lookup("go.plugin.tabs")
                for _, p := range ptabs {
index c446c9d083bcd0cc4e32c6c2481abe4f4c8ec4fb..3c5f11c5abf1b2210aa0121743da23eceb442f2e 100644 (file)
@@ -79,7 +79,7 @@ func (s *InitSchedule) staticcopy(l ir.Node, r ir.Node) bool {
                pfuncsym(l, r)
                return true
        }
-       if r.Class() != ir.PEXTERN || r.Sym().Pkg != ir.LocalPkg {
+       if r.Class() != ir.PEXTERN || r.Sym().Pkg != types.LocalPkg {
                return false
        }
        if r.Name().Defn == nil { // probably zeroed but perhaps supplied externally and of unknown value
index 89918e21333cb323a67b234ae0eeae8b90031e99..add50c35d7495c92b12ce5e3076b4b930c419f85 100644 (file)
@@ -4127,7 +4127,7 @@ func findIntrinsic(sym *types.Sym) intrinsicBuilder {
                return nil
        }
        pkg := sym.Pkg.Path
-       if sym.Pkg == ir.LocalPkg {
+       if sym.Pkg == types.LocalPkg {
                pkg = base.Ctxt.Pkgpath
        }
        if base.Flag.Race && pkg == "sync/atomic" {
@@ -7073,7 +7073,7 @@ func (e *ssafn) SplitSlot(parent *ssa.LocalSlot, suffix string, offset int64, t
                return ssa.LocalSlot{N: node, Type: t, Off: parent.Off + offset}
        }
 
-       s := &types.Sym{Name: node.Sym().Name + suffix, Pkg: ir.LocalPkg}
+       s := &types.Sym{Name: node.Sym().Name + suffix, Pkg: types.LocalPkg}
        n := ir.NewNameAt(parent.N.Pos(), s)
        s.Def = n
        ir.AsNode(s.Def).Name().SetUsed(true)
index 65eb61e6800f5b6d316b54ee9e775bd3e1200adf..dffebc58f2d1765dd2fe5b4e4aac75c7b217b5b1 100644 (file)
@@ -69,7 +69,7 @@ func setlineno(n ir.Node) src.XPos {
 }
 
 func lookup(name string) *types.Sym {
-       return ir.LocalPkg.Lookup(name)
+       return types.LocalPkg.Lookup(name)
 }
 
 // lookupN looks up the symbol starting with prefix and ending with
@@ -78,7 +78,7 @@ func lookupN(prefix string, n int) *types.Sym {
        var buf [20]byte // plenty long enough for all current users
        copy(buf[:], prefix)
        b := strconv.AppendInt(buf[:len(prefix)], int64(n), 10)
-       return ir.LocalPkg.LookupBytes(b)
+       return types.LocalPkg.LookupBytes(b)
 }
 
 // autolabel generates a new Name node for use with
@@ -1109,13 +1109,13 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
 
        // Only generate (*T).M wrappers for T.M in T's own package.
        if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type &&
-               rcvr.Elem().Sym() != nil && rcvr.Elem().Sym().Pkg != ir.LocalPkg {
+               rcvr.Elem().Sym() != nil && rcvr.Elem().Sym().Pkg != types.LocalPkg {
                return
        }
 
        // Only generate I.M wrappers for I in I's own package
        // but keep doing it for error.Error (was issue #29304).
-       if rcvr.IsInterface() && rcvr.Sym() != nil && rcvr.Sym().Pkg != ir.LocalPkg && rcvr != types.ErrorType {
+       if rcvr.IsInterface() && rcvr.Sym() != nil && rcvr.Sym().Pkg != types.LocalPkg && rcvr != types.ErrorType {
                return
        }
 
index dc9e23069e6925d4e91744f800ee19cd1585c9d5..85094dbebcad79af0bb48b525a8c298e97682a17 100644 (file)
@@ -90,7 +90,7 @@ func resolve(n ir.Node) (res ir.Node) {
                defer tracePrint("resolve", n)(&res)
        }
 
-       if n.Sym().Pkg != ir.LocalPkg {
+       if n.Sym().Pkg != types.LocalPkg {
                if inimport {
                        base.Fatalf("recursive inimport")
                }
@@ -2386,7 +2386,7 @@ func typecheckMethodExpr(n ir.Node) (res ir.Node) {
        me.(*ir.MethodExpr).Method = m
 
        // Issue 25065. Make sure that we emit the symbol for a local method.
-       if base.Ctxt.Flag_dynlink && !inimport && (t.Sym() == nil || t.Sym().Pkg == ir.LocalPkg) {
+       if base.Ctxt.Flag_dynlink && !inimport && (t.Sym() == nil || t.Sym().Pkg == types.LocalPkg) {
                makefuncsym(me.Sym())
        }
 
@@ -2862,7 +2862,7 @@ func typecheckcomplit(n ir.Node) (res ir.Node) {
 
                                f := t.Field(i)
                                s := f.Sym
-                               if s != nil && !types.IsExported(s.Name) && s.Pkg != ir.LocalPkg {
+                               if s != nil && !types.IsExported(s.Name) && s.Pkg != types.LocalPkg {
                                        base.Errorf("implicit assignment of unexported field '%s' in %v literal", s.Name, t)
                                }
                                // No pushtype allowed here. Must name fields for that.
@@ -2903,7 +2903,7 @@ func typecheckcomplit(n ir.Node) (res ir.Node) {
                                        // package, because of import dot. Redirect to correct sym
                                        // before we do the lookup.
                                        s := key.Sym()
-                                       if s.Pkg != ir.LocalPkg && types.IsExported(s.Name) {
+                                       if s.Pkg != types.LocalPkg && types.IsExported(s.Name) {
                                                s1 := lookup(s.Name)
                                                if s1.Origpkg == s.Pkg {
                                                        s = s1
@@ -3034,7 +3034,7 @@ func typecheckarraylit(elemType *types.Type, bound int64, elts []ir.Node, ctx st
 
 // visible reports whether sym is exported or locally defined.
 func visible(sym *types.Sym) bool {
-       return sym != nil && (types.IsExported(sym.Name) || sym.Pkg == ir.LocalPkg)
+       return sym != nil && (types.IsExported(sym.Name) || sym.Pkg == types.LocalPkg)
 }
 
 // nonexported reports whether sym is an unexported field.
@@ -3929,7 +3929,7 @@ func curpkg() *types.Pkg {
        fn := Curfn
        if fn == nil {
                // Initialization expressions for package-scope variables.
-               return ir.LocalPkg
+               return types.LocalPkg
        }
        return fnpkg(fn.Nname)
 }
index cd68719a9978aa513848382017bff32a06b0972a..42b996d88d918afb9dedcbca28375a406ddc21d0 100644 (file)
@@ -104,7 +104,7 @@ func initUniverse() {
        }
 
        types.Types[types.TANY] = types.New(types.TANY)
-       types.Types[types.TINTER] = types.NewInterface(ir.LocalPkg, nil)
+       types.Types[types.TINTER] = types.NewInterface(types.LocalPkg, nil)
 
        defBasic := func(kind types.Kind, pkg *types.Pkg, name string) *types.Type {
                sym := pkg.Lookup(name)
@@ -120,7 +120,7 @@ func initUniverse() {
        }
 
        for _, s := range &basicTypes {
-               types.Types[s.etype] = defBasic(s.etype, ir.BuiltinPkg, s.name)
+               types.Types[s.etype] = defBasic(s.etype, types.BuiltinPkg, s.name)
        }
 
        for _, s := range &typedefs {
@@ -130,7 +130,7 @@ func initUniverse() {
                }
                simtype[s.etype] = sameas
 
-               types.Types[s.etype] = defBasic(s.etype, ir.BuiltinPkg, s.name)
+               types.Types[s.etype] = defBasic(s.etype, types.BuiltinPkg, s.name)
        }
 
        // We create separate byte and rune types for better error messages
@@ -140,11 +140,11 @@ func initUniverse() {
        // of less informative error messages involving bytes and runes)?
        // (Alternatively, we could introduce an OTALIAS node representing
        // type aliases, albeit at the cost of having to deal with it everywhere).
-       types.ByteType = defBasic(types.TUINT8, ir.BuiltinPkg, "byte")
-       types.RuneType = defBasic(types.TINT32, ir.BuiltinPkg, "rune")
+       types.ByteType = defBasic(types.TUINT8, types.BuiltinPkg, "byte")
+       types.RuneType = defBasic(types.TINT32, types.BuiltinPkg, "rune")
 
        // error type
-       s := ir.BuiltinPkg.Lookup("error")
+       s := types.BuiltinPkg.Lookup("error")
        n := ir.NewDeclNameAt(src.NoXPos, s)
        n.SetOp(ir.OTYPE)
        types.ErrorType = types.NewNamed(n)
@@ -162,7 +162,7 @@ func initUniverse() {
        simtype[types.TUNSAFEPTR] = types.TPTR
 
        for _, s := range &builtinFuncs {
-               s2 := ir.BuiltinPkg.Lookup(s.name)
+               s2 := types.BuiltinPkg.Lookup(s.name)
                s2.Def = NewName(s2)
                ir.AsNode(s2.Def).SetSubOp(s.op)
        }
@@ -173,16 +173,16 @@ func initUniverse() {
                ir.AsNode(s2.Def).SetSubOp(s.op)
        }
 
-       s = ir.BuiltinPkg.Lookup("true")
+       s = types.BuiltinPkg.Lookup("true")
        s.Def = nodbool(true)
        ir.AsNode(s.Def).SetSym(lookup("true"))
 
-       s = ir.BuiltinPkg.Lookup("false")
+       s = types.BuiltinPkg.Lookup("false")
        s.Def = nodbool(false)
        ir.AsNode(s.Def).SetSym(lookup("false"))
 
        s = lookup("_")
-       ir.BlankSym = s
+       types.BlankSym = s
        s.Block = -100
        s.Def = NewName(s)
        types.Types[types.TBLANK] = types.New(types.TBLANK)
@@ -190,18 +190,18 @@ func initUniverse() {
        ir.BlankNode = ir.AsNode(s.Def)
        ir.BlankNode.SetTypecheck(1)
 
-       s = ir.BuiltinPkg.Lookup("_")
+       s = types.BuiltinPkg.Lookup("_")
        s.Block = -100
        s.Def = NewName(s)
        types.Types[types.TBLANK] = types.New(types.TBLANK)
        ir.AsNode(s.Def).SetType(types.Types[types.TBLANK])
 
        types.Types[types.TNIL] = types.New(types.TNIL)
-       s = ir.BuiltinPkg.Lookup("nil")
+       s = types.BuiltinPkg.Lookup("nil")
        s.Def = nodnil()
        ir.AsNode(s.Def).SetSym(s)
 
-       s = ir.BuiltinPkg.Lookup("iota")
+       s = types.BuiltinPkg.Lookup("iota")
        s.Def = ir.Nod(ir.OIOTA, nil, nil)
        ir.AsNode(s.Def).SetSym(s)
 
@@ -339,7 +339,7 @@ func finishUniverse() {
        // that we silently skip symbols that are already declared in the
        // package block rather than emitting a redeclared symbol error.
 
-       for _, s := range ir.BuiltinPkg.Syms {
+       for _, s := range types.BuiltinPkg.Syms {
                if s.Def == nil {
                        continue
                }
index 574c7c470933ae6b46b37383038d72595d83d9a5..346817e589fe58cb5f1ef646300dee98630a0e11 100644 (file)
@@ -983,7 +983,7 @@ opswitch:
                if param == types.Txxx {
                        break
                }
-               fn := ir.BasicTypeNames[param] + "to" + ir.BasicTypeNames[result]
+               fn := types.BasicTypeNames[param] + "to" + types.BasicTypeNames[result]
                n = conv(mkcall(fn, types.Types[result], init, conv(n.Left(), types.Types[param])), n.Type())
 
        case ir.ODIV, ir.OMOD:
index 117c7417d2c8e6e31d7cfd47d6b830b03a200113..79d85d1803871f48698ac229df2087212b075d76 100644 (file)
@@ -10,9 +10,7 @@ import (
        "go/constant"
        "io"
        "os"
-       "strconv"
-       "strings"
-       "sync"
+
        "unicode/utf8"
 
        "cmd/compile/internal/base"
@@ -20,74 +18,6 @@ import (
        "cmd/internal/src"
 )
 
-// Format conversions:
-// TODO(gri) verify these; eliminate those not used anymore
-//
-//     %v Op           Node opcodes
-//             Flags:  #: print Go syntax (automatic unless mode == FDbg)
-//
-//     %j *Node        Node details
-//             Flags:  0: suppresses things not relevant until walk
-//
-//     %v *Val         Constant values
-//
-//     %v *types.Sym           Symbols
-//     %S              unqualified identifier in any mode
-//             Flags:  +,- #: mode (see below)
-//                     0: in export mode: unqualified identifier if exported, qualified if not
-//
-//     %v *types.Type  Types
-//     %S              omit "func" and receiver in function types
-//     %L              definition instead of name.
-//             Flags:  +,- #: mode (see below)
-//                     ' ' (only in -/Sym mode) print type identifiers wit package name instead of prefix.
-//
-//     %v *Node        Nodes
-//     %S              (only in +/debug mode) suppress recursion
-//     %L              (only in Error mode) print "foo (type Bar)"
-//             Flags:  +,- #: mode (see below)
-//
-//     %v Nodes        Node lists
-//             Flags:  those of *Node
-//                     .: separate items with ',' instead of ';'
-
-// *types.Sym, *types.Type, and *Node types use the flags below to set the format mode
-
-// The mode flags '+', '-', and '#' are sticky; they persist through
-// recursions of *Node, *types.Type, and *types.Sym values. The ' ' flag is
-// sticky only on *types.Type recursions and only used in %-/*types.Sym mode.
-//
-// Example: given a *types.Sym: %+v %#v %-v print an identifier properly qualified for debug/export/internal mode
-
-// Useful format combinations:
-// TODO(gri): verify these
-//
-// *Node, Nodes:
-//   %+v    multiline recursive debug dump of *Node/Nodes
-//   %+S    non-recursive debug dump
-//
-// *Node:
-//   %#v    Go format
-//   %L     "foo (type Bar)" for error messages
-//
-// *types.Type:
-//   %#v    Go format
-//   %#L    type definition instead of name
-//   %#S    omit "func" and receiver in function signature
-//
-//   %-v    type identifiers
-//   %-S    type identifiers without "func" and arg names in type signatures (methodsym)
-//   %- v   type identifiers with package name instead of prefix (typesym, dcommontype, typehash)
-
-type FmtMode int
-
-const (
-       FErr FmtMode = iota
-       FDbg
-       FTypeId
-       FTypeIdName // same as FTypeId, but use package name instead of prefix
-)
-
 // Op
 
 var OpNames = []string{
@@ -177,584 +107,6 @@ func (o Op) Format(s fmt.State, verb rune) {
        }
 }
 
-// Val
-
-func FmtConst(v constant.Value, sharp bool) string {
-       if !sharp && v.Kind() == constant.Complex {
-               real, imag := constant.Real(v), constant.Imag(v)
-
-               var re string
-               sre := constant.Sign(real)
-               if sre != 0 {
-                       re = real.String()
-               }
-
-               var im string
-               sim := constant.Sign(imag)
-               if sim != 0 {
-                       im = imag.String()
-               }
-
-               switch {
-               case sre == 0 && sim == 0:
-                       return "0"
-               case sre == 0:
-                       return im + "i"
-               case sim == 0:
-                       return re
-               case sim < 0:
-                       return fmt.Sprintf("(%s%si)", re, im)
-               default:
-                       return fmt.Sprintf("(%s+%si)", re, im)
-               }
-       }
-
-       return v.String()
-}
-
-// Sym
-
-// numImport tracks how often a package with a given name is imported.
-// It is used to provide a better error message (by using the package
-// path to disambiguate) if a package that appears multiple times with
-// the same name appears in an error message.
-var NumImport = make(map[string]int)
-
-// "%S" suppresses qualifying with package
-func symFormat(s *types.Sym, f fmt.State, verb rune) {
-       mode := FErr
-       switch verb {
-       case 'v', 'S':
-               if verb == 'v' && f.Flag('+') {
-                       mode = FDbg
-               }
-               fmt.Fprint(f, sconv(s, verb, mode))
-
-       default:
-               fmt.Fprintf(f, "%%!%c(*types.Sym=%p)", verb, s)
-       }
-}
-
-// See #16897 for details about performance implications
-// before changing the implementation of sconv.
-func sconv(s *types.Sym, verb rune, mode FmtMode) string {
-       if verb == 'L' {
-               panic("linksymfmt")
-       }
-
-       if s == nil {
-               return "<S>"
-       }
-
-       if s.Name == "_" {
-               return "_"
-       }
-       buf := fmtBufferPool.Get().(*bytes.Buffer)
-       buf.Reset()
-       defer fmtBufferPool.Put(buf)
-
-       symfmt(buf, s, verb, mode)
-       return types.InternString(buf.Bytes())
-}
-
-func sconv2(b *bytes.Buffer, s *types.Sym, verb rune, mode FmtMode) {
-       if verb == 'L' {
-               panic("linksymfmt")
-       }
-       if s == nil {
-               b.WriteString("<S>")
-               return
-       }
-       if s.Name == "_" {
-               b.WriteString("_")
-               return
-       }
-
-       symfmt(b, s, verb, mode)
-}
-
-func symfmt(b *bytes.Buffer, s *types.Sym, verb rune, mode FmtMode) {
-       if verb != 'S' {
-               switch mode {
-               case FErr: // This is for the user
-                       if s.Pkg == BuiltinPkg || s.Pkg == LocalPkg {
-                               b.WriteString(s.Name)
-                               return
-                       }
-
-                       // If the name was used by multiple packages, display the full path,
-                       if s.Pkg.Name != "" && NumImport[s.Pkg.Name] > 1 {
-                               fmt.Fprintf(b, "%q.%s", s.Pkg.Path, s.Name)
-                               return
-                       }
-                       b.WriteString(s.Pkg.Name)
-                       b.WriteByte('.')
-                       b.WriteString(s.Name)
-                       return
-
-               case FDbg:
-                       b.WriteString(s.Pkg.Name)
-                       b.WriteByte('.')
-                       b.WriteString(s.Name)
-                       return
-
-               case FTypeIdName:
-                       // dcommontype, typehash
-                       b.WriteString(s.Pkg.Name)
-                       b.WriteByte('.')
-                       b.WriteString(s.Name)
-                       return
-
-               case FTypeId:
-                       // (methodsym), typesym, weaksym
-                       b.WriteString(s.Pkg.Prefix)
-                       b.WriteByte('.')
-                       b.WriteString(s.Name)
-                       return
-               }
-       }
-
-       b.WriteString(s.Name)
-}
-
-func methodSymName(s *types.Sym) string {
-       // Skip leading "type." in method name
-       name := s.Name
-       if i := strings.LastIndex(name, "."); i >= 0 {
-               name = name[i+1:]
-       }
-       return name
-}
-
-// Type
-
-var BasicTypeNames = []string{
-       types.TINT:        "int",
-       types.TUINT:       "uint",
-       types.TINT8:       "int8",
-       types.TUINT8:      "uint8",
-       types.TINT16:      "int16",
-       types.TUINT16:     "uint16",
-       types.TINT32:      "int32",
-       types.TUINT32:     "uint32",
-       types.TINT64:      "int64",
-       types.TUINT64:     "uint64",
-       types.TUINTPTR:    "uintptr",
-       types.TFLOAT32:    "float32",
-       types.TFLOAT64:    "float64",
-       types.TCOMPLEX64:  "complex64",
-       types.TCOMPLEX128: "complex128",
-       types.TBOOL:       "bool",
-       types.TANY:        "any",
-       types.TSTRING:     "string",
-       types.TNIL:        "nil",
-       types.TIDEAL:      "untyped number",
-       types.TBLANK:      "blank",
-}
-
-var fmtBufferPool = sync.Pool{
-       New: func() interface{} {
-               return new(bytes.Buffer)
-       },
-}
-
-func InstallTypeFormats() {
-       types.SymString = func(s *types.Sym) string {
-               return sconv(s, 0, FErr)
-       }
-       types.TypeString = func(t *types.Type) string {
-               return tconv(t, 0, FErr)
-       }
-       types.TypeShortString = func(t *types.Type) string {
-               return tconv(t, 0, FTypeId)
-       }
-       types.TypeLongString = func(t *types.Type) string {
-               return tconv(t, 0, FTypeIdName)
-       }
-       types.FormatSym = symFormat
-       types.FormatType = typeFormat
-}
-
-// "%L"  print definition, not name
-// "%S"  omit 'func' and receiver from function types, short type names
-func typeFormat(t *types.Type, s fmt.State, verb rune) {
-       mode := FErr
-       switch verb {
-       case 'v', 'S', 'L':
-               if verb == 'v' && s.Flag('+') { // %+v is debug format
-                       mode = FDbg
-               }
-               if verb == 'S' && s.Flag('-') { // %-S is special case for receiver - short typeid format
-                       mode = FTypeId
-               }
-               fmt.Fprint(s, tconv(t, verb, mode))
-       default:
-               fmt.Fprintf(s, "%%!%c(*Type=%p)", verb, t)
-       }
-}
-
-func tconv(t *types.Type, verb rune, mode FmtMode) string {
-       buf := fmtBufferPool.Get().(*bytes.Buffer)
-       buf.Reset()
-       defer fmtBufferPool.Put(buf)
-
-       tconv2(buf, t, verb, mode, nil)
-       return types.InternString(buf.Bytes())
-}
-
-// tconv2 writes a string representation of t to b.
-// flag and mode control exactly what is printed.
-// Any types x that are already in the visited map get printed as @%d where %d=visited[x].
-// See #16897 before changing the implementation of tconv.
-func tconv2(b *bytes.Buffer, t *types.Type, verb rune, mode FmtMode, visited map[*types.Type]int) {
-       if off, ok := visited[t]; ok {
-               // We've seen this type before, so we're trying to print it recursively.
-               // Print a reference to it instead.
-               fmt.Fprintf(b, "@%d", off)
-               return
-       }
-       if t == nil {
-               b.WriteString("<T>")
-               return
-       }
-       if t.Kind() == types.TSSA {
-               b.WriteString(t.Extra.(string))
-               return
-       }
-       if t.Kind() == types.TTUPLE {
-               b.WriteString(t.FieldType(0).String())
-               b.WriteByte(',')
-               b.WriteString(t.FieldType(1).String())
-               return
-       }
-
-       if t.Kind() == types.TRESULTS {
-               tys := t.Extra.(*types.Results).Types
-               for i, et := range tys {
-                       if i > 0 {
-                               b.WriteByte(',')
-                       }
-                       b.WriteString(et.String())
-               }
-               return
-       }
-
-       if t == types.ByteType || t == types.RuneType {
-               // in %-T mode collapse rune and byte with their originals.
-               switch mode {
-               case FTypeIdName, FTypeId:
-                       t = types.Types[t.Kind()]
-               default:
-                       sconv2(b, t.Sym(), 'S', mode)
-                       return
-               }
-       }
-       if t == types.ErrorType {
-               b.WriteString("error")
-               return
-       }
-
-       // Unless the 'L' flag was specified, if the type has a name, just print that name.
-       if verb != 'L' && t.Sym() != nil && t != types.Types[t.Kind()] {
-               switch mode {
-               case FTypeId, FTypeIdName:
-                       if verb == 'S' {
-                               if t.Vargen != 0 {
-                                       sconv2(b, t.Sym(), 'S', mode)
-                                       fmt.Fprintf(b, "·%d", t.Vargen)
-                                       return
-                               }
-                               sconv2(b, t.Sym(), 'S', mode)
-                               return
-                       }
-
-                       if mode == FTypeIdName {
-                               sconv2(b, t.Sym(), 'v', FTypeIdName)
-                               return
-                       }
-
-                       if t.Sym().Pkg == LocalPkg && t.Vargen != 0 {
-                               sconv2(b, t.Sym(), 'v', mode)
-                               fmt.Fprintf(b, "·%d", t.Vargen)
-                               return
-                       }
-               }
-
-               sconv2(b, t.Sym(), 'v', mode)
-               return
-       }
-
-       if int(t.Kind()) < len(BasicTypeNames) && BasicTypeNames[t.Kind()] != "" {
-               var name string
-               switch t {
-               case types.UntypedBool:
-                       name = "untyped bool"
-               case types.UntypedString:
-                       name = "untyped string"
-               case types.UntypedInt:
-                       name = "untyped int"
-               case types.UntypedRune:
-                       name = "untyped rune"
-               case types.UntypedFloat:
-                       name = "untyped float"
-               case types.UntypedComplex:
-                       name = "untyped complex"
-               default:
-                       name = BasicTypeNames[t.Kind()]
-               }
-               b.WriteString(name)
-               return
-       }
-
-       if mode == FDbg {
-               b.WriteString(t.Kind().String())
-               b.WriteByte('-')
-               tconv2(b, t, 'v', FErr, visited)
-               return
-       }
-
-       // At this point, we might call tconv2 recursively. Add the current type to the visited list so we don't
-       // try to print it recursively.
-       // We record the offset in the result buffer where the type's text starts. This offset serves as a reference
-       // point for any later references to the same type.
-       // Note that we remove the type from the visited map as soon as the recursive call is done.
-       // This prevents encoding types like map[*int]*int as map[*int]@4. (That encoding would work,
-       // but I'd like to use the @ notation only when strictly necessary.)
-       if visited == nil {
-               visited = map[*types.Type]int{}
-       }
-       visited[t] = b.Len()
-       defer delete(visited, t)
-
-       switch t.Kind() {
-       case types.TPTR:
-               b.WriteByte('*')
-               switch mode {
-               case FTypeId, FTypeIdName:
-                       if verb == 'S' {
-                               tconv2(b, t.Elem(), 'S', mode, visited)
-                               return
-                       }
-               }
-               tconv2(b, t.Elem(), 'v', mode, visited)
-
-       case types.TARRAY:
-               b.WriteByte('[')
-               b.WriteString(strconv.FormatInt(t.NumElem(), 10))
-               b.WriteByte(']')
-               tconv2(b, t.Elem(), 0, mode, visited)
-
-       case types.TSLICE:
-               b.WriteString("[]")
-               tconv2(b, t.Elem(), 0, mode, visited)
-
-       case types.TCHAN:
-               switch t.ChanDir() {
-               case types.Crecv:
-                       b.WriteString("<-chan ")
-                       tconv2(b, t.Elem(), 0, mode, visited)
-               case types.Csend:
-                       b.WriteString("chan<- ")
-                       tconv2(b, t.Elem(), 0, mode, visited)
-               default:
-                       b.WriteString("chan ")
-                       if t.Elem() != nil && t.Elem().IsChan() && t.Elem().Sym() == nil && t.Elem().ChanDir() == types.Crecv {
-                               b.WriteByte('(')
-                               tconv2(b, t.Elem(), 0, mode, visited)
-                               b.WriteByte(')')
-                       } else {
-                               tconv2(b, t.Elem(), 0, mode, visited)
-                       }
-               }
-
-       case types.TMAP:
-               b.WriteString("map[")
-               tconv2(b, t.Key(), 0, mode, visited)
-               b.WriteByte(']')
-               tconv2(b, t.Elem(), 0, mode, visited)
-
-       case types.TINTER:
-               if t.IsEmptyInterface() {
-                       b.WriteString("interface {}")
-                       break
-               }
-               b.WriteString("interface {")
-               for i, f := range t.Fields().Slice() {
-                       if i != 0 {
-                               b.WriteByte(';')
-                       }
-                       b.WriteByte(' ')
-                       switch {
-                       case f.Sym == nil:
-                               // Check first that a symbol is defined for this type.
-                               // Wrong interface definitions may have types lacking a symbol.
-                               break
-                       case types.IsExported(f.Sym.Name):
-                               sconv2(b, f.Sym, 'S', mode)
-                       default:
-                               if mode != FTypeIdName {
-                                       mode = FTypeId
-                               }
-                               sconv2(b, f.Sym, 'v', mode)
-                       }
-                       tconv2(b, f.Type, 'S', mode, visited)
-               }
-               if t.NumFields() != 0 {
-                       b.WriteByte(' ')
-               }
-               b.WriteByte('}')
-
-       case types.TFUNC:
-               if verb == 'S' {
-                       // no leading func
-               } else {
-                       if t.Recv() != nil {
-                               b.WriteString("method")
-                               tconv2(b, t.Recvs(), 0, mode, visited)
-                               b.WriteByte(' ')
-                       }
-                       b.WriteString("func")
-               }
-               tconv2(b, t.Params(), 0, mode, visited)
-
-               switch t.NumResults() {
-               case 0:
-                       // nothing to do
-
-               case 1:
-                       b.WriteByte(' ')
-                       tconv2(b, t.Results().Field(0).Type, 0, mode, visited) // struct->field->field's type
-
-               default:
-                       b.WriteByte(' ')
-                       tconv2(b, t.Results(), 0, mode, visited)
-               }
-
-       case types.TSTRUCT:
-               if m := t.StructType().Map; m != nil {
-                       mt := m.MapType()
-                       // Format the bucket struct for map[x]y as map.bucket[x]y.
-                       // This avoids a recursive print that generates very long names.
-                       switch t {
-                       case mt.Bucket:
-                               b.WriteString("map.bucket[")
-                       case mt.Hmap:
-                               b.WriteString("map.hdr[")
-                       case mt.Hiter:
-                               b.WriteString("map.iter[")
-                       default:
-                               base.Fatalf("unknown internal map type")
-                       }
-                       tconv2(b, m.Key(), 0, mode, visited)
-                       b.WriteByte(']')
-                       tconv2(b, m.Elem(), 0, mode, visited)
-                       break
-               }
-
-               if funarg := t.StructType().Funarg; funarg != types.FunargNone {
-                       b.WriteByte('(')
-                       fieldVerb := 'v'
-                       switch mode {
-                       case FTypeId, FTypeIdName, FErr:
-                               // no argument names on function signature, and no "noescape"/"nosplit" tags
-                               fieldVerb = 'S'
-                       }
-                       for i, f := range t.Fields().Slice() {
-                               if i != 0 {
-                                       b.WriteString(", ")
-                               }
-                               fldconv(b, f, fieldVerb, mode, visited, funarg)
-                       }
-                       b.WriteByte(')')
-               } else {
-                       b.WriteString("struct {")
-                       for i, f := range t.Fields().Slice() {
-                               if i != 0 {
-                                       b.WriteByte(';')
-                               }
-                               b.WriteByte(' ')
-                               fldconv(b, f, 'L', mode, visited, funarg)
-                       }
-                       if t.NumFields() != 0 {
-                               b.WriteByte(' ')
-                       }
-                       b.WriteByte('}')
-               }
-
-       case types.TFORW:
-               b.WriteString("undefined")
-               if t.Sym() != nil {
-                       b.WriteByte(' ')
-                       sconv2(b, t.Sym(), 'v', mode)
-               }
-
-       case types.TUNSAFEPTR:
-               b.WriteString("unsafe.Pointer")
-
-       case types.Txxx:
-               b.WriteString("Txxx")
-
-       default:
-               // Don't know how to handle - fall back to detailed prints
-               b.WriteString(t.Kind().String())
-               b.WriteString(" <")
-               sconv2(b, t.Sym(), 'v', mode)
-               b.WriteString(">")
-
-       }
-}
-
-func fldconv(b *bytes.Buffer, f *types.Field, verb rune, mode FmtMode, visited map[*types.Type]int, funarg types.Funarg) {
-       if f == nil {
-               b.WriteString("<T>")
-               return
-       }
-
-       var name string
-       if verb != 'S' {
-               s := f.Sym
-
-               // Take the name from the original.
-               if mode == FErr {
-                       s = OrigSym(s)
-               }
-
-               if s != nil && f.Embedded == 0 {
-                       if funarg != types.FunargNone {
-                               name = fmt.Sprint(f.Nname)
-                       } else if verb == 'L' {
-                               name = methodSymName(s)
-                               if !types.IsExported(name) && mode != FTypeIdName {
-                                       name = sconv(s, 0, mode) // qualify non-exported names (used on structs, not on funarg)
-                               }
-                       } else {
-                               name = sconv(s, 0, mode)
-                       }
-               }
-       }
-
-       if name != "" {
-               b.WriteString(name)
-               b.WriteString(" ")
-       }
-
-       if f.IsDDD() {
-               var et *types.Type
-               if f.Type != nil {
-                       et = f.Type.Elem()
-               }
-               b.WriteString("...")
-               tconv2(b, et, 0, mode, visited)
-       } else {
-               tconv2(b, f.Type, 0, mode, visited)
-       }
-
-       if verb != 'S' && funarg == types.FunargNone && f.Note != "" {
-               b.WriteString(" ")
-               b.WriteString(strconv.Quote(f.Note))
-       }
-}
-
 // Node
 
 func FmtNode(n Node, s fmt.State, verb rune) {
@@ -1198,7 +550,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
                                fmt.Fprintf(s, "'\\U%08x'", uint64(x))
                        }
                } else {
-                       fmt.Fprint(s, FmtConst(n.Val(), s.Flag('#')))
+                       fmt.Fprint(s, types.FmtConst(n.Val(), s.Flag('#')))
                }
 
                if needUnparen {
@@ -1338,7 +690,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
                        fmt.Fprint(s, ".<nil>")
                        return
                }
-               fmt.Fprintf(s, ".%s", methodSymName(n.Sym()))
+               fmt.Fprintf(s, ".%s", types.SymMethodName(n.Sym()))
 
        case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
                exprFmt(n.Left(), s, nprec)
@@ -1346,7 +698,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
                        fmt.Fprint(s, ".<nil>")
                        return
                }
-               fmt.Fprintf(s, ".%s", methodSymName(n.Sym()))
+               fmt.Fprintf(s, ".%s", types.SymMethodName(n.Sym()))
 
        case ODOTTYPE, ODOTTYPE2:
                exprFmt(n.Left(), s, nprec)
index ad7f692b077824a5e797457ee993d32c8231880a..82224ca2ed8350660cb412acb7e483e27e073ff3 100644 (file)
@@ -3,10 +3,3 @@
 // license that can be found in the LICENSE file.
 
 package ir
-
-import "cmd/compile/internal/types"
-
-var LocalPkg *types.Pkg // package being compiled
-
-// builtinpkg is a fake package that declares the universe block.
-var BuiltinPkg *types.Pkg
index 56b320e7264827938afc770058fc23adaf39bdf6..ba7eaae1b901255ef7d255224a6f33700d66fa0e 100644 (file)
@@ -10,7 +10,6 @@ import (
        "fmt"
        "go/constant"
        "sort"
-       "strings"
 
        "cmd/compile/internal/base"
        "cmd/compile/internal/types"
@@ -654,33 +653,6 @@ func AsNode(n types.Object) Node {
 
 var BlankNode Node
 
-var BlankSym *types.Sym
-
-// origSym returns the original symbol written by the user.
-func OrigSym(s *types.Sym) *types.Sym {
-       if s == nil {
-               return nil
-       }
-
-       if len(s.Name) > 1 && s.Name[0] == '~' {
-               switch s.Name[1] {
-               case 'r': // originally an unnamed result
-                       return nil
-               case 'b': // originally the blank identifier _
-                       // TODO(mdempsky): Does s.Pkg matter here?
-                       return BlankSym
-               }
-               return s
-       }
-
-       if strings.HasPrefix(s.Name, ".anon") {
-               // originally an unnamed or _ name (see subr.go: structargs)
-               return nil
-       }
-
-       return s
-}
-
 func IsConst(n Node, ct constant.Kind) bool {
        return ConstType(n) == ct
 }
index cb3b9c0e2a0eabaf76510192a53aedd2c7e7e434..decb843465e54f35e286eae0fff5e96ceb0cede3 100644 (file)
@@ -137,7 +137,7 @@ func init() {
        // Initialize just enough of the universe and the types package to make our tests function.
        // TODO(josharian): move universe initialization to the types package,
        // so this test setup can share it.
-       ir.InstallTypeFormats()
+       types.InstallTypeFormats()
        types.Dowidth = func(t *types.Type) {}
 
        for _, typ := range [...]struct {
diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go
new file mode 100644 (file)
index 0000000..4f36e4c
--- /dev/null
@@ -0,0 +1,694 @@
+// Copyright 2009 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 types
+
+import (
+       "bytes"
+       "fmt"
+       "go/constant"
+       "strconv"
+       "strings"
+       "sync"
+
+       "cmd/compile/internal/base"
+)
+
+// builtinpkg is a fake package that declares the universe block.
+var BuiltinPkg *Pkg
+
+var LocalPkg *Pkg // package being compiled
+
+var BlankSym *Sym
+
+// origSym returns the original symbol written by the user.
+func OrigSym(s *Sym) *Sym {
+       if s == nil {
+               return nil
+       }
+
+       if len(s.Name) > 1 && s.Name[0] == '~' {
+               switch s.Name[1] {
+               case 'r': // originally an unnamed result
+                       return nil
+               case 'b': // originally the blank identifier _
+                       // TODO(mdempsky): Does s.Pkg matter here?
+                       return BlankSym
+               }
+               return s
+       }
+
+       if strings.HasPrefix(s.Name, ".anon") {
+               // originally an unnamed or _ name (see subr.go: structargs)
+               return nil
+       }
+
+       return s
+}
+
+// Sym
+
+// numImport tracks how often a package with a given name is imported.
+// It is used to provide a better error message (by using the package
+// path to disambiguate) if a package that appears multiple times with
+// the same name appears in an error message.
+var NumImport = make(map[string]int)
+
+// Format conversions:
+// TODO(gri) verify these; eliminate those not used anymore
+//
+//     %v Op           Node opcodes
+//             Flags:  #: print Go syntax (automatic unless mode == FDbg)
+//
+//     %j *Node        Node details
+//             Flags:  0: suppresses things not relevant until walk
+//
+//     %v *Val         Constant values
+//
+//     %v *types.Sym           Symbols
+//     %S              unqualified identifier in any mode
+//             Flags:  +,- #: mode (see below)
+//                     0: in export mode: unqualified identifier if exported, qualified if not
+//
+//     %v *types.Type  Types
+//     %S              omit "func" and receiver in function types
+//     %L              definition instead of name.
+//             Flags:  +,- #: mode (see below)
+//                     ' ' (only in -/Sym mode) print type identifiers wit package name instead of prefix.
+//
+//     %v *Node        Nodes
+//     %S              (only in +/debug mode) suppress recursion
+//     %L              (only in Error mode) print "foo (type Bar)"
+//             Flags:  +,- #: mode (see below)
+//
+//     %v Nodes        Node lists
+//             Flags:  those of *Node
+//                     .: separate items with ',' instead of ';'
+
+// *types.Sym, *types.Type, and *Node types use the flags below to set the format mode
+
+// The mode flags '+', '-', and '#' are sticky; they persist through
+// recursions of *Node, *types.Type, and *types.Sym values. The ' ' flag is
+// sticky only on *types.Type recursions and only used in %-/*types.Sym mode.
+//
+// Example: given a *types.Sym: %+v %#v %-v print an identifier properly qualified for debug/export/internal mode
+
+// Useful format combinations:
+// TODO(gri): verify these
+//
+// *Node, Nodes:
+//   %+v    multiline recursive debug dump of *Node/Nodes
+//   %+S    non-recursive debug dump
+//
+// *Node:
+//   %#v    Go format
+//   %L     "foo (type Bar)" for error messages
+//
+// *types.Type:
+//   %#v    Go format
+//   %#L    type definition instead of name
+//   %#S    omit "func" and receiver in function signature
+//
+//   %-v    type identifiers
+//   %-S    type identifiers without "func" and arg names in type signatures (methodsym)
+//   %- v   type identifiers with package name instead of prefix (typesym, dcommontype, typehash)
+
+type fmtMode int
+
+const (
+       fmtGo fmtMode = iota
+       fmtDebug
+       fmtTypeID
+       fmtTypeIDName // same as FTypeId, but use package name instead of prefix
+)
+
+// "%S" suppresses qualifying with package
+func symFormat(s *Sym, f fmt.State, verb rune) {
+       mode := fmtGo
+       switch verb {
+       case 'v', 'S':
+               if verb == 'v' && f.Flag('+') {
+                       mode = fmtDebug
+               }
+               fmt.Fprint(f, sconv(s, verb, mode))
+
+       default:
+               fmt.Fprintf(f, "%%!%c(*types.Sym=%p)", verb, s)
+       }
+}
+
+// See #16897 for details about performance implications
+// before changing the implementation of sconv.
+func sconv(s *Sym, verb rune, mode fmtMode) string {
+       if verb == 'L' {
+               panic("linksymfmt")
+       }
+
+       if s == nil {
+               return "<S>"
+       }
+
+       if s.Name == "_" {
+               return "_"
+       }
+       buf := fmtBufferPool.Get().(*bytes.Buffer)
+       buf.Reset()
+       defer fmtBufferPool.Put(buf)
+
+       symfmt(buf, s, verb, mode)
+       return InternString(buf.Bytes())
+}
+
+func sconv2(b *bytes.Buffer, s *Sym, verb rune, mode fmtMode) {
+       if verb == 'L' {
+               panic("linksymfmt")
+       }
+       if s == nil {
+               b.WriteString("<S>")
+               return
+       }
+       if s.Name == "_" {
+               b.WriteString("_")
+               return
+       }
+
+       symfmt(b, s, verb, mode)
+}
+
+func symfmt(b *bytes.Buffer, s *Sym, verb rune, mode fmtMode) {
+       if verb != 'S' {
+               switch mode {
+               case fmtGo: // This is for the user
+                       if s.Pkg == BuiltinPkg || s.Pkg == LocalPkg {
+                               b.WriteString(s.Name)
+                               return
+                       }
+
+                       // If the name was used by multiple packages, display the full path,
+                       if s.Pkg.Name != "" && NumImport[s.Pkg.Name] > 1 {
+                               fmt.Fprintf(b, "%q.%s", s.Pkg.Path, s.Name)
+                               return
+                       }
+                       b.WriteString(s.Pkg.Name)
+                       b.WriteByte('.')
+                       b.WriteString(s.Name)
+                       return
+
+               case fmtDebug:
+                       b.WriteString(s.Pkg.Name)
+                       b.WriteByte('.')
+                       b.WriteString(s.Name)
+                       return
+
+               case fmtTypeIDName:
+                       // dcommontype, typehash
+                       b.WriteString(s.Pkg.Name)
+                       b.WriteByte('.')
+                       b.WriteString(s.Name)
+                       return
+
+               case fmtTypeID:
+                       // (methodsym), typesym, weaksym
+                       b.WriteString(s.Pkg.Prefix)
+                       b.WriteByte('.')
+                       b.WriteString(s.Name)
+                       return
+               }
+       }
+
+       b.WriteString(s.Name)
+}
+
+func SymMethodName(s *Sym) string {
+       // Skip leading "type." in method name
+       name := s.Name
+       if i := strings.LastIndex(name, "."); i >= 0 {
+               name = name[i+1:]
+       }
+       return name
+}
+
+// Type
+
+var BasicTypeNames = []string{
+       TINT:        "int",
+       TUINT:       "uint",
+       TINT8:       "int8",
+       TUINT8:      "uint8",
+       TINT16:      "int16",
+       TUINT16:     "uint16",
+       TINT32:      "int32",
+       TUINT32:     "uint32",
+       TINT64:      "int64",
+       TUINT64:     "uint64",
+       TUINTPTR:    "uintptr",
+       TFLOAT32:    "float32",
+       TFLOAT64:    "float64",
+       TCOMPLEX64:  "complex64",
+       TCOMPLEX128: "complex128",
+       TBOOL:       "bool",
+       TANY:        "any",
+       TSTRING:     "string",
+       TNIL:        "nil",
+       TIDEAL:      "untyped number",
+       TBLANK:      "blank",
+}
+
+var fmtBufferPool = sync.Pool{
+       New: func() interface{} {
+               return new(bytes.Buffer)
+       },
+}
+
+func InstallTypeFormats() {
+       SymString = func(s *Sym) string {
+               return sconv(s, 0, fmtGo)
+       }
+       TypeString = func(t *Type) string {
+               return tconv(t, 0, fmtGo)
+       }
+       TypeShortString = func(t *Type) string {
+               return tconv(t, 0, fmtTypeID)
+       }
+       TypeLongString = func(t *Type) string {
+               return tconv(t, 0, fmtTypeIDName)
+       }
+       FormatSym = symFormat
+       FormatType = typeFormat
+}
+
+// "%L"  print definition, not name
+// "%S"  omit 'func' and receiver from function types, short type names
+func typeFormat(t *Type, s fmt.State, verb rune) {
+       mode := fmtGo
+       switch verb {
+       case 'v', 'S', 'L':
+               if verb == 'v' && s.Flag('+') { // %+v is debug format
+                       mode = fmtDebug
+               }
+               if verb == 'S' && s.Flag('-') { // %-S is special case for receiver - short typeid format
+                       mode = fmtTypeID
+               }
+               fmt.Fprint(s, tconv(t, verb, mode))
+       default:
+               fmt.Fprintf(s, "%%!%c(*Type=%p)", verb, t)
+       }
+}
+
+func tconv(t *Type, verb rune, mode fmtMode) string {
+       buf := fmtBufferPool.Get().(*bytes.Buffer)
+       buf.Reset()
+       defer fmtBufferPool.Put(buf)
+
+       tconv2(buf, t, verb, mode, nil)
+       return InternString(buf.Bytes())
+}
+
+// tconv2 writes a string representation of t to b.
+// flag and mode control exactly what is printed.
+// Any types x that are already in the visited map get printed as @%d where %d=visited[x].
+// See #16897 before changing the implementation of tconv.
+func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type]int) {
+       if off, ok := visited[t]; ok {
+               // We've seen this type before, so we're trying to print it recursively.
+               // Print a reference to it instead.
+               fmt.Fprintf(b, "@%d", off)
+               return
+       }
+       if t == nil {
+               b.WriteString("<T>")
+               return
+       }
+       if t.Kind() == TSSA {
+               b.WriteString(t.Extra.(string))
+               return
+       }
+       if t.Kind() == TTUPLE {
+               b.WriteString(t.FieldType(0).String())
+               b.WriteByte(',')
+               b.WriteString(t.FieldType(1).String())
+               return
+       }
+
+       if t.Kind() == TRESULTS {
+               tys := t.Extra.(*Results).Types
+               for i, et := range tys {
+                       if i > 0 {
+                               b.WriteByte(',')
+                       }
+                       b.WriteString(et.String())
+               }
+               return
+       }
+
+       if t == ByteType || t == RuneType {
+               // in %-T mode collapse rune and byte with their originals.
+               switch mode {
+               case fmtTypeIDName, fmtTypeID:
+                       t = Types[t.Kind()]
+               default:
+                       sconv2(b, t.Sym(), 'S', mode)
+                       return
+               }
+       }
+       if t == ErrorType {
+               b.WriteString("error")
+               return
+       }
+
+       // Unless the 'L' flag was specified, if the type has a name, just print that name.
+       if verb != 'L' && t.Sym() != nil && t != Types[t.Kind()] {
+               switch mode {
+               case fmtTypeID, fmtTypeIDName:
+                       if verb == 'S' {
+                               if t.Vargen != 0 {
+                                       sconv2(b, t.Sym(), 'S', mode)
+                                       fmt.Fprintf(b, "·%d", t.Vargen)
+                                       return
+                               }
+                               sconv2(b, t.Sym(), 'S', mode)
+                               return
+                       }
+
+                       if mode == fmtTypeIDName {
+                               sconv2(b, t.Sym(), 'v', fmtTypeIDName)
+                               return
+                       }
+
+                       if t.Sym().Pkg == LocalPkg && t.Vargen != 0 {
+                               sconv2(b, t.Sym(), 'v', mode)
+                               fmt.Fprintf(b, "·%d", t.Vargen)
+                               return
+                       }
+               }
+
+               sconv2(b, t.Sym(), 'v', mode)
+               return
+       }
+
+       if int(t.Kind()) < len(BasicTypeNames) && BasicTypeNames[t.Kind()] != "" {
+               var name string
+               switch t {
+               case UntypedBool:
+                       name = "untyped bool"
+               case UntypedString:
+                       name = "untyped string"
+               case UntypedInt:
+                       name = "untyped int"
+               case UntypedRune:
+                       name = "untyped rune"
+               case UntypedFloat:
+                       name = "untyped float"
+               case UntypedComplex:
+                       name = "untyped complex"
+               default:
+                       name = BasicTypeNames[t.Kind()]
+               }
+               b.WriteString(name)
+               return
+       }
+
+       if mode == fmtDebug {
+               b.WriteString(t.Kind().String())
+               b.WriteByte('-')
+               tconv2(b, t, 'v', fmtGo, visited)
+               return
+       }
+
+       // At this point, we might call tconv2 recursively. Add the current type to the visited list so we don't
+       // try to print it recursively.
+       // We record the offset in the result buffer where the type's text starts. This offset serves as a reference
+       // point for any later references to the same type.
+       // Note that we remove the type from the visited map as soon as the recursive call is done.
+       // This prevents encoding types like map[*int]*int as map[*int]@4. (That encoding would work,
+       // but I'd like to use the @ notation only when strictly necessary.)
+       if visited == nil {
+               visited = map[*Type]int{}
+       }
+       visited[t] = b.Len()
+       defer delete(visited, t)
+
+       switch t.Kind() {
+       case TPTR:
+               b.WriteByte('*')
+               switch mode {
+               case fmtTypeID, fmtTypeIDName:
+                       if verb == 'S' {
+                               tconv2(b, t.Elem(), 'S', mode, visited)
+                               return
+                       }
+               }
+               tconv2(b, t.Elem(), 'v', mode, visited)
+
+       case TARRAY:
+               b.WriteByte('[')
+               b.WriteString(strconv.FormatInt(t.NumElem(), 10))
+               b.WriteByte(']')
+               tconv2(b, t.Elem(), 0, mode, visited)
+
+       case TSLICE:
+               b.WriteString("[]")
+               tconv2(b, t.Elem(), 0, mode, visited)
+
+       case TCHAN:
+               switch t.ChanDir() {
+               case Crecv:
+                       b.WriteString("<-chan ")
+                       tconv2(b, t.Elem(), 0, mode, visited)
+               case Csend:
+                       b.WriteString("chan<- ")
+                       tconv2(b, t.Elem(), 0, mode, visited)
+               default:
+                       b.WriteString("chan ")
+                       if t.Elem() != nil && t.Elem().IsChan() && t.Elem().Sym() == nil && t.Elem().ChanDir() == Crecv {
+                               b.WriteByte('(')
+                               tconv2(b, t.Elem(), 0, mode, visited)
+                               b.WriteByte(')')
+                       } else {
+                               tconv2(b, t.Elem(), 0, mode, visited)
+                       }
+               }
+
+       case TMAP:
+               b.WriteString("map[")
+               tconv2(b, t.Key(), 0, mode, visited)
+               b.WriteByte(']')
+               tconv2(b, t.Elem(), 0, mode, visited)
+
+       case TINTER:
+               if t.IsEmptyInterface() {
+                       b.WriteString("interface {}")
+                       break
+               }
+               b.WriteString("interface {")
+               for i, f := range t.Fields().Slice() {
+                       if i != 0 {
+                               b.WriteByte(';')
+                       }
+                       b.WriteByte(' ')
+                       switch {
+                       case f.Sym == nil:
+                               // Check first that a symbol is defined for this type.
+                               // Wrong interface definitions may have types lacking a symbol.
+                               break
+                       case IsExported(f.Sym.Name):
+                               sconv2(b, f.Sym, 'S', mode)
+                       default:
+                               if mode != fmtTypeIDName {
+                                       mode = fmtTypeID
+                               }
+                               sconv2(b, f.Sym, 'v', mode)
+                       }
+                       tconv2(b, f.Type, 'S', mode, visited)
+               }
+               if t.NumFields() != 0 {
+                       b.WriteByte(' ')
+               }
+               b.WriteByte('}')
+
+       case TFUNC:
+               if verb == 'S' {
+                       // no leading func
+               } else {
+                       if t.Recv() != nil {
+                               b.WriteString("method")
+                               tconv2(b, t.Recvs(), 0, mode, visited)
+                               b.WriteByte(' ')
+                       }
+                       b.WriteString("func")
+               }
+               tconv2(b, t.Params(), 0, mode, visited)
+
+               switch t.NumResults() {
+               case 0:
+                       // nothing to do
+
+               case 1:
+                       b.WriteByte(' ')
+                       tconv2(b, t.Results().Field(0).Type, 0, mode, visited) // struct->field->field's type
+
+               default:
+                       b.WriteByte(' ')
+                       tconv2(b, t.Results(), 0, mode, visited)
+               }
+
+       case TSTRUCT:
+               if m := t.StructType().Map; m != nil {
+                       mt := m.MapType()
+                       // Format the bucket struct for map[x]y as map.bucket[x]y.
+                       // This avoids a recursive print that generates very long names.
+                       switch t {
+                       case mt.Bucket:
+                               b.WriteString("map.bucket[")
+                       case mt.Hmap:
+                               b.WriteString("map.hdr[")
+                       case mt.Hiter:
+                               b.WriteString("map.iter[")
+                       default:
+                               base.Fatalf("unknown internal map type")
+                       }
+                       tconv2(b, m.Key(), 0, mode, visited)
+                       b.WriteByte(']')
+                       tconv2(b, m.Elem(), 0, mode, visited)
+                       break
+               }
+
+               if funarg := t.StructType().Funarg; funarg != FunargNone {
+                       b.WriteByte('(')
+                       fieldVerb := 'v'
+                       switch mode {
+                       case fmtTypeID, fmtTypeIDName, fmtGo:
+                               // no argument names on function signature, and no "noescape"/"nosplit" tags
+                               fieldVerb = 'S'
+                       }
+                       for i, f := range t.Fields().Slice() {
+                               if i != 0 {
+                                       b.WriteString(", ")
+                               }
+                               fldconv(b, f, fieldVerb, mode, visited, funarg)
+                       }
+                       b.WriteByte(')')
+               } else {
+                       b.WriteString("struct {")
+                       for i, f := range t.Fields().Slice() {
+                               if i != 0 {
+                                       b.WriteByte(';')
+                               }
+                               b.WriteByte(' ')
+                               fldconv(b, f, 'L', mode, visited, funarg)
+                       }
+                       if t.NumFields() != 0 {
+                               b.WriteByte(' ')
+                       }
+                       b.WriteByte('}')
+               }
+
+       case TFORW:
+               b.WriteString("undefined")
+               if t.Sym() != nil {
+                       b.WriteByte(' ')
+                       sconv2(b, t.Sym(), 'v', mode)
+               }
+
+       case TUNSAFEPTR:
+               b.WriteString("unsafe.Pointer")
+
+       case Txxx:
+               b.WriteString("Txxx")
+
+       default:
+               // Don't know how to handle - fall back to detailed prints
+               b.WriteString(t.Kind().String())
+               b.WriteString(" <")
+               sconv2(b, t.Sym(), 'v', mode)
+               b.WriteString(">")
+
+       }
+}
+
+func fldconv(b *bytes.Buffer, f *Field, verb rune, mode fmtMode, visited map[*Type]int, funarg Funarg) {
+       if f == nil {
+               b.WriteString("<T>")
+               return
+       }
+
+       var name string
+       if verb != 'S' {
+               s := f.Sym
+
+               // Take the name from the original.
+               if mode == fmtGo {
+                       s = OrigSym(s)
+               }
+
+               if s != nil && f.Embedded == 0 {
+                       if funarg != FunargNone {
+                               name = fmt.Sprint(f.Nname)
+                       } else if verb == 'L' {
+                               name = SymMethodName(s)
+                               if !IsExported(name) && mode != fmtTypeIDName {
+                                       name = sconv(s, 0, mode) // qualify non-exported names (used on structs, not on funarg)
+                               }
+                       } else {
+                               name = sconv(s, 0, mode)
+                       }
+               }
+       }
+
+       if name != "" {
+               b.WriteString(name)
+               b.WriteString(" ")
+       }
+
+       if f.IsDDD() {
+               var et *Type
+               if f.Type != nil {
+                       et = f.Type.Elem()
+               }
+               b.WriteString("...")
+               tconv2(b, et, 0, mode, visited)
+       } else {
+               tconv2(b, f.Type, 0, mode, visited)
+       }
+
+       if verb != 'S' && funarg == FunargNone && f.Note != "" {
+               b.WriteString(" ")
+               b.WriteString(strconv.Quote(f.Note))
+       }
+}
+
+// Val
+
+func FmtConst(v constant.Value, sharp bool) string {
+       if !sharp && v.Kind() == constant.Complex {
+               real, imag := constant.Real(v), constant.Imag(v)
+
+               var re string
+               sre := constant.Sign(real)
+               if sre != 0 {
+                       re = real.String()
+               }
+
+               var im string
+               sim := constant.Sign(imag)
+               if sim != 0 {
+                       im = imag.String()
+               }
+
+               switch {
+               case sre == 0 && sim == 0:
+                       return "0"
+               case sre == 0:
+                       return im + "i"
+               case sim == 0:
+                       return re
+               case sim < 0:
+                       return fmt.Sprintf("(%s%si)", re, im)
+               default:
+                       return fmt.Sprintf("(%s+%si)", re, im)
+               }
+       }
+
+       return v.String()
+}