mirror of
https://github.com/golang/go
synced 2024-11-11 19:31:37 -07:00
[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:
parent
70155cca81
commit
bb4a37bd93
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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] {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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:
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
694
src/cmd/compile/internal/types/fmt.go
Normal file
694
src/cmd/compile/internal/types/fmt.go
Normal 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()
|
||||
}
|
Loading…
Reference in New Issue
Block a user