mirror of
https://github.com/golang/go
synced 2024-10-14 03:43:28 +00:00
[dev.regabi] cmd/compile: update ir/fmt for concrete types
An automated rewrite will add concrete type assertions after a test of n.Op(), when n can be safely type-asserted (meaning, n is not reassigned a different type, n is not reassigned and then used outside the scope of the type assertion, and so on). This sequence of CLs handles the code that the automated rewrite does not: adding specific types to function arguments, adjusting code not to call n.Left() etc when n may have multiple representations, and so on. This CL handles package fmt. There are various type assertions but also some rewriting to lean more heavily on reflection. Passes buildall w/ toolstash -cmp. Change-Id: I503467468b42ace11bff2ba014b03cfa345e6d03 Reviewed-on: https://go-review.googlesource.com/c/go/+/277915 Trust: Russ Cox <rsc@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
a997543292
commit
4dfc7333f4
|
@ -9,6 +9,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/constant"
|
"go/constant"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
@ -141,7 +142,7 @@ func FmtNode(n Node, s fmt.State, verb rune) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if n == nil {
|
if n == nil {
|
||||||
fmt.Fprint(s, "<N>")
|
fmt.Fprint(s, "<nil>")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,12 +331,14 @@ func stmtFmt(n Node, s fmt.State) {
|
||||||
|
|
||||||
switch n.Op() {
|
switch n.Op() {
|
||||||
case ODCL:
|
case ODCL:
|
||||||
|
n := n.(*Decl)
|
||||||
fmt.Fprintf(s, "var %v %v", n.Left().Sym(), n.Left().Type())
|
fmt.Fprintf(s, "var %v %v", n.Left().Sym(), n.Left().Type())
|
||||||
|
|
||||||
// Don't export "v = <N>" initializing statements, hope they're always
|
// Don't export "v = <N>" initializing statements, hope they're always
|
||||||
// preceded by the DCL which will be re-parsed and typechecked to reproduce
|
// preceded by the DCL which will be re-parsed and typechecked to reproduce
|
||||||
// the "v = <N>" again.
|
// the "v = <N>" again.
|
||||||
case OAS:
|
case OAS:
|
||||||
|
n := n.(*AssignStmt)
|
||||||
if n.Colas() && !complexinit {
|
if n.Colas() && !complexinit {
|
||||||
fmt.Fprintf(s, "%v := %v", n.Left(), n.Right())
|
fmt.Fprintf(s, "%v := %v", n.Left(), n.Right())
|
||||||
} else {
|
} else {
|
||||||
|
@ -343,6 +346,7 @@ func stmtFmt(n Node, s fmt.State) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case OASOP:
|
case OASOP:
|
||||||
|
n := n.(*AssignOpStmt)
|
||||||
if n.Implicit() {
|
if n.Implicit() {
|
||||||
if n.SubOp() == OADD {
|
if n.SubOp() == OADD {
|
||||||
fmt.Fprintf(s, "%v++", n.Left())
|
fmt.Fprintf(s, "%v++", n.Left())
|
||||||
|
@ -355,6 +359,7 @@ func stmtFmt(n Node, s fmt.State) {
|
||||||
fmt.Fprintf(s, "%v %v= %v", n.Left(), n.SubOp(), n.Right())
|
fmt.Fprintf(s, "%v %v= %v", n.Left(), n.SubOp(), n.Right())
|
||||||
|
|
||||||
case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
|
case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
|
||||||
|
n := n.(*AssignListStmt)
|
||||||
if n.Colas() && !complexinit {
|
if n.Colas() && !complexinit {
|
||||||
fmt.Fprintf(s, "%.v := %.v", n.List(), n.Rlist())
|
fmt.Fprintf(s, "%.v := %.v", n.List(), n.Rlist())
|
||||||
} else {
|
} else {
|
||||||
|
@ -362,26 +367,33 @@ func stmtFmt(n Node, s fmt.State) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case OBLOCK:
|
case OBLOCK:
|
||||||
|
n := n.(*BlockStmt)
|
||||||
if n.List().Len() != 0 {
|
if n.List().Len() != 0 {
|
||||||
fmt.Fprintf(s, "%v", n.List())
|
fmt.Fprintf(s, "%v", n.List())
|
||||||
}
|
}
|
||||||
|
|
||||||
case ORETURN:
|
case ORETURN:
|
||||||
|
n := n.(*ReturnStmt)
|
||||||
fmt.Fprintf(s, "return %.v", n.List())
|
fmt.Fprintf(s, "return %.v", n.List())
|
||||||
|
|
||||||
case ORETJMP:
|
case ORETJMP:
|
||||||
|
n := n.(*BranchStmt)
|
||||||
fmt.Fprintf(s, "retjmp %v", n.Sym())
|
fmt.Fprintf(s, "retjmp %v", n.Sym())
|
||||||
|
|
||||||
case OINLMARK:
|
case OINLMARK:
|
||||||
|
n := n.(*InlineMarkStmt)
|
||||||
fmt.Fprintf(s, "inlmark %d", n.Offset())
|
fmt.Fprintf(s, "inlmark %d", n.Offset())
|
||||||
|
|
||||||
case OGO:
|
case OGO:
|
||||||
|
n := n.(*GoDeferStmt)
|
||||||
fmt.Fprintf(s, "go %v", n.Left())
|
fmt.Fprintf(s, "go %v", n.Left())
|
||||||
|
|
||||||
case ODEFER:
|
case ODEFER:
|
||||||
|
n := n.(*GoDeferStmt)
|
||||||
fmt.Fprintf(s, "defer %v", n.Left())
|
fmt.Fprintf(s, "defer %v", n.Left())
|
||||||
|
|
||||||
case OIF:
|
case OIF:
|
||||||
|
n := n.(*IfStmt)
|
||||||
if simpleinit {
|
if simpleinit {
|
||||||
fmt.Fprintf(s, "if %v; %v { %v }", n.Init().First(), n.Left(), n.Body())
|
fmt.Fprintf(s, "if %v; %v { %v }", n.Init().First(), n.Left(), n.Body())
|
||||||
} else {
|
} else {
|
||||||
|
@ -392,6 +404,7 @@ func stmtFmt(n Node, s fmt.State) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case OFOR, OFORUNTIL:
|
case OFOR, OFORUNTIL:
|
||||||
|
n := n.(*ForStmt)
|
||||||
opname := "for"
|
opname := "for"
|
||||||
if n.Op() == OFORUNTIL {
|
if n.Op() == OFORUNTIL {
|
||||||
opname = "foruntil"
|
opname = "foruntil"
|
||||||
|
@ -425,6 +438,7 @@ func stmtFmt(n Node, s fmt.State) {
|
||||||
fmt.Fprintf(s, " { %v }", n.Body())
|
fmt.Fprintf(s, " { %v }", n.Body())
|
||||||
|
|
||||||
case ORANGE:
|
case ORANGE:
|
||||||
|
n := n.(*RangeStmt)
|
||||||
if !exportFormat {
|
if !exportFormat {
|
||||||
fmt.Fprint(s, "for loop")
|
fmt.Fprint(s, "for loop")
|
||||||
break
|
break
|
||||||
|
@ -437,23 +451,31 @@ func stmtFmt(n Node, s fmt.State) {
|
||||||
|
|
||||||
fmt.Fprintf(s, "for %.v = range %v { %v }", n.List(), n.Right(), n.Body())
|
fmt.Fprintf(s, "for %.v = range %v { %v }", n.List(), n.Right(), n.Body())
|
||||||
|
|
||||||
case OSELECT, OSWITCH:
|
case OSELECT:
|
||||||
|
n := n.(*SelectStmt)
|
||||||
if !exportFormat {
|
if !exportFormat {
|
||||||
fmt.Fprintf(s, "%v statement", n.Op())
|
fmt.Fprintf(s, "%v statement", n.Op())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
fmt.Fprintf(s, "select { %v }", n.List())
|
||||||
|
|
||||||
fmt.Fprintf(s, "%v", n.Op())
|
case OSWITCH:
|
||||||
|
n := n.(*SwitchStmt)
|
||||||
|
if !exportFormat {
|
||||||
|
fmt.Fprintf(s, "%v statement", n.Op())
|
||||||
|
break
|
||||||
|
}
|
||||||
|
fmt.Fprintf(s, "switch")
|
||||||
if simpleinit {
|
if simpleinit {
|
||||||
fmt.Fprintf(s, " %v;", n.Init().First())
|
fmt.Fprintf(s, " %v;", n.Init().First())
|
||||||
}
|
}
|
||||||
if n.Left() != nil {
|
if n.Left() != nil {
|
||||||
fmt.Fprintf(s, " %v ", n.Left())
|
fmt.Fprintf(s, " %v ", n.Left())
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.Fprintf(s, " { %v }", n.List())
|
fmt.Fprintf(s, " { %v }", n.List())
|
||||||
|
|
||||||
case OCASE:
|
case OCASE:
|
||||||
|
n := n.(*CaseStmt)
|
||||||
if n.List().Len() != 0 {
|
if n.List().Len() != 0 {
|
||||||
fmt.Fprintf(s, "case %.v", n.List())
|
fmt.Fprintf(s, "case %.v", n.List())
|
||||||
} else {
|
} else {
|
||||||
|
@ -462,6 +484,7 @@ func stmtFmt(n Node, s fmt.State) {
|
||||||
fmt.Fprintf(s, ": %v", n.Body())
|
fmt.Fprintf(s, ": %v", n.Body())
|
||||||
|
|
||||||
case OBREAK, OCONTINUE, OGOTO, OFALL:
|
case OBREAK, OCONTINUE, OGOTO, OFALL:
|
||||||
|
n := n.(*BranchStmt)
|
||||||
if n.Sym() != nil {
|
if n.Sym() != nil {
|
||||||
fmt.Fprintf(s, "%v %v", n.Op(), n.Sym())
|
fmt.Fprintf(s, "%v %v", n.Op(), n.Sym())
|
||||||
} else {
|
} else {
|
||||||
|
@ -469,6 +492,7 @@ func stmtFmt(n Node, s fmt.State) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case OLABEL:
|
case OLABEL:
|
||||||
|
n := n.(*LabelStmt)
|
||||||
fmt.Fprintf(s, "%v: ", n.Sym())
|
fmt.Fprintf(s, "%v: ", n.Sym())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,7 +512,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if n == nil {
|
if n == nil {
|
||||||
fmt.Fprint(s, "<N>")
|
fmt.Fprint(s, "<nil>")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,10 +523,23 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skip implicit operations introduced during typechecking.
|
// Skip implicit operations introduced during typechecking.
|
||||||
switch n.Op() {
|
switch nn := n; nn.Op() {
|
||||||
case OADDR, ODEREF, OCONV, OCONVNOP, OCONVIFACE:
|
case OADDR:
|
||||||
if n.Implicit() {
|
nn := nn.(*AddrExpr)
|
||||||
n = n.Left()
|
if nn.Implicit() {
|
||||||
|
n = nn.Left()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case ODEREF:
|
||||||
|
nn := nn.(*StarExpr)
|
||||||
|
if nn.Implicit() {
|
||||||
|
n = nn.Left()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
case OCONV, OCONVNOP, OCONVIFACE:
|
||||||
|
nn := nn.(*ConvExpr)
|
||||||
|
if nn.Implicit() {
|
||||||
|
n = nn.Left()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -522,6 +559,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||||
|
|
||||||
switch n.Op() {
|
switch n.Op() {
|
||||||
case OPAREN:
|
case OPAREN:
|
||||||
|
n := n.(*ParenExpr)
|
||||||
fmt.Fprintf(s, "(%v)", n.Left())
|
fmt.Fprintf(s, "(%v)", n.Left())
|
||||||
|
|
||||||
case ONIL:
|
case ONIL:
|
||||||
|
@ -570,6 +608,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||||
}
|
}
|
||||||
|
|
||||||
case ODCLFUNC:
|
case ODCLFUNC:
|
||||||
|
n := n.(*Func)
|
||||||
if sym := n.Sym(); sym != nil {
|
if sym := n.Sym(); sym != nil {
|
||||||
fmt.Fprint(s, sym)
|
fmt.Fprint(s, sym)
|
||||||
return
|
return
|
||||||
|
@ -577,6 +616,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||||
fmt.Fprintf(s, "<unnamed Func>")
|
fmt.Fprintf(s, "<unnamed Func>")
|
||||||
|
|
||||||
case ONAME:
|
case ONAME:
|
||||||
|
n := n.(*Name)
|
||||||
// Special case: name used as local variable in export.
|
// Special case: name used as local variable in export.
|
||||||
// _ becomes ~b%d internally; print as _ for export
|
// _ becomes ~b%d internally; print as _ for export
|
||||||
if !exportFormat && n.Sym() != nil && n.Sym().Name[0] == '~' && n.Sym().Name[1] == 'b' {
|
if !exportFormat && n.Sym() != nil && n.Sym().Name[0] == '~' && n.Sym().Name[1] == 'b' {
|
||||||
|
@ -641,17 +681,15 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||||
fmt.Fprint(s, "<func>")
|
fmt.Fprint(s, "<func>")
|
||||||
|
|
||||||
case OCLOSURE:
|
case OCLOSURE:
|
||||||
|
n := n.(*ClosureExpr)
|
||||||
if !exportFormat {
|
if !exportFormat {
|
||||||
fmt.Fprint(s, "func literal")
|
fmt.Fprint(s, "func literal")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if n.Body().Len() != 0 {
|
|
||||||
fmt.Fprintf(s, "%v { %v }", n.Type(), n.Body())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fmt.Fprintf(s, "%v { %v }", n.Type(), n.Func().Body())
|
fmt.Fprintf(s, "%v { %v }", n.Type(), n.Func().Body())
|
||||||
|
|
||||||
case OCOMPLIT:
|
case OCOMPLIT:
|
||||||
|
n := n.(*CompLitExpr)
|
||||||
if !exportFormat {
|
if !exportFormat {
|
||||||
if n.Implicit() {
|
if n.Implicit() {
|
||||||
fmt.Fprintf(s, "... argument")
|
fmt.Fprintf(s, "... argument")
|
||||||
|
@ -668,9 +706,11 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||||
fmt.Fprintf(s, "(%v{ %.v })", n.Right(), n.List())
|
fmt.Fprintf(s, "(%v{ %.v })", n.Right(), n.List())
|
||||||
|
|
||||||
case OPTRLIT:
|
case OPTRLIT:
|
||||||
|
n := n.(*AddrExpr)
|
||||||
fmt.Fprintf(s, "&%v", n.Left())
|
fmt.Fprintf(s, "&%v", n.Left())
|
||||||
|
|
||||||
case OSTRUCTLIT, OARRAYLIT, OSLICELIT, OMAPLIT:
|
case OSTRUCTLIT, OARRAYLIT, OSLICELIT, OMAPLIT:
|
||||||
|
n := n.(*CompLitExpr)
|
||||||
if !exportFormat {
|
if !exportFormat {
|
||||||
fmt.Fprintf(s, "%v{%s}", n.Type(), ellipsisIf(n.List().Len() != 0))
|
fmt.Fprintf(s, "%v{%s}", n.Type(), ellipsisIf(n.List().Len() != 0))
|
||||||
return
|
return
|
||||||
|
@ -678,6 +718,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||||
fmt.Fprintf(s, "(%v{ %.v })", n.Type(), n.List())
|
fmt.Fprintf(s, "(%v{ %.v })", n.Type(), n.List())
|
||||||
|
|
||||||
case OKEY:
|
case OKEY:
|
||||||
|
n := n.(*KeyExpr)
|
||||||
if n.Left() != nil && n.Right() != nil {
|
if n.Left() != nil && n.Right() != nil {
|
||||||
fmt.Fprintf(s, "%v:%v", n.Left(), n.Right())
|
fmt.Fprintf(s, "%v:%v", n.Left(), n.Right())
|
||||||
return
|
return
|
||||||
|
@ -694,9 +735,11 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||||
fmt.Fprint(s, ":")
|
fmt.Fprint(s, ":")
|
||||||
|
|
||||||
case OSTRUCTKEY:
|
case OSTRUCTKEY:
|
||||||
|
n := n.(*StructKeyExpr)
|
||||||
fmt.Fprintf(s, "%v:%v", n.Sym(), n.Left())
|
fmt.Fprintf(s, "%v:%v", n.Sym(), n.Left())
|
||||||
|
|
||||||
case OCALLPART:
|
case OCALLPART:
|
||||||
|
n := n.(*CallPartExpr)
|
||||||
exprFmt(n.Left(), s, nprec)
|
exprFmt(n.Left(), s, nprec)
|
||||||
if n.Sym() == nil {
|
if n.Sym() == nil {
|
||||||
fmt.Fprint(s, ".<nil>")
|
fmt.Fprint(s, ".<nil>")
|
||||||
|
@ -705,6 +748,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||||
fmt.Fprintf(s, ".%s", types.SymMethodName(n.Sym()))
|
fmt.Fprintf(s, ".%s", types.SymMethodName(n.Sym()))
|
||||||
|
|
||||||
case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
|
case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
|
||||||
|
n := n.(*SelectorExpr)
|
||||||
exprFmt(n.Left(), s, nprec)
|
exprFmt(n.Left(), s, nprec)
|
||||||
if n.Sym() == nil {
|
if n.Sym() == nil {
|
||||||
fmt.Fprint(s, ".<nil>")
|
fmt.Fprint(s, ".<nil>")
|
||||||
|
@ -713,6 +757,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||||
fmt.Fprintf(s, ".%s", types.SymMethodName(n.Sym()))
|
fmt.Fprintf(s, ".%s", types.SymMethodName(n.Sym()))
|
||||||
|
|
||||||
case ODOTTYPE, ODOTTYPE2:
|
case ODOTTYPE, ODOTTYPE2:
|
||||||
|
n := n.(*TypeAssertExpr)
|
||||||
exprFmt(n.Left(), s, nprec)
|
exprFmt(n.Left(), s, nprec)
|
||||||
if n.Right() != nil {
|
if n.Right() != nil {
|
||||||
fmt.Fprintf(s, ".(%v)", n.Right())
|
fmt.Fprintf(s, ".(%v)", n.Right())
|
||||||
|
@ -721,10 +766,12 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||||
fmt.Fprintf(s, ".(%v)", n.Type())
|
fmt.Fprintf(s, ".(%v)", n.Type())
|
||||||
|
|
||||||
case OINDEX, OINDEXMAP:
|
case OINDEX, OINDEXMAP:
|
||||||
|
n := n.(*IndexExpr)
|
||||||
exprFmt(n.Left(), s, nprec)
|
exprFmt(n.Left(), s, nprec)
|
||||||
fmt.Fprintf(s, "[%v]", n.Right())
|
fmt.Fprintf(s, "[%v]", n.Right())
|
||||||
|
|
||||||
case OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR:
|
case OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR:
|
||||||
|
n := n.(*SliceExpr)
|
||||||
exprFmt(n.Left(), s, nprec)
|
exprFmt(n.Left(), s, nprec)
|
||||||
fmt.Fprint(s, "[")
|
fmt.Fprint(s, "[")
|
||||||
low, high, max := n.SliceBounds()
|
low, high, max := n.SliceBounds()
|
||||||
|
@ -744,17 +791,15 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||||
fmt.Fprint(s, "]")
|
fmt.Fprint(s, "]")
|
||||||
|
|
||||||
case OSLICEHEADER:
|
case OSLICEHEADER:
|
||||||
|
n := n.(*SliceHeaderExpr)
|
||||||
if n.List().Len() != 2 {
|
if n.List().Len() != 2 {
|
||||||
base.Fatalf("bad OSLICEHEADER list length %d", n.List().Len())
|
base.Fatalf("bad OSLICEHEADER list length %d", n.List().Len())
|
||||||
}
|
}
|
||||||
fmt.Fprintf(s, "sliceheader{%v,%v,%v}", n.Left(), n.List().First(), n.List().Second())
|
fmt.Fprintf(s, "sliceheader{%v,%v,%v}", n.Left(), n.List().First(), n.List().Second())
|
||||||
|
|
||||||
case OCOMPLEX, OCOPY:
|
case OCOMPLEX, OCOPY:
|
||||||
if n.Left() != nil {
|
n := n.(*BinaryExpr)
|
||||||
fmt.Fprintf(s, "%v(%v, %v)", n.Op(), n.Left(), n.Right())
|
fmt.Fprintf(s, "%v(%v, %v)", n.Op(), n.Left(), n.Right())
|
||||||
} else {
|
|
||||||
fmt.Fprintf(s, "%v(%.v)", n.Op(), n.List())
|
|
||||||
}
|
|
||||||
|
|
||||||
case OCONV,
|
case OCONV,
|
||||||
OCONVIFACE,
|
OCONVIFACE,
|
||||||
|
@ -764,37 +809,34 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||||
OSTR2BYTES,
|
OSTR2BYTES,
|
||||||
OSTR2RUNES,
|
OSTR2RUNES,
|
||||||
ORUNESTR:
|
ORUNESTR:
|
||||||
|
n := n.(*ConvExpr)
|
||||||
if n.Type() == nil || n.Type().Sym() == nil {
|
if n.Type() == nil || n.Type().Sym() == nil {
|
||||||
fmt.Fprintf(s, "(%v)", n.Type())
|
fmt.Fprintf(s, "(%v)", n.Type())
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintf(s, "%v", n.Type())
|
fmt.Fprintf(s, "%v", n.Type())
|
||||||
}
|
}
|
||||||
if n.Left() != nil {
|
fmt.Fprintf(s, "(%v)", n.Left())
|
||||||
fmt.Fprintf(s, "(%v)", n.Left())
|
|
||||||
} else {
|
|
||||||
fmt.Fprintf(s, "(%.v)", n.List())
|
|
||||||
}
|
|
||||||
|
|
||||||
case OREAL,
|
case OREAL,
|
||||||
OIMAG,
|
OIMAG,
|
||||||
OAPPEND,
|
|
||||||
OCAP,
|
OCAP,
|
||||||
OCLOSE,
|
OCLOSE,
|
||||||
ODELETE,
|
|
||||||
OLEN,
|
OLEN,
|
||||||
OMAKE,
|
|
||||||
ONEW,
|
ONEW,
|
||||||
OPANIC,
|
OPANIC,
|
||||||
ORECOVER,
|
|
||||||
OALIGNOF,
|
OALIGNOF,
|
||||||
OOFFSETOF,
|
OOFFSETOF,
|
||||||
OSIZEOF,
|
OSIZEOF:
|
||||||
|
n := n.(*UnaryExpr)
|
||||||
|
fmt.Fprintf(s, "%v(%v)", n.Op(), n.Left())
|
||||||
|
|
||||||
|
case OAPPEND,
|
||||||
|
ODELETE,
|
||||||
|
OMAKE,
|
||||||
|
ORECOVER,
|
||||||
OPRINT,
|
OPRINT,
|
||||||
OPRINTN:
|
OPRINTN:
|
||||||
if n.Left() != nil {
|
n := n.(*CallExpr)
|
||||||
fmt.Fprintf(s, "%v(%v)", n.Op(), n.Left())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if n.IsDDD() {
|
if n.IsDDD() {
|
||||||
fmt.Fprintf(s, "%v(%.v...)", n.Op(), n.List())
|
fmt.Fprintf(s, "%v(%.v...)", n.Op(), n.List())
|
||||||
return
|
return
|
||||||
|
@ -802,6 +844,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||||
fmt.Fprintf(s, "%v(%.v)", n.Op(), n.List())
|
fmt.Fprintf(s, "%v(%.v)", n.Op(), n.List())
|
||||||
|
|
||||||
case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, OGETG:
|
case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, OGETG:
|
||||||
|
n := n.(*CallExpr)
|
||||||
exprFmt(n.Left(), s, nprec)
|
exprFmt(n.Left(), s, nprec)
|
||||||
if n.IsDDD() {
|
if n.IsDDD() {
|
||||||
fmt.Fprintf(s, "(%.v...)", n.List())
|
fmt.Fprintf(s, "(%.v...)", n.List())
|
||||||
|
@ -810,10 +853,7 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||||
fmt.Fprintf(s, "(%.v)", n.List())
|
fmt.Fprintf(s, "(%.v)", n.List())
|
||||||
|
|
||||||
case OMAKEMAP, OMAKECHAN, OMAKESLICE:
|
case OMAKEMAP, OMAKECHAN, OMAKESLICE:
|
||||||
if n.List().Len() != 0 { // pre-typecheck
|
n := n.(*MakeExpr)
|
||||||
fmt.Fprintf(s, "make(%v, %.v)", n.Type(), n.List())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if n.Right() != nil {
|
if n.Right() != nil {
|
||||||
fmt.Fprintf(s, "make(%v, %v, %v)", n.Type(), n.Left(), n.Right())
|
fmt.Fprintf(s, "make(%v, %v, %v)", n.Type(), n.Left(), n.Right())
|
||||||
return
|
return
|
||||||
|
@ -825,20 +865,34 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||||
fmt.Fprintf(s, "make(%v)", n.Type())
|
fmt.Fprintf(s, "make(%v)", n.Type())
|
||||||
|
|
||||||
case OMAKESLICECOPY:
|
case OMAKESLICECOPY:
|
||||||
|
n := n.(*MakeExpr)
|
||||||
fmt.Fprintf(s, "makeslicecopy(%v, %v, %v)", n.Type(), n.Left(), n.Right())
|
fmt.Fprintf(s, "makeslicecopy(%v, %v, %v)", n.Type(), n.Left(), n.Right())
|
||||||
|
|
||||||
case OPLUS, ONEG, OADDR, OBITNOT, ODEREF, ONOT, ORECV:
|
case OPLUS, ONEG, OBITNOT, ONOT, ORECV:
|
||||||
// Unary
|
// Unary
|
||||||
|
n := n.(*UnaryExpr)
|
||||||
fmt.Fprintf(s, "%v", n.Op())
|
fmt.Fprintf(s, "%v", n.Op())
|
||||||
if n.Left() != nil && n.Left().Op() == n.Op() {
|
if n.Left() != nil && n.Left().Op() == n.Op() {
|
||||||
fmt.Fprint(s, " ")
|
fmt.Fprint(s, " ")
|
||||||
}
|
}
|
||||||
exprFmt(n.Left(), s, nprec+1)
|
exprFmt(n.Left(), s, nprec+1)
|
||||||
|
|
||||||
|
case OADDR:
|
||||||
|
n := n.(*AddrExpr)
|
||||||
|
fmt.Fprintf(s, "%v", n.Op())
|
||||||
|
if n.Left() != nil && n.Left().Op() == n.Op() {
|
||||||
|
fmt.Fprint(s, " ")
|
||||||
|
}
|
||||||
|
exprFmt(n.Left(), s, nprec+1)
|
||||||
|
|
||||||
|
case ODEREF:
|
||||||
|
n := n.(*StarExpr)
|
||||||
|
fmt.Fprintf(s, "%v", n.Op())
|
||||||
|
exprFmt(n.Left(), s, nprec+1)
|
||||||
|
|
||||||
// Binary
|
// Binary
|
||||||
case OADD,
|
case OADD,
|
||||||
OAND,
|
OAND,
|
||||||
OANDAND,
|
|
||||||
OANDNOT,
|
OANDNOT,
|
||||||
ODIV,
|
ODIV,
|
||||||
OEQ,
|
OEQ,
|
||||||
|
@ -851,16 +905,29 @@ func exprFmt(n Node, s fmt.State, prec int) {
|
||||||
OMUL,
|
OMUL,
|
||||||
ONE,
|
ONE,
|
||||||
OOR,
|
OOR,
|
||||||
OOROR,
|
|
||||||
ORSH,
|
ORSH,
|
||||||
OSEND,
|
|
||||||
OSUB,
|
OSUB,
|
||||||
OXOR:
|
OXOR:
|
||||||
|
n := n.(*BinaryExpr)
|
||||||
exprFmt(n.Left(), s, nprec)
|
exprFmt(n.Left(), s, nprec)
|
||||||
fmt.Fprintf(s, " %v ", n.Op())
|
fmt.Fprintf(s, " %v ", n.Op())
|
||||||
exprFmt(n.Right(), s, nprec+1)
|
exprFmt(n.Right(), s, nprec+1)
|
||||||
|
|
||||||
|
case OANDAND,
|
||||||
|
OOROR:
|
||||||
|
n := n.(*LogicalExpr)
|
||||||
|
exprFmt(n.Left(), s, nprec)
|
||||||
|
fmt.Fprintf(s, " %v ", n.Op())
|
||||||
|
exprFmt(n.Right(), s, nprec+1)
|
||||||
|
|
||||||
|
case OSEND:
|
||||||
|
n := n.(*SendStmt)
|
||||||
|
exprFmt(n.Left(), s, nprec)
|
||||||
|
fmt.Fprintf(s, " <- ")
|
||||||
|
exprFmt(n.Right(), s, nprec+1)
|
||||||
|
|
||||||
case OADDSTR:
|
case OADDSTR:
|
||||||
|
n := n.(*AddStringExpr)
|
||||||
for i, n1 := range n.List().Slice() {
|
for i, n1 := range n.List().Slice() {
|
||||||
if i != 0 {
|
if i != 0 {
|
||||||
fmt.Fprint(s, " + ")
|
fmt.Fprint(s, " + ")
|
||||||
|
@ -951,27 +1018,12 @@ func dumpNodeHeader(w io.Writer, n Node) {
|
||||||
if base.Debug.DumpPtrs != 0 {
|
if base.Debug.DumpPtrs != 0 {
|
||||||
fmt.Fprintf(w, " p(%p)", n)
|
fmt.Fprintf(w, " p(%p)", n)
|
||||||
}
|
}
|
||||||
if n.Name() != nil && n.Name().Vargen != 0 {
|
|
||||||
fmt.Fprintf(w, " g(%d)", n.Name().Vargen)
|
|
||||||
}
|
|
||||||
|
|
||||||
if base.Debug.DumpPtrs != 0 && n.Name() != nil && n.Name().Defn != nil {
|
if base.Debug.DumpPtrs != 0 && n.Name() != nil && n.Name().Defn != nil {
|
||||||
// Useful to see where Defn is set and what node it points to
|
// Useful to see where Defn is set and what node it points to
|
||||||
fmt.Fprintf(w, " defn(%p)", n.Name().Defn)
|
fmt.Fprintf(w, " defn(%p)", n.Name().Defn)
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Offset() != types.BADWIDTH {
|
|
||||||
fmt.Fprintf(w, " x(%d)", n.Offset())
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.Class() != 0 {
|
|
||||||
fmt.Fprintf(w, " class(%v)", n.Class())
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.Colas() {
|
|
||||||
fmt.Fprintf(w, " colas(%v)", n.Colas())
|
|
||||||
}
|
|
||||||
|
|
||||||
if EscFmt != nil {
|
if EscFmt != nil {
|
||||||
if esc := EscFmt(n); esc != "" {
|
if esc := EscFmt(n); esc != "" {
|
||||||
fmt.Fprintf(w, " %s", esc)
|
fmt.Fprintf(w, " %s", esc)
|
||||||
|
@ -982,47 +1034,62 @@ func dumpNodeHeader(w io.Writer, n Node) {
|
||||||
fmt.Fprintf(w, " tc(%d)", n.Typecheck())
|
fmt.Fprintf(w, " tc(%d)", n.Typecheck())
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.IsDDD() {
|
// Print Node-specific fields of basic type in header line.
|
||||||
fmt.Fprintf(w, " isddd(%v)", n.IsDDD())
|
v := reflect.ValueOf(n).Elem()
|
||||||
|
t := v.Type()
|
||||||
|
nf := t.NumField()
|
||||||
|
for i := 0; i < nf; i++ {
|
||||||
|
tf := t.Field(i)
|
||||||
|
if tf.PkgPath != "" {
|
||||||
|
// skip unexported field - Interface will fail
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
k := tf.Type.Kind()
|
||||||
|
if reflect.Bool <= k && k <= reflect.Complex128 {
|
||||||
|
name := strings.TrimSuffix(tf.Name, "_")
|
||||||
|
vf := v.Field(i)
|
||||||
|
vfi := vf.Interface()
|
||||||
|
if name == "Offset" && vfi == types.BADWIDTH || name != "Offset" && isZero(vf) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if vfi == true {
|
||||||
|
fmt.Fprintf(w, " %s", name)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(w, " %s:%+v", name, vf.Interface())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Implicit() {
|
// Print Node-specific booleans by looking for methods.
|
||||||
fmt.Fprintf(w, " implicit(%v)", n.Implicit())
|
// Different v, t from above - want *Struct not Struct, for methods.
|
||||||
}
|
v = reflect.ValueOf(n)
|
||||||
|
t = v.Type()
|
||||||
if n.Op() == ONAME {
|
nm := t.NumMethod()
|
||||||
if n.Name().Addrtaken() {
|
for i := 0; i < nm; i++ {
|
||||||
fmt.Fprint(w, " addrtaken")
|
tm := t.Method(i)
|
||||||
|
if tm.PkgPath != "" {
|
||||||
|
// skip unexported method - call will fail
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
if n.Name().Assigned() {
|
m := v.Method(i)
|
||||||
fmt.Fprint(w, " assigned")
|
mt := m.Type()
|
||||||
|
if mt.NumIn() == 0 && mt.NumOut() == 1 && mt.Out(0).Kind() == reflect.Bool {
|
||||||
|
// TODO(rsc): Remove the func/defer/recover wrapping,
|
||||||
|
// which is guarding against panics in miniExpr,
|
||||||
|
// once we get down to the simpler state in which
|
||||||
|
// nodes have no getter methods that aren't allowed to be called.
|
||||||
|
func() {
|
||||||
|
defer func() { recover() }()
|
||||||
|
if m.Call(nil)[0].Bool() {
|
||||||
|
name := strings.TrimSuffix(tm.Name, "_")
|
||||||
|
fmt.Fprintf(w, " %s", name)
|
||||||
|
}
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
if n.Name().IsClosureVar() {
|
|
||||||
fmt.Fprint(w, " closurevar")
|
|
||||||
}
|
|
||||||
if n.Name().Captured() {
|
|
||||||
fmt.Fprint(w, " captured")
|
|
||||||
}
|
|
||||||
if n.Name().IsOutputParamHeapAddr() {
|
|
||||||
fmt.Fprint(w, " outputparamheapaddr")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if n.Bounded() {
|
|
||||||
fmt.Fprint(w, " bounded")
|
|
||||||
}
|
|
||||||
if n.NonNil() {
|
|
||||||
fmt.Fprint(w, " nonnil")
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.HasCall() {
|
|
||||||
fmt.Fprint(w, " hascall")
|
|
||||||
}
|
|
||||||
|
|
||||||
if n.Name() != nil && n.Name().Used() {
|
|
||||||
fmt.Fprint(w, " used")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if n.Op() == OCLOSURE {
|
if n.Op() == OCLOSURE {
|
||||||
|
n := n.(*ClosureExpr)
|
||||||
if fn := n.Func(); fn != nil && fn.Nname.Sym() != nil {
|
if fn := n.Func(); fn != nil && fn.Nname.Sym() != nil {
|
||||||
fmt.Fprintf(w, " fnName(%+v)", fn.Nname.Sym())
|
fmt.Fprintf(w, " fnName(%+v)", fn.Nname.Sym())
|
||||||
}
|
}
|
||||||
|
@ -1087,6 +1154,7 @@ func dumpNode(w io.Writer, n Node, depth int) {
|
||||||
return
|
return
|
||||||
|
|
||||||
case OASOP:
|
case OASOP:
|
||||||
|
n := n.(*AssignOpStmt)
|
||||||
fmt.Fprintf(w, "%+v-%+v", n.Op(), n.SubOp())
|
fmt.Fprintf(w, "%+v-%+v", n.Op(), n.SubOp())
|
||||||
dumpNodeHeader(w, n)
|
dumpNodeHeader(w, n)
|
||||||
|
|
||||||
|
@ -1120,7 +1188,7 @@ func dumpNode(w io.Writer, n Node, depth int) {
|
||||||
if fn.Body().Len() > 0 {
|
if fn.Body().Len() > 0 {
|
||||||
indent(w, depth)
|
indent(w, depth)
|
||||||
fmt.Fprintf(w, "%+v-body", n.Op())
|
fmt.Fprintf(w, "%+v-body", n.Op())
|
||||||
dumpNodes(w, n.Body(), depth+1)
|
dumpNodes(w, fn.Body(), depth+1)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -1186,3 +1254,40 @@ func dumpNodes(w io.Writer, list Nodes, depth int) {
|
||||||
dumpNode(w, n, depth)
|
dumpNode(w, n, depth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reflect.IsZero is not available in Go 1.4 (added in Go 1.13), so we use this copy instead.
|
||||||
|
func isZero(v reflect.Value) bool {
|
||||||
|
switch v.Kind() {
|
||||||
|
case reflect.Bool:
|
||||||
|
return !v.Bool()
|
||||||
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||||
|
return v.Int() == 0
|
||||||
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||||
|
return v.Uint() == 0
|
||||||
|
case reflect.Float32, reflect.Float64:
|
||||||
|
return math.Float64bits(v.Float()) == 0
|
||||||
|
case reflect.Complex64, reflect.Complex128:
|
||||||
|
c := v.Complex()
|
||||||
|
return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0
|
||||||
|
case reflect.Array:
|
||||||
|
for i := 0; i < v.Len(); i++ {
|
||||||
|
if !isZero(v.Index(i)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
case reflect.Chan, reflect.Func, reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice, reflect.UnsafePointer:
|
||||||
|
return v.IsNil()
|
||||||
|
case reflect.String:
|
||||||
|
return v.Len() == 0
|
||||||
|
case reflect.Struct:
|
||||||
|
for i := 0; i < v.NumField(); i++ {
|
||||||
|
if !isZero(v.Field(i)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -34,13 +34,13 @@ func (*Ident) CanBeNtype() {}
|
||||||
// Name holds Node fields used only by named nodes (ONAME, OTYPE, some OLITERAL).
|
// Name holds Node fields used only by named nodes (ONAME, OTYPE, some OLITERAL).
|
||||||
type Name struct {
|
type Name struct {
|
||||||
miniExpr
|
miniExpr
|
||||||
subOp Op // uint8
|
BuiltinOp Op // uint8
|
||||||
class Class // uint8
|
Class_ Class // uint8
|
||||||
flags bitset16
|
flags bitset16
|
||||||
pragma PragmaFlag // int16
|
pragma PragmaFlag // int16
|
||||||
sym *types.Sym
|
sym *types.Sym
|
||||||
fn *Func
|
fn *Func
|
||||||
offset int64
|
Offset_ int64
|
||||||
val constant.Value
|
val constant.Value
|
||||||
orig Node
|
orig Node
|
||||||
embedFiles *[]string // list of embedded files, for ONAME var
|
embedFiles *[]string // list of embedded files, for ONAME var
|
||||||
|
@ -180,16 +180,16 @@ func newNameAt(pos src.XPos, op Op, sym *types.Sym) *Name {
|
||||||
func (n *Name) Name() *Name { return n }
|
func (n *Name) Name() *Name { return n }
|
||||||
func (n *Name) Sym() *types.Sym { return n.sym }
|
func (n *Name) Sym() *types.Sym { return n.sym }
|
||||||
func (n *Name) SetSym(x *types.Sym) { n.sym = x }
|
func (n *Name) SetSym(x *types.Sym) { n.sym = x }
|
||||||
func (n *Name) SubOp() Op { return n.subOp }
|
func (n *Name) SubOp() Op { return n.BuiltinOp }
|
||||||
func (n *Name) SetSubOp(x Op) { n.subOp = x }
|
func (n *Name) SetSubOp(x Op) { n.BuiltinOp = x }
|
||||||
func (n *Name) Class() Class { return n.class }
|
func (n *Name) Class() Class { return n.Class_ }
|
||||||
func (n *Name) SetClass(x Class) { n.class = x }
|
func (n *Name) SetClass(x Class) { n.Class_ = x }
|
||||||
func (n *Name) Func() *Func { return n.fn }
|
func (n *Name) Func() *Func { return n.fn }
|
||||||
func (n *Name) SetFunc(x *Func) { n.fn = x }
|
func (n *Name) SetFunc(x *Func) { n.fn = x }
|
||||||
func (n *Name) Offset() int64 { return n.offset }
|
func (n *Name) Offset() int64 { return n.Offset_ }
|
||||||
func (n *Name) SetOffset(x int64) { n.offset = x }
|
func (n *Name) SetOffset(x int64) { n.Offset_ = x }
|
||||||
func (n *Name) Iota() int64 { return n.offset }
|
func (n *Name) Iota() int64 { return n.Offset_ }
|
||||||
func (n *Name) SetIota(x int64) { n.offset = x }
|
func (n *Name) SetIota(x int64) { n.Offset_ = x }
|
||||||
|
|
||||||
func (*Name) CanBeNtype() {}
|
func (*Name) CanBeNtype() {}
|
||||||
func (*Name) CanBeAnSSASym() {}
|
func (*Name) CanBeAnSSASym() {}
|
||||||
|
|
|
@ -212,7 +212,7 @@ func caller7() {
|
||||||
|
|
||||||
// **in -> heap
|
// **in -> heap
|
||||||
func param8(i **int) { // ERROR "i does not escape$"
|
func param8(i **int) { // ERROR "i does not escape$"
|
||||||
sink = **i // ERROR "\* \(\*i\) escapes to heap"
|
sink = **i // ERROR "\*\(\*i\) escapes to heap"
|
||||||
}
|
}
|
||||||
|
|
||||||
func caller8() {
|
func caller8() {
|
||||||
|
@ -402,7 +402,7 @@ func caller13h() {
|
||||||
var p *int
|
var p *int
|
||||||
v := &Val{&p} // ERROR "&Val{...} does not escape$"
|
v := &Val{&p} // ERROR "&Val{...} does not escape$"
|
||||||
v.param13(&i)
|
v.param13(&i)
|
||||||
sink = **v.p // ERROR "\* \(\*v\.p\) escapes to heap"
|
sink = **v.p // ERROR "\*\(\*v\.p\) escapes to heap"
|
||||||
}
|
}
|
||||||
|
|
||||||
type Node struct {
|
type Node struct {
|
||||||
|
|
Loading…
Reference in a new issue