[dev.regabi] cmd/compile: move Type, Sym printing to package types [generated]

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>
This commit is contained in:
Russ Cox 2020-12-06 13:54:50 -05:00
parent 70155cca81
commit bb4a37bd93
27 changed files with 786 additions and 774 deletions

View 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 // Type imported from package, so it can't be part of
// a type loop (otherwise that package should have // a type loop (otherwise that package should have
// failed to compile). // failed to compile).
if t.Sym().Pkg != ir.LocalPkg { if t.Sym().Pkg != types.LocalPkg {
return false return false
} }

View file

@ -6,6 +6,7 @@ package gc
import ( import (
"cmd/compile/internal/ir" "cmd/compile/internal/ir"
"cmd/compile/internal/types"
"cmd/internal/src" "cmd/internal/src"
) )
@ -15,5 +16,5 @@ func npos(pos src.XPos, n ir.Node) ir.Node {
} }
func builtinCall(op ir.Op) 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)
} }

View file

@ -384,7 +384,7 @@ func overflow(v constant.Value, t *types.Type) bool {
return true return true
} }
if doesoverflow(v, t) { 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 true
} }
return false return false

View file

@ -66,7 +66,7 @@ func declare(n *ir.Name, ctxt ir.Class) {
s := n.Sym() s := n.Sym()
// kludgy: typecheckok means we're past parsing. Eg genwrapper may declare out of package names later. // 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) 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. // but it reports an error if sym is from another package and not exported.
func importName(sym *types.Sym) ir.Node { func importName(sym *types.Sym) ir.Node {
n := oldname(sym) n := oldname(sym)
if !types.IsExported(sym.Name) && sym.Pkg != ir.LocalPkg { if !types.IsExported(sym.Name) && sym.Pkg != types.LocalPkg {
n.SetDiag(true) n.SetDiag(true)
base.Errorf("cannot refer to unexported name %s.%s", sym.Pkg.Name, sym.Name) 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) checkdupfields("field", fields)
base.Pos = lno base.Pos = lno
return types.NewStruct(ir.LocalPkg, fields) return types.NewStruct(types.LocalPkg, fields)
} }
func tointerface(nmethods []*ir.Field) *types.Type { func tointerface(nmethods []*ir.Field) *types.Type {
@ -533,7 +533,7 @@ func tointerface(nmethods []*ir.Field) *types.Type {
} }
base.Pos = lno base.Pos = lno
return types.NewInterface(ir.LocalPkg, methods) return types.NewInterface(types.LocalPkg, methods)
} }
func fakeRecv() *ir.Field { func fakeRecv() *ir.Field {
@ -585,14 +585,14 @@ func functype(nrecv *ir.Field, nparams, nresults []*ir.Field) *types.Type {
recv = funarg(nrecv) 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()) checkdupfields("argument", t.Recvs().FieldSlice(), t.Params().FieldSlice(), t.Results().FieldSlice())
return t return t
} }
func hasNamedResults(fn *ir.Func) bool { func hasNamedResults(fn *ir.Func) bool {
typ := fn.Type() 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 // 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 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) base.Errorf("cannot define new methods on non-local type %v", mt)
return nil return nil
} }

View 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". // can't tell whether "string" and "byte" really mean "string" and "byte".
// The result must be confirmed later, after type checking, using embedKind. // The result must be confirmed later, after type checking, using embedKind.
func embedKindApprox(typ ir.Node) int { 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 return embedFiles
} }
// These are not guaranteed to match only string and []byte - // These are not guaranteed to match only string and []byte -
// maybe the local package has redefined one of those words. // maybe the local package has redefined one of those words.
// But it's the best we can do now during the noder. // But it's the best we can do now during the noder.
// The stricter check happens later, in initEmbed calling embedKind. // 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 return embedString
} }
if typ, ok := typ.(*ir.SliceType); ok { 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 return embedBytes
} }
} }
@ -151,7 +151,7 @@ func embedKindApprox(typ ir.Node) int {
// embedKind determines the kind of embedding variable. // embedKind determines the kind of embedding variable.
func embedKind(typ *types.Type) int { 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 return embedFiles
} }
if typ == types.Types[types.TSTRING] { if typ == types.Types[types.TSTRING] {

View file

@ -42,7 +42,7 @@ func initname(s string) bool {
} }
func autoexport(n *ir.Name, ctxt ir.Class) { func autoexport(n *ir.Name, ctxt ir.Class) {
if n.Sym().Pkg != ir.LocalPkg { if n.Sym().Pkg != types.LocalPkg {
return return
} }
if (ctxt != ir.PEXTERN && ctxt != ir.PFUNC) || dclcontext != ir.PEXTERN { if (ctxt != ir.PEXTERN && ctxt != ir.PFUNC) || dclcontext != ir.PEXTERN {
@ -202,7 +202,7 @@ func dumpasmhdr() {
if err != nil { if err != nil {
base.Fatalf("%v", err) 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 { for _, n := range asmlist {
if n.Sym().IsBlank() { if n.Sym().IsBlank() {
continue continue

View file

@ -66,7 +66,7 @@ func tempAt(pos src.XPos, curfn *ir.Func, t *types.Type) *ir.Name {
s := &types.Sym{ s := &types.Sym{
Name: autotmpname(len(curfn.Dcl)), Name: autotmpname(len(curfn.Dcl)),
Pkg: ir.LocalPkg, Pkg: types.LocalPkg,
} }
n := ir.NewNameAt(pos, s) n := ir.NewNameAt(pos, s)
s.Def = n s.Def = n

View file

@ -37,7 +37,7 @@ var (
// isRuntimePkg reports whether p is package runtime. // isRuntimePkg reports whether p is package runtime.
func isRuntimePkg(p *types.Pkg) bool { func isRuntimePkg(p *types.Pkg) bool {
if base.Flag.CompilingRuntime && p == ir.LocalPkg { if base.Flag.CompilingRuntime && p == types.LocalPkg {
return true return true
} }
return p.Path == "runtime" return p.Path == "runtime"
@ -45,7 +45,7 @@ func isRuntimePkg(p *types.Pkg) bool {
// isReflectPkg reports whether p is package reflect. // isReflectPkg reports whether p is package reflect.
func isReflectPkg(p *types.Pkg) bool { func isReflectPkg(p *types.Pkg) bool {
if p == ir.LocalPkg { if p == types.LocalPkg {
return base.Ctxt.Pkgpath == "reflect" return base.Ctxt.Pkgpath == "reflect"
} }
return p.Path == "reflect" return p.Path == "reflect"

View 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) // we reference, even if we're not exporting (or reexporting)
// any symbols from it. // any symbols from it.
if mainIndex { if mainIndex {
pkgSyms[ir.LocalPkg] = nil pkgSyms[types.LocalPkg] = nil
for pkg := range w.p.allPkgs { for pkg := range w.p.allPkgs {
pkgSyms[pkg] = nil pkgSyms[pkg] = nil
} }
@ -402,7 +402,7 @@ func (p *iexporter) pushDecl(n *ir.Name) {
} }
// Don't export predeclared declarations. // 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 return
} }
@ -596,7 +596,7 @@ func (w *exportWriter) selector(s *types.Sym) {
} else { } else {
pkg := w.currPkg pkg := w.currPkg
if types.IsExported(name) { if types.IsExported(name) {
pkg = ir.LocalPkg pkg = types.LocalPkg
} }
if s.Pkg != pkg { if s.Pkg != pkg {
base.Fatalf("package mismatch in selector: %v in package %q, but want %q", s, s.Pkg.Path, pkg.Path) 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) { func (w *exportWriter) doTyp(t *types.Type) {
if t.Sym() != nil { 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) 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) { func (w *exportWriter) param(f *types.Field) {
w.pos(f.Pos) w.pos(f.Pos)
w.localIdent(ir.OrigSym(f.Sym), 0) w.localIdent(types.OrigSym(f.Sym), 0)
w.typ(f.Type) w.typ(f.Type)
} }

View file

@ -148,7 +148,7 @@ func iimport(pkg *types.Pkg, in *bio.Reader) (fingerprint goobj.FingerprintType)
if pkg.Name == "" { if pkg.Name == "" {
pkg.Name = pkgName pkg.Name = pkgName
pkg.Height = pkgHeight pkg.Height = pkgHeight
ir.NumImport[pkgName]++ types.NumImport[pkgName]++
// TODO(mdempsky): This belongs somewhere else. // TODO(mdempsky): This belongs somewhere else.
pkg.Lookup("_").Def = ir.BlankNode pkg.Lookup("_").Def = ir.BlankNode
@ -437,7 +437,7 @@ func (r *importReader) ident() *types.Sym {
} }
pkg := r.currPkg pkg := r.currPkg
if types.IsExported(name) { if types.IsExported(name) {
pkg = ir.LocalPkg pkg = types.LocalPkg
} }
return pkg.Lookup(name) return pkg.Lookup(name)
} }

View file

@ -96,7 +96,7 @@ func fninit(n []ir.Node) {
fns = append(fns, s.Linksym()) 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 return // nothing to initialize
} }

View file

@ -85,7 +85,7 @@ func typecheckinl(fn *ir.Func) {
// the ->inl of a local function has been typechecked before caninl copied it. // the ->inl of a local function has been typechecked before caninl copied it.
pkg := fnpkg(fn.Nname) pkg := fnpkg(fn.Nname)
if pkg == ir.LocalPkg || pkg == nil { if pkg == types.LocalPkg || pkg == nil {
return // typecheckinl on local function return // typecheckinl on local function
} }

View file

@ -77,17 +77,17 @@ func Main(archInit func(*Arch)) {
// See bugs 31188 and 21945 (CLs 170638, 98075, 72371). // See bugs 31188 and 21945 (CLs 170638, 98075, 72371).
base.Ctxt.UseBASEntries = base.Ctxt.Headtype != objabi.Hdarwin base.Ctxt.UseBASEntries = base.Ctxt.Headtype != objabi.Hdarwin
ir.LocalPkg = types.NewPkg("", "") types.LocalPkg = types.NewPkg("", "")
ir.LocalPkg.Prefix = "\"\"" types.LocalPkg.Prefix = "\"\""
// We won't know localpkg's height until after import // We won't know localpkg's height until after import
// processing. In the mean time, set to MaxPkgHeight to ensure // processing. In the mean time, set to MaxPkgHeight to ensure
// height comparisons at least work until then. // height comparisons at least work until then.
ir.LocalPkg.Height = types.MaxPkgHeight types.LocalPkg.Height = types.MaxPkgHeight
// pseudo-package, for scoping // pseudo-package, for scoping
ir.BuiltinPkg = types.NewPkg("go.builtin", "") // TODO(gri) name this package go.builtin? types.BuiltinPkg = types.NewPkg("go.builtin", "") // TODO(gri) name this package go.builtin?
ir.BuiltinPkg.Prefix = "go.builtin" // not go%2ebuiltin types.BuiltinPkg.Prefix = "go.builtin" // not go%2ebuiltin
// pseudo-package, accessed by import "unsafe" // pseudo-package, accessed by import "unsafe"
unsafepkg = types.NewPkg("unsafe", "unsafe") unsafepkg = types.NewPkg("unsafe", "unsafe")
@ -212,7 +212,7 @@ func Main(archInit func(*Arch)) {
// would lead to import cycles) // would lead to import cycles)
types.Widthptr = Widthptr types.Widthptr = Widthptr
types.Dowidth = dowidth types.Dowidth = dowidth
ir.InstallTypeFormats() types.InstallTypeFormats()
types.TypeLinkSym = func(t *types.Type) *obj.LSym { types.TypeLinkSym = func(t *types.Type) *obj.LSym {
return typenamesym(t).Linksym() return typenamesym(t).Linksym()
} }
@ -922,14 +922,14 @@ func pkgnotused(lineno src.XPos, path string, name string) {
} }
func mkpackage(pkgname string) { func mkpackage(pkgname string) {
if ir.LocalPkg.Name == "" { if types.LocalPkg.Name == "" {
if pkgname == "_" { if pkgname == "_" {
base.Errorf("invalid package name _") base.Errorf("invalid package name _")
} }
ir.LocalPkg.Name = pkgname types.LocalPkg.Name = pkgname
} else { } else {
if pkgname != ir.LocalPkg.Name { if pkgname != types.LocalPkg.Name {
base.Errorf("package %s; expected %s", pkgname, ir.LocalPkg.Name) base.Errorf("package %s; expected %s", pkgname, types.LocalPkg.Name)
} }
} }
} }
@ -942,7 +942,7 @@ func clearImports() {
} }
var unused []importedPkg var unused []importedPkg
for _, s := range ir.LocalPkg.Syms { for _, s := range types.LocalPkg.Syms {
n := ir.AsNode(s.Def) n := ir.AsNode(s.Def)
if n == nil { if n == nil {
continue continue
@ -1046,7 +1046,7 @@ func recordPackageName() {
// together two package main archives. So allow dups. // together two package main archives. So allow dups.
s.Set(obj.AttrDuplicateOK, true) s.Set(obj.AttrDuplicateOK, true)
base.Ctxt.Data = append(base.Ctxt.Data, s) 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. // currentLang returns the current language version.
@ -1073,9 +1073,9 @@ var langWant lang
func langSupported(major, minor int, pkg *types.Pkg) bool { func langSupported(major, minor int, pkg *types.Pkg) bool {
if pkg == nil { if pkg == nil {
// TODO(mdempsky): Set Pkg for local types earlier. // 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. // Assume imported packages passed type-checking.
return true return true
} }

View file

@ -79,7 +79,7 @@ func parseFiles(filenames []string) uint {
p.processPragmas() p.processPragmas()
} }
ir.LocalPkg.Height = myheight types.LocalPkg.Height = myheight
return lines return lines
} }
@ -501,7 +501,7 @@ func (p *noder) typeDecl(decl *syntax.TypeDecl) ir.Node {
} }
nod := p.nod(decl, ir.ODCLTYPE, n, nil) 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") base.ErrorfAt(nod.Pos(), "type aliases only supported as of -lang=go1.9")
} }
return nod 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 { if t.List().Len() > 0 || t.Rlist().Len() > 0 {
base.ErrorfAt(f.Pos(), "func main must have no arguments and no return values") 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 var pkg *types.Pkg
if def.Op() != ir.OPACK { if def.Op() != ir.OPACK {
base.Errorf("%v is not a package", name) base.Errorf("%v is not a package", name)
pkg = ir.LocalPkg pkg = types.LocalPkg
} else { } else {
def := def.(*ir.PkgName) def := def.(*ir.PkgName)
def.Used = true 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. // literal is not compatible with the current language version.
func checkLangCompat(lit *syntax.BasicLit) { func checkLangCompat(lit *syntax.BasicLit) {
s := lit.Value s := lit.Value
if len(s) <= 2 || langSupported(1, 13, ir.LocalPkg) { if len(s) <= 2 || langSupported(1, 13, types.LocalPkg) {
return return
} }
// len(s) > 2 // len(s) > 2

View file

@ -84,7 +84,7 @@ func printObjHeader(bout *bio.Writer) {
if base.Flag.BuildID != "" { if base.Flag.BuildID != "" {
fmt.Fprintf(bout, "build id %q\n", 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, "main\n")
} }
fmt.Fprintf(bout, "\n") // header ends with blank line fmt.Fprintf(bout, "\n") // header ends with blank line
@ -200,7 +200,7 @@ func dumpLinkerObj(bout *bio.Writer) {
} }
func addptabs() { func addptabs() {
if !base.Ctxt.Flag_dynlink || ir.LocalPkg.Name != "main" { if !base.Ctxt.Flag_dynlink || types.LocalPkg.Name != "main" {
return return
} }
for _, exportn := range exportlist { for _, exportn := range exportlist {
@ -235,7 +235,7 @@ func dumpGlobal(n ir.Node) {
if n.Class() == ir.PFUNC { if n.Class() == ir.PFUNC {
return return
} }
if n.Sym().Pkg != ir.LocalPkg { if n.Sym().Pkg != types.LocalPkg {
return return
} }
dowidth(n.Type()) dowidth(n.Type())
@ -248,7 +248,7 @@ func dumpGlobalConst(n ir.Node) {
if t == nil { if t == nil {
return return
} }
if n.Sym().Pkg != ir.LocalPkg { if n.Sym().Pkg != types.LocalPkg {
return return
} }
// only export integer constants for now // only export integer constants for now
@ -478,7 +478,7 @@ var slicedataGen int
func slicedata(pos src.XPos, s string) ir.Node { func slicedata(pos src.XPos, s string) ir.Node {
slicedataGen++ slicedataGen++
symname := fmt.Sprintf(".gobytes.%d", slicedataGen) symname := fmt.Sprintf(".gobytes.%d", slicedataGen)
sym := ir.LocalPkg.Lookup(symname) sym := types.LocalPkg.Lookup(symname)
symnode := NewName(sym) symnode := NewName(sym)
sym.Def = symnode sym.Def = symnode

View file

@ -301,7 +301,7 @@ func deferstruct(stksize int64) *types.Type {
// Unlike the global makefield function, this one needs to set Pkg // Unlike the global makefield function, this one needs to set Pkg
// because these types might be compared (in SSA CSE sorting). // because these types might be compared (in SSA CSE sorting).
// TODO: unify this makefield and the global one above. // 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) return types.NewField(src.NoXPos, sym, typ)
} }
argtype := types.NewArray(types.Types[types.TUINT8], stksize) argtype := types.NewArray(types.Types[types.TUINT8], stksize)
@ -491,7 +491,7 @@ func dimportpath(p *types.Pkg) {
} }
str := p.Path str := p.Path
if p == ir.LocalPkg { if p == types.LocalPkg {
// Note: myimportpath != "", or else dgopkgpath won't call dimportpath. // Note: myimportpath != "", or else dgopkgpath won't call dimportpath.
str = base.Ctxt.Pkgpath str = base.Ctxt.Pkgpath
} }
@ -508,7 +508,7 @@ func dgopkgpath(s *obj.LSym, ot int, pkg *types.Pkg) int {
return duintptr(s, ot, 0) 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 // 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 // (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. // 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 { if pkg == nil {
return duint32(s, ot, 0) 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 // 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 // (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. // 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 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 // 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 { if i, ok := typeSymIdx[tbase]; ok {
lsym.Pkg = tbase.Sym().Pkg.Prefix lsym.Pkg = tbase.Sym().Pkg.Prefix
if t != tbase { if t != tbase {
@ -1568,7 +1568,7 @@ func dumptabs() {
} }
// process ptabs // process ptabs
if ir.LocalPkg.Name == "main" && len(ptabs) > 0 { if types.LocalPkg.Name == "main" && len(ptabs) > 0 {
ot := 0 ot := 0
s := base.Ctxt.Lookup("go.plugin.tabs") s := base.Ctxt.Lookup("go.plugin.tabs")
for _, p := range ptabs { for _, p := range ptabs {

View file

@ -79,7 +79,7 @@ func (s *InitSchedule) staticcopy(l ir.Node, r ir.Node) bool {
pfuncsym(l, r) pfuncsym(l, r)
return true return true
} }
if r.Class() != ir.PEXTERN || r.Sym().Pkg != ir.LocalPkg { if r.Class() != ir.PEXTERN || r.Sym().Pkg != types.LocalPkg {
return false return false
} }
if r.Name().Defn == nil { // probably zeroed but perhaps supplied externally and of unknown value if r.Name().Defn == nil { // probably zeroed but perhaps supplied externally and of unknown value

View file

@ -4127,7 +4127,7 @@ func findIntrinsic(sym *types.Sym) intrinsicBuilder {
return nil return nil
} }
pkg := sym.Pkg.Path pkg := sym.Pkg.Path
if sym.Pkg == ir.LocalPkg { if sym.Pkg == types.LocalPkg {
pkg = base.Ctxt.Pkgpath pkg = base.Ctxt.Pkgpath
} }
if base.Flag.Race && pkg == "sync/atomic" { 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} 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) n := ir.NewNameAt(parent.N.Pos(), s)
s.Def = n s.Def = n
ir.AsNode(s.Def).Name().SetUsed(true) ir.AsNode(s.Def).Name().SetUsed(true)

View file

@ -69,7 +69,7 @@ func setlineno(n ir.Node) src.XPos {
} }
func lookup(name string) *types.Sym { 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 // 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 var buf [20]byte // plenty long enough for all current users
copy(buf[:], prefix) copy(buf[:], prefix)
b := strconv.AppendInt(buf[:len(prefix)], int64(n), 10) 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 // 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. // Only generate (*T).M wrappers for T.M in T's own package.
if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && 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 return
} }
// Only generate I.M wrappers for I in I's own package // Only generate I.M wrappers for I in I's own package
// but keep doing it for error.Error (was issue #29304). // 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 return
} }

View file

@ -90,7 +90,7 @@ func resolve(n ir.Node) (res ir.Node) {
defer tracePrint("resolve", n)(&res) defer tracePrint("resolve", n)(&res)
} }
if n.Sym().Pkg != ir.LocalPkg { if n.Sym().Pkg != types.LocalPkg {
if inimport { if inimport {
base.Fatalf("recursive inimport") base.Fatalf("recursive inimport")
} }
@ -2386,7 +2386,7 @@ func typecheckMethodExpr(n ir.Node) (res ir.Node) {
me.(*ir.MethodExpr).Method = m me.(*ir.MethodExpr).Method = m
// Issue 25065. Make sure that we emit the symbol for a local method. // 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()) makefuncsym(me.Sym())
} }
@ -2862,7 +2862,7 @@ func typecheckcomplit(n ir.Node) (res ir.Node) {
f := t.Field(i) f := t.Field(i)
s := f.Sym 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) base.Errorf("implicit assignment of unexported field '%s' in %v literal", s.Name, t)
} }
// No pushtype allowed here. Must name fields for that. // 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 // package, because of import dot. Redirect to correct sym
// before we do the lookup. // before we do the lookup.
s := key.Sym() 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) s1 := lookup(s.Name)
if s1.Origpkg == s.Pkg { if s1.Origpkg == s.Pkg {
s = s1 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. // visible reports whether sym is exported or locally defined.
func visible(sym *types.Sym) bool { 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. // nonexported reports whether sym is an unexported field.
@ -3929,7 +3929,7 @@ func curpkg() *types.Pkg {
fn := Curfn fn := Curfn
if fn == nil { if fn == nil {
// Initialization expressions for package-scope variables. // Initialization expressions for package-scope variables.
return ir.LocalPkg return types.LocalPkg
} }
return fnpkg(fn.Nname) return fnpkg(fn.Nname)
} }

View file

@ -104,7 +104,7 @@ func initUniverse() {
} }
types.Types[types.TANY] = types.New(types.TANY) 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 { defBasic := func(kind types.Kind, pkg *types.Pkg, name string) *types.Type {
sym := pkg.Lookup(name) sym := pkg.Lookup(name)
@ -120,7 +120,7 @@ func initUniverse() {
} }
for _, s := range &basicTypes { 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 { for _, s := range &typedefs {
@ -130,7 +130,7 @@ func initUniverse() {
} }
simtype[s.etype] = sameas 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 // 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)? // of less informative error messages involving bytes and runes)?
// (Alternatively, we could introduce an OTALIAS node representing // (Alternatively, we could introduce an OTALIAS node representing
// type aliases, albeit at the cost of having to deal with it everywhere). // type aliases, albeit at the cost of having to deal with it everywhere).
types.ByteType = defBasic(types.TUINT8, ir.BuiltinPkg, "byte") types.ByteType = defBasic(types.TUINT8, types.BuiltinPkg, "byte")
types.RuneType = defBasic(types.TINT32, ir.BuiltinPkg, "rune") types.RuneType = defBasic(types.TINT32, types.BuiltinPkg, "rune")
// error type // error type
s := ir.BuiltinPkg.Lookup("error") s := types.BuiltinPkg.Lookup("error")
n := ir.NewDeclNameAt(src.NoXPos, s) n := ir.NewDeclNameAt(src.NoXPos, s)
n.SetOp(ir.OTYPE) n.SetOp(ir.OTYPE)
types.ErrorType = types.NewNamed(n) types.ErrorType = types.NewNamed(n)
@ -162,7 +162,7 @@ func initUniverse() {
simtype[types.TUNSAFEPTR] = types.TPTR simtype[types.TUNSAFEPTR] = types.TPTR
for _, s := range &builtinFuncs { for _, s := range &builtinFuncs {
s2 := ir.BuiltinPkg.Lookup(s.name) s2 := types.BuiltinPkg.Lookup(s.name)
s2.Def = NewName(s2) s2.Def = NewName(s2)
ir.AsNode(s2.Def).SetSubOp(s.op) ir.AsNode(s2.Def).SetSubOp(s.op)
} }
@ -173,16 +173,16 @@ func initUniverse() {
ir.AsNode(s2.Def).SetSubOp(s.op) ir.AsNode(s2.Def).SetSubOp(s.op)
} }
s = ir.BuiltinPkg.Lookup("true") s = types.BuiltinPkg.Lookup("true")
s.Def = nodbool(true) s.Def = nodbool(true)
ir.AsNode(s.Def).SetSym(lookup("true")) ir.AsNode(s.Def).SetSym(lookup("true"))
s = ir.BuiltinPkg.Lookup("false") s = types.BuiltinPkg.Lookup("false")
s.Def = nodbool(false) s.Def = nodbool(false)
ir.AsNode(s.Def).SetSym(lookup("false")) ir.AsNode(s.Def).SetSym(lookup("false"))
s = lookup("_") s = lookup("_")
ir.BlankSym = s types.BlankSym = s
s.Block = -100 s.Block = -100
s.Def = NewName(s) s.Def = NewName(s)
types.Types[types.TBLANK] = types.New(types.TBLANK) types.Types[types.TBLANK] = types.New(types.TBLANK)
@ -190,18 +190,18 @@ func initUniverse() {
ir.BlankNode = ir.AsNode(s.Def) ir.BlankNode = ir.AsNode(s.Def)
ir.BlankNode.SetTypecheck(1) ir.BlankNode.SetTypecheck(1)
s = ir.BuiltinPkg.Lookup("_") s = types.BuiltinPkg.Lookup("_")
s.Block = -100 s.Block = -100
s.Def = NewName(s) s.Def = NewName(s)
types.Types[types.TBLANK] = types.New(types.TBLANK) types.Types[types.TBLANK] = types.New(types.TBLANK)
ir.AsNode(s.Def).SetType(types.Types[types.TBLANK]) ir.AsNode(s.Def).SetType(types.Types[types.TBLANK])
types.Types[types.TNIL] = types.New(types.TNIL) types.Types[types.TNIL] = types.New(types.TNIL)
s = ir.BuiltinPkg.Lookup("nil") s = types.BuiltinPkg.Lookup("nil")
s.Def = nodnil() s.Def = nodnil()
ir.AsNode(s.Def).SetSym(s) ir.AsNode(s.Def).SetSym(s)
s = ir.BuiltinPkg.Lookup("iota") s = types.BuiltinPkg.Lookup("iota")
s.Def = ir.Nod(ir.OIOTA, nil, nil) s.Def = ir.Nod(ir.OIOTA, nil, nil)
ir.AsNode(s.Def).SetSym(s) ir.AsNode(s.Def).SetSym(s)
@ -339,7 +339,7 @@ func finishUniverse() {
// that we silently skip symbols that are already declared in the // that we silently skip symbols that are already declared in the
// package block rather than emitting a redeclared symbol error. // 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 { if s.Def == nil {
continue continue
} }

View file

@ -983,7 +983,7 @@ opswitch:
if param == types.Txxx { if param == types.Txxx {
break 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()) n = conv(mkcall(fn, types.Types[result], init, conv(n.Left(), types.Types[param])), n.Type())
case ir.ODIV, ir.OMOD: case ir.ODIV, ir.OMOD:

View file

@ -10,9 +10,7 @@ import (
"go/constant" "go/constant"
"io" "io"
"os" "os"
"strconv"
"strings"
"sync"
"unicode/utf8" "unicode/utf8"
"cmd/compile/internal/base" "cmd/compile/internal/base"
@ -20,74 +18,6 @@ import (
"cmd/internal/src" "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 // Op
var OpNames = []string{ 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 // Node
func FmtNode(n Node, s fmt.State, verb rune) { 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)) fmt.Fprintf(s, "'\\U%08x'", uint64(x))
} }
} else { } else {
fmt.Fprint(s, FmtConst(n.Val(), s.Flag('#'))) fmt.Fprint(s, types.FmtConst(n.Val(), s.Flag('#')))
} }
if needUnparen { if needUnparen {
@ -1338,7 +690,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
fmt.Fprint(s, ".<nil>") fmt.Fprint(s, ".<nil>")
return return
} }
fmt.Fprintf(s, ".%s", methodSymName(n.Sym())) fmt.Fprintf(s, ".%s", types.SymMethodName(n.Sym()))
case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH: case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
exprFmt(n.Left(), s, nprec) exprFmt(n.Left(), s, nprec)
@ -1346,7 +698,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
fmt.Fprint(s, ".<nil>") fmt.Fprint(s, ".<nil>")
return return
} }
fmt.Fprintf(s, ".%s", methodSymName(n.Sym())) fmt.Fprintf(s, ".%s", types.SymMethodName(n.Sym()))
case ODOTTYPE, ODOTTYPE2: case ODOTTYPE, ODOTTYPE2:
exprFmt(n.Left(), s, nprec) exprFmt(n.Left(), s, nprec)

View file

@ -3,10 +3,3 @@
// license that can be found in the LICENSE file. // license that can be found in the LICENSE file.
package ir 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

View file

@ -10,7 +10,6 @@ import (
"fmt" "fmt"
"go/constant" "go/constant"
"sort" "sort"
"strings"
"cmd/compile/internal/base" "cmd/compile/internal/base"
"cmd/compile/internal/types" "cmd/compile/internal/types"
@ -654,33 +653,6 @@ func AsNode(n types.Object) Node {
var BlankNode 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 { func IsConst(n Node, ct constant.Kind) bool {
return ConstType(n) == ct return ConstType(n) == ct
} }

View file

@ -137,7 +137,7 @@ func init() {
// Initialize just enough of the universe and the types package to make our tests function. // Initialize just enough of the universe and the types package to make our tests function.
// TODO(josharian): move universe initialization to the types package, // TODO(josharian): move universe initialization to the types package,
// so this test setup can share it. // so this test setup can share it.
ir.InstallTypeFormats() types.InstallTypeFormats()
types.Dowidth = func(t *types.Type) {} types.Dowidth = func(t *types.Type) {}
for _, typ := range [...]struct { for _, typ := range [...]struct {

View file

@ -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()
}