2015-02-13 14:40:36 -05:00
|
|
|
// Copyright 2011 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.
|
|
|
|
|
|
[dev.regabi] cmd/compile: introduce cmd/compile/internal/ir [generated]
If we want to break up package gc at all, we will need to move
the compiler IR it defines into a separate package that can be
imported by packages that gc itself imports. This CL does that.
It also removes the TINT8 etc aliases so that all code is clear
about which package things are coming from.
This CL is automatically generated by the script below.
See the comments in the script for details about the changes.
[git-generate]
cd src/cmd/compile/internal/gc
rf '
# These names were never fully qualified
# when the types package was added.
# Do it now, to avoid confusion about where they live.
inline -rm \
Txxx \
TINT8 \
TUINT8 \
TINT16 \
TUINT16 \
TINT32 \
TUINT32 \
TINT64 \
TUINT64 \
TINT \
TUINT \
TUINTPTR \
TCOMPLEX64 \
TCOMPLEX128 \
TFLOAT32 \
TFLOAT64 \
TBOOL \
TPTR \
TFUNC \
TSLICE \
TARRAY \
TSTRUCT \
TCHAN \
TMAP \
TINTER \
TFORW \
TANY \
TSTRING \
TUNSAFEPTR \
TIDEAL \
TNIL \
TBLANK \
TFUNCARGS \
TCHANARGS \
NTYPE \
BADWIDTH
# esc.go and escape.go do not need to be split.
# Append esc.go onto the end of escape.go.
mv esc.go escape.go
# Pull out the type format installation from func Main,
# so it can be carried into package ir.
mv Main:/Sconv.=/-0,/TypeLinkSym/-1 InstallTypeFormats
# Names that need to be exported for use by code left in gc.
mv Isconst IsConst
mv asNode AsNode
mv asNodes AsNodes
mv asTypesNode AsTypesNode
mv basicnames BasicTypeNames
mv builtinpkg BuiltinPkg
mv consttype ConstType
mv dumplist DumpList
mv fdumplist FDumpList
mv fmtMode FmtMode
mv goopnames OpNames
mv inspect Inspect
mv inspectList InspectList
mv localpkg LocalPkg
mv nblank BlankNode
mv numImport NumImport
mv opprec OpPrec
mv origSym OrigSym
mv stmtwithinit StmtWithInit
mv dump DumpAny
mv fdump FDumpAny
mv nod Nod
mv nodl NodAt
mv newname NewName
mv newnamel NewNameAt
mv assertRepresents AssertValidTypeForConst
mv represents ValidTypeForConst
mv nodlit NewLiteral
# Types and fields that need to be exported for use by gc.
mv nowritebarrierrecCallSym SymAndPos
mv SymAndPos.lineno SymAndPos.Pos
mv SymAndPos.target SymAndPos.Sym
mv Func.lsym Func.LSym
mv Func.setWBPos Func.SetWBPos
mv Func.numReturns Func.NumReturns
mv Func.numDefers Func.NumDefers
mv Func.nwbrCalls Func.NWBRCalls
# initLSym is an algorithm left behind in gc,
# not an operation on Func itself.
mv Func.initLSym initLSym
mv nodeQueue NodeQueue
mv NodeQueue.empty NodeQueue.Empty
mv NodeQueue.popLeft NodeQueue.PopLeft
mv NodeQueue.pushRight NodeQueue.PushRight
# Many methods on Node are actually algorithms that
# would apply to any node implementation.
# Those become plain functions.
mv Node.funcname FuncName
mv Node.isBlank IsBlank
mv Node.isGoConst isGoConst
mv Node.isNil IsNil
mv Node.isParamHeapCopy isParamHeapCopy
mv Node.isParamStackCopy isParamStackCopy
mv Node.isSimpleName isSimpleName
mv Node.mayBeShared MayBeShared
mv Node.pkgFuncName PkgFuncName
mv Node.backingArrayPtrLen backingArrayPtrLen
mv Node.isterminating isTermNode
mv Node.labeledControl labeledControl
mv Nodes.isterminating isTermNodes
mv Nodes.sigerr fmtSignature
mv Node.MethodName methodExprName
mv Node.MethodFunc methodExprFunc
mv Node.IsMethod IsMethod
# Every node will need to implement RawCopy;
# Copy and SepCopy algorithms will use it.
mv Node.rawcopy Node.RawCopy
mv Node.copy Copy
mv Node.sepcopy SepCopy
# Extract Node.Format method body into func FmtNode,
# but leave method wrapper behind.
mv Node.Format:0,$ FmtNode
# Formatting helpers that will apply to all node implementations.
mv Node.Line Line
mv Node.exprfmt exprFmt
mv Node.jconv jconvFmt
mv Node.modeString modeString
mv Node.nconv nconvFmt
mv Node.nodedump nodeDumpFmt
mv Node.nodefmt nodeFmt
mv Node.stmtfmt stmtFmt
# Constant support needed for code moving to ir.
mv okforconst OKForConst
mv vconv FmtConst
mv int64Val Int64Val
mv float64Val Float64Val
mv Node.ValueInterface ConstValue
# Organize code into files.
mv LocalPkg BuiltinPkg ir.go
mv NumImport InstallTypeFormats Line fmt.go
mv syntax.go Nod NodAt NewNameAt Class Pxxx PragmaFlag Nointerface SymAndPos \
AsNode AsTypesNode BlankNode OrigSym \
Node.SliceBounds Node.SetSliceBounds Op.IsSlice3 \
IsConst Node.Int64Val Node.CanInt64 Node.Uint64Val Node.BoolVal Node.StringVal \
Node.RawCopy SepCopy Copy \
IsNil IsBlank IsMethod \
Node.Typ Node.StorageClass node.go
mv ConstType ConstValue Int64Val Float64Val AssertValidTypeForConst ValidTypeForConst NewLiteral idealType OKForConst val.go
# Move files to new ir package.
mv bitset.go class_string.go dump.go fmt.go \
ir.go node.go op_string.go val.go \
sizeof_test.go cmd/compile/internal/ir
'
: # fix mkbuiltin.go to generate the changes made to builtin.go during rf
sed -i '' '
s/\[T/[types.T/g
s/\*Node/*ir.Node/g
/internal\/types/c \
fmt.Fprintln(&b, `import (`) \
fmt.Fprintln(&b, ` "cmd/compile/internal/ir"`) \
fmt.Fprintln(&b, ` "cmd/compile/internal/types"`) \
fmt.Fprintln(&b, `)`)
' mkbuiltin.go
gofmt -w mkbuiltin.go
: # update cmd/dist to add internal/ir
cd ../../../dist
sed -i '' '/compile.internal.gc/a\
"cmd/compile/internal/ir",
' buildtool.go
gofmt -w buildtool.go
: # update cmd/compile TestFormats
cd ../..
go install std cmd
cd cmd/compile
go test -u || go test # first one updates but fails; second passes
Change-Id: I5f7caf6b20629b51970279e81231a3574d5b51db
Reviewed-on: https://go-review.googlesource.com/c/go/+/273008
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-11-19 21:09:22 -05:00
|
|
|
package ir
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
import (
|
2020-01-09 14:58:18 -08:00
|
|
|
"bytes"
|
2015-02-13 14:40:36 -05:00
|
|
|
"fmt"
|
2020-11-13 23:36:48 -08:00
|
|
|
"go/constant"
|
2018-07-31 18:13:05 +03:00
|
|
|
"io"
|
2020-12-10 20:55:10 -05:00
|
|
|
"math"
|
2020-12-05 00:02:46 -05:00
|
|
|
"os"
|
2020-12-06 15:17:05 -05:00
|
|
|
"path/filepath"
|
|
|
|
|
"reflect"
|
|
|
|
|
"strings"
|
2020-12-06 13:54:50 -05:00
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
"unicode/utf8"
|
[dev.regabi] cmd/compile: introduce cmd/compile/internal/ir [generated]
If we want to break up package gc at all, we will need to move
the compiler IR it defines into a separate package that can be
imported by packages that gc itself imports. This CL does that.
It also removes the TINT8 etc aliases so that all code is clear
about which package things are coming from.
This CL is automatically generated by the script below.
See the comments in the script for details about the changes.
[git-generate]
cd src/cmd/compile/internal/gc
rf '
# These names were never fully qualified
# when the types package was added.
# Do it now, to avoid confusion about where they live.
inline -rm \
Txxx \
TINT8 \
TUINT8 \
TINT16 \
TUINT16 \
TINT32 \
TUINT32 \
TINT64 \
TUINT64 \
TINT \
TUINT \
TUINTPTR \
TCOMPLEX64 \
TCOMPLEX128 \
TFLOAT32 \
TFLOAT64 \
TBOOL \
TPTR \
TFUNC \
TSLICE \
TARRAY \
TSTRUCT \
TCHAN \
TMAP \
TINTER \
TFORW \
TANY \
TSTRING \
TUNSAFEPTR \
TIDEAL \
TNIL \
TBLANK \
TFUNCARGS \
TCHANARGS \
NTYPE \
BADWIDTH
# esc.go and escape.go do not need to be split.
# Append esc.go onto the end of escape.go.
mv esc.go escape.go
# Pull out the type format installation from func Main,
# so it can be carried into package ir.
mv Main:/Sconv.=/-0,/TypeLinkSym/-1 InstallTypeFormats
# Names that need to be exported for use by code left in gc.
mv Isconst IsConst
mv asNode AsNode
mv asNodes AsNodes
mv asTypesNode AsTypesNode
mv basicnames BasicTypeNames
mv builtinpkg BuiltinPkg
mv consttype ConstType
mv dumplist DumpList
mv fdumplist FDumpList
mv fmtMode FmtMode
mv goopnames OpNames
mv inspect Inspect
mv inspectList InspectList
mv localpkg LocalPkg
mv nblank BlankNode
mv numImport NumImport
mv opprec OpPrec
mv origSym OrigSym
mv stmtwithinit StmtWithInit
mv dump DumpAny
mv fdump FDumpAny
mv nod Nod
mv nodl NodAt
mv newname NewName
mv newnamel NewNameAt
mv assertRepresents AssertValidTypeForConst
mv represents ValidTypeForConst
mv nodlit NewLiteral
# Types and fields that need to be exported for use by gc.
mv nowritebarrierrecCallSym SymAndPos
mv SymAndPos.lineno SymAndPos.Pos
mv SymAndPos.target SymAndPos.Sym
mv Func.lsym Func.LSym
mv Func.setWBPos Func.SetWBPos
mv Func.numReturns Func.NumReturns
mv Func.numDefers Func.NumDefers
mv Func.nwbrCalls Func.NWBRCalls
# initLSym is an algorithm left behind in gc,
# not an operation on Func itself.
mv Func.initLSym initLSym
mv nodeQueue NodeQueue
mv NodeQueue.empty NodeQueue.Empty
mv NodeQueue.popLeft NodeQueue.PopLeft
mv NodeQueue.pushRight NodeQueue.PushRight
# Many methods on Node are actually algorithms that
# would apply to any node implementation.
# Those become plain functions.
mv Node.funcname FuncName
mv Node.isBlank IsBlank
mv Node.isGoConst isGoConst
mv Node.isNil IsNil
mv Node.isParamHeapCopy isParamHeapCopy
mv Node.isParamStackCopy isParamStackCopy
mv Node.isSimpleName isSimpleName
mv Node.mayBeShared MayBeShared
mv Node.pkgFuncName PkgFuncName
mv Node.backingArrayPtrLen backingArrayPtrLen
mv Node.isterminating isTermNode
mv Node.labeledControl labeledControl
mv Nodes.isterminating isTermNodes
mv Nodes.sigerr fmtSignature
mv Node.MethodName methodExprName
mv Node.MethodFunc methodExprFunc
mv Node.IsMethod IsMethod
# Every node will need to implement RawCopy;
# Copy and SepCopy algorithms will use it.
mv Node.rawcopy Node.RawCopy
mv Node.copy Copy
mv Node.sepcopy SepCopy
# Extract Node.Format method body into func FmtNode,
# but leave method wrapper behind.
mv Node.Format:0,$ FmtNode
# Formatting helpers that will apply to all node implementations.
mv Node.Line Line
mv Node.exprfmt exprFmt
mv Node.jconv jconvFmt
mv Node.modeString modeString
mv Node.nconv nconvFmt
mv Node.nodedump nodeDumpFmt
mv Node.nodefmt nodeFmt
mv Node.stmtfmt stmtFmt
# Constant support needed for code moving to ir.
mv okforconst OKForConst
mv vconv FmtConst
mv int64Val Int64Val
mv float64Val Float64Val
mv Node.ValueInterface ConstValue
# Organize code into files.
mv LocalPkg BuiltinPkg ir.go
mv NumImport InstallTypeFormats Line fmt.go
mv syntax.go Nod NodAt NewNameAt Class Pxxx PragmaFlag Nointerface SymAndPos \
AsNode AsTypesNode BlankNode OrigSym \
Node.SliceBounds Node.SetSliceBounds Op.IsSlice3 \
IsConst Node.Int64Val Node.CanInt64 Node.Uint64Val Node.BoolVal Node.StringVal \
Node.RawCopy SepCopy Copy \
IsNil IsBlank IsMethod \
Node.Typ Node.StorageClass node.go
mv ConstType ConstValue Int64Val Float64Val AssertValidTypeForConst ValidTypeForConst NewLiteral idealType OKForConst val.go
# Move files to new ir package.
mv bitset.go class_string.go dump.go fmt.go \
ir.go node.go op_string.go val.go \
sizeof_test.go cmd/compile/internal/ir
'
: # fix mkbuiltin.go to generate the changes made to builtin.go during rf
sed -i '' '
s/\[T/[types.T/g
s/\*Node/*ir.Node/g
/internal\/types/c \
fmt.Fprintln(&b, `import (`) \
fmt.Fprintln(&b, ` "cmd/compile/internal/ir"`) \
fmt.Fprintln(&b, ` "cmd/compile/internal/types"`) \
fmt.Fprintln(&b, `)`)
' mkbuiltin.go
gofmt -w mkbuiltin.go
: # update cmd/dist to add internal/ir
cd ../../../dist
sed -i '' '/compile.internal.gc/a\
"cmd/compile/internal/ir",
' buildtool.go
gofmt -w buildtool.go
: # update cmd/compile TestFormats
cd ../..
go install std cmd
cd cmd/compile
go test -u || go test # first one updates but fails; second passes
Change-Id: I5f7caf6b20629b51970279e81231a3574d5b51db
Reviewed-on: https://go-review.googlesource.com/c/go/+/273008
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-11-19 21:09:22 -05:00
|
|
|
|
|
|
|
|
"cmd/compile/internal/base"
|
|
|
|
|
"cmd/compile/internal/types"
|
|
|
|
|
"cmd/internal/src"
|
2015-02-13 14:40:36 -05:00
|
|
|
)
|
|
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
// Op
|
|
|
|
|
|
[dev.regabi] cmd/compile: introduce cmd/compile/internal/ir [generated]
If we want to break up package gc at all, we will need to move
the compiler IR it defines into a separate package that can be
imported by packages that gc itself imports. This CL does that.
It also removes the TINT8 etc aliases so that all code is clear
about which package things are coming from.
This CL is automatically generated by the script below.
See the comments in the script for details about the changes.
[git-generate]
cd src/cmd/compile/internal/gc
rf '
# These names were never fully qualified
# when the types package was added.
# Do it now, to avoid confusion about where they live.
inline -rm \
Txxx \
TINT8 \
TUINT8 \
TINT16 \
TUINT16 \
TINT32 \
TUINT32 \
TINT64 \
TUINT64 \
TINT \
TUINT \
TUINTPTR \
TCOMPLEX64 \
TCOMPLEX128 \
TFLOAT32 \
TFLOAT64 \
TBOOL \
TPTR \
TFUNC \
TSLICE \
TARRAY \
TSTRUCT \
TCHAN \
TMAP \
TINTER \
TFORW \
TANY \
TSTRING \
TUNSAFEPTR \
TIDEAL \
TNIL \
TBLANK \
TFUNCARGS \
TCHANARGS \
NTYPE \
BADWIDTH
# esc.go and escape.go do not need to be split.
# Append esc.go onto the end of escape.go.
mv esc.go escape.go
# Pull out the type format installation from func Main,
# so it can be carried into package ir.
mv Main:/Sconv.=/-0,/TypeLinkSym/-1 InstallTypeFormats
# Names that need to be exported for use by code left in gc.
mv Isconst IsConst
mv asNode AsNode
mv asNodes AsNodes
mv asTypesNode AsTypesNode
mv basicnames BasicTypeNames
mv builtinpkg BuiltinPkg
mv consttype ConstType
mv dumplist DumpList
mv fdumplist FDumpList
mv fmtMode FmtMode
mv goopnames OpNames
mv inspect Inspect
mv inspectList InspectList
mv localpkg LocalPkg
mv nblank BlankNode
mv numImport NumImport
mv opprec OpPrec
mv origSym OrigSym
mv stmtwithinit StmtWithInit
mv dump DumpAny
mv fdump FDumpAny
mv nod Nod
mv nodl NodAt
mv newname NewName
mv newnamel NewNameAt
mv assertRepresents AssertValidTypeForConst
mv represents ValidTypeForConst
mv nodlit NewLiteral
# Types and fields that need to be exported for use by gc.
mv nowritebarrierrecCallSym SymAndPos
mv SymAndPos.lineno SymAndPos.Pos
mv SymAndPos.target SymAndPos.Sym
mv Func.lsym Func.LSym
mv Func.setWBPos Func.SetWBPos
mv Func.numReturns Func.NumReturns
mv Func.numDefers Func.NumDefers
mv Func.nwbrCalls Func.NWBRCalls
# initLSym is an algorithm left behind in gc,
# not an operation on Func itself.
mv Func.initLSym initLSym
mv nodeQueue NodeQueue
mv NodeQueue.empty NodeQueue.Empty
mv NodeQueue.popLeft NodeQueue.PopLeft
mv NodeQueue.pushRight NodeQueue.PushRight
# Many methods on Node are actually algorithms that
# would apply to any node implementation.
# Those become plain functions.
mv Node.funcname FuncName
mv Node.isBlank IsBlank
mv Node.isGoConst isGoConst
mv Node.isNil IsNil
mv Node.isParamHeapCopy isParamHeapCopy
mv Node.isParamStackCopy isParamStackCopy
mv Node.isSimpleName isSimpleName
mv Node.mayBeShared MayBeShared
mv Node.pkgFuncName PkgFuncName
mv Node.backingArrayPtrLen backingArrayPtrLen
mv Node.isterminating isTermNode
mv Node.labeledControl labeledControl
mv Nodes.isterminating isTermNodes
mv Nodes.sigerr fmtSignature
mv Node.MethodName methodExprName
mv Node.MethodFunc methodExprFunc
mv Node.IsMethod IsMethod
# Every node will need to implement RawCopy;
# Copy and SepCopy algorithms will use it.
mv Node.rawcopy Node.RawCopy
mv Node.copy Copy
mv Node.sepcopy SepCopy
# Extract Node.Format method body into func FmtNode,
# but leave method wrapper behind.
mv Node.Format:0,$ FmtNode
# Formatting helpers that will apply to all node implementations.
mv Node.Line Line
mv Node.exprfmt exprFmt
mv Node.jconv jconvFmt
mv Node.modeString modeString
mv Node.nconv nconvFmt
mv Node.nodedump nodeDumpFmt
mv Node.nodefmt nodeFmt
mv Node.stmtfmt stmtFmt
# Constant support needed for code moving to ir.
mv okforconst OKForConst
mv vconv FmtConst
mv int64Val Int64Val
mv float64Val Float64Val
mv Node.ValueInterface ConstValue
# Organize code into files.
mv LocalPkg BuiltinPkg ir.go
mv NumImport InstallTypeFormats Line fmt.go
mv syntax.go Nod NodAt NewNameAt Class Pxxx PragmaFlag Nointerface SymAndPos \
AsNode AsTypesNode BlankNode OrigSym \
Node.SliceBounds Node.SetSliceBounds Op.IsSlice3 \
IsConst Node.Int64Val Node.CanInt64 Node.Uint64Val Node.BoolVal Node.StringVal \
Node.RawCopy SepCopy Copy \
IsNil IsBlank IsMethod \
Node.Typ Node.StorageClass node.go
mv ConstType ConstValue Int64Val Float64Val AssertValidTypeForConst ValidTypeForConst NewLiteral idealType OKForConst val.go
# Move files to new ir package.
mv bitset.go class_string.go dump.go fmt.go \
ir.go node.go op_string.go val.go \
sizeof_test.go cmd/compile/internal/ir
'
: # fix mkbuiltin.go to generate the changes made to builtin.go during rf
sed -i '' '
s/\[T/[types.T/g
s/\*Node/*ir.Node/g
/internal\/types/c \
fmt.Fprintln(&b, `import (`) \
fmt.Fprintln(&b, ` "cmd/compile/internal/ir"`) \
fmt.Fprintln(&b, ` "cmd/compile/internal/types"`) \
fmt.Fprintln(&b, `)`)
' mkbuiltin.go
gofmt -w mkbuiltin.go
: # update cmd/dist to add internal/ir
cd ../../../dist
sed -i '' '/compile.internal.gc/a\
"cmd/compile/internal/ir",
' buildtool.go
gofmt -w buildtool.go
: # update cmd/compile TestFormats
cd ../..
go install std cmd
cd cmd/compile
go test -u || go test # first one updates but fails; second passes
Change-Id: I5f7caf6b20629b51970279e81231a3574d5b51db
Reviewed-on: https://go-review.googlesource.com/c/go/+/273008
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-11-19 21:09:22 -05:00
|
|
|
var OpNames = []string{
|
2015-02-13 14:40:36 -05:00
|
|
|
OADDR: "&",
|
|
|
|
|
OADD: "+",
|
|
|
|
|
OADDSTR: "+",
|
2016-10-18 14:17:05 -07:00
|
|
|
OALIGNOF: "unsafe.Alignof",
|
2015-02-13 14:40:36 -05:00
|
|
|
OANDAND: "&&",
|
|
|
|
|
OANDNOT: "&^",
|
|
|
|
|
OAND: "&",
|
|
|
|
|
OAPPEND: "append",
|
|
|
|
|
OAS: "=",
|
|
|
|
|
OAS2: "=",
|
|
|
|
|
OBREAK: "break",
|
|
|
|
|
OCALL: "function call", // not actual syntax
|
|
|
|
|
OCAP: "cap",
|
|
|
|
|
OCASE: "case",
|
|
|
|
|
OCLOSE: "close",
|
|
|
|
|
OCOMPLEX: "complex",
|
2018-11-18 08:34:38 -08:00
|
|
|
OBITNOT: "^",
|
2015-02-13 14:40:36 -05:00
|
|
|
OCONTINUE: "continue",
|
|
|
|
|
OCOPY: "copy",
|
|
|
|
|
ODELETE: "delete",
|
|
|
|
|
ODEFER: "defer",
|
|
|
|
|
ODIV: "/",
|
|
|
|
|
OEQ: "==",
|
|
|
|
|
OFALL: "fallthrough",
|
|
|
|
|
OFOR: "for",
|
2017-02-02 11:53:41 -05:00
|
|
|
OFORUNTIL: "foruntil", // not actual syntax; used to avoid off-end pointer live on backedge.892
|
2015-02-13 14:40:36 -05:00
|
|
|
OGE: ">=",
|
|
|
|
|
OGOTO: "goto",
|
|
|
|
|
OGT: ">",
|
|
|
|
|
OIF: "if",
|
|
|
|
|
OIMAG: "imag",
|
2018-12-04 07:58:18 -08:00
|
|
|
OINLMARK: "inlmark",
|
2018-11-18 08:34:38 -08:00
|
|
|
ODEREF: "*",
|
2015-02-13 14:40:36 -05:00
|
|
|
OLEN: "len",
|
|
|
|
|
OLE: "<=",
|
|
|
|
|
OLSH: "<<",
|
|
|
|
|
OLT: "<",
|
|
|
|
|
OMAKE: "make",
|
2018-11-18 08:34:38 -08:00
|
|
|
ONEG: "-",
|
2015-02-13 14:40:36 -05:00
|
|
|
OMOD: "%",
|
|
|
|
|
OMUL: "*",
|
|
|
|
|
ONEW: "new",
|
|
|
|
|
ONE: "!=",
|
|
|
|
|
ONOT: "!",
|
2016-10-18 14:17:05 -07:00
|
|
|
OOFFSETOF: "unsafe.Offsetof",
|
2015-02-13 14:40:36 -05:00
|
|
|
OOROR: "||",
|
|
|
|
|
OOR: "|",
|
|
|
|
|
OPANIC: "panic",
|
|
|
|
|
OPLUS: "+",
|
|
|
|
|
OPRINTN: "println",
|
|
|
|
|
OPRINT: "print",
|
|
|
|
|
ORANGE: "range",
|
|
|
|
|
OREAL: "real",
|
|
|
|
|
ORECV: "<-",
|
|
|
|
|
ORECOVER: "recover",
|
|
|
|
|
ORETURN: "return",
|
|
|
|
|
ORSH: ">>",
|
|
|
|
|
OSELECT: "select",
|
|
|
|
|
OSEND: "<-",
|
2016-10-18 14:17:05 -07:00
|
|
|
OSIZEOF: "unsafe.Sizeof",
|
2015-02-13 14:40:36 -05:00
|
|
|
OSUB: "-",
|
|
|
|
|
OSWITCH: "switch",
|
|
|
|
|
OXOR: "^",
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-06 14:15:09 -05:00
|
|
|
// GoString returns the Go syntax for the Op, or else its name.
|
2016-04-27 19:34:17 +10:00
|
|
|
func (o Op) GoString() string {
|
2020-12-05 00:02:46 -05:00
|
|
|
if int(o) < len(OpNames) && OpNames[o] != "" {
|
|
|
|
|
return OpNames[o]
|
|
|
|
|
}
|
|
|
|
|
return o.String()
|
2016-04-27 19:34:17 +10:00
|
|
|
}
|
|
|
|
|
|
2020-12-06 14:15:09 -05:00
|
|
|
// Format implements formatting for an Op.
|
|
|
|
|
// The valid formats are:
|
|
|
|
|
//
|
|
|
|
|
// %v Go syntax ("+", "<-", "print")
|
|
|
|
|
// %+v Debug syntax ("ADD", "RECV", "PRINT")
|
|
|
|
|
//
|
2020-12-05 00:02:46 -05:00
|
|
|
func (o Op) Format(s fmt.State, verb rune) {
|
2016-09-08 16:51:26 -07:00
|
|
|
switch verb {
|
2016-08-30 14:21:33 -07:00
|
|
|
default:
|
2016-09-08 16:51:26 -07:00
|
|
|
fmt.Fprintf(s, "%%!%c(Op=%d)", verb, int(o))
|
2020-12-05 00:02:46 -05:00
|
|
|
case 'v':
|
|
|
|
|
if s.Flag('+') {
|
|
|
|
|
// %+v is OMUL instead of "*"
|
|
|
|
|
io.WriteString(s, o.String())
|
2016-08-30 14:21:33 -07:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-12-05 00:02:46 -05:00
|
|
|
io.WriteString(s, o.GoString())
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
// Node
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-06 14:15:09 -05:00
|
|
|
// FmtNode implements formatting for a Node n.
|
|
|
|
|
// Every Node implementation must define a Format method that calls FmtNode.
|
|
|
|
|
// The valid formats are:
|
|
|
|
|
//
|
|
|
|
|
// %v Go syntax
|
|
|
|
|
// %L Go syntax followed by " (type T)" if type is known.
|
|
|
|
|
// %+v Debug syntax, as in Dump.
|
|
|
|
|
//
|
2020-12-05 00:02:46 -05:00
|
|
|
func FmtNode(n Node, s fmt.State, verb rune) {
|
2020-12-05 00:02:46 -05:00
|
|
|
// %+v prints Dump.
|
2020-12-05 14:46:19 -05:00
|
|
|
// Otherwise we print Go syntax.
|
2020-12-05 00:02:46 -05:00
|
|
|
if s.Flag('+') && verb == 'v' {
|
|
|
|
|
dumpNode(s, n, 1)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-05 14:46:19 -05:00
|
|
|
if verb != 'v' && verb != 'S' && verb != 'L' {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(s, "%%!%c(*Node=%p)", verb, n)
|
2020-12-05 14:46:19 -05:00
|
|
|
return
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
if n == nil {
|
2020-12-10 20:55:10 -05:00
|
|
|
fmt.Fprint(s, "<nil>")
|
2020-12-05 00:02:46 -05:00
|
|
|
return
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
t := n.Type()
|
2020-12-05 14:46:19 -05:00
|
|
|
if verb == 'L' && t != nil {
|
2020-12-05 00:02:46 -05:00
|
|
|
if t.Kind() == types.TNIL {
|
|
|
|
|
fmt.Fprint(s, "nil")
|
|
|
|
|
} else if n.Op() == ONAME && n.Name().AutoTemp() {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%v value", t)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%v (type %v)", n, t)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-12-05 00:02:46 -05:00
|
|
|
return
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
// TODO inlining produces expressions with ninits. we can't print these yet.
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
if OpPrec[n.Op()] < 0 {
|
2020-12-05 14:46:19 -05:00
|
|
|
stmtFmt(n, s)
|
2020-12-05 00:02:46 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2020-12-05 14:46:19 -05:00
|
|
|
exprFmt(n, s, 0)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
[dev.regabi] cmd/compile: introduce cmd/compile/internal/ir [generated]
If we want to break up package gc at all, we will need to move
the compiler IR it defines into a separate package that can be
imported by packages that gc itself imports. This CL does that.
It also removes the TINT8 etc aliases so that all code is clear
about which package things are coming from.
This CL is automatically generated by the script below.
See the comments in the script for details about the changes.
[git-generate]
cd src/cmd/compile/internal/gc
rf '
# These names were never fully qualified
# when the types package was added.
# Do it now, to avoid confusion about where they live.
inline -rm \
Txxx \
TINT8 \
TUINT8 \
TINT16 \
TUINT16 \
TINT32 \
TUINT32 \
TINT64 \
TUINT64 \
TINT \
TUINT \
TUINTPTR \
TCOMPLEX64 \
TCOMPLEX128 \
TFLOAT32 \
TFLOAT64 \
TBOOL \
TPTR \
TFUNC \
TSLICE \
TARRAY \
TSTRUCT \
TCHAN \
TMAP \
TINTER \
TFORW \
TANY \
TSTRING \
TUNSAFEPTR \
TIDEAL \
TNIL \
TBLANK \
TFUNCARGS \
TCHANARGS \
NTYPE \
BADWIDTH
# esc.go and escape.go do not need to be split.
# Append esc.go onto the end of escape.go.
mv esc.go escape.go
# Pull out the type format installation from func Main,
# so it can be carried into package ir.
mv Main:/Sconv.=/-0,/TypeLinkSym/-1 InstallTypeFormats
# Names that need to be exported for use by code left in gc.
mv Isconst IsConst
mv asNode AsNode
mv asNodes AsNodes
mv asTypesNode AsTypesNode
mv basicnames BasicTypeNames
mv builtinpkg BuiltinPkg
mv consttype ConstType
mv dumplist DumpList
mv fdumplist FDumpList
mv fmtMode FmtMode
mv goopnames OpNames
mv inspect Inspect
mv inspectList InspectList
mv localpkg LocalPkg
mv nblank BlankNode
mv numImport NumImport
mv opprec OpPrec
mv origSym OrigSym
mv stmtwithinit StmtWithInit
mv dump DumpAny
mv fdump FDumpAny
mv nod Nod
mv nodl NodAt
mv newname NewName
mv newnamel NewNameAt
mv assertRepresents AssertValidTypeForConst
mv represents ValidTypeForConst
mv nodlit NewLiteral
# Types and fields that need to be exported for use by gc.
mv nowritebarrierrecCallSym SymAndPos
mv SymAndPos.lineno SymAndPos.Pos
mv SymAndPos.target SymAndPos.Sym
mv Func.lsym Func.LSym
mv Func.setWBPos Func.SetWBPos
mv Func.numReturns Func.NumReturns
mv Func.numDefers Func.NumDefers
mv Func.nwbrCalls Func.NWBRCalls
# initLSym is an algorithm left behind in gc,
# not an operation on Func itself.
mv Func.initLSym initLSym
mv nodeQueue NodeQueue
mv NodeQueue.empty NodeQueue.Empty
mv NodeQueue.popLeft NodeQueue.PopLeft
mv NodeQueue.pushRight NodeQueue.PushRight
# Many methods on Node are actually algorithms that
# would apply to any node implementation.
# Those become plain functions.
mv Node.funcname FuncName
mv Node.isBlank IsBlank
mv Node.isGoConst isGoConst
mv Node.isNil IsNil
mv Node.isParamHeapCopy isParamHeapCopy
mv Node.isParamStackCopy isParamStackCopy
mv Node.isSimpleName isSimpleName
mv Node.mayBeShared MayBeShared
mv Node.pkgFuncName PkgFuncName
mv Node.backingArrayPtrLen backingArrayPtrLen
mv Node.isterminating isTermNode
mv Node.labeledControl labeledControl
mv Nodes.isterminating isTermNodes
mv Nodes.sigerr fmtSignature
mv Node.MethodName methodExprName
mv Node.MethodFunc methodExprFunc
mv Node.IsMethod IsMethod
# Every node will need to implement RawCopy;
# Copy and SepCopy algorithms will use it.
mv Node.rawcopy Node.RawCopy
mv Node.copy Copy
mv Node.sepcopy SepCopy
# Extract Node.Format method body into func FmtNode,
# but leave method wrapper behind.
mv Node.Format:0,$ FmtNode
# Formatting helpers that will apply to all node implementations.
mv Node.Line Line
mv Node.exprfmt exprFmt
mv Node.jconv jconvFmt
mv Node.modeString modeString
mv Node.nconv nconvFmt
mv Node.nodedump nodeDumpFmt
mv Node.nodefmt nodeFmt
mv Node.stmtfmt stmtFmt
# Constant support needed for code moving to ir.
mv okforconst OKForConst
mv vconv FmtConst
mv int64Val Int64Val
mv float64Val Float64Val
mv Node.ValueInterface ConstValue
# Organize code into files.
mv LocalPkg BuiltinPkg ir.go
mv NumImport InstallTypeFormats Line fmt.go
mv syntax.go Nod NodAt NewNameAt Class Pxxx PragmaFlag Nointerface SymAndPos \
AsNode AsTypesNode BlankNode OrigSym \
Node.SliceBounds Node.SetSliceBounds Op.IsSlice3 \
IsConst Node.Int64Val Node.CanInt64 Node.Uint64Val Node.BoolVal Node.StringVal \
Node.RawCopy SepCopy Copy \
IsNil IsBlank IsMethod \
Node.Typ Node.StorageClass node.go
mv ConstType ConstValue Int64Val Float64Val AssertValidTypeForConst ValidTypeForConst NewLiteral idealType OKForConst val.go
# Move files to new ir package.
mv bitset.go class_string.go dump.go fmt.go \
ir.go node.go op_string.go val.go \
sizeof_test.go cmd/compile/internal/ir
'
: # fix mkbuiltin.go to generate the changes made to builtin.go during rf
sed -i '' '
s/\[T/[types.T/g
s/\*Node/*ir.Node/g
/internal\/types/c \
fmt.Fprintln(&b, `import (`) \
fmt.Fprintln(&b, ` "cmd/compile/internal/ir"`) \
fmt.Fprintln(&b, ` "cmd/compile/internal/types"`) \
fmt.Fprintln(&b, `)`)
' mkbuiltin.go
gofmt -w mkbuiltin.go
: # update cmd/dist to add internal/ir
cd ../../../dist
sed -i '' '/compile.internal.gc/a\
"cmd/compile/internal/ir",
' buildtool.go
gofmt -w buildtool.go
: # update cmd/compile TestFormats
cd ../..
go install std cmd
cd cmd/compile
go test -u || go test # first one updates but fails; second passes
Change-Id: I5f7caf6b20629b51970279e81231a3574d5b51db
Reviewed-on: https://go-review.googlesource.com/c/go/+/273008
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-11-19 21:09:22 -05:00
|
|
|
var OpPrec = []int{
|
2018-10-23 13:50:07 +02:00
|
|
|
OALIGNOF: 8,
|
|
|
|
|
OAPPEND: 8,
|
|
|
|
|
OBYTES2STR: 8,
|
|
|
|
|
OARRAYLIT: 8,
|
|
|
|
|
OSLICELIT: 8,
|
|
|
|
|
ORUNES2STR: 8,
|
|
|
|
|
OCALLFUNC: 8,
|
|
|
|
|
OCALLINTER: 8,
|
|
|
|
|
OCALLMETH: 8,
|
|
|
|
|
OCALL: 8,
|
|
|
|
|
OCAP: 8,
|
|
|
|
|
OCLOSE: 8,
|
2020-12-03 11:56:29 -08:00
|
|
|
OCOMPLIT: 8,
|
2018-10-23 13:50:07 +02:00
|
|
|
OCONVIFACE: 8,
|
|
|
|
|
OCONVNOP: 8,
|
|
|
|
|
OCONV: 8,
|
|
|
|
|
OCOPY: 8,
|
|
|
|
|
ODELETE: 8,
|
|
|
|
|
OGETG: 8,
|
|
|
|
|
OLEN: 8,
|
|
|
|
|
OLITERAL: 8,
|
|
|
|
|
OMAKESLICE: 8,
|
|
|
|
|
OMAKESLICECOPY: 8,
|
|
|
|
|
OMAKE: 8,
|
|
|
|
|
OMAPLIT: 8,
|
|
|
|
|
ONAME: 8,
|
|
|
|
|
ONEW: 8,
|
2020-11-13 20:38:21 -08:00
|
|
|
ONIL: 8,
|
2018-10-23 13:50:07 +02:00
|
|
|
ONONAME: 8,
|
|
|
|
|
OOFFSETOF: 8,
|
|
|
|
|
OPACK: 8,
|
|
|
|
|
OPANIC: 8,
|
|
|
|
|
OPAREN: 8,
|
|
|
|
|
OPRINTN: 8,
|
|
|
|
|
OPRINT: 8,
|
|
|
|
|
ORUNESTR: 8,
|
|
|
|
|
OSIZEOF: 8,
|
|
|
|
|
OSTR2BYTES: 8,
|
|
|
|
|
OSTR2RUNES: 8,
|
|
|
|
|
OSTRUCTLIT: 8,
|
|
|
|
|
OTARRAY: 8,
|
2020-11-26 07:02:13 -05:00
|
|
|
OTSLICE: 8,
|
2018-10-23 13:50:07 +02:00
|
|
|
OTCHAN: 8,
|
|
|
|
|
OTFUNC: 8,
|
|
|
|
|
OTINTER: 8,
|
|
|
|
|
OTMAP: 8,
|
|
|
|
|
OTSTRUCT: 8,
|
|
|
|
|
OINDEXMAP: 8,
|
|
|
|
|
OINDEX: 8,
|
|
|
|
|
OSLICE: 8,
|
|
|
|
|
OSLICESTR: 8,
|
|
|
|
|
OSLICEARR: 8,
|
|
|
|
|
OSLICE3: 8,
|
|
|
|
|
OSLICE3ARR: 8,
|
|
|
|
|
OSLICEHEADER: 8,
|
|
|
|
|
ODOTINTER: 8,
|
|
|
|
|
ODOTMETH: 8,
|
|
|
|
|
ODOTPTR: 8,
|
|
|
|
|
ODOTTYPE2: 8,
|
|
|
|
|
ODOTTYPE: 8,
|
|
|
|
|
ODOT: 8,
|
|
|
|
|
OXDOT: 8,
|
|
|
|
|
OCALLPART: 8,
|
|
|
|
|
OPLUS: 7,
|
|
|
|
|
ONOT: 7,
|
|
|
|
|
OBITNOT: 7,
|
|
|
|
|
ONEG: 7,
|
|
|
|
|
OADDR: 7,
|
|
|
|
|
ODEREF: 7,
|
|
|
|
|
ORECV: 7,
|
|
|
|
|
OMUL: 6,
|
|
|
|
|
ODIV: 6,
|
|
|
|
|
OMOD: 6,
|
|
|
|
|
OLSH: 6,
|
|
|
|
|
ORSH: 6,
|
|
|
|
|
OAND: 6,
|
|
|
|
|
OANDNOT: 6,
|
|
|
|
|
OADD: 5,
|
|
|
|
|
OSUB: 5,
|
|
|
|
|
OOR: 5,
|
|
|
|
|
OXOR: 5,
|
|
|
|
|
OEQ: 4,
|
|
|
|
|
OLT: 4,
|
|
|
|
|
OLE: 4,
|
|
|
|
|
OGE: 4,
|
|
|
|
|
OGT: 4,
|
|
|
|
|
ONE: 4,
|
|
|
|
|
OSEND: 3,
|
|
|
|
|
OANDAND: 2,
|
|
|
|
|
OOROR: 1,
|
2017-01-12 14:35:20 -08:00
|
|
|
|
2015-02-20 13:54:45 -05:00
|
|
|
// Statements handled by stmtfmt
|
|
|
|
|
OAS: -1,
|
2015-02-13 14:40:36 -05:00
|
|
|
OAS2: -1,
|
|
|
|
|
OAS2DOTTYPE: -1,
|
|
|
|
|
OAS2FUNC: -1,
|
|
|
|
|
OAS2MAPR: -1,
|
|
|
|
|
OAS2RECV: -1,
|
|
|
|
|
OASOP: -1,
|
2020-11-30 21:56:24 -05:00
|
|
|
OBLOCK: -1,
|
2015-02-13 14:40:36 -05:00
|
|
|
OBREAK: -1,
|
|
|
|
|
OCASE: -1,
|
|
|
|
|
OCONTINUE: -1,
|
|
|
|
|
ODCL: -1,
|
|
|
|
|
ODEFER: -1,
|
|
|
|
|
OFALL: -1,
|
|
|
|
|
OFOR: -1,
|
2017-02-02 11:53:41 -05:00
|
|
|
OFORUNTIL: -1,
|
2015-02-13 14:40:36 -05:00
|
|
|
OGOTO: -1,
|
|
|
|
|
OIF: -1,
|
|
|
|
|
OLABEL: -1,
|
2018-11-18 08:34:38 -08:00
|
|
|
OGO: -1,
|
2015-02-13 14:40:36 -05:00
|
|
|
ORANGE: -1,
|
|
|
|
|
ORETURN: -1,
|
|
|
|
|
OSELECT: -1,
|
|
|
|
|
OSWITCH: -1,
|
2017-01-12 14:35:20 -08:00
|
|
|
|
|
|
|
|
OEND: 0,
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2020-12-06 14:15:09 -05:00
|
|
|
// StmtWithInit reports whether op is a statement with an explicit init list.
|
2020-12-05 00:02:46 -05:00
|
|
|
func StmtWithInit(op Op) bool {
|
|
|
|
|
switch op {
|
|
|
|
|
case OIF, OFOR, OFORUNTIL, OSWITCH:
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-05 14:46:19 -05:00
|
|
|
func stmtFmt(n Node, s fmt.State) {
|
|
|
|
|
// NOTE(rsc): This code used to support the text-based
|
|
|
|
|
// which was more aggressive about printing full Go syntax
|
|
|
|
|
// (for example, an actual loop instead of "for loop").
|
|
|
|
|
// The code is preserved for now in case we want to expand
|
|
|
|
|
// any of those shortenings later. Or maybe we will delete
|
|
|
|
|
// the code. But for now, keep it.
|
|
|
|
|
const exportFormat = false
|
|
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
// some statements allow for an init, but at most one,
|
|
|
|
|
// but we may have an arbitrary number added, eg by typecheck
|
|
|
|
|
// and inlining. If it doesn't fit the syntax, emit an enclosing
|
|
|
|
|
// block starting with the init statements.
|
2020-12-03 11:56:29 -08:00
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
// if we can just say "for" n->ninit; ... then do so
|
|
|
|
|
simpleinit := n.Init().Len() == 1 && n.Init().First().Init().Len() == 0 && StmtWithInit(n.Op())
|
2020-12-03 11:56:29 -08:00
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
// otherwise, print the inits as separate statements
|
2020-12-05 14:46:19 -05:00
|
|
|
complexinit := n.Init().Len() != 0 && !simpleinit && exportFormat
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
// but if it was for if/for/switch, put in an extra surrounding block to limit the scope
|
|
|
|
|
extrablock := complexinit && StmtWithInit(n.Op())
|
|
|
|
|
|
|
|
|
|
if extrablock {
|
|
|
|
|
fmt.Fprint(s, "{")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
if complexinit {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, " %v; ", n.Init())
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2020-11-22 09:59:15 -05:00
|
|
|
switch n.Op() {
|
2020-12-05 00:02:46 -05:00
|
|
|
case ODCL:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*Decl)
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "var %v %v", n.Left().Sym(), n.Left().Type())
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
// Don't export "v = <N>" initializing statements, hope they're always
|
|
|
|
|
// preceded by the DCL which will be re-parsed and typechecked to reproduce
|
|
|
|
|
// the "v = <N>" again.
|
|
|
|
|
case OAS:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*AssignStmt)
|
2020-12-05 00:02:46 -05:00
|
|
|
if n.Colas() && !complexinit {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%v := %v", n.Left(), n.Right())
|
2020-12-05 00:02:46 -05:00
|
|
|
} else {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%v = %v", n.Left(), n.Right())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
2020-11-13 20:38:21 -08:00
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
case OASOP:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*AssignOpStmt)
|
2020-12-05 00:02:46 -05:00
|
|
|
if n.Implicit() {
|
|
|
|
|
if n.SubOp() == OADD {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%v++", n.Left())
|
2020-12-05 00:02:46 -05:00
|
|
|
} else {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%v--", n.Left())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
[dev.regabi] cmd/compile: rewrite stale format strings
On ir.Node, ir.Nodes, and ir.Op, # is ignored, so %#v is %v.
On ir.Node, %S is the same as %v.
On types.Type, # is ignored, so %#L is %L, %#v is %v.
On types.Type, 0 is ignored, so %0S is %S.
Rewrite all these using go test cmd/compile -r, plus a
few multiline formats mentioning %0S on types updated by hand.
Now the formats used in the compiler match the documentation
for the format methods, a minor miracle.
Passes buildall w/ toolstash -cmp.
Change-Id: I3d4a3fae543145a68da13eede91166632c5b1ceb
Reviewed-on: https://go-review.googlesource.com/c/go/+/275782
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-12-06 14:53:38 -05:00
|
|
|
fmt.Fprintf(s, "%v %v= %v", n.Left(), n.SubOp(), n.Right())
|
2020-12-05 00:02:46 -05:00
|
|
|
|
|
|
|
|
case OAS2, OAS2DOTTYPE, OAS2FUNC, OAS2MAPR, OAS2RECV:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*AssignListStmt)
|
2020-12-05 00:02:46 -05:00
|
|
|
if n.Colas() && !complexinit {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%.v := %.v", n.List(), n.Rlist())
|
2020-12-05 00:02:46 -05:00
|
|
|
} else {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%.v = %.v", n.List(), n.Rlist())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OBLOCK:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*BlockStmt)
|
2020-12-05 00:02:46 -05:00
|
|
|
if n.List().Len() != 0 {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%v", n.List())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case ORETURN:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*ReturnStmt)
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "return %.v", n.List())
|
2020-12-05 00:02:46 -05:00
|
|
|
|
|
|
|
|
case ORETJMP:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*BranchStmt)
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "retjmp %v", n.Sym())
|
2020-12-05 00:02:46 -05:00
|
|
|
|
|
|
|
|
case OINLMARK:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*InlineMarkStmt)
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "inlmark %d", n.Offset())
|
2020-12-05 00:02:46 -05:00
|
|
|
|
|
|
|
|
case OGO:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*GoDeferStmt)
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "go %v", n.Left())
|
2020-12-05 00:02:46 -05:00
|
|
|
|
|
|
|
|
case ODEFER:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*GoDeferStmt)
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "defer %v", n.Left())
|
2020-12-05 00:02:46 -05:00
|
|
|
|
|
|
|
|
case OIF:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*IfStmt)
|
2020-12-05 00:02:46 -05:00
|
|
|
if simpleinit {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "if %v; %v { %v }", n.Init().First(), n.Left(), n.Body())
|
2020-12-05 00:02:46 -05:00
|
|
|
} else {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "if %v { %v }", n.Left(), n.Body())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
if n.Rlist().Len() != 0 {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, " else { %v }", n.Rlist())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OFOR, OFORUNTIL:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*ForStmt)
|
2020-12-05 00:02:46 -05:00
|
|
|
opname := "for"
|
|
|
|
|
if n.Op() == OFORUNTIL {
|
|
|
|
|
opname = "foruntil"
|
|
|
|
|
}
|
2020-12-05 14:46:19 -05:00
|
|
|
if !exportFormat { // TODO maybe only if FmtShort, same below
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(s, "%s loop", opname)
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fmt.Fprint(s, opname)
|
|
|
|
|
if simpleinit {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, " %v;", n.Init().First())
|
2020-12-05 00:02:46 -05:00
|
|
|
} else if n.Right() != nil {
|
|
|
|
|
fmt.Fprint(s, " ;")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Left() != nil {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, " %v", n.Left())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Right() != nil {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "; %v", n.Right())
|
2020-12-05 00:02:46 -05:00
|
|
|
} else if simpleinit {
|
|
|
|
|
fmt.Fprint(s, ";")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Op() == OFORUNTIL && n.List().Len() != 0 {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "; %v", n.List())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, " { %v }", n.Body())
|
2020-12-05 00:02:46 -05:00
|
|
|
|
|
|
|
|
case ORANGE:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*RangeStmt)
|
2020-12-05 14:46:19 -05:00
|
|
|
if !exportFormat {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprint(s, "for loop")
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.List().Len() == 0 {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "for range %v { %v }", n.Right(), n.Body())
|
2020-12-05 00:02:46 -05:00
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "for %.v = range %v { %v }", n.List(), n.Right(), n.Body())
|
2020-12-05 00:02:46 -05:00
|
|
|
|
2020-12-10 20:55:10 -05:00
|
|
|
case OSELECT:
|
|
|
|
|
n := n.(*SelectStmt)
|
2020-12-05 14:46:19 -05:00
|
|
|
if !exportFormat {
|
|
|
|
|
fmt.Fprintf(s, "%v statement", n.Op())
|
2020-12-05 00:02:46 -05:00
|
|
|
break
|
|
|
|
|
}
|
2020-12-10 20:55:10 -05:00
|
|
|
fmt.Fprintf(s, "select { %v }", n.List())
|
2020-12-05 00:02:46 -05:00
|
|
|
|
2020-12-10 20:55:10 -05:00
|
|
|
case OSWITCH:
|
|
|
|
|
n := n.(*SwitchStmt)
|
|
|
|
|
if !exportFormat {
|
|
|
|
|
fmt.Fprintf(s, "%v statement", n.Op())
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
fmt.Fprintf(s, "switch")
|
2020-12-05 00:02:46 -05:00
|
|
|
if simpleinit {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, " %v;", n.Init().First())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
if n.Left() != nil {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, " %v ", n.Left())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, " { %v }", n.List())
|
2020-12-05 00:02:46 -05:00
|
|
|
|
|
|
|
|
case OCASE:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*CaseStmt)
|
2020-12-05 00:02:46 -05:00
|
|
|
if n.List().Len() != 0 {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "case %.v", n.List())
|
2020-12-05 00:02:46 -05:00
|
|
|
} else {
|
|
|
|
|
fmt.Fprint(s, "default")
|
|
|
|
|
}
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, ": %v", n.Body())
|
2020-12-05 00:02:46 -05:00
|
|
|
|
|
|
|
|
case OBREAK, OCONTINUE, OGOTO, OFALL:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*BranchStmt)
|
2020-12-05 00:02:46 -05:00
|
|
|
if n.Sym() != nil {
|
[dev.regabi] cmd/compile: rewrite stale format strings
On ir.Node, ir.Nodes, and ir.Op, # is ignored, so %#v is %v.
On ir.Node, %S is the same as %v.
On types.Type, # is ignored, so %#L is %L, %#v is %v.
On types.Type, 0 is ignored, so %0S is %S.
Rewrite all these using go test cmd/compile -r, plus a
few multiline formats mentioning %0S on types updated by hand.
Now the formats used in the compiler match the documentation
for the format methods, a minor miracle.
Passes buildall w/ toolstash -cmp.
Change-Id: I3d4a3fae543145a68da13eede91166632c5b1ceb
Reviewed-on: https://go-review.googlesource.com/c/go/+/275782
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-12-06 14:53:38 -05:00
|
|
|
fmt.Fprintf(s, "%v %v", n.Op(), n.Sym())
|
2020-12-05 00:02:46 -05:00
|
|
|
} else {
|
[dev.regabi] cmd/compile: rewrite stale format strings
On ir.Node, ir.Nodes, and ir.Op, # is ignored, so %#v is %v.
On ir.Node, %S is the same as %v.
On types.Type, # is ignored, so %#L is %L, %#v is %v.
On types.Type, 0 is ignored, so %0S is %S.
Rewrite all these using go test cmd/compile -r, plus a
few multiline formats mentioning %0S on types updated by hand.
Now the formats used in the compiler match the documentation
for the format methods, a minor miracle.
Passes buildall w/ toolstash -cmp.
Change-Id: I3d4a3fae543145a68da13eede91166632c5b1ceb
Reviewed-on: https://go-review.googlesource.com/c/go/+/275782
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-12-06 14:53:38 -05:00
|
|
|
fmt.Fprintf(s, "%v", n.Op())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OLABEL:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*LabelStmt)
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%v: ", n.Sym())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if extrablock {
|
|
|
|
|
fmt.Fprint(s, "}")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-05 14:46:19 -05:00
|
|
|
func exprFmt(n Node, s fmt.State, prec int) {
|
|
|
|
|
// NOTE(rsc): This code used to support the text-based
|
|
|
|
|
// which was more aggressive about printing full Go syntax
|
|
|
|
|
// (for example, an actual loop instead of "for loop").
|
|
|
|
|
// The code is preserved for now in case we want to expand
|
|
|
|
|
// any of those shortenings later. Or maybe we will delete
|
|
|
|
|
// the code. But for now, keep it.
|
|
|
|
|
const exportFormat = false
|
|
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
for {
|
|
|
|
|
if n == nil {
|
2020-12-10 20:55:10 -05:00
|
|
|
fmt.Fprint(s, "<nil>")
|
2020-12-05 00:02:46 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We always want the original, if any.
|
|
|
|
|
if o := Orig(n); o != n {
|
|
|
|
|
n = o
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Skip implicit operations introduced during typechecking.
|
2020-12-10 20:55:10 -05:00
|
|
|
switch nn := n; nn.Op() {
|
|
|
|
|
case OADDR:
|
|
|
|
|
nn := nn.(*AddrExpr)
|
|
|
|
|
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()
|
2020-12-05 00:02:46 -05:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
nprec := OpPrec[n.Op()]
|
|
|
|
|
if n.Op() == OTYPE && n.Sym() != nil {
|
|
|
|
|
nprec = 8
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if prec > nprec {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "(%v)", n)
|
2020-12-05 00:02:46 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch n.Op() {
|
|
|
|
|
case OPAREN:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*ParenExpr)
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "(%v)", n.Left())
|
2020-12-05 00:02:46 -05:00
|
|
|
|
|
|
|
|
case ONIL:
|
|
|
|
|
fmt.Fprint(s, "nil")
|
|
|
|
|
|
|
|
|
|
case OLITERAL: // this is a bit of a mess
|
2020-12-05 14:46:19 -05:00
|
|
|
if !exportFormat && n.Sym() != nil {
|
2020-12-06 12:38:11 -05:00
|
|
|
fmt.Fprint(s, n.Sym())
|
2020-12-03 11:56:29 -08:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-11-13 20:38:21 -08:00
|
|
|
|
2020-11-13 18:33:19 -08:00
|
|
|
needUnparen := false
|
2020-11-22 09:59:15 -05:00
|
|
|
if n.Type() != nil && !n.Type().IsUntyped() {
|
2015-02-13 14:40:36 -05:00
|
|
|
// Need parens when type begins with what might
|
|
|
|
|
// be misinterpreted as a unary operator: * or <-.
|
2020-11-22 09:59:15 -05:00
|
|
|
if n.Type().IsPtr() || (n.Type().IsChan() && n.Type().ChanDir() == types.Crecv) {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "(%v)(", n.Type())
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%v(", n.Type())
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-11-13 18:33:19 -08:00
|
|
|
needUnparen = true
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2020-11-22 09:59:15 -05:00
|
|
|
if n.Type() == types.UntypedRune {
|
2020-11-13 23:36:48 -08:00
|
|
|
switch x, ok := constant.Int64Val(n.Val()); {
|
|
|
|
|
case !ok:
|
|
|
|
|
fallthrough
|
|
|
|
|
default:
|
|
|
|
|
fmt.Fprintf(s, "('\\x00' + %v)", n.Val())
|
|
|
|
|
|
2020-11-13 18:33:19 -08:00
|
|
|
case ' ' <= x && x < utf8.RuneSelf && x != '\\' && x != '\'':
|
|
|
|
|
fmt.Fprintf(s, "'%c'", int(x))
|
|
|
|
|
|
|
|
|
|
case 0 <= x && x < 1<<16:
|
|
|
|
|
fmt.Fprintf(s, "'\\u%04x'", uint(int(x)))
|
|
|
|
|
|
|
|
|
|
case 0 <= x && x <= utf8.MaxRune:
|
|
|
|
|
fmt.Fprintf(s, "'\\U%08x'", uint64(x))
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2020-12-06 13:54:50 -05:00
|
|
|
fmt.Fprint(s, types.FmtConst(n.Val(), s.Flag('#')))
|
2020-11-13 18:33:19 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if needUnparen {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, ")")
|
2020-11-13 18:33:19 -08:00
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-11-28 07:23:50 -05:00
|
|
|
case ODCLFUNC:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*Func)
|
2020-11-28 07:23:50 -05:00
|
|
|
if sym := n.Sym(); sym != nil {
|
2020-12-06 12:38:11 -05:00
|
|
|
fmt.Fprint(s, sym)
|
2020-11-28 07:23:50 -05:00
|
|
|
return
|
|
|
|
|
}
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "<unnamed Func>")
|
2020-11-28 07:23:50 -05:00
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
case ONAME:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*Name)
|
2020-11-18 11:25:29 -05:00
|
|
|
// Special case: name used as local variable in export.
|
|
|
|
|
// _ becomes ~b%d internally; print as _ for export
|
2020-12-05 14:46:19 -05:00
|
|
|
if !exportFormat && n.Sym() != nil && n.Sym().Name[0] == '~' && n.Sym().Name[1] == 'b' {
|
2016-08-31 16:02:36 -07:00
|
|
|
fmt.Fprint(s, "_")
|
|
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
fallthrough
|
2020-12-10 18:47:09 -05:00
|
|
|
case OPACK, ONONAME:
|
2020-12-06 12:38:11 -05:00
|
|
|
fmt.Fprint(s, n.Sym())
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-10 18:47:09 -05:00
|
|
|
case OMETHEXPR:
|
|
|
|
|
n := n.(*MethodExpr)
|
|
|
|
|
fmt.Fprint(s, n.FuncName().Sym())
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
case OTYPE:
|
2020-11-22 09:59:15 -05:00
|
|
|
if n.Type() == nil && n.Sym() != nil {
|
2020-12-06 12:38:11 -05:00
|
|
|
fmt.Fprint(s, n.Sym())
|
2016-08-31 16:02:36 -07:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%v", n.Type())
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-11-26 07:02:13 -05:00
|
|
|
case OTSLICE:
|
|
|
|
|
n := n.(*SliceType)
|
|
|
|
|
if n.DDD {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "...%v", n.Elem)
|
2020-11-26 07:02:13 -05:00
|
|
|
} else {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "[]%v", n.Elem) // happens before typecheck
|
2020-11-26 07:02:13 -05:00
|
|
|
}
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
case OTARRAY:
|
2020-11-26 07:02:13 -05:00
|
|
|
n := n.(*ArrayType)
|
|
|
|
|
if n.Len == nil {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "[...]%v", n.Elem)
|
2020-11-26 07:02:13 -05:00
|
|
|
} else {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "[%v]%v", n.Len, n.Elem)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OTMAP:
|
2020-11-26 07:02:13 -05:00
|
|
|
n := n.(*MapType)
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "map[%v]%v", n.Key, n.Elem)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OTCHAN:
|
2020-11-26 07:02:13 -05:00
|
|
|
n := n.(*ChanType)
|
|
|
|
|
switch n.Dir {
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
case types.Crecv:
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "<-chan %v", n.Elem)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
cmd/compile: factor out Pkg, Sym, and Type into package types
- created new package cmd/compile/internal/types
- moved Pkg, Sym, Type to new package
- to break cycles, for now we need the (ugly) types/utils.go
file which contains a handful of functions that must be installed
early by the gc frontend
- to break cycles, for now we need two functions to convert between
*gc.Node and *types.Node (the latter is a dummy type)
- adjusted the gc's code to use the new package and the conversion
functions as needed
- made several Pkg, Sym, and Type methods functions as needed
- renamed constructors typ, typPtr, typArray, etc. to types.New,
types.NewPtr, types.NewArray, etc.
Passes toolstash-check -all.
Change-Id: I8adfa5e85c731645d0a7fd2030375ed6ebf54b72
Reviewed-on: https://go-review.googlesource.com/39855
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2017-04-04 17:54:02 -07:00
|
|
|
case types.Csend:
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "chan<- %v", n.Elem)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
default:
|
2020-11-26 07:02:13 -05:00
|
|
|
if n.Elem != nil && n.Elem.Op() == OTCHAN && n.Elem.(*ChanType).Dir == types.Crecv {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "chan (%v)", n.Elem)
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "chan %v", n.Elem)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OTSTRUCT:
|
2016-08-31 16:02:36 -07:00
|
|
|
fmt.Fprint(s, "<struct>")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OTINTER:
|
2016-08-31 16:02:36 -07:00
|
|
|
fmt.Fprint(s, "<inter>")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OTFUNC:
|
2016-08-31 16:02:36 -07:00
|
|
|
fmt.Fprint(s, "<func>")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OCLOSURE:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*ClosureExpr)
|
2020-12-05 14:46:19 -05:00
|
|
|
if !exportFormat {
|
2016-08-31 16:02:36 -07:00
|
|
|
fmt.Fprint(s, "func literal")
|
|
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%v { %v }", n.Type(), n.Func().Body())
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OCOMPLIT:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*CompLitExpr)
|
2020-12-05 14:46:19 -05:00
|
|
|
if !exportFormat {
|
cmd/compile: use fixVariadicCall in escape analysis
This CL uses fixVariadicCall before escape analyzing function calls.
This has a number of benefits, though also some minor obstacles:
Most notably, it allows us to remove ODDDARG along with the logic
involved in setting it up, manipulating EscHoles, and later copying
its escape analysis flags to the actual slice argument. Instead, we
uniformly handle all variadic calls the same way. (E.g., issue31573.go
is updated because now f() and f(nil...) are handled identically.)
It also allows us to simplify handling of builtins and generic
function calls. Previously handling of calls was hairy enough to
require multiple dispatches on n.Op, whereas now the logic is uniform
enough that we can easily handle it with a single dispatch.
The downside is handling //go:uintptrescapes is now somewhat clumsy.
(It used to be clumsy, but it still is, too.) The proper fix here is
probably to stop using escape analysis tags for //go:uintptrescapes
and unsafe-uintptr, and have an earlier pass responsible for them.
Finally, note that while we now call fixVariadicCall in Escape, we
still have to call it in Order, because we don't (yet) run Escape on
all compiler-generated functions. In particular, the generated "init"
function for initializing package-level variables can contain calls to
variadic functions and isn't escape analyzed.
Passes toolstash-check -race.
Change-Id: I4cdb92a393ac487910aeee58a5cb8c1500eef881
Reviewed-on: https://go-review.googlesource.com/c/go/+/229759
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
2020-04-21 19:48:02 -07:00
|
|
|
if n.Implicit() {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "... argument")
|
cmd/compile: use fixVariadicCall in escape analysis
This CL uses fixVariadicCall before escape analyzing function calls.
This has a number of benefits, though also some minor obstacles:
Most notably, it allows us to remove ODDDARG along with the logic
involved in setting it up, manipulating EscHoles, and later copying
its escape analysis flags to the actual slice argument. Instead, we
uniformly handle all variadic calls the same way. (E.g., issue31573.go
is updated because now f() and f(nil...) are handled identically.)
It also allows us to simplify handling of builtins and generic
function calls. Previously handling of calls was hairy enough to
require multiple dispatches on n.Op, whereas now the logic is uniform
enough that we can easily handle it with a single dispatch.
The downside is handling //go:uintptrescapes is now somewhat clumsy.
(It used to be clumsy, but it still is, too.) The proper fix here is
probably to stop using escape analysis tags for //go:uintptrescapes
and unsafe-uintptr, and have an earlier pass responsible for them.
Finally, note that while we now call fixVariadicCall in Escape, we
still have to call it in Order, because we don't (yet) run Escape on
all compiler-generated functions. In particular, the generated "init"
function for initializing package-level variables can contain calls to
variadic functions and isn't escape analyzed.
Passes toolstash-check -race.
Change-Id: I4cdb92a393ac487910aeee58a5cb8c1500eef881
Reviewed-on: https://go-review.googlesource.com/c/go/+/229759
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
2020-04-21 19:48:02 -07:00
|
|
|
return
|
|
|
|
|
}
|
2020-11-22 09:59:15 -05:00
|
|
|
if n.Right() != nil {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%v{%s}", n.Right(), ellipsisIf(n.List().Len() != 0))
|
2018-09-19 16:19:05 -07:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2016-08-31 16:02:36 -07:00
|
|
|
fmt.Fprint(s, "composite literal")
|
|
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "(%v{ %.v })", n.Right(), n.List())
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OPTRLIT:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*AddrExpr)
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "&%v", n.Left())
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-06-19 07:20:28 -07:00
|
|
|
case OSTRUCTLIT, OARRAYLIT, OSLICELIT, OMAPLIT:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*CompLitExpr)
|
2020-12-05 14:46:19 -05:00
|
|
|
if !exportFormat {
|
|
|
|
|
fmt.Fprintf(s, "%v{%s}", n.Type(), ellipsisIf(n.List().Len() != 0))
|
2016-08-31 16:02:36 -07:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "(%v{ %.v })", n.Type(), n.List())
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OKEY:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*KeyExpr)
|
2020-11-22 09:59:15 -05:00
|
|
|
if n.Left() != nil && n.Right() != nil {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%v:%v", n.Left(), n.Right())
|
2016-08-31 16:02:36 -07:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2020-11-22 09:59:15 -05:00
|
|
|
if n.Left() == nil && n.Right() != nil {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, ":%v", n.Right())
|
2016-08-31 16:02:36 -07:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-11-22 09:59:15 -05:00
|
|
|
if n.Left() != nil && n.Right() == nil {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%v:", n.Left())
|
2016-08-31 16:02:36 -07:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-08-31 16:02:36 -07:00
|
|
|
fmt.Fprint(s, ":")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-10-12 15:48:18 -07:00
|
|
|
case OSTRUCTKEY:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*StructKeyExpr)
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%v:%v", n.Sym(), n.Left())
|
2016-10-12 15:48:18 -07:00
|
|
|
|
cmd/compile: change ODOT and friends to use Sym, not Right
The Node type ODOT and its variants all represent a selector, with a
simple name to the right of the dot. Before this change this was
represented by using an ONAME Node in the Right field. This ONAME node
served no useful purpose. This CL changes these Node types to store the
symbol in the Sym field instead, thus not requiring allocating a Node
for each selector.
When compiling x/tools/go/types this CL eliminates nearly 5000 calls to
newname and reduces the total number of Nodes allocated by about 6.6%.
It seems to cut compilation time by 1 to 2 percent.
Getting this right was somewhat subtle, and I added two dubious changes
to produce the exact same output as before. One is to ishairy in
inl.go: the ONAME node increased the cost of ODOT and friends by 1, and
I retained that, although really ODOT is not more expensive than any
other node. The other is to varexpr in walk.go: because the ONAME in
the Right field of an ODOT has no class, varexpr would always return
false for an ODOT, although in fact for some ODOT's it seemingly ought
to return true; I added an && false for now. I will send separate CLs,
that will break toolstash -cmp, to clean these up.
This CL passes toolstash -cmp.
Change-Id: I4af8a10cc59078c436130ce472f25abc3a9b2f80
Reviewed-on: https://go-review.googlesource.com/20890
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-03-18 16:52:30 -07:00
|
|
|
case OCALLPART:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*CallPartExpr)
|
2020-12-05 14:46:19 -05:00
|
|
|
exprFmt(n.Left(), s, nprec)
|
2020-12-02 21:38:20 -08:00
|
|
|
if n.Sym() == nil {
|
2016-08-31 16:02:36 -07:00
|
|
|
fmt.Fprint(s, ".<nil>")
|
|
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-12-06 13:54:50 -05:00
|
|
|
fmt.Fprintf(s, ".%s", types.SymMethodName(n.Sym()))
|
2015-02-13 14:40:36 -05:00
|
|
|
|
cmd/compile: change ODOT and friends to use Sym, not Right
The Node type ODOT and its variants all represent a selector, with a
simple name to the right of the dot. Before this change this was
represented by using an ONAME Node in the Right field. This ONAME node
served no useful purpose. This CL changes these Node types to store the
symbol in the Sym field instead, thus not requiring allocating a Node
for each selector.
When compiling x/tools/go/types this CL eliminates nearly 5000 calls to
newname and reduces the total number of Nodes allocated by about 6.6%.
It seems to cut compilation time by 1 to 2 percent.
Getting this right was somewhat subtle, and I added two dubious changes
to produce the exact same output as before. One is to ishairy in
inl.go: the ONAME node increased the cost of ODOT and friends by 1, and
I retained that, although really ODOT is not more expensive than any
other node. The other is to varexpr in walk.go: because the ONAME in
the Right field of an ODOT has no class, varexpr would always return
false for an ODOT, although in fact for some ODOT's it seemingly ought
to return true; I added an && false for now. I will send separate CLs,
that will break toolstash -cmp, to clean these up.
This CL passes toolstash -cmp.
Change-Id: I4af8a10cc59078c436130ce472f25abc3a9b2f80
Reviewed-on: https://go-review.googlesource.com/20890
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-03-18 16:52:30 -07:00
|
|
|
case OXDOT, ODOT, ODOTPTR, ODOTINTER, ODOTMETH:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*SelectorExpr)
|
2020-12-05 14:46:19 -05:00
|
|
|
exprFmt(n.Left(), s, nprec)
|
2020-11-22 09:59:15 -05:00
|
|
|
if n.Sym() == nil {
|
2016-08-31 16:02:36 -07:00
|
|
|
fmt.Fprint(s, ".<nil>")
|
|
|
|
|
return
|
cmd/compile: change ODOT and friends to use Sym, not Right
The Node type ODOT and its variants all represent a selector, with a
simple name to the right of the dot. Before this change this was
represented by using an ONAME Node in the Right field. This ONAME node
served no useful purpose. This CL changes these Node types to store the
symbol in the Sym field instead, thus not requiring allocating a Node
for each selector.
When compiling x/tools/go/types this CL eliminates nearly 5000 calls to
newname and reduces the total number of Nodes allocated by about 6.6%.
It seems to cut compilation time by 1 to 2 percent.
Getting this right was somewhat subtle, and I added two dubious changes
to produce the exact same output as before. One is to ishairy in
inl.go: the ONAME node increased the cost of ODOT and friends by 1, and
I retained that, although really ODOT is not more expensive than any
other node. The other is to varexpr in walk.go: because the ONAME in
the Right field of an ODOT has no class, varexpr would always return
false for an ODOT, although in fact for some ODOT's it seemingly ought
to return true; I added an && false for now. I will send separate CLs,
that will break toolstash -cmp, to clean these up.
This CL passes toolstash -cmp.
Change-Id: I4af8a10cc59078c436130ce472f25abc3a9b2f80
Reviewed-on: https://go-review.googlesource.com/20890
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-03-18 16:52:30 -07:00
|
|
|
}
|
2020-12-06 13:54:50 -05:00
|
|
|
fmt.Fprintf(s, ".%s", types.SymMethodName(n.Sym()))
|
cmd/compile: change ODOT and friends to use Sym, not Right
The Node type ODOT and its variants all represent a selector, with a
simple name to the right of the dot. Before this change this was
represented by using an ONAME Node in the Right field. This ONAME node
served no useful purpose. This CL changes these Node types to store the
symbol in the Sym field instead, thus not requiring allocating a Node
for each selector.
When compiling x/tools/go/types this CL eliminates nearly 5000 calls to
newname and reduces the total number of Nodes allocated by about 6.6%.
It seems to cut compilation time by 1 to 2 percent.
Getting this right was somewhat subtle, and I added two dubious changes
to produce the exact same output as before. One is to ishairy in
inl.go: the ONAME node increased the cost of ODOT and friends by 1, and
I retained that, although really ODOT is not more expensive than any
other node. The other is to varexpr in walk.go: because the ONAME in
the Right field of an ODOT has no class, varexpr would always return
false for an ODOT, although in fact for some ODOT's it seemingly ought
to return true; I added an && false for now. I will send separate CLs,
that will break toolstash -cmp, to clean these up.
This CL passes toolstash -cmp.
Change-Id: I4af8a10cc59078c436130ce472f25abc3a9b2f80
Reviewed-on: https://go-review.googlesource.com/20890
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2016-03-18 16:52:30 -07:00
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case ODOTTYPE, ODOTTYPE2:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*TypeAssertExpr)
|
2020-12-05 14:46:19 -05:00
|
|
|
exprFmt(n.Left(), s, nprec)
|
2020-11-22 09:59:15 -05:00
|
|
|
if n.Right() != nil {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, ".(%v)", n.Right())
|
2016-08-31 16:02:36 -07:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, ".(%v)", n.Type())
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2016-04-21 11:55:33 -07:00
|
|
|
case OINDEX, OINDEXMAP:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*IndexExpr)
|
2020-12-05 14:46:19 -05:00
|
|
|
exprFmt(n.Left(), s, nprec)
|
|
|
|
|
fmt.Fprintf(s, "[%v]", n.Right())
|
2016-04-21 11:55:33 -07:00
|
|
|
|
|
|
|
|
case OSLICE, OSLICESTR, OSLICEARR, OSLICE3, OSLICE3ARR:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*SliceExpr)
|
2020-12-05 14:46:19 -05:00
|
|
|
exprFmt(n.Left(), s, nprec)
|
2016-08-31 16:02:36 -07:00
|
|
|
fmt.Fprint(s, "[")
|
2016-04-21 11:55:33 -07:00
|
|
|
low, high, max := n.SliceBounds()
|
|
|
|
|
if low != nil {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprint(s, low)
|
2016-04-21 11:55:33 -07:00
|
|
|
}
|
2016-08-31 16:02:36 -07:00
|
|
|
fmt.Fprint(s, ":")
|
2016-04-21 11:55:33 -07:00
|
|
|
if high != nil {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprint(s, high)
|
2016-04-21 11:55:33 -07:00
|
|
|
}
|
2020-11-22 09:59:15 -05:00
|
|
|
if n.Op().IsSlice3() {
|
2016-08-31 16:02:36 -07:00
|
|
|
fmt.Fprint(s, ":")
|
2016-04-21 11:55:33 -07:00
|
|
|
if max != nil {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprint(s, max)
|
2016-04-21 11:55:33 -07:00
|
|
|
}
|
|
|
|
|
}
|
2016-08-31 16:02:36 -07:00
|
|
|
fmt.Fprint(s, "]")
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2018-11-02 14:38:33 +01:00
|
|
|
case OSLICEHEADER:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*SliceHeaderExpr)
|
2020-11-22 09:59:15 -05:00
|
|
|
if n.List().Len() != 2 {
|
|
|
|
|
base.Fatalf("bad OSLICEHEADER list length %d", n.List().Len())
|
2018-11-02 14:38:33 +01:00
|
|
|
}
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "sliceheader{%v,%v,%v}", n.Left(), n.List().First(), n.List().Second())
|
2018-11-02 14:38:33 +01:00
|
|
|
|
cmd/compile: rewrite f(g()) for multi-value g() during typecheck
This is a re-attempt at CL 153841, which caused two regressions:
1. crypto/ecdsa failed to build with -gcflags=-l=4. This was because
when "t1, t2, ... := g(); f(t1, t2, ...)" was exported, we were losing
the first assignment from the call's Ninit field.
2. net/http/pprof failed to run with -gcflags=-N. This is due to a
conflict with CL 159717: as of that CL, package-scope initialization
statements are executed within the "init.ializer" function, rather
than the "init" function, and the generated temp variables need to be
moved accordingly too.
[Rest of description is as before.]
This CL moves order.go's copyRet logic for rewriting f(g()) into t1,
t2, ... := g(); f(t1, t2, ...) earlier into typecheck. This allows the
rest of the compiler to stop worrying about multi-value functions
appearing outside of OAS2FUNC nodes.
This changes compiler behavior in a few observable ways:
1. Typechecking error messages for builtin functions now use general
case error messages rather than unnecessarily differing ones.
2. Because f(g()) is rewritten before inlining, saved inline bodies
now see the rewritten form too. This could be addressed, but doesn't
seem worthwhile.
3. Most notably, this simplifies escape analysis and fixes a memory
corruption issue in esc.go. See #29197 for details.
Fixes #15992.
Fixes #29197.
Change-Id: I930b10f7e27af68a0944d6c9bfc8707c3fab27a4
Reviewed-on: https://go-review.googlesource.com/c/go/+/166983
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2018-12-12 11:15:37 -08:00
|
|
|
case OCOMPLEX, OCOPY:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*BinaryExpr)
|
|
|
|
|
fmt.Fprintf(s, "%v(%v, %v)", n.Op(), n.Left(), n.Right())
|
2018-11-26 12:59:54 -08:00
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
case OCONV,
|
|
|
|
|
OCONVIFACE,
|
|
|
|
|
OCONVNOP,
|
2018-11-18 08:34:38 -08:00
|
|
|
OBYTES2STR,
|
|
|
|
|
ORUNES2STR,
|
|
|
|
|
OSTR2BYTES,
|
|
|
|
|
OSTR2RUNES,
|
2015-02-13 14:40:36 -05:00
|
|
|
ORUNESTR:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*ConvExpr)
|
2020-12-01 03:25:29 -08:00
|
|
|
if n.Type() == nil || n.Type().Sym() == nil {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "(%v)", n.Type())
|
2016-07-30 01:45:27 -07:00
|
|
|
} else {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%v", n.Type())
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-12-10 20:55:10 -05:00
|
|
|
fmt.Fprintf(s, "(%v)", n.Left())
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OREAL,
|
|
|
|
|
OIMAG,
|
|
|
|
|
OCAP,
|
|
|
|
|
OCLOSE,
|
|
|
|
|
OLEN,
|
|
|
|
|
ONEW,
|
|
|
|
|
OPANIC,
|
2016-10-18 14:17:05 -07:00
|
|
|
OALIGNOF,
|
|
|
|
|
OOFFSETOF,
|
2020-12-10 20:55:10 -05:00
|
|
|
OSIZEOF:
|
|
|
|
|
n := n.(*UnaryExpr)
|
|
|
|
|
fmt.Fprintf(s, "%v(%v)", n.Op(), n.Left())
|
|
|
|
|
|
|
|
|
|
case OAPPEND,
|
|
|
|
|
ODELETE,
|
|
|
|
|
OMAKE,
|
|
|
|
|
ORECOVER,
|
2015-02-13 14:40:36 -05:00
|
|
|
OPRINT,
|
|
|
|
|
OPRINTN:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*CallExpr)
|
2018-11-18 08:34:38 -08:00
|
|
|
if n.IsDDD() {
|
[dev.regabi] cmd/compile: rewrite stale format strings
On ir.Node, ir.Nodes, and ir.Op, # is ignored, so %#v is %v.
On ir.Node, %S is the same as %v.
On types.Type, # is ignored, so %#L is %L, %#v is %v.
On types.Type, 0 is ignored, so %0S is %S.
Rewrite all these using go test cmd/compile -r, plus a
few multiline formats mentioning %0S on types updated by hand.
Now the formats used in the compiler match the documentation
for the format methods, a minor miracle.
Passes buildall w/ toolstash -cmp.
Change-Id: I3d4a3fae543145a68da13eede91166632c5b1ceb
Reviewed-on: https://go-review.googlesource.com/c/go/+/275782
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-12-06 14:53:38 -05:00
|
|
|
fmt.Fprintf(s, "%v(%.v...)", n.Op(), n.List())
|
2016-08-31 16:02:36 -07:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
[dev.regabi] cmd/compile: rewrite stale format strings
On ir.Node, ir.Nodes, and ir.Op, # is ignored, so %#v is %v.
On ir.Node, %S is the same as %v.
On types.Type, # is ignored, so %#L is %L, %#v is %v.
On types.Type, 0 is ignored, so %0S is %S.
Rewrite all these using go test cmd/compile -r, plus a
few multiline formats mentioning %0S on types updated by hand.
Now the formats used in the compiler match the documentation
for the format methods, a minor miracle.
Passes buildall w/ toolstash -cmp.
Change-Id: I3d4a3fae543145a68da13eede91166632c5b1ceb
Reviewed-on: https://go-review.googlesource.com/c/go/+/275782
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-12-06 14:53:38 -05:00
|
|
|
fmt.Fprintf(s, "%v(%.v)", n.Op(), n.List())
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-04-03 12:23:28 -04:00
|
|
|
case OCALL, OCALLFUNC, OCALLINTER, OCALLMETH, OGETG:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*CallExpr)
|
2020-12-05 14:46:19 -05:00
|
|
|
exprFmt(n.Left(), s, nprec)
|
2018-11-18 08:34:38 -08:00
|
|
|
if n.IsDDD() {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "(%.v...)", n.List())
|
2016-08-31 16:02:36 -07:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "(%.v)", n.List())
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2015-04-01 09:38:44 -07:00
|
|
|
case OMAKEMAP, OMAKECHAN, OMAKESLICE:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*MakeExpr)
|
2020-11-22 09:59:15 -05:00
|
|
|
if n.Right() != nil {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "make(%v, %v, %v)", n.Type(), n.Left(), n.Right())
|
2016-08-31 16:02:36 -07:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-11-22 09:59:15 -05:00
|
|
|
if n.Left() != nil && (n.Op() == OMAKESLICE || !n.Left().Type().IsUntyped()) {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "make(%v, %v)", n.Type(), n.Left())
|
2016-08-31 16:02:36 -07:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "make(%v)", n.Type())
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2018-10-23 13:50:07 +02:00
|
|
|
case OMAKESLICECOPY:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*MakeExpr)
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "makeslicecopy(%v, %v, %v)", n.Type(), n.Left(), n.Right())
|
2018-10-23 13:50:07 +02:00
|
|
|
|
2020-12-10 20:55:10 -05:00
|
|
|
case OPLUS, ONEG, OBITNOT, ONOT, ORECV:
|
2015-02-13 14:40:36 -05:00
|
|
|
// Unary
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*UnaryExpr)
|
|
|
|
|
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 OADDR:
|
|
|
|
|
n := n.(*AddrExpr)
|
[dev.regabi] cmd/compile: rewrite stale format strings
On ir.Node, ir.Nodes, and ir.Op, # is ignored, so %#v is %v.
On ir.Node, %S is the same as %v.
On types.Type, # is ignored, so %#L is %L, %#v is %v.
On types.Type, 0 is ignored, so %0S is %S.
Rewrite all these using go test cmd/compile -r, plus a
few multiline formats mentioning %0S on types updated by hand.
Now the formats used in the compiler match the documentation
for the format methods, a minor miracle.
Passes buildall w/ toolstash -cmp.
Change-Id: I3d4a3fae543145a68da13eede91166632c5b1ceb
Reviewed-on: https://go-review.googlesource.com/c/go/+/275782
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-12-06 14:53:38 -05:00
|
|
|
fmt.Fprintf(s, "%v", n.Op())
|
2020-11-22 09:59:15 -05:00
|
|
|
if n.Left() != nil && n.Left().Op() == n.Op() {
|
2016-08-31 16:02:36 -07:00
|
|
|
fmt.Fprint(s, " ")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-12-05 14:46:19 -05:00
|
|
|
exprFmt(n.Left(), s, nprec+1)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-10 20:55:10 -05:00
|
|
|
case ODEREF:
|
|
|
|
|
n := n.(*StarExpr)
|
|
|
|
|
fmt.Fprintf(s, "%v", n.Op())
|
|
|
|
|
exprFmt(n.Left(), s, nprec+1)
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
// Binary
|
|
|
|
|
case OADD,
|
|
|
|
|
OAND,
|
|
|
|
|
OANDNOT,
|
|
|
|
|
ODIV,
|
|
|
|
|
OEQ,
|
|
|
|
|
OGE,
|
|
|
|
|
OGT,
|
|
|
|
|
OLE,
|
|
|
|
|
OLT,
|
|
|
|
|
OLSH,
|
|
|
|
|
OMOD,
|
|
|
|
|
OMUL,
|
|
|
|
|
ONE,
|
|
|
|
|
OOR,
|
|
|
|
|
ORSH,
|
|
|
|
|
OSUB,
|
|
|
|
|
OXOR:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*BinaryExpr)
|
|
|
|
|
exprFmt(n.Left(), s, nprec)
|
|
|
|
|
fmt.Fprintf(s, " %v ", n.Op())
|
|
|
|
|
exprFmt(n.Right(), s, nprec+1)
|
|
|
|
|
|
|
|
|
|
case OANDAND,
|
|
|
|
|
OOROR:
|
|
|
|
|
n := n.(*LogicalExpr)
|
2020-12-05 14:46:19 -05:00
|
|
|
exprFmt(n.Left(), s, nprec)
|
[dev.regabi] cmd/compile: rewrite stale format strings
On ir.Node, ir.Nodes, and ir.Op, # is ignored, so %#v is %v.
On ir.Node, %S is the same as %v.
On types.Type, # is ignored, so %#L is %L, %#v is %v.
On types.Type, 0 is ignored, so %0S is %S.
Rewrite all these using go test cmd/compile -r, plus a
few multiline formats mentioning %0S on types updated by hand.
Now the formats used in the compiler match the documentation
for the format methods, a minor miracle.
Passes buildall w/ toolstash -cmp.
Change-Id: I3d4a3fae543145a68da13eede91166632c5b1ceb
Reviewed-on: https://go-review.googlesource.com/c/go/+/275782
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-12-06 14:53:38 -05:00
|
|
|
fmt.Fprintf(s, " %v ", n.Op())
|
2020-12-05 14:46:19 -05:00
|
|
|
exprFmt(n.Right(), s, nprec+1)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-10 20:55:10 -05:00
|
|
|
case OSEND:
|
|
|
|
|
n := n.(*SendStmt)
|
|
|
|
|
exprFmt(n.Left(), s, nprec)
|
|
|
|
|
fmt.Fprintf(s, " <- ")
|
|
|
|
|
exprFmt(n.Right(), s, nprec+1)
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
case OADDSTR:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*AddStringExpr)
|
2020-11-22 09:59:15 -05:00
|
|
|
for i, n1 := range n.List().Slice() {
|
2016-03-04 13:16:48 -08:00
|
|
|
if i != 0 {
|
2016-08-31 16:02:36 -07:00
|
|
|
fmt.Fprint(s, " + ")
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-12-05 14:46:19 -05:00
|
|
|
exprFmt(n1, s, nprec)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2016-08-31 17:49:49 -07:00
|
|
|
default:
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "<node %v>", n.Op())
|
2016-08-31 17:49:49 -07:00
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
func ellipsisIf(b bool) string {
|
|
|
|
|
if b {
|
|
|
|
|
return "..."
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-12-05 00:02:46 -05:00
|
|
|
return ""
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
// Nodes
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-06 14:15:09 -05:00
|
|
|
// Format implements formatting for a Nodes.
|
|
|
|
|
// The valid formats are:
|
|
|
|
|
//
|
|
|
|
|
// %v Go syntax, semicolon-separated
|
|
|
|
|
// %.v Go syntax, comma-separated
|
|
|
|
|
// %+v Debug syntax, as in DumpList.
|
|
|
|
|
//
|
2020-12-05 14:46:19 -05:00
|
|
|
func (l Nodes) Format(s fmt.State, verb rune) {
|
2020-12-05 00:02:46 -05:00
|
|
|
if s.Flag('+') && verb == 'v' {
|
|
|
|
|
// %+v is DumpList output
|
|
|
|
|
dumpNodes(s, l, 1)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-05 14:46:19 -05:00
|
|
|
if verb != 'v' {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(s, "%%!%c(Nodes)", verb)
|
2020-12-05 14:46:19 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
sep := "; "
|
2020-12-05 14:46:19 -05:00
|
|
|
if _, ok := s.Precision(); ok { // %.v is expr list
|
2020-12-05 00:02:46 -05:00
|
|
|
sep = ", "
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
for i, n := range l.Slice() {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprint(s, n)
|
2020-12-05 00:02:46 -05:00
|
|
|
if i+1 < l.Len() {
|
|
|
|
|
fmt.Fprint(s, sep)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
// Dump
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-06 14:15:09 -05:00
|
|
|
// Dump prints the message s followed by a debug dump of n.
|
2020-12-05 00:02:46 -05:00
|
|
|
func Dump(s string, n Node) {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Printf("%s [%p]%+v", s, n, n)
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
2020-12-06 14:15:09 -05:00
|
|
|
// DumpList prints the message s followed by a debug dump of each node in the list.
|
|
|
|
|
func DumpList(s string, list Nodes) {
|
2020-12-05 00:02:46 -05:00
|
|
|
var buf bytes.Buffer
|
2020-12-06 14:15:09 -05:00
|
|
|
FDumpList(&buf, s, list)
|
2020-12-05 00:02:46 -05:00
|
|
|
os.Stdout.Write(buf.Bytes())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
2020-12-06 14:15:09 -05:00
|
|
|
// FDumpList prints to w the message s followed by a debug dump of each node in the list.
|
|
|
|
|
func FDumpList(w io.Writer, s string, list Nodes) {
|
2020-12-05 00:02:46 -05:00
|
|
|
io.WriteString(w, s)
|
2020-12-06 14:15:09 -05:00
|
|
|
dumpNodes(w, list, 1)
|
2020-12-05 00:02:46 -05:00
|
|
|
io.WriteString(w, "\n")
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
// indent prints indentation to w.
|
|
|
|
|
func indent(w io.Writer, depth int) {
|
|
|
|
|
fmt.Fprint(w, "\n")
|
|
|
|
|
for i := 0; i < depth; i++ {
|
|
|
|
|
fmt.Fprint(w, ". ")
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// EscFmt is set by the escape analysis code to add escape analysis details to the node print.
|
|
|
|
|
var EscFmt func(n Node) string
|
|
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
// dumpNodeHeader prints the debug-format node header line to w.
|
|
|
|
|
func dumpNodeHeader(w io.Writer, n Node) {
|
2020-12-05 00:02:46 -05:00
|
|
|
// Useful to see which nodes in an AST printout are actually identical
|
|
|
|
|
if base.Debug.DumpPtrs != 0 {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, " p(%p)", n)
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, " defn(%p)", n.Name().Defn)
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if EscFmt != nil {
|
|
|
|
|
if esc := EscFmt(n); esc != "" {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, " %s", esc)
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Typecheck() != 0 {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, " tc(%d)", n.Typecheck())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
2020-12-10 20:55:10 -05:00
|
|
|
// Print Node-specific fields of basic type in header line.
|
|
|
|
|
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
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
2020-12-10 20:55:10 -05:00
|
|
|
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())
|
|
|
|
|
}
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-10 20:55:10 -05:00
|
|
|
// Print Node-specific booleans by looking for methods.
|
|
|
|
|
// Different v, t from above - want *Struct not Struct, for methods.
|
|
|
|
|
v = reflect.ValueOf(n)
|
|
|
|
|
t = v.Type()
|
|
|
|
|
nm := t.NumMethod()
|
|
|
|
|
for i := 0; i < nm; i++ {
|
|
|
|
|
tm := t.Method(i)
|
|
|
|
|
if tm.PkgPath != "" {
|
|
|
|
|
// skip unexported method - call will fail
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
m := v.Method(i)
|
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
}
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
2020-12-06 15:17:05 -05:00
|
|
|
|
|
|
|
|
if n.Op() == OCLOSURE {
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*ClosureExpr)
|
2020-12-06 15:17:05 -05:00
|
|
|
if fn := n.Func(); fn != nil && fn.Nname.Sym() != nil {
|
|
|
|
|
fmt.Fprintf(w, " fnName(%+v)", fn.Nname.Sym())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Type() != nil {
|
|
|
|
|
if n.Op() == OTYPE {
|
|
|
|
|
fmt.Fprintf(w, " type")
|
|
|
|
|
}
|
|
|
|
|
fmt.Fprintf(w, " %+v", n.Type())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Pos().IsKnown() {
|
|
|
|
|
pfx := ""
|
|
|
|
|
switch n.Pos().IsStmt() {
|
|
|
|
|
case src.PosNotStmt:
|
|
|
|
|
pfx = "_" // "-" would be confusing
|
|
|
|
|
case src.PosIsStmt:
|
|
|
|
|
pfx = "+"
|
|
|
|
|
}
|
|
|
|
|
pos := base.Ctxt.PosTable.Pos(n.Pos())
|
|
|
|
|
file := filepath.Base(pos.Filename())
|
|
|
|
|
fmt.Fprintf(w, " # %s%s:%d", pfx, file, pos.Line())
|
|
|
|
|
}
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
func dumpNode(w io.Writer, n Node, depth int) {
|
|
|
|
|
indent(w, depth)
|
|
|
|
|
if depth > 40 {
|
|
|
|
|
fmt.Fprint(w, "...")
|
|
|
|
|
return
|
|
|
|
|
}
|
2020-12-05 00:02:46 -05:00
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
if n.Init().Len() != 0 {
|
|
|
|
|
fmt.Fprintf(w, "%+v-init", n.Op())
|
|
|
|
|
dumpNodes(w, n.Init(), depth+1)
|
|
|
|
|
indent(w, depth)
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch n.Op() {
|
|
|
|
|
default:
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, "%+v", n.Op())
|
|
|
|
|
dumpNodeHeader(w, n)
|
2020-12-05 00:02:46 -05:00
|
|
|
|
|
|
|
|
case OLITERAL:
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, "%+v-%v", n.Op(), n.Val())
|
|
|
|
|
dumpNodeHeader(w, n)
|
2020-12-06 15:17:05 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-10 18:47:09 -05:00
|
|
|
case ONAME, ONONAME:
|
2020-11-22 09:59:15 -05:00
|
|
|
if n.Sym() != nil {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, "%+v-%+v", n.Op(), n.Sym())
|
2015-02-13 14:40:36 -05:00
|
|
|
} else {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, "%+v", n.Op())
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-12-05 00:02:46 -05:00
|
|
|
dumpNodeHeader(w, n)
|
|
|
|
|
if n.Type() == nil && n.Name() != nil && n.Name().Ntype != nil {
|
|
|
|
|
indent(w, depth)
|
|
|
|
|
fmt.Fprintf(w, "%+v-ntype", n.Op())
|
|
|
|
|
dumpNode(w, n.Name().Ntype, depth+1)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-12-06 15:17:05 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-10 18:47:09 -05:00
|
|
|
case OMETHEXPR:
|
|
|
|
|
n := n.(*MethodExpr)
|
|
|
|
|
fmt.Fprintf(w, "%+v-%+v", n.Op(), n.FuncName().Sym())
|
|
|
|
|
dumpNodeHeader(w, n)
|
|
|
|
|
return
|
|
|
|
|
|
2015-02-13 14:40:36 -05:00
|
|
|
case OASOP:
|
2020-12-10 20:55:10 -05:00
|
|
|
n := n.(*AssignOpStmt)
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, "%+v-%+v", n.Op(), n.SubOp())
|
|
|
|
|
dumpNodeHeader(w, n)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OTYPE:
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, "%+v %+v", n.Op(), n.Sym())
|
|
|
|
|
dumpNodeHeader(w, n)
|
|
|
|
|
if n.Type() == nil && n.Name() != nil && n.Name().Ntype != nil {
|
|
|
|
|
indent(w, depth)
|
|
|
|
|
fmt.Fprintf(w, "%+v-ntype", n.Op())
|
|
|
|
|
dumpNode(w, n.Name().Ntype, depth+1)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-12-06 15:17:05 -05:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-06 15:17:05 -05:00
|
|
|
case OCLOSURE:
|
|
|
|
|
fmt.Fprintf(w, "%+v", n.Op())
|
|
|
|
|
dumpNodeHeader(w, n)
|
|
|
|
|
|
|
|
|
|
case ODCLFUNC:
|
|
|
|
|
// Func has many fields we don't want to print.
|
|
|
|
|
// Bypass reflection and just print what we want.
|
|
|
|
|
fmt.Fprintf(w, "%+v", n.Op())
|
|
|
|
|
dumpNodeHeader(w, n)
|
|
|
|
|
fn := n.Func()
|
|
|
|
|
if len(fn.Dcl) > 0 {
|
|
|
|
|
indent(w, depth)
|
|
|
|
|
fmt.Fprintf(w, "%+v-Dcl", n.Op())
|
|
|
|
|
for _, dcl := range n.Func().Dcl {
|
|
|
|
|
dumpNode(w, dcl, depth+1)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if fn.Body().Len() > 0 {
|
|
|
|
|
indent(w, depth)
|
|
|
|
|
fmt.Fprintf(w, "%+v-body", n.Op())
|
2020-12-10 20:55:10 -05:00
|
|
|
dumpNodes(w, fn.Body(), depth+1)
|
2020-12-06 15:17:05 -05:00
|
|
|
}
|
|
|
|
|
return
|
2020-10-29 15:31:16 -07:00
|
|
|
}
|
2020-12-06 15:17:05 -05:00
|
|
|
|
|
|
|
|
if n.Sym() != nil {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, " %+v", n.Sym())
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-11-22 09:59:15 -05:00
|
|
|
if n.Type() != nil {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, " %+v", n.Type())
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
2020-12-06 15:17:05 -05:00
|
|
|
v := reflect.ValueOf(n).Elem()
|
|
|
|
|
t := reflect.TypeOf(n).Elem()
|
|
|
|
|
nf := t.NumField()
|
|
|
|
|
for i := 0; i < nf; i++ {
|
|
|
|
|
tf := t.Field(i)
|
|
|
|
|
vf := v.Field(i)
|
|
|
|
|
if tf.PkgPath != "" {
|
|
|
|
|
// skip unexported field - Interface will fail
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
switch tf.Type.Kind() {
|
|
|
|
|
case reflect.Interface, reflect.Ptr, reflect.Slice:
|
|
|
|
|
if vf.IsNil() {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
name := strings.TrimSuffix(tf.Name, "_")
|
|
|
|
|
// Do not bother with field name header lines for the
|
|
|
|
|
// most common positional arguments: unary, binary expr,
|
|
|
|
|
// index expr, send stmt, go and defer call expression.
|
|
|
|
|
switch name {
|
|
|
|
|
case "X", "Y", "Index", "Chan", "Value", "Call":
|
|
|
|
|
name = ""
|
|
|
|
|
}
|
|
|
|
|
switch val := vf.Interface().(type) {
|
|
|
|
|
case Node:
|
|
|
|
|
if name != "" {
|
|
|
|
|
indent(w, depth)
|
|
|
|
|
fmt.Fprintf(w, "%+v-%s", n.Op(), name)
|
|
|
|
|
}
|
|
|
|
|
dumpNode(w, val, depth+1)
|
|
|
|
|
case Nodes:
|
|
|
|
|
if val.Len() == 0 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if name != "" {
|
|
|
|
|
indent(w, depth)
|
|
|
|
|
fmt.Fprintf(w, "%+v-%s", n.Op(), name)
|
|
|
|
|
}
|
|
|
|
|
dumpNodes(w, val, depth+1)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
func dumpNodes(w io.Writer, list Nodes, depth int) {
|
|
|
|
|
if list.Len() == 0 {
|
|
|
|
|
fmt.Fprintf(w, " <nil>")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, n := range list.Slice() {
|
|
|
|
|
dumpNode(w, n, depth)
|
2020-11-28 07:31:18 -05:00
|
|
|
}
|
|
|
|
|
}
|
2020-12-10 20:55:10 -05:00
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
}
|
|
|
|
|
}
|