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-05 00:02:46 -05:00
|
|
|
"os"
|
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: "^",
|
|
|
|
|
}
|
|
|
|
|
|
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-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-05 00:02:46 -05:00
|
|
|
func FmtNode(n Node, s fmt.State, verb rune) {
|
2020-12-05 14:46:19 -05:00
|
|
|
// TODO(rsc): Remove uses of %#v, which behaves just like %v.
|
|
|
|
|
// TODO(rsc): Remove uses of %S, which behaves just like %v.
|
|
|
|
|
if verb == 'S' {
|
|
|
|
|
verb = 'v'
|
|
|
|
|
}
|
|
|
|
|
|
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 {
|
|
|
|
|
fmt.Fprint(s, "<N>")
|
|
|
|
|
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-05 00:02:46 -05:00
|
|
|
// Statements which may be rendered with a simplestmt as init.
|
|
|
|
|
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-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:
|
|
|
|
|
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:
|
|
|
|
|
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
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-05 14:46:19 -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:
|
|
|
|
|
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:
|
|
|
|
|
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-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-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-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-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-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "defer %v", n.Left())
|
2020-12-05 00:02:46 -05:00
|
|
|
|
|
|
|
|
case OIF:
|
|
|
|
|
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:
|
|
|
|
|
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-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
|
|
|
|
|
|
|
|
case OSELECT, OSWITCH:
|
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-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%#v", n.Op())
|
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:
|
|
|
|
|
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:
|
|
|
|
|
if n.Sym() != nil {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%#v %v", n.Op(), n.Sym())
|
2020-12-05 00:02:46 -05:00
|
|
|
} else {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%#v", n.Op())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OLABEL:
|
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 {
|
|
|
|
|
fmt.Fprint(s, "<N>")
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// We always want the original, if any.
|
|
|
|
|
if o := Orig(n); o != n {
|
|
|
|
|
n = o
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Skip implicit operations introduced during typechecking.
|
|
|
|
|
switch n.Op() {
|
|
|
|
|
case OADDR, ODEREF, OCONV, OCONVNOP, OCONVIFACE:
|
|
|
|
|
if n.Implicit() {
|
|
|
|
|
n = n.Left()
|
|
|
|
|
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-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:
|
|
|
|
|
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-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-11-18 11:25:29 -05:00
|
|
|
case OPACK, ONONAME, OMETHEXPR:
|
2020-12-06 12:38:11 -05:00
|
|
|
fmt.Fprint(s, n.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-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-11-22 09:59:15 -05:00
|
|
|
if n.Body().Len() != 0 {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%v { %v }", n.Type(), n.Body())
|
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.Func().Body())
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OCOMPLIT:
|
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-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-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-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-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-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-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-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-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-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-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-11-22 09:59:15 -05:00
|
|
|
if n.Left() != nil {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%#v(%v, %v)", n.Op(), n.Left(), n.Right())
|
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
|
|
|
} else {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%#v(%.v)", n.Op(), n.List())
|
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-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-11-22 09:59:15 -05:00
|
|
|
if n.Left() != nil {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "(%v)", n.Left())
|
2016-07-30 01:45:27 -07:00
|
|
|
} else {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "(%.v)", n.List())
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OREAL,
|
|
|
|
|
OIMAG,
|
|
|
|
|
OAPPEND,
|
|
|
|
|
OCAP,
|
|
|
|
|
OCLOSE,
|
|
|
|
|
ODELETE,
|
|
|
|
|
OLEN,
|
|
|
|
|
OMAKE,
|
|
|
|
|
ONEW,
|
|
|
|
|
OPANIC,
|
|
|
|
|
ORECOVER,
|
2016-10-18 14:17:05 -07:00
|
|
|
OALIGNOF,
|
|
|
|
|
OOFFSETOF,
|
|
|
|
|
OSIZEOF,
|
2015-02-13 14:40:36 -05:00
|
|
|
OPRINT,
|
|
|
|
|
OPRINTN:
|
2020-11-22 09:59:15 -05:00
|
|
|
if n.Left() != nil {
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "%#v(%v)", n.Op(), n.Left())
|
2016-08-31 16:02:36 -07:00
|
|
|
return
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2018-11-18 08:34:38 -08:00
|
|
|
if n.IsDDD() {
|
2020-12-05 14:46:19 -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
|
|
|
}
|
2020-12-05 14:46:19 -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-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-11-22 09:59:15 -05:00
|
|
|
if n.List().Len() != 0 { // pre-typecheck
|
2020-12-05 14:46:19 -05:00
|
|
|
fmt.Fprintf(s, "make(%v, %.v)", n.Type(), n.List())
|
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.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-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
|
|
|
|
2018-11-18 08:34:38 -08:00
|
|
|
case OPLUS, ONEG, OADDR, OBITNOT, ODEREF, ONOT, ORECV:
|
2015-02-13 14:40:36 -05:00
|
|
|
// Unary
|
2020-12-05 14:46:19 -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
|
|
|
|
|
|
|
|
// Binary
|
|
|
|
|
case OADD,
|
|
|
|
|
OAND,
|
|
|
|
|
OANDAND,
|
|
|
|
|
OANDNOT,
|
|
|
|
|
ODIV,
|
|
|
|
|
OEQ,
|
|
|
|
|
OGE,
|
|
|
|
|
OGT,
|
|
|
|
|
OLE,
|
|
|
|
|
OLT,
|
|
|
|
|
OLSH,
|
|
|
|
|
OMOD,
|
|
|
|
|
OMUL,
|
|
|
|
|
ONE,
|
|
|
|
|
OOR,
|
|
|
|
|
OOROR,
|
|
|
|
|
ORSH,
|
|
|
|
|
OSEND,
|
|
|
|
|
OSUB,
|
|
|
|
|
OXOR:
|
2020-12-05 14:46:19 -05:00
|
|
|
exprFmt(n.Left(), s, nprec)
|
|
|
|
|
fmt.Fprintf(s, " %#v ", n.Op())
|
|
|
|
|
exprFmt(n.Right(), s, nprec+1)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
|
|
|
|
case OADDSTR:
|
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-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-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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func DumpList(s string, l Nodes) {
|
2020-12-05 00:02:46 -05:00
|
|
|
var buf bytes.Buffer
|
|
|
|
|
FDumpList(&buf, s, l)
|
|
|
|
|
os.Stdout.Write(buf.Bytes())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func FDumpList(w io.Writer, s string, l Nodes) {
|
2020-12-05 00:02:46 -05:00
|
|
|
io.WriteString(w, s)
|
|
|
|
|
dumpNodes(w, l, 1)
|
|
|
|
|
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 n.Name() != nil && n.Name().Vargen != 0 {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, " g(%d)", n.Name().Vargen)
|
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 n.Pos().IsKnown() {
|
|
|
|
|
pfx := ""
|
|
|
|
|
switch n.Pos().IsStmt() {
|
|
|
|
|
case src.PosNotStmt:
|
|
|
|
|
pfx = "_" // "-" would be confusing
|
|
|
|
|
case src.PosIsStmt:
|
|
|
|
|
pfx = "+"
|
|
|
|
|
}
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, " l(%s%d)", pfx, n.Pos().Line())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Offset() != types.BADWIDTH {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, " x(%d)", n.Offset())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Class() != 0 {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, " class(%v)", n.Class())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Colas() {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, " colas(%v)", n.Colas())
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.IsDDD() {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, " isddd(%v)", n.IsDDD())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Implicit() {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, " implicit(%v)", n.Implicit())
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Op() == ONAME {
|
|
|
|
|
if n.Name().Addrtaken() {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprint(w, " addrtaken")
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
if n.Name().Assigned() {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprint(w, " assigned")
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
if n.Name().IsClosureVar() {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprint(w, " closurevar")
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
if n.Name().Captured() {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprint(w, " captured")
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
if n.Name().IsOutputParamHeapAddr() {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprint(w, " outputparamheapaddr")
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if n.Bounded() {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprint(w, " bounded")
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
if n.NonNil() {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprint(w, " nonnil")
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.HasCall() {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprint(w, " hascall")
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if n.Name() != nil && n.Name().Used() {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprint(w, " used")
|
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)
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-11-18 11:25:29 -05:00
|
|
|
case ONAME, ONONAME, OMETHEXPR:
|
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
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case OASOP:
|
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)
|
|
|
|
|
fmt.Fprintf(w, " type=%+v", n.Type())
|
|
|
|
|
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-11-28 07:31:18 -05:00
|
|
|
if n.Op() == OCLOSURE && n.Func() != nil && n.Func().Nname.Sym() != nil {
|
2020-12-05 00:02:46 -05:00
|
|
|
fmt.Fprintf(w, " fnName %+v", n.Func().Nname.Sym())
|
2020-10-29 15:31:16 -07:00
|
|
|
}
|
2020-11-22 09:59:15 -05:00
|
|
|
if n.Sym() != nil && n.Op() != ONAME {
|
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-05 00:02:46 -05:00
|
|
|
if n.Left() != nil {
|
|
|
|
|
dumpNode(w, n.Left(), depth+1)
|
|
|
|
|
}
|
|
|
|
|
if n.Right() != nil {
|
|
|
|
|
dumpNode(w, n.Right(), depth+1)
|
|
|
|
|
}
|
|
|
|
|
if n.Op() == OCLOSURE && n.Func() != nil && n.Func().Body().Len() != 0 {
|
|
|
|
|
indent(w, depth)
|
|
|
|
|
// The function associated with a closure
|
|
|
|
|
fmt.Fprintf(w, "%+v-clofunc", n.Op())
|
|
|
|
|
dumpNode(w, n.Func(), depth+1)
|
|
|
|
|
}
|
|
|
|
|
if n.Op() == ODCLFUNC && n.Func() != nil && n.Func().Dcl != nil && len(n.Func().Dcl) != 0 {
|
|
|
|
|
indent(w, depth)
|
|
|
|
|
// The dcls for a func or closure
|
|
|
|
|
fmt.Fprintf(w, "%+v-dcl", n.Op())
|
|
|
|
|
for _, dcl := range n.Func().Dcl {
|
|
|
|
|
dumpNode(w, dcl, depth+1)
|
2015-02-13 14:40:36 -05:00
|
|
|
}
|
2020-12-05 00:02:46 -05:00
|
|
|
}
|
|
|
|
|
if n.List().Len() != 0 {
|
|
|
|
|
indent(w, depth)
|
|
|
|
|
fmt.Fprintf(w, "%+v-list", n.Op())
|
|
|
|
|
dumpNodes(w, n.List(), depth+1)
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
if n.Rlist().Len() != 0 {
|
|
|
|
|
indent(w, depth)
|
|
|
|
|
fmt.Fprintf(w, "%+v-rlist", n.Op())
|
|
|
|
|
dumpNodes(w, n.Rlist(), depth+1)
|
|
|
|
|
}
|
2015-02-13 14:40:36 -05:00
|
|
|
|
2020-12-05 00:02:46 -05:00
|
|
|
if n.Body().Len() != 0 {
|
|
|
|
|
indent(w, depth)
|
|
|
|
|
fmt.Fprintf(w, "%+v-body", n.Op())
|
|
|
|
|
dumpNodes(w, n.Body(), 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
|
|
|
}
|
|
|
|
|
}
|