Commit 8d0bbe2b authored by Robert Griesemer's avatar Robert Griesemer

cmd/compile: implement fmt.Formatter for *Type formats %s, %v

Change-Id: I878ac549430abc7859c30d176d52d52ce02c5827
Reviewed-on: https://go-review.googlesource.com/28333Reviewed-by: default avatarMatthew Dempsky <mdempsky@google.com>
parent 97ba3c82
...@@ -231,7 +231,7 @@ func gmove(f *gc.Node, t *gc.Node) { ...@@ -231,7 +231,7 @@ func gmove(f *gc.Node, t *gc.Node) {
default: default:
gc.Dump("f", f) gc.Dump("f", f)
gc.Dump("t", t) gc.Dump("t", t)
gc.Fatalf("gmove %v -> %v", gc.Tconv(f.Type, gc.FmtLong), gc.Tconv(t.Type, gc.FmtLong)) gc.Fatalf("gmove %2v -> %2v", f.Type, t.Type)
/* /*
* integer copy and truncate * integer copy and truncate
......
...@@ -210,7 +210,7 @@ func gmove(f *gc.Node, t *gc.Node) { ...@@ -210,7 +210,7 @@ func gmove(f *gc.Node, t *gc.Node) {
switch uint32(ft)<<16 | uint32(tt) { switch uint32(ft)<<16 | uint32(tt) {
default: default:
gc.Fatalf("gmove %v -> %v", gc.Tconv(f.Type, gc.FmtLong), gc.Tconv(t.Type, gc.FmtLong)) gc.Fatalf("gmove %2v -> %2v", f.Type, t.Type)
/* /*
* integer copy and truncate * integer copy and truncate
......
...@@ -75,7 +75,7 @@ func widstruct(errtype *Type, t *Type, o int64, flag int) int64 { ...@@ -75,7 +75,7 @@ func widstruct(errtype *Type, t *Type, o int64, flag int) int64 {
} }
o += w o += w
if o >= Thearch.MAXWIDTH { if o >= Thearch.MAXWIDTH {
Yyerror("type %v too large", Tconv(errtype, FmtLong)) Yyerror("type %2v too large", errtype)
o = 8 // small but nonzero o = 8 // small but nonzero
} }
} }
...@@ -253,7 +253,7 @@ func dowidth(t *Type) { ...@@ -253,7 +253,7 @@ func dowidth(t *Type) {
if t.Elem().Width != 0 { if t.Elem().Width != 0 {
cap := (uint64(Thearch.MAXWIDTH) - 1) / uint64(t.Elem().Width) cap := (uint64(Thearch.MAXWIDTH) - 1) / uint64(t.Elem().Width)
if uint64(t.NumElem()) > cap { if uint64(t.NumElem()) > cap {
Yyerror("type %v larger than address space", Tconv(t, FmtLong)) Yyerror("type %2v larger than address space", t)
} }
} }
w = t.NumElem() * t.Elem().Width w = t.NumElem() * t.Elem().Width
......
...@@ -807,7 +807,7 @@ func (p *exporter) typ(t *Type) { ...@@ -807,7 +807,7 @@ func (p *exporter) typ(t *Type) {
p.typ(t.Elem()) p.typ(t.Elem())
default: default:
Fatalf("exporter: unexpected type: %s (Etype = %d)", Tconv(t, 0), t.Etype) Fatalf("exporter: unexpected type: %s (Etype = %d)", t, t.Etype)
} }
} }
......
...@@ -235,7 +235,7 @@ func (p *importer) verifyTypes() { ...@@ -235,7 +235,7 @@ func (p *importer) verifyTypes() {
pt := pair.pt pt := pair.pt
t := pair.t t := pair.t
if !Eqtype(pt.Orig, t) { if !Eqtype(pt.Orig, t) {
formatErrorf("inconsistent definition for type %v during import\n\t%v (in %q)\n\t%v (in %q)", pt.Sym, Tconv(pt, FmtLong), pt.Sym.Importdef.Path, Tconv(t, FmtLong), importpkg.Path) formatErrorf("inconsistent definition for type %v during import\n\t%2v (in %q)\n\t%2v (in %q)", pt.Sym, pt, pt.Sym.Importdef.Path, t, importpkg.Path)
} }
} }
} }
...@@ -416,7 +416,7 @@ func (p *importer) importtype(pt, t *Type) { ...@@ -416,7 +416,7 @@ func (p *importer) importtype(pt, t *Type) {
} }
if Debug['E'] != 0 { if Debug['E'] != 0 {
fmt.Printf("import type %v %v\n", pt, Tconv(t, FmtLong)) fmt.Printf("import type %v %2v\n", pt, t)
} }
} }
......
...@@ -599,7 +599,7 @@ func cgen_wb(n, res *Node, wb bool) { ...@@ -599,7 +599,7 @@ func cgen_wb(n, res *Node, wb bool) {
break break
} }
Fatalf("cgen: OLEN: unknown type %v", Tconv(nl.Type, FmtLong)) Fatalf("cgen: OLEN: unknown type %2v", nl.Type)
case OCAP: case OCAP:
if nl.Type.IsChan() { if nl.Type.IsChan() {
...@@ -637,7 +637,7 @@ func cgen_wb(n, res *Node, wb bool) { ...@@ -637,7 +637,7 @@ func cgen_wb(n, res *Node, wb bool) {
break break
} }
Fatalf("cgen: OCAP: unknown type %v", Tconv(nl.Type, FmtLong)) Fatalf("cgen: OCAP: unknown type %2v", nl.Type)
case OADDR: case OADDR:
if n.Bounded { // let race detector avoid nil checks if n.Bounded { // let race detector avoid nil checks
......
...@@ -540,9 +540,9 @@ func makepartialcall(fn *Node, t0 *Type, meth *Sym) *Node { ...@@ -540,9 +540,9 @@ func makepartialcall(fn *Node, t0 *Type, meth *Sym) *Node {
rcvrtype := fn.Left.Type rcvrtype := fn.Left.Type
if exportname(meth.Name) { if exportname(meth.Name) {
p = fmt.Sprintf("(%v).%s-fm", Tconv(rcvrtype, FmtLeft|FmtShort), meth.Name) p = fmt.Sprintf("(%-1v).%s-fm", rcvrtype, meth.Name)
} else { } else {
p = fmt.Sprintf("(%v).(%v)-fm", Tconv(rcvrtype, FmtLeft|FmtShort), sconv(meth, FmtLeft)) p = fmt.Sprintf("(%-1v).(%v)-fm", rcvrtype, sconv(meth, FmtLeft))
} }
basetype := rcvrtype basetype := rcvrtype
if rcvrtype.IsPtr() { if rcvrtype.IsPtr() {
......
...@@ -1595,7 +1595,7 @@ func (n *Node) Convconst(con *Node, t *Type) { ...@@ -1595,7 +1595,7 @@ func (n *Node) Convconst(con *Node, t *Type) {
var i int64 var i int64
switch n.Val().Ctype() { switch n.Val().Ctype() {
default: default:
Fatalf("convconst ctype=%d %v", n.Val().Ctype(), Tconv(t, FmtLong)) Fatalf("convconst ctype=%d %2v", n.Val().Ctype(), t)
case CTINT, CTRUNE: case CTINT, CTRUNE:
i = n.Int64() i = n.Int64()
...@@ -1632,7 +1632,7 @@ func (n *Node) Convconst(con *Node, t *Type) { ...@@ -1632,7 +1632,7 @@ func (n *Node) Convconst(con *Node, t *Type) {
return return
} }
Fatalf("convconst %v constant", Tconv(t, FmtLong)) Fatalf("convconst %2v constant", t)
} }
// complex multiply v *= rv // complex multiply v *= rv
......
...@@ -1095,15 +1095,15 @@ func methodsym(nsym *Sym, t0 *Type, iface int) *Sym { ...@@ -1095,15 +1095,15 @@ func methodsym(nsym *Sym, t0 *Type, iface int) *Sym {
if (spkg == nil || nsym.Pkg != spkg) && !exportname(nsym.Name) { if (spkg == nil || nsym.Pkg != spkg) && !exportname(nsym.Name) {
if t0.Sym == nil && t0.IsPtr() { if t0.Sym == nil && t0.IsPtr() {
p = fmt.Sprintf("(%v).%s.%s%s", Tconv(t0, FmtLeft|FmtShort), nsym.Pkg.Prefix, nsym.Name, suffix) p = fmt.Sprintf("(%-1v).%s.%s%s", t0, nsym.Pkg.Prefix, nsym.Name, suffix)
} else { } else {
p = fmt.Sprintf("%v.%s.%s%s", Tconv(t0, FmtLeft|FmtShort), nsym.Pkg.Prefix, nsym.Name, suffix) p = fmt.Sprintf("%-1v.%s.%s%s", t0, nsym.Pkg.Prefix, nsym.Name, suffix)
} }
} else { } else {
if t0.Sym == nil && t0.IsPtr() { if t0.Sym == nil && t0.IsPtr() {
p = fmt.Sprintf("(%v).%s%s", Tconv(t0, FmtLeft|FmtShort), nsym.Name, suffix) p = fmt.Sprintf("(%-1v).%s%s", t0, nsym.Name, suffix)
} else { } else {
p = fmt.Sprintf("%v.%s%s", Tconv(t0, FmtLeft|FmtShort), nsym.Name, suffix) p = fmt.Sprintf("%-1v.%s%s", t0, nsym.Name, suffix)
} }
} }
...@@ -1190,7 +1190,7 @@ func addmethod(msym *Sym, t *Type, local, nointerface bool) { ...@@ -1190,7 +1190,7 @@ func addmethod(msym *Sym, t *Type, local, nointerface bool) {
default: default:
// Should have picked off all the reasons above, // Should have picked off all the reasons above,
// but just in case, fall back to generic error. // but just in case, fall back to generic error.
Yyerror("invalid receiver type %v (%v / %v)", pa, Tconv(pa, FmtLong), Tconv(t, FmtLong)) Yyerror("invalid receiver type %v (%2v / %2v)", pa, pa, t)
} }
return return
} }
......
...@@ -340,7 +340,7 @@ func importvar(s *Sym, t *Type) { ...@@ -340,7 +340,7 @@ func importvar(s *Sym, t *Type) {
declare(n, PEXTERN) declare(n, PEXTERN)
if Debug['E'] != 0 { if Debug['E'] != 0 {
fmt.Printf("import var %v %v\n", s, Tconv(t, FmtLong)) fmt.Printf("import var %v %2v\n", s, t)
} }
} }
...@@ -362,11 +362,11 @@ func importtype(pt *Type, t *Type) { ...@@ -362,11 +362,11 @@ func importtype(pt *Type, t *Type) {
declare(n, PEXTERN) declare(n, PEXTERN)
checkwidth(pt) checkwidth(pt)
} else if !Eqtype(pt.Orig, t) { } else if !Eqtype(pt.Orig, t) {
Yyerror("inconsistent definition for type %v during import\n\t%v (in %q)\n\t%v (in %q)", pt.Sym, Tconv(pt, FmtLong), pt.Sym.Importdef.Path, Tconv(t, FmtLong), importpkg.Path) Yyerror("inconsistent definition for type %v during import\n\t%2v (in %q)\n\t%2v (in %q)", pt.Sym, pt, pt.Sym.Importdef.Path, t, importpkg.Path)
} }
if Debug['E'] != 0 { if Debug['E'] != 0 {
fmt.Printf("import type %v %v\n", pt, Tconv(t, FmtLong)) fmt.Printf("import type %v %2v\n", pt, t)
} }
} }
......
...@@ -585,21 +585,24 @@ var basicnames = []string{ ...@@ -585,21 +585,24 @@ var basicnames = []string{
TBLANK: "blank", TBLANK: "blank",
} }
func (p *printer) typefmt(t *Type, flag FmtFlag) *printer { func (t *Type) typefmt(s fmt.State, flag FmtFlag) {
if t == nil { if t == nil {
return p.s("<T>") fmt.Fprint(s, "<T>")
return
} }
if t == bytetype || t == runetype { if t == bytetype || t == runetype {
// in %-T mode collapse rune and byte with their originals. // in %-T mode collapse rune and byte with their originals.
if fmtmode != FTypeId { if fmtmode != FTypeId {
return p.sconv(t.Sym, FmtShort) fmt.Fprintf(s, "%1v", t.Sym)
return
} }
t = Types[t.Etype] t = Types[t.Etype]
} }
if t == errortype { if t == errortype {
return p.s("error") fmt.Fprint(s, "error")
return
} }
// Unless the 'l' flag was specified, if the type has a name, just print that name. // Unless the 'l' flag was specified, if the type has a name, just print that name.
...@@ -608,120 +611,134 @@ func (p *printer) typefmt(t *Type, flag FmtFlag) *printer { ...@@ -608,120 +611,134 @@ func (p *printer) typefmt(t *Type, flag FmtFlag) *printer {
case FTypeId: case FTypeId:
if flag&FmtShort != 0 { if flag&FmtShort != 0 {
if t.Vargen != 0 { if t.Vargen != 0 {
return p.f("%v·%d", sconv(t.Sym, FmtShort), t.Vargen) fmt.Fprintf(s, "%v·%d", sconv(t.Sym, FmtShort), t.Vargen)
return
} }
return p.sconv(t.Sym, FmtShort) fmt.Fprint(s, sconv(t.Sym, FmtShort))
return
} }
if flag&FmtUnsigned != 0 { if flag&FmtUnsigned != 0 {
return p.sconv(t.Sym, FmtUnsigned) fmt.Fprint(s, sconv(t.Sym, FmtUnsigned))
return
} }
if t.Sym.Pkg == localpkg && t.Vargen != 0 { if t.Sym.Pkg == localpkg && t.Vargen != 0 {
return p.f("%v·%d", t.Sym, t.Vargen) fmt.Fprintf(s, "%v·%d", t.Sym, t.Vargen)
return
} }
} }
return p.sconv(t.Sym, 0) fmt.Fprint(s, sconv(t.Sym, 0))
return
} }
if int(t.Etype) < len(basicnames) && basicnames[t.Etype] != "" { if int(t.Etype) < len(basicnames) && basicnames[t.Etype] != "" {
if fmtmode == FErr && (t == idealbool || t == idealstring) { if fmtmode == FErr && (t == idealbool || t == idealstring) {
p.s("untyped ") fmt.Fprint(s, "untyped ")
} }
return p.s(basicnames[t.Etype]) fmt.Fprint(s, basicnames[t.Etype])
return
} }
if fmtmode == FDbg { if fmtmode == FDbg {
fmtmode = 0 fmtmode = 0
p.s(t.Etype.String()).s("-").typefmt(t, flag) fmt.Fprintf(s, "%v-", t.Etype)
t.typefmt(s, flag)
fmtmode = FDbg fmtmode = FDbg
return p return
} }
switch t.Etype { switch t.Etype {
case TPTR32, TPTR64: case TPTR32, TPTR64:
if fmtmode == FTypeId && (flag&FmtShort != 0) { if fmtmode == FTypeId && (flag&FmtShort != 0) {
return p.s("*" + Tconv(t.Elem(), FmtShort)) fmt.Fprintf(s, "*%1v", t.Elem())
return
} }
return p.s("*" + t.Elem().String()) fmt.Fprint(s, "*"+t.Elem().String())
return
case TARRAY: case TARRAY:
if t.isDDDArray() { if t.isDDDArray() {
return p.s("[...]" + t.Elem().String()) fmt.Fprint(s, "[...]"+t.Elem().String())
return
} }
return p.f("[%d]%v", t.NumElem(), t.Elem()) fmt.Fprintf(s, "[%d]%v", t.NumElem(), t.Elem())
return
case TSLICE: case TSLICE:
return p.s("[]" + t.Elem().String()) fmt.Fprint(s, "[]"+t.Elem().String())
return
case TCHAN: case TCHAN:
switch t.ChanDir() { switch t.ChanDir() {
case Crecv: case Crecv:
return p.s("<-chan " + t.Elem().String()) fmt.Fprint(s, "<-chan "+t.Elem().String())
return
case Csend: case Csend:
return p.s("chan<- " + t.Elem().String()) fmt.Fprint(s, "chan<- "+t.Elem().String())
return
} }
if t.Elem() != nil && t.Elem().IsChan() && t.Elem().Sym == nil && t.Elem().ChanDir() == Crecv { if t.Elem() != nil && t.Elem().IsChan() && t.Elem().Sym == nil && t.Elem().ChanDir() == Crecv {
return p.s("chan (" + t.Elem().String() + ")") fmt.Fprint(s, "chan ("+t.Elem().String()+")")
return
} }
return p.s("chan " + t.Elem().String()) fmt.Fprint(s, "chan "+t.Elem().String())
return
case TMAP: case TMAP:
return p.s("map[" + t.Key().String() + "]" + t.Val().String()) fmt.Fprint(s, "map["+t.Key().String()+"]"+t.Val().String())
return
case TINTER: case TINTER:
p.s("interface {") fmt.Fprint(s, "interface {")
for i, f := range t.Fields().Slice() { for i, f := range t.Fields().Slice() {
if i != 0 { if i != 0 {
p.s(";") fmt.Fprint(s, ";")
} }
p.s(" ") fmt.Fprint(s, " ")
switch { switch {
case f.Sym == nil: case f.Sym == nil:
// Check first that a symbol is defined for this type. // Check first that a symbol is defined for this type.
// Wrong interface definitions may have types lacking a symbol. // Wrong interface definitions may have types lacking a symbol.
break break
case exportname(f.Sym.Name): case exportname(f.Sym.Name):
p.sconv(f.Sym, FmtShort) fmt.Fprint(s, sconv(f.Sym, FmtShort))
default: default:
p.sconv(f.Sym, FmtUnsigned) fmt.Fprint(s, sconv(f.Sym, FmtUnsigned))
} }
p.Tconv(f.Type, FmtShort) fmt.Fprintf(s, "%1v", f.Type)
} }
if t.NumFields() != 0 { if t.NumFields() != 0 {
p.s(" ") fmt.Fprint(s, " ")
} }
return p.s("}") fmt.Fprint(s, "}")
return
case TFUNC: case TFUNC:
if flag&FmtShort != 0 { if flag&FmtShort != 0 {
// no leading func // no leading func
} else { } else {
if t.Recv() != nil { if t.Recv() != nil {
p.s("method") fmt.Fprintf(s, "method %v ", t.Recvs())
p.Tconv(t.Recvs(), 0)
p.s(" ")
} }
p.s("func") fmt.Fprint(s, "func")
} }
p.Tconv(t.Params(), 0) fmt.Fprintf(s, "%v", t.Params())
switch t.Results().NumFields() { switch t.Results().NumFields() {
case 0: case 0:
// nothing to do // nothing to do
case 1: case 1:
p.s(" ") fmt.Fprintf(s, " %v", t.Results().Field(0).Type) // struct->field->field's type
p.Tconv(t.Results().Field(0).Type, 0) // struct->field->field's type
default: default:
p.s(" ") fmt.Fprintf(s, " %v", t.Results())
p.Tconv(t.Results(), 0)
} }
return p return
case TSTRUCT: case TSTRUCT:
if m := t.StructType().Map; m != nil { if m := t.StructType().Map; m != nil {
...@@ -729,67 +746,75 @@ func (p *printer) typefmt(t *Type, flag FmtFlag) *printer { ...@@ -729,67 +746,75 @@ func (p *printer) typefmt(t *Type, flag FmtFlag) *printer {
// Format the bucket struct for map[x]y as map.bucket[x]y. // Format the bucket struct for map[x]y as map.bucket[x]y.
// This avoids a recursive print that generates very long names. // This avoids a recursive print that generates very long names.
if mt.Bucket == t { if mt.Bucket == t {
return p.s("map.bucket[" + m.Key().String() + "]" + m.Val().String()) fmt.Fprint(s, "map.bucket["+m.Key().String()+"]"+m.Val().String())
return
} }
if mt.Hmap == t { if mt.Hmap == t {
return p.s("map.hdr[" + m.Key().String() + "]" + m.Val().String()) fmt.Fprint(s, "map.hdr["+m.Key().String()+"]"+m.Val().String())
return
} }
if mt.Hiter == t { if mt.Hiter == t {
return p.s("map.iter[" + m.Key().String() + "]" + m.Val().String()) fmt.Fprint(s, "map.iter["+m.Key().String()+"]"+m.Val().String())
return
} }
Yyerror("unknown internal map type") Yyerror("unknown internal map type")
} }
if t.IsFuncArgStruct() { if t.IsFuncArgStruct() {
p.s("(") fmt.Fprint(s, "(")
var flag1 FmtFlag var flag1 FmtFlag
if fmtmode == FTypeId || fmtmode == FErr { // no argument names on function signature, and no "noescape"/"nosplit" tags if fmtmode == FTypeId || fmtmode == FErr { // no argument names on function signature, and no "noescape"/"nosplit" tags
flag1 = FmtShort flag1 = FmtShort
} }
for i, f := range t.Fields().Slice() { for i, f := range t.Fields().Slice() {
if i != 0 { if i != 0 {
p.s(", ") fmt.Fprint(s, ", ")
} }
p.s(Fldconv(f, flag1)) fmt.Fprint(s, Fldconv(f, flag1))
} }
p.s(")") fmt.Fprint(s, ")")
} else { } else {
p.s("struct {") fmt.Fprint(s, "struct {")
for i, f := range t.Fields().Slice() { for i, f := range t.Fields().Slice() {
if i != 0 { if i != 0 {
p.s(";") fmt.Fprint(s, ";")
} }
p.s(" ") fmt.Fprint(s, " ")
p.s(Fldconv(f, FmtLong)) fmt.Fprint(s, Fldconv(f, FmtLong))
} }
if t.NumFields() != 0 { if t.NumFields() != 0 {
p.s(" ") fmt.Fprint(s, " ")
} }
p.s("}") fmt.Fprint(s, "}")
} }
return p return
case TFORW: case TFORW:
if t.Sym != nil { if t.Sym != nil {
return p.s("undefined " + t.Sym.String()) fmt.Fprint(s, "undefined "+t.Sym.String())
return
} }
return p.s("undefined") fmt.Fprint(s, "undefined")
return
case TUNSAFEPTR: case TUNSAFEPTR:
return p.s("unsafe.Pointer") fmt.Fprint(s, "unsafe.Pointer")
return
case TDDDFIELD: case TDDDFIELD:
return p.f("%v <%v> %v", t.Etype, t.Sym, t.DDDField()) fmt.Fprintf(s, "%v <%v> %v", t.Etype, t.Sym, t.DDDField())
return
case Txxx: case Txxx:
return p.s("Txxx") fmt.Fprint(s, "Txxx")
return
} }
// Don't know how to handle - fall back to detailed prints. // Don't know how to handle - fall back to detailed prints.
return p.f("%v <%v> %v", t.Etype, t.Sym, t.Elem()) fmt.Fprintf(s, "%v <%v> %v", t.Etype, t.Sym, t.Elem())
} }
// Statements which may be rendered with a simplestmt as init. // Statements which may be rendered with a simplestmt as init.
...@@ -1175,7 +1200,7 @@ func (p *printer) exprfmt(n *Node, prec int) *printer { ...@@ -1175,7 +1200,7 @@ func (p *printer) exprfmt(n *Node, prec int) *printer {
if n.Type == nil && n.Sym != nil { if n.Type == nil && n.Sym != nil {
return p.sconv(n.Sym, 0) return p.sconv(n.Sym, 0)
} }
return p.Tconv(n.Type, 0) return p.f("%v", n.Type)
case OTARRAY: case OTARRAY:
if n.Left != nil { if n.Left != nil {
...@@ -1572,14 +1597,8 @@ func (p *printer) sconv(s *Sym, flag FmtFlag) *printer { ...@@ -1572,14 +1597,8 @@ func (p *printer) sconv(s *Sym, flag FmtFlag) *printer {
return p return p
} }
func (t *Type) Print(p *printer) {
p.Tconv(t, 0)
}
var _ Printable = new(Type) // verify Type implements Printable
func (t *Type) String() string { func (t *Type) String() string {
return Tconv(t, 0) return fmt.Sprint(t)
} }
func Fldconv(f *Field, flag FmtFlag) string { func Fldconv(f *Field, flag FmtFlag) string {
...@@ -1634,9 +1653,9 @@ func Fldconv(f *Field, flag FmtFlag) string { ...@@ -1634,9 +1653,9 @@ func Fldconv(f *Field, flag FmtFlag) string {
var typ string var typ string
if f.Isddd { if f.Isddd {
typ = "..." + Tconv(f.Type.Elem(), 0) typ = fmt.Sprintf("...%v", f.Type.Elem())
} else { } else {
typ = Tconv(f.Type, 0) typ = fmt.Sprintf("%v", f.Type)
} }
str := typ str := typ
...@@ -1657,21 +1676,31 @@ func Fldconv(f *Field, flag FmtFlag) string { ...@@ -1657,21 +1676,31 @@ func Fldconv(f *Field, flag FmtFlag) string {
return str return str
} }
func (t *Type) Format(s fmt.State, format rune) {
switch format {
case 's', 'v':
t.tconv(s)
default:
fmt.Fprintf(s, "%%!%c(*Type=%p)", format, t)
}
}
// Fmt "%T": types. // Fmt "%T": types.
// Flags: 'l' print definition, not name // Flags: 'l' print definition, not name
// 'h' omit 'func' and receiver from function types, short type names // 'h' omit 'func' and receiver from function types, short type names
// 'u' package name, not prefix (FTypeId mode, sticky) // 'u' package name, not prefix (FTypeId mode, sticky)
func Tconv(t *Type, flag FmtFlag) string { func (t *Type) tconv(s fmt.State) {
return new(printer).Tconv(t, flag).String() flag := fmtFlag(s)
}
func (p *printer) Tconv(t *Type, flag FmtFlag) *printer {
if t == nil { if t == nil {
return p.s("<T>") fmt.Fprint(s, "<T>")
return
} }
if t.Trecur > 4 { if t.Trecur > 4 {
return p.s("<...>") fmt.Fprint(s, "<...>")
return
} }
t.Trecur++ t.Trecur++
...@@ -1685,7 +1714,7 @@ func (p *printer) Tconv(t *Type, flag FmtFlag) *printer { ...@@ -1685,7 +1714,7 @@ func (p *printer) Tconv(t *Type, flag FmtFlag) *printer {
flag |= FmtUnsigned flag |= FmtUnsigned
} }
p.typefmt(t, flag) t.typefmt(s, flag)
if fmtmode == FTypeId && (sf&FmtUnsigned != 0) { if fmtmode == FTypeId && (sf&FmtUnsigned != 0) {
fmtpkgpfx-- fmtpkgpfx--
...@@ -1694,8 +1723,6 @@ func (p *printer) Tconv(t *Type, flag FmtFlag) *printer { ...@@ -1694,8 +1723,6 @@ func (p *printer) Tconv(t *Type, flag FmtFlag) *printer {
flag = sf flag = sf
fmtmode = sm fmtmode = sm
t.Trecur-- t.Trecur--
return p
} }
func (n *Node) Print(p *printer) { func (n *Node) Print(p *printer) {
......
...@@ -1208,7 +1208,7 @@ func componentgen_wb(nr, nl *Node, wb bool) bool { ...@@ -1208,7 +1208,7 @@ func componentgen_wb(nr, nl *Node, wb bool) bool {
visitComponents(nl.Type, 0, func(t *Type, offset int64) bool { visitComponents(nl.Type, 0, func(t *Type, offset int64) bool {
if wb && Simtype[t.Etype] == Tptr && t != itable { if wb && Simtype[t.Etype] == Tptr && t != itable {
if ptrType != nil { if ptrType != nil {
Fatalf("componentgen_wb %v", Tconv(nl.Type, 0)) Fatalf("componentgen_wb %v", nl.Type)
} }
ptrType = t ptrType = t
ptrOffset = offset ptrOffset = offset
......
...@@ -420,7 +420,7 @@ func Naddr(a *obj.Addr, n *Node) { ...@@ -420,7 +420,7 @@ func Naddr(a *obj.Addr, n *Node) {
} }
switch u := n.Val().U.(type) { switch u := n.Val().U.(type) {
default: default:
Fatalf("naddr: const %v", Tconv(n.Type, FmtLong)) Fatalf("naddr: const %2v", n.Type)
case *Mpflt: case *Mpflt:
a.Type = obj.TYPE_FCONST a.Type = obj.TYPE_FCONST
......
...@@ -165,7 +165,7 @@ func caninl(fn *Node) { ...@@ -165,7 +165,7 @@ func caninl(fn *Node) {
fn.Type.SetNname(n) fn.Type.SetNname(n)
if Debug['m'] > 1 { if Debug['m'] > 1 {
fmt.Printf("%v: can inline %v as: %v { %v }\n", fn.Line(), Nconv(n, FmtSharp), Tconv(fn.Type, FmtSharp), hconv(n.Func.Inl, FmtSharp)) fmt.Printf("%v: can inline %v as: %#v { %v }\n", fn.Line(), Nconv(n, FmtSharp), fn.Type, hconv(n.Func.Inl, FmtSharp))
} else if Debug['m'] != 0 { } else if Debug['m'] != 0 {
fmt.Printf("%v: can inline %v\n", fn.Line(), n) fmt.Printf("%v: can inline %v\n", fn.Line(), n)
} }
...@@ -214,7 +214,7 @@ func ishairy(n *Node, budget *int32, reason *string) bool { ...@@ -214,7 +214,7 @@ func ishairy(n *Node, budget *int32, reason *string) bool {
Fatalf("no function type for [%p] %v\n", n.Left, Nconv(n.Left, FmtSign)) Fatalf("no function type for [%p] %v\n", n.Left, Nconv(n.Left, FmtSign))
} }
if t.Nname() == nil { if t.Nname() == nil {
Fatalf("no function definition for [%p] %v\n", t, Tconv(t, FmtSign)) Fatalf("no function definition for [%p] %+v\n", t, t)
} }
if inlfn := t.Nname().Func; inlfn.Inl.Len() != 0 { if inlfn := t.Nname().Func; inlfn.Inl.Len() != 0 {
*budget -= inlfn.InlCost *budget -= inlfn.InlCost
...@@ -494,7 +494,7 @@ func inlnode(n *Node) *Node { ...@@ -494,7 +494,7 @@ func inlnode(n *Node) *Node {
} }
if n.Left.Type.Nname() == nil { if n.Left.Type.Nname() == nil {
Fatalf("no function definition for [%p] %v\n", n.Left.Type, Tconv(n.Left.Type, FmtSign)) Fatalf("no function definition for [%p] %+v\n", n.Left.Type, n.Left.Type)
} }
n = mkinlcall(n, n.Left.Type.Nname(), n.Isddd) n = mkinlcall(n, n.Left.Type.Nname(), n.Isddd)
...@@ -556,7 +556,7 @@ func mkinlcall1(n *Node, fn *Node, isddd bool) *Node { ...@@ -556,7 +556,7 @@ func mkinlcall1(n *Node, fn *Node, isddd bool) *Node {
// Bingo, we have a function node, and it has an inlineable body // Bingo, we have a function node, and it has an inlineable body
if Debug['m'] > 1 { if Debug['m'] > 1 {
fmt.Printf("%v: inlining call to %v %v { %v }\n", n.Line(), fn.Sym, Tconv(fn.Type, FmtSharp), hconv(fn.Func.Inl, FmtSharp)) fmt.Printf("%v: inlining call to %v %#v { %v }\n", n.Line(), fn.Sym, fn.Type, hconv(fn.Func.Inl, FmtSharp))
} else if Debug['m'] != 0 { } else if Debug['m'] != 0 {
fmt.Printf("%v: inlining call to %v\n", n.Line(), fn) fmt.Printf("%v: inlining call to %v\n", n.Line(), fn)
} }
...@@ -752,7 +752,7 @@ func mkinlcall1(n *Node, fn *Node, isddd bool) *Node { ...@@ -752,7 +752,7 @@ func mkinlcall1(n *Node, fn *Node, isddd bool) *Node {
} }
if li < n.List.Len() || t != nil { if li < n.List.Len() || t != nil {
Fatalf("arg count mismatch: %v vs %v\n", Tconv(fn.Type.Params(), FmtSharp), hconv(n.List, FmtComma)) Fatalf("arg count mismatch: %#v vs %v\n", fn.Type.Params(), hconv(n.List, FmtComma))
} }
} }
......
...@@ -864,7 +864,7 @@ func dcommontype(s *Sym, ot int, t *Type) int { ...@@ -864,7 +864,7 @@ func dcommontype(s *Sym, ot int, t *Type) int {
} }
exported := false exported := false
p := Tconv(t, FmtLeft|FmtUnsigned) p := fmt.Sprintf("%- v", t)
// If we're writing out type T, // If we're writing out type T,
// we are very likely to write out type *T as well. // we are very likely to write out type *T as well.
// Use the string "*T"[1:] for "T", so that the two // Use the string "*T"[1:] for "T", so that the two
...@@ -926,22 +926,22 @@ func dcommontype(s *Sym, ot int, t *Type) int { ...@@ -926,22 +926,22 @@ func dcommontype(s *Sym, ot int, t *Type) int {
} }
func typesym(t *Type) *Sym { func typesym(t *Type) *Sym {
return Pkglookup(Tconv(t, FmtLeft), typepkg) return Pkglookup(fmt.Sprintf("%-v", t), typepkg)
} }
// tracksym returns the symbol for tracking use of field/method f, assumed // tracksym returns the symbol for tracking use of field/method f, assumed
// to be a member of struct/interface type t. // to be a member of struct/interface type t.
func tracksym(t *Type, f *Field) *Sym { func tracksym(t *Type, f *Field) *Sym {
return Pkglookup(Tconv(t, FmtLeft)+"."+f.Sym.Name, trackpkg) return Pkglookup(fmt.Sprintf("%-v.%s", t, f.Sym.Name), trackpkg)
} }
func typelinkLSym(t *Type) *obj.LSym { func typelinkLSym(t *Type) *obj.LSym {
name := "go.typelink." + Tconv(t, FmtLeft) // complete, unambiguous type name name := fmt.Sprintf("go.typelink.%-v", t) // complete, unambiguous type name
return obj.Linklookup(Ctxt, name, 0) return obj.Linklookup(Ctxt, name, 0)
} }
func typesymprefix(prefix string, t *Type) *Sym { func typesymprefix(prefix string, t *Type) *Sym {
p := prefix + "." + Tconv(t, FmtLeft) p := fmt.Sprintf("%s.%-v", prefix, t)
s := Pkglookup(p, typepkg) s := Pkglookup(p, typepkg)
//print("algsym: %s -> %+S\n", p, s); //print("algsym: %s -> %+S\n", p, s);
...@@ -981,7 +981,7 @@ func itabname(t, itype *Type) *Node { ...@@ -981,7 +981,7 @@ func itabname(t, itype *Type) *Node {
if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() { if t == nil || (t.IsPtr() && t.Elem() == nil) || t.IsUntyped() {
Fatalf("itabname %v", t) Fatalf("itabname %v", t)
} }
s := Pkglookup(Tconv(t, FmtLeft)+","+Tconv(itype, FmtLeft), itabpkg) s := Pkglookup(fmt.Sprintf("%-v,%-v", t, itype), itabpkg)
if s.Def == nil { if s.Def == nil {
n := newname(s) n := newname(s)
n.Type = Types[TUINT8] n.Type = Types[TUINT8]
...@@ -1406,7 +1406,7 @@ func dumptypestructs() { ...@@ -1406,7 +1406,7 @@ func dumptypestructs() {
// method functions. None are allocated on heap, so we can use obj.NOPTR. // method functions. None are allocated on heap, so we can use obj.NOPTR.
ggloblsym(i.sym, int32(o), int16(obj.DUPOK|obj.NOPTR)) ggloblsym(i.sym, int32(o), int16(obj.DUPOK|obj.NOPTR))
ilink := Pkglookup(Tconv(i.t, FmtLeft)+","+Tconv(i.itype, FmtLeft), itablinkpkg) ilink := Pkglookup(fmt.Sprintf("%-v,%-v", i.t, i.itype), itablinkpkg)
dsymptr(ilink, 0, i.sym, 0) dsymptr(ilink, 0, i.sym, 0)
ggloblsym(ilink, int32(Widthptr), int16(obj.DUPOK|obj.RODATA)) ggloblsym(ilink, int32(Widthptr), int16(obj.DUPOK|obj.RODATA))
} }
......
...@@ -810,11 +810,11 @@ func assignop(src *Type, dst *Type, why *string) Op { ...@@ -810,11 +810,11 @@ func assignop(src *Type, dst *Type, why *string) Op {
} else if have != nil && have.Sym == missing.Sym && have.Nointerface { } else if have != nil && have.Sym == missing.Sym && have.Nointerface {
*why = fmt.Sprintf(":\n\t%v does not implement %v (%v method is marked 'nointerface')", src, dst, missing.Sym) *why = fmt.Sprintf(":\n\t%v does not implement %v (%v method is marked 'nointerface')", src, dst, missing.Sym)
} else if have != nil && have.Sym == missing.Sym { } else if have != nil && have.Sym == missing.Sym {
*why = fmt.Sprintf(":\n\t%v does not implement %v (wrong type for %v method)\n"+"\t\thave %v%v\n\t\twant %v%v", src, dst, missing.Sym, have.Sym, Tconv(have.Type, FmtShort|FmtByte), missing.Sym, Tconv(missing.Type, FmtShort|FmtByte)) *why = fmt.Sprintf(":\n\t%v does not implement %v (wrong type for %v method)\n"+"\t\thave %v%01v\n\t\twant %v%01v", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
} else if ptr != 0 { } else if ptr != 0 {
*why = fmt.Sprintf(":\n\t%v does not implement %v (%v method has pointer receiver)", src, dst, missing.Sym) *why = fmt.Sprintf(":\n\t%v does not implement %v (%v method has pointer receiver)", src, dst, missing.Sym)
} else if have != nil { } else if have != nil {
*why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)\n"+"\t\thave %v%v\n\t\twant %v%v", src, dst, missing.Sym, have.Sym, Tconv(have.Type, FmtShort|FmtByte), missing.Sym, Tconv(missing.Type, FmtShort|FmtByte)) *why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)\n"+"\t\thave %v%01v\n\t\twant %v%01v", src, dst, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
} else { } else {
*why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)", src, dst, missing.Sym) *why = fmt.Sprintf(":\n\t%v does not implement %v (missing %v method)", src, dst, missing.Sym)
} }
...@@ -1139,10 +1139,10 @@ func syslook(name string) *Node { ...@@ -1139,10 +1139,10 @@ func syslook(name string) *Node {
// typehash computes a hash value for type t to use in type switch // typehash computes a hash value for type t to use in type switch
// statements. // statements.
func typehash(t *Type) uint32 { func typehash(t *Type) uint32 {
// Tconv already contains all the necessary logic to generate // fmt.Sprintf("%- v", t) already contains all the necessary logic to generate
// a representation that completely describes the type, so using // a representation that completely describes the type, so using
// it here avoids duplicating that code. // it here avoids duplicating that code.
p := Tconv(t, FmtLeft|FmtUnsigned) p := fmt.Sprintf("%- v", t)
// Using MD5 is overkill, but reduces accidental collisions. // Using MD5 is overkill, but reduces accidental collisions.
h := md5.Sum([]byte(p)) h := md5.Sum([]byte(p))
......
...@@ -4,7 +4,10 @@ ...@@ -4,7 +4,10 @@
package gc package gc
import "sort" import (
"fmt"
"sort"
)
const ( const (
// expression switch // expression switch
...@@ -162,7 +165,7 @@ func typecheckswitch(n *Node) { ...@@ -162,7 +165,7 @@ func typecheckswitch(n *Node) {
ls[i1] = n1 ls[i1] = n1
case !n1.Type.IsInterface() && t.IsInterface() && !implements(n1.Type, t, &missing, &have, &ptr): case !n1.Type.IsInterface() && t.IsInterface() && !implements(n1.Type, t, &missing, &have, &ptr):
if have != nil && !missing.Broke && !have.Broke { if have != nil && !missing.Broke && !have.Broke {
Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (wrong type for %v method)\n\thave %v%v\n\twant %v%v", Nconv(n.Left.Right, FmtLong), n1.Type, missing.Sym, have.Sym, Tconv(have.Type, FmtShort), missing.Sym, Tconv(missing.Type, FmtShort)) Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (wrong type for %v method)\n\thave %v%1v\n\twant %v%1v", Nconv(n.Left.Right, FmtLong), n1.Type, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
} else if !missing.Broke { } else if !missing.Broke {
Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (missing %v method)", Nconv(n.Left.Right, FmtLong), n1.Type, missing.Sym) Yyerror("impossible type switch case: %v cannot have dynamic type %v"+" (missing %v method)", Nconv(n.Left.Right, FmtLong), n1.Type, missing.Sym)
} }
...@@ -642,9 +645,9 @@ func (s *exprSwitch) checkDupCases(cc []caseClause) { ...@@ -642,9 +645,9 @@ func (s *exprSwitch) checkDupCases(cc []caseClause) {
} }
n := c.node.Left n := c.node.Left
tv := typeVal{ tv := typeVal{
// Tconv here serves to completely describe the type. // fmt.Sprintf("% -v", n.Type) here serves to completely describe the type.
// See the comments in func typehash. // See the comments in func typehash.
typ: Tconv(n.Type, FmtLeft|FmtUnsigned), typ: fmt.Sprintf("% -v", n.Type),
val: n.Val().Interface(), val: n.Val().Interface(),
} }
prev, dup := seen[tv] prev, dup := seen[tv]
......
...@@ -964,11 +964,11 @@ OpSwitch: ...@@ -964,11 +964,11 @@ OpSwitch:
var ptr int var ptr int
if !implements(n.Type, t, &missing, &have, &ptr) { if !implements(n.Type, t, &missing, &have, &ptr) {
if have != nil && have.Sym == missing.Sym { if have != nil && have.Sym == missing.Sym {
Yyerror("impossible type assertion:\n\t%v does not implement %v (wrong type for %v method)\n"+"\t\thave %v%v\n\t\twant %v%v", n.Type, t, missing.Sym, have.Sym, Tconv(have.Type, FmtShort|FmtByte), missing.Sym, Tconv(missing.Type, FmtShort|FmtByte)) Yyerror("impossible type assertion:\n\t%v does not implement %v (wrong type for %v method)\n"+"\t\thave %v%01v\n\t\twant %v%01v", n.Type, t, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
} else if ptr != 0 { } else if ptr != 0 {
Yyerror("impossible type assertion:\n\t%v does not implement %v (%v method has pointer receiver)", n.Type, t, missing.Sym) Yyerror("impossible type assertion:\n\t%v does not implement %v (%v method has pointer receiver)", n.Type, t, missing.Sym)
} else if have != nil { } else if have != nil {
Yyerror("impossible type assertion:\n\t%v does not implement %v (missing %v method)\n"+"\t\thave %v%v\n\t\twant %v%v", n.Type, t, missing.Sym, have.Sym, Tconv(have.Type, FmtShort|FmtByte), missing.Sym, Tconv(missing.Type, FmtShort|FmtByte)) Yyerror("impossible type assertion:\n\t%v does not implement %v (missing %v method)\n"+"\t\thave %v%01v\n\t\twant %v%01v", n.Type, t, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
} else { } else {
Yyerror("impossible type assertion:\n\t%v does not implement %v (missing %v method)", n.Type, t, missing.Sym) Yyerror("impossible type assertion:\n\t%v does not implement %v (missing %v method)", n.Type, t, missing.Sym)
} }
...@@ -1515,7 +1515,7 @@ OpSwitch: ...@@ -1515,7 +1515,7 @@ OpSwitch:
l := args.First() l := args.First()
r := args.Second() r := args.Second()
if l.Type != nil && !l.Type.IsMap() { if l.Type != nil && !l.Type.IsMap() {
Yyerror("first argument to delete must be map; have %v", Tconv(l.Type, FmtLong)) Yyerror("first argument to delete must be map; have %2v", l.Type)
n.Type = nil n.Type = nil
return n return n
} }
...@@ -1559,7 +1559,7 @@ OpSwitch: ...@@ -1559,7 +1559,7 @@ OpSwitch:
return n return n
} }
Yyerror("first argument to append must be slice; have %v", Tconv(t, FmtLong)) Yyerror("first argument to append must be slice; have %2v", t)
n.Type = nil n.Type = nil
return n return n
} }
...@@ -1642,25 +1642,25 @@ OpSwitch: ...@@ -1642,25 +1642,25 @@ OpSwitch:
if Eqtype(n.Left.Type.Elem(), bytetype) { if Eqtype(n.Left.Type.Elem(), bytetype) {
break OpSwitch break OpSwitch
} }
Yyerror("arguments to copy have different element types: %v and string", Tconv(n.Left.Type, FmtLong)) Yyerror("arguments to copy have different element types: %2v and string", n.Left.Type)
n.Type = nil n.Type = nil
return n return n
} }
if !n.Left.Type.IsSlice() || !n.Right.Type.IsSlice() { if !n.Left.Type.IsSlice() || !n.Right.Type.IsSlice() {
if !n.Left.Type.IsSlice() && !n.Right.Type.IsSlice() { if !n.Left.Type.IsSlice() && !n.Right.Type.IsSlice() {
Yyerror("arguments to copy must be slices; have %v, %v", Tconv(n.Left.Type, FmtLong), Tconv(n.Right.Type, FmtLong)) Yyerror("arguments to copy must be slices; have %2v, %2v", n.Left.Type, n.Right.Type)
} else if !n.Left.Type.IsSlice() { } else if !n.Left.Type.IsSlice() {
Yyerror("first argument to copy should be slice; have %v", Tconv(n.Left.Type, FmtLong)) Yyerror("first argument to copy should be slice; have %2v", n.Left.Type)
} else { } else {
Yyerror("second argument to copy should be slice or string; have %v", Tconv(n.Right.Type, FmtLong)) Yyerror("second argument to copy should be slice or string; have %2v", n.Right.Type)
} }
n.Type = nil n.Type = nil
return n return n
} }
if !Eqtype(n.Left.Type.Elem(), n.Right.Type.Elem()) { if !Eqtype(n.Left.Type.Elem(), n.Right.Type.Elem()) {
Yyerror("arguments to copy have different element types: %v and %v", Tconv(n.Left.Type, FmtLong), Tconv(n.Right.Type, FmtLong)) Yyerror("arguments to copy have different element types: %2v and %2v", n.Left.Type, n.Right.Type)
n.Type = nil n.Type = nil
return n return n
} }
......
...@@ -1875,7 +1875,7 @@ func dumpnodetypes(l []*Node, what string) string { ...@@ -1875,7 +1875,7 @@ func dumpnodetypes(l []*Node, what string) string {
if s != "" { if s != "" {
s += ", " s += ", "
} }
s += Tconv(r.Type, 0) s += r.Type.String()
} }
if s == "" { if s == "" {
s = fmt.Sprintf("[no arguments %s]", what) s = fmt.Sprintf("[no arguments %s]", what)
...@@ -3951,7 +3951,7 @@ func usemethod(n *Node) { ...@@ -3951,7 +3951,7 @@ func usemethod(n *Node) {
return return
} }
} }
if Tconv(res0.Type, 0) != "reflect.Method" { if res0.Type.String() != "reflect.Method" {
return return
} }
......
...@@ -293,7 +293,7 @@ func gmove(f *gc.Node, t *gc.Node) { ...@@ -293,7 +293,7 @@ func gmove(f *gc.Node, t *gc.Node) {
switch uint32(ft)<<16 | uint32(tt) { switch uint32(ft)<<16 | uint32(tt) {
default: default:
gc.Fatalf("gmove %v -> %v", gc.Tconv(f.Type, gc.FmtLong), gc.Tconv(t.Type, gc.FmtLong)) gc.Fatalf("gmove %2v -> %2v", f.Type, t.Type)
/* /*
* integer copy and truncate * integer copy and truncate
......
...@@ -256,7 +256,7 @@ func gmove(f *gc.Node, t *gc.Node) { ...@@ -256,7 +256,7 @@ func gmove(f *gc.Node, t *gc.Node) {
switch uint32(ft)<<16 | uint32(tt) { switch uint32(ft)<<16 | uint32(tt) {
default: default:
gc.Fatalf("gmove %v -> %v", gc.Tconv(f.Type, gc.FmtLong), gc.Tconv(t.Type, gc.FmtLong)) gc.Fatalf("gmove %2v -> %2v", f.Type, t.Type)
/* /*
* integer copy and truncate * integer copy and truncate
......
...@@ -253,7 +253,7 @@ func gmove(f *gc.Node, t *gc.Node) { ...@@ -253,7 +253,7 @@ func gmove(f *gc.Node, t *gc.Node) {
// otherwise handle and return. // otherwise handle and return.
switch uint32(ft)<<16 | uint32(tt) { switch uint32(ft)<<16 | uint32(tt) {
default: default:
gc.Fatalf("gmove %v -> %v", gc.Tconv(f.Type, gc.FmtLong), gc.Tconv(t.Type, gc.FmtLong)) gc.Fatalf("gmove %2v -> %2v", f.Type, t.Type)
// integer copy and truncate // integer copy and truncate
case gc.TINT8<<16 | gc.TINT8, case gc.TINT8<<16 | gc.TINT8,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment