Commit graph

281 commits

Author SHA1 Message Date
Russ Cox
b9693d7627 [dev.regabi] cmd/compile: split out package typecheck [generated]
This commit splits the typechecking logic into its own package,
the first of a sequence of CLs to break package gc into more
manageable units.

[git-generate]
cd src/cmd/compile/internal/gc
rf '
	# The binary import/export has to be part of typechecking,
	# because we load inlined function bodies lazily, but "exporter"
	# should not be. Move that out of bexport.go.
	mv exporter exporter.markObject exporter.markType export.go

	# Use the typechecking helpers, so that the calls left behind
	# in package gc do not need access to ctxExpr etc.
	ex {
		import "cmd/compile/internal/ir"

		# TODO(rsc): Should not be necessary.
		avoid TypecheckExpr
		avoid TypecheckStmt
		avoid TypecheckExprs
		avoid TypecheckStmts
		avoid TypecheckAssignExpr
		avoid TypecheckCallee

		var n ir.Node
		var ns []ir.Node
		typecheck(n, ctxExpr) -> TypecheckExpr(n)
		typecheck(n, ctxStmt) -> TypecheckStmt(n)
		typecheckslice(ns, ctxExpr) -> TypecheckExprs(ns)
		typecheckslice(ns, ctxStmt) -> TypecheckStmts(ns)
		typecheck(n, ctxExpr|ctxAssign) -> TypecheckAssignExpr(n)
		typecheck(n, ctxExpr|ctxCallee) -> TypecheckCallee(n)
	}

	# Move some typechecking API to typecheck.
	mv syslook LookupRuntime
	mv substArgTypes SubstArgTypes
	mv LookupRuntime SubstArgTypes syms.go

	mv conv Conv
	mv convnop ConvNop
	mv Conv ConvNop typecheck.go

	mv colasdefn AssignDefn
	mv colasname assignableName

	mv Target target.go

	mv initname autoexport exportsym dcl.go
	mv exportsym Export

	# Export API to be called from outside typecheck.
	# The ones with "Typecheck" prefixes will be renamed later to drop the prefix.
	mv adddot AddImplicitDots
	mv assignconv AssignConv
	mv expandmeth CalcMethods
	mv capturevarscomplete CaptureVarsComplete
	mv checkMapKeys CheckMapKeys
	mv checkreturn CheckReturn
	mv dclcontext DeclContext
	mv dclfunc DeclFunc
	mv declare Declare
	mv dotImportRefs DotImportRefs
	mv declImporter DeclImporter
	mv variter DeclVars
	mv defaultlit DefaultLit
	mv evalConst EvalConst
	mv expandInline ImportBody
	mv finishUniverse declareUniverse
	mv funcbody FinishFuncBody
	mv funchdr StartFuncBody
	mv indexconst IndexConst
	mv initTodo InitTodoFunc
	mv lookup Lookup
	mv resolve Resolve
	mv lookupN LookupNum
	mv nodAddr NodAddr
	mv nodAddrAt NodAddrAt
	mv nodnil NodNil
	mv origBoolConst OrigBool
	mv origConst OrigConst
	mv origIntConst OrigInt
	mv redeclare Redeclared
	mv tostruct NewStructType
	mv functype NewFuncType
	mv methodfunc NewMethodType
	mv structargs NewFuncParams
	mv temp Temp
	mv tempAt TempAt
	mv typecheckok TypecheckAllowed
	mv typecheck _typecheck # make room for typecheck pkg
	mv typecheckinl TypecheckImportedBody
	mv typecheckFunc TypecheckFunc
	mv iimport ReadImports
	mv iexport WriteExports
	mv sysfunc LookupRuntimeFunc
	mv sysvar LookupRuntimeVar

	# Move function constructors to typecheck.
	mv mkdotargslice MakeDotArgs
	mv fixVariadicCall FixVariadicCall
	mv closureType ClosureType
	mv partialCallType PartialCallType
	mv capturevars CaptureVars
	mv MakeDotArgs FixVariadicCall ClosureType PartialCallType CaptureVars typecheckclosure func.go

	mv autolabel AutoLabel
	mv AutoLabel syms.go

	mv Dlist dlist
	mv Symlink symlink

	mv \
		AssignDefn assignableName \
		AssignConv \
		CaptureVarsComplete \
		DeclContext \
		DeclFunc \
		DeclImporter \
		DeclVars \
		Declare \
		DotImportRefs \
		Export \
		InitTodoFunc \
		Lookup \
		LookupNum \
		LookupRuntimeFunc \
		LookupRuntimeVar \
		NewFuncParams \
		NewName \
		NodAddr \
		NodAddrAt \
		NodNil \
		Redeclared \
		StartFuncBody \
		FinishFuncBody \
		TypecheckImportedBody \
		AddImplicitDots \
		CalcMethods \
		CheckFuncStack \
		NewFuncType \
		NewMethodType \
		NewStructType \
		TypecheckAllowed \
		Temp \
		TempAt \
		adddot1 \
		dotlist \
		addmethod \
		assignconvfn \
		assignop \
		autotmpname \
		autoexport \
		bexport.go \
		checkdupfields \
		checkembeddedtype \
		closurename \
		convertop \
		declare_typegen \
		decldepth \
		dlist \
		dotpath \
		expand0 \
		expand1 \
		expandDecl \
		fakeRecvField \
		fnpkg \
		funcStack \
		funcStackEnt \
		funcarg \
		funcarg2 \
		funcargs \
		funcargs2 \
		globClosgen \
		ifacelookdot \
		implements \
		importalias \
		importconst \
		importfunc \
		importobj \
		importsym \
		importtype \
		importvar \
		inimport \
		initname \
		isptrto \
		loadsys \
		lookdot0 \
		lookdot1 \
		makepartialcall \
		okfor \
		okforlen \
		operandType \
		slist \
		symlink \
		tointerface \
		typeSet \
		typeSet.add \
		typeSetEntry \
		typecheckExprSwitch \
		typecheckTypeSwitch \
		typecheckpartialcall \
		typecheckrange \
		typecheckrangeExpr \
		typecheckselect \
		typecheckswitch \
		vargen \
		builtin.go \
		builtin_test.go \
		const.go \
		func.go \
		iexport.go \
		iimport.go \
		mapfile_mmap.go \
		syms.go \
		target.go \
		typecheck.go \
		unsafe.go \
		universe.go \
		cmd/compile/internal/typecheck
'
rm gen.go types.go types_acc.go

sed -i '' 's/package gc/package typecheck/' mapfile_read.go mkbuiltin.go
mv mapfile_read.go ../typecheck # not part of default build
mv mkbuiltin.go ../typecheck # package main helper
mv builtin ../typecheck

cd ../typecheck
mv dcl.go dcl1.go
mv typecheck.go typecheck1.go
mv universe.go universe1.go
rf '
	# Sweep some small files into larger ones.
	# "mv sym... file1.go file.go" (after the mv file1.go file.go above)
	# lets us insert sym... at the top of file.go.
	mv okfor okforeq universe1.go universe.go
	mv DeclContext vargen dcl1.go Temp TempAt autotmpname NewMethodType dcl.go
	mv InitTodoFunc inimport decldepth TypecheckAllowed typecheck1.go typecheck.go
	mv inl.go closure.go func.go
	mv range.go select.go swt.go stmt.go
	mv Lookup loadsys LookupRuntimeFunc LookupRuntimeVar syms.go
	mv unsafe.go const.go

	mv TypecheckAssignExpr AssignExpr
	mv TypecheckExpr Expr
	mv TypecheckStmt Stmt
	mv TypecheckExprs Exprs
	mv TypecheckStmts Stmts
	mv TypecheckCall Call
	mv TypecheckCallee Callee
	mv _typecheck check
	mv TypecheckFunc Func
	mv TypecheckFuncBody FuncBody
	mv TypecheckImports AllImportedBodies
	mv TypecheckImportedBody ImportedBody
	mv TypecheckInit Init
	mv TypecheckPackage Package
'
rm gen.go go.go init.go main.go reflect.go

Change-Id: Iea6a7aaf6407d690670ec58aeb36cc0b280f80b0
Reviewed-on: https://go-review.googlesource.com/c/go/+/279236
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-12-23 06:38:26 +00:00
Russ Cox
dac0de3748 [dev.regabi] cmd/compile: move type size calculations into package types [generated]
To break up package gc, we need to put these calculations somewhere
lower in the import graph, either an existing or new package. Package types
already needs this code and is using hacks to get it without an import cycle.
We can remove the hacks and set up for the new package gc by moving the
code into package types itself.

[git-generate]
cd src/cmd/compile/internal/gc
rf '
	# Remove old import cycle hacks in gc.
	rm TypecheckInit:/types.Widthptr =/-0,/types.Dowidth =/+0 \
		../ssa/export_test.go:/types.Dowidth =/-+
	ex {
		import "cmd/compile/internal/types"
		types.Widthptr -> Widthptr
		types.Dowidth -> dowidth
	}

	# Disable CalcSize in tests instead of base.Fatalf
	sub dowidth:/base.Fatalf\("dowidth without betypeinit"\)/ \
		// Assume this is a test. \
		return

	# Move size calculation into cmd/compile/internal/types
	mv Widthptr PtrSize
	mv Widthreg RegSize
	mv slicePtrOffset SlicePtrOffset
	mv sliceLenOffset SliceLenOffset
	mv sliceCapOffset SliceCapOffset
	mv sizeofSlice SliceSize
	mv sizeofString StringSize
	mv skipDowidthForTracing SkipSizeForTracing
	mv dowidth CalcSize
	mv checkwidth CheckSize
	mv widstruct calcStructOffset
	mv sizeCalculationDisabled CalcSizeDisabled
	mv defercheckwidth DeferCheckSize
	mv resumecheckwidth ResumeCheckSize
	mv typeptrdata PtrDataSize
	mv \
		PtrSize RegSize SlicePtrOffset SkipSizeForTracing typePos align.go PtrDataSize \
		size.go
	mv size.go cmd/compile/internal/types
'

: # Remove old import cycle hacks in types.
cd ../types
rf '
	ex {
		Widthptr -> PtrSize
		Dowidth -> CalcSize
	}
	rm Widthptr Dowidth
'

Change-Id: Ib96cdc6bda2617235480c29392ea5cfb20f60cd8
Reviewed-on: https://go-review.googlesource.com/c/go/+/279234
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-12-23 06:38:20 +00:00
Russ Cox
527a1895d6 [dev.regabi] cmd/compile: move helpers into package ir [generated]
[git-generate]
cd src/cmd/compile/internal/gc
sed -i '' 's/TestBuiltin.*/& t.Skip("mkbuiltin needs fixing")/' builtin_test.go
gofmt -w builtin_test.go
rf '
	# Inline a few little-used constructors to avoid bringing them.
	ex {
		import "cmd/compile/internal/base"
		import "cmd/compile/internal/ir"
		import "cmd/compile/internal/types"
		import "cmd/internal/src"

		var typ *types.Type
		var sym *types.Sym
		var str string
		symfield(sym, typ) -> ir.NewField(base.Pos, sym, nil, typ)
		anonfield(typ) -> ir.NewField(base.Pos, nil, nil, typ)
		namedfield(str, typ) -> ir.NewField(base.Pos, lookup(str), nil, typ)

		var cp *ir.CallPartExpr
		callpartMethod(cp) -> cp.Method
		var n ir.Node
		callpartMethod(n) -> n.(*ir.CallPartExpr).Method

		var ns []ir.Node
		liststmt(ns) -> ir.NewBlockStmt(src.NoXPos, ns)
	}
	rm symfield anonfield namedfield liststmt callpartMethod

	mv maxStackVarSize MaxStackVarSize
	mv maxImplicitStackVarSize MaxImplicitStackVarSize
	mv smallArrayBytes MaxSmallArraySize
	mv MaxStackVarSize cfg.go

	mv nodbool NewBool
	mv nodintconst NewInt
	mv nodstr NewString
	mv NewBool NewInt NewString const.go

	mv Mpprec ConstPrec
	mv bigFloatVal BigFloat
	mv doesoverflow ConstOverflow
	mv isGoConst IsConstNode
	mv smallintconst IsSmallIntConst

	mv isZero IsZero
	mv islvalue IsAssignable
	mv staticValue StaticValue
	mv samesafeexpr SameSafeExpr
	mv checkPtr ShouldCheckPtr
	mv isReflectHeaderDataField IsReflectHeaderDataField
	mv paramNnames ParamNames
	mv methodSym MethodSym
	mv methodSymSuffix MethodSymSuffix
	mv methodExprFunc MethodExprFunc
	mv methodExprName MethodExprName
	mv IsZero IsAssignable StaticValue staticValue1 reassigned \
		IsIntrinsicCall \
		SameSafeExpr ShouldCheckPtr IsReflectHeaderDataField \
		ParamNames MethodSym MethodSymSuffix \
		MethodExprName MethodExprFunc \
		expr.go

	mv Curfn CurFunc
	mv funcsymname FuncSymName
	mv newFuncNameAt NewFuncNameAt
	mv setNodeNameFunc MarkFunc
	mv CurFunc FuncSymName NewFuncNameAt MarkFunc func.go

	mv isParamStackCopy IsParamStackCopy
	mv isParamHeapCopy IsParamHeapCopy
	mv nodfp RegFP
	mv IsParamStackCopy IsParamHeapCopy RegFP name.go

	mv hasUniquePos HasUniquePos
	mv setlineno SetPos
	mv initExpr InitExpr
	mv hasNamedResults HasNamedResults
	mv outervalue OuterValue
	mv HasNamedResults HasUniquePos SetPos InitExpr OuterValue EscNever node.go

	mv visitBottomUp VisitFuncsBottomUp # scc.go

	mv cfg.go \
		NewBool NewInt NewString \ # parts of const.go
		ConstPrec BigFloat ConstOverflow IsConstNode IsSmallIntConst \
		expr.go func.go name.go node.go scc.go \
		cmd/compile/internal/ir

'

Change-Id: I13402c5a2cedbf78d993a1eae2940718f23ac166
Reviewed-on: https://go-review.googlesource.com/c/go/+/279421
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-12-23 06:38:14 +00:00
Russ Cox
65c4c6dfb2 [dev.regabi] cmd/compile: group known symbols, packages, names [generated]
There are a handful of pre-computed magic symbols known by
package gc, and we need a place to store them.

If we keep them together, the need for type *ir.Name means that
package ir is the lowest package in the import hierarchy that they
can go in. And package ir needs gopkg for methodSymSuffix
(in a later CL), so they can't go any higher either, at least not all together.
So package ir it is.

Rather than dump them all into the top-level package ir
namespace, however, we introduce global structs, Syms, Pkgs, and Names,
and make the known symbols, packages, and names fields of those.

[git-generate]
cd src/cmd/compile/internal/gc

rf '
	add go.go:$ \
		// Names holds known names. \
		var Names struct{} \
		\
		// Syms holds known symbols. \
		var Syms struct {} \
		\
		// Pkgs holds known packages. \
		var Pkgs struct {} \

	mv staticuint64s Names.Staticuint64s
	mv zerobase Names.Zerobase

	mv assertE2I Syms.AssertE2I
	mv assertE2I2 Syms.AssertE2I2
	mv assertI2I Syms.AssertI2I
	mv assertI2I2 Syms.AssertI2I2
	mv deferproc Syms.Deferproc
	mv deferprocStack Syms.DeferprocStack
	mv Deferreturn Syms.Deferreturn
	mv Duffcopy Syms.Duffcopy
	mv Duffzero Syms.Duffzero
	mv gcWriteBarrier Syms.GCWriteBarrier
	mv goschedguarded Syms.Goschedguarded
	mv growslice Syms.Growslice
	mv msanread Syms.Msanread
	mv msanwrite Syms.Msanwrite
	mv msanmove Syms.Msanmove
	mv newobject Syms.Newobject
	mv newproc Syms.Newproc
	mv panicdivide Syms.Panicdivide
	mv panicshift Syms.Panicshift
	mv panicdottypeE Syms.PanicdottypeE
	mv panicdottypeI Syms.PanicdottypeI
	mv panicnildottype Syms.Panicnildottype
	mv panicoverflow Syms.Panicoverflow
	mv raceread Syms.Raceread
	mv racereadrange Syms.Racereadrange
	mv racewrite Syms.Racewrite
	mv racewriterange Syms.Racewriterange
	mv SigPanic Syms.SigPanic
	mv typedmemclr Syms.Typedmemclr
	mv typedmemmove Syms.Typedmemmove
	mv Udiv Syms.Udiv
	mv writeBarrier Syms.WriteBarrier
	mv zerobaseSym Syms.Zerobase
	mv arm64HasATOMICS Syms.ARM64HasATOMICS
	mv armHasVFPv4 Syms.ARMHasVFPv4
	mv x86HasFMA Syms.X86HasFMA
	mv x86HasPOPCNT Syms.X86HasPOPCNT
	mv x86HasSSE41 Syms.X86HasSSE41
	mv WasmDiv Syms.WasmDiv
	mv WasmMove Syms.WasmMove
	mv WasmZero Syms.WasmZero
	mv WasmTruncS Syms.WasmTruncS
	mv WasmTruncU Syms.WasmTruncU

	mv gopkg Pkgs.Go
	mv itabpkg Pkgs.Itab
	mv itablinkpkg Pkgs.Itablink
	mv mappkg Pkgs.Map
	mv msanpkg Pkgs.Msan
	mv racepkg Pkgs.Race
	mv Runtimepkg Pkgs.Runtime
	mv trackpkg Pkgs.Track
	mv unsafepkg Pkgs.Unsafe

	mv Names Syms Pkgs symtab.go
	mv symtab.go cmd/compile/internal/ir
'

Change-Id: Ic143862148569a3bcde8e70b26d75421aa2d00f3
Reviewed-on: https://go-review.googlesource.com/c/go/+/279235
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-12-23 06:38:07 +00:00
Russ Cox
9ee309255a [dev.regabi] cmd/compile: move helpers into package types [generated]
[git-generate]
cd src/cmd/compile/internal/gc
rf '
	# Type hash (formatting).
	mv typehash TypeHash
	mv TypeHash fmt.go

	# Method sorting.
	mv methcmp MethodsByName
	mv MethodsByName MethodsByName.Len MethodsByName.Swap \
		MethodsByName.Less sort.go

	# Move version check into types.
	# A little surprising, but its keyed off the types.Pkg.
	ex {
		import "cmd/compile/internal/types"
		var p *types.Pkg
		var major, minor int
		langSupported(major, minor, p) -> AllowsGoVersion(p, major, minor)
	}
	rm langSupported
	mv checkLang ParseLangFlag
	mv lang langWant AllowsGoVersion ParseLangFlag \
		parseLang currentLang goVersionRE goversion.go

	mv testdclstack CheckDclstack
	mv CheckDclstack scope.go

	mv algtype1 AlgType
	mv isComplex IsComplex
	mv isFloat IsFloat
	mv isInt IsInt
	mv issimple IsSimple
	mv okforcmp IsOrdered
	mv floatForComplex FloatForComplex
	mv complexForFloat ComplexForFloat
	mv isdirectiface IsDirectIface
	mv isifacemethod IsInterfaceMethod
	mv isMethodApplicable IsMethodApplicable
	mv ispaddedfield IsPaddedField
	mv isRuntimePkg IsRuntimePkg
	mv isReflectPkg IsReflectPkg
	mv methtype ReceiverBaseType
	mv typesymname TypeSymName
	mv typesym TypeSym
	mv typeLookup TypeSymLookup
	mv IsAlias IsDotAlias
	mv isreflexive IsReflexive
	mv simtype SimType

	# The type1.go here is to avoid an undiagnosed bug in rf
	# that does not get the follow-up typechecking right if we
	# move directly to type.go during the mv into package types below.
	mv \
		IsInt IsOrdered IsReflexive \
		IsDirectIface IsInterfaceMethod IsMethodApplicable IsPaddedField \
		IsRuntimePkg IsReflectPkg ReceiverBaseType \
		FloatForComplex ComplexForFloat \
		TypeSym TypeSymLookup TypeSymName \
		typepkg SimType \
		type1.go

	# The alg1.go here is because we are only moving part of alg.go.
	mv typeHasNoAlg TypeHasNoAlg
	mv AlgKind ANOEQ AlgType TypeHasNoAlg IsComparable IncomparableField IsPaddedField alg1.go

	mv IsDotAlias pkg.go

	mv alg1.go algkind_string.go fmt.go goversion.go pkg.go \
		CheckDclstack \ # scope.go
		sort.go type1.go \
		cmd/compile/internal/types
'
cd ../types
rf '
	mv IsDclstackValid isDclstackValid
	mv alg1.go alg.go
	mv type1.go type.go
'

Change-Id: I8bd53b21c7bdd1770e1b525de32f136833e84c9d
Reviewed-on: https://go-review.googlesource.com/c/go/+/279307
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-12-23 06:38:01 +00:00
Russ Cox
f9d373720e [dev.regabi] cmd/compile: remove Left, Right etc methods [generated]
Now that the generic graph structure methods - Left, Right, and so on -
have been removed from the Node interface, each implementation's uses
can be replaced with direct field access, using more specific names,
and the methods themselves can be deleted.

Passes buildall w/ toolstash -cmp.

[git-generate]

cd src/cmd/compile/internal/ir
rf '
	mv Func.iota Func.Iota_
	mv Name.fn Name.Func_
'

cd ../gc
rf '
ex . ../ir {
        import "cmd/compile/internal/ir"
        import "cmd/compile/internal/types"

        var ns ir.Nodes
        var b bool
        var i64 int64
        var n ir.Node
        var op ir.Op
        var sym *types.Sym
        var class ir.Class

        var decl *ir.Decl
        decl.Left()         -> decl.X
        decl.SetLeft(n)     -> decl.X = n

        var asl *ir.AssignListStmt
        asl.List()          -> asl.Lhs
        asl.PtrList()       -> &asl.Lhs
        asl.SetList(ns)     -> asl.Lhs = ns
        asl.Rlist()         -> asl.Rhs
        asl.PtrRlist()      -> &asl.Rhs
        asl.SetRlist(ns)    -> asl.Rhs = ns
        asl.Colas()         -> asl.Def
        asl.SetColas(b)     -> asl.Def = b

        var as *ir.AssignStmt
        as.Left()           -> as.X
        as.SetLeft(n)       -> as.X = n
        as.Right()          -> as.Y
        as.SetRight(n)      -> as.Y = n
        as.Colas()          -> as.Def
        as.SetColas(b)      -> as.Def = b

        var ao *ir.AssignOpStmt
        ao.Left()           -> ao.X
        ao.SetLeft(n)       -> ao.X = n
        ao.Right()          -> ao.Y
        ao.SetRight(n)      -> ao.Y = n
        ao.SubOp()          -> ao.AsOp
        ao.SetSubOp(op)     -> ao.AsOp = op
        ao.Implicit()       -> ao.IncDec
        ao.SetImplicit(b)   -> ao.IncDec = b

        var bl *ir.BlockStmt
        bl.List()           -> bl.List_
        bl.PtrList()        -> &bl.List_
        bl.SetList(ns)      -> bl.List_ = ns

        var br *ir.BranchStmt
        br.Sym()            -> br.Label
        br.SetSym(sym)      -> br.Label = sym

        var cas *ir.CaseStmt
        cas.List()          -> cas.List_
        cas.PtrList()       -> &cas.List_
        cas.SetList(ns)     -> cas.List_ = ns
        cas.Body()          -> cas.Body_
        cas.PtrBody()       -> &cas.Body_
        cas.SetBody(ns)     -> cas.Body_ = ns
        cas.Rlist()         -> cas.Vars
        cas.PtrRlist()      -> &cas.Vars
        cas.SetRlist(ns)    -> cas.Vars = ns
        cas.Left()          -> cas.Comm
        cas.SetLeft(n)      -> cas.Comm = n

        var fr *ir.ForStmt
        fr.Sym()            -> fr.Label
        fr.SetSym(sym)      -> fr.Label = sym
        fr.Left()           -> fr.Cond
        fr.SetLeft(n)       -> fr.Cond = n
        fr.Right()          -> fr.Post
        fr.SetRight(n)      -> fr.Post = n
        fr.Body()           -> fr.Body_
        fr.PtrBody()        -> &fr.Body_
        fr.SetBody(ns)      -> fr.Body_ = ns
        fr.List()           -> fr.Late
        fr.PtrList()        -> &fr.Late
        fr.SetList(ns)      -> fr.Late = ns
        fr.HasBreak()       -> fr.HasBreak_
        fr.SetHasBreak(b)   -> fr.HasBreak_ = b

        var gs *ir.GoDeferStmt
        gs.Left()           -> gs.Call
        gs.SetLeft(n)       -> gs.Call = n

        var ifs *ir.IfStmt
        ifs.Left()          -> ifs.Cond
        ifs.SetLeft(n)      -> ifs.Cond = n
        ifs.Body()          -> ifs.Body_
        ifs.PtrBody()       -> &ifs.Body_
        ifs.SetBody(ns)     -> ifs.Body_ = ns
        ifs.Rlist()         -> ifs.Else
        ifs.PtrRlist()      -> &ifs.Else
        ifs.SetRlist(ns)    -> ifs.Else = ns
        ifs.Likely()        -> ifs.Likely_
        ifs.SetLikely(b)    -> ifs.Likely_ = b

        var im *ir.InlineMarkStmt
        im.Offset()         -> im.Index
        im.SetOffset(i64)   -> im.Index = i64

        var lab *ir.LabelStmt
        lab.Sym()           -> lab.Label
        lab.SetSym(sym)     -> lab.Label = sym

        var rng *ir.RangeStmt
        rng.Sym()           -> rng.Label
        rng.SetSym(sym)     -> rng.Label = sym
        rng.Right()         -> rng.X
        rng.SetRight(n)     -> rng.X = n
        rng.Body()          -> rng.Body_
        rng.PtrBody()       -> &rng.Body_
        rng.SetBody(ns)     -> rng.Body_ = ns
        rng.List()          -> rng.Vars
        rng.PtrList()       -> &rng.Vars
        rng.SetList(ns)     -> rng.Vars = ns
        rng.HasBreak()      -> rng.HasBreak_
        rng.SetHasBreak(b)  -> rng.HasBreak_ = b
        rng.Colas()         -> rng.Def
        rng.SetColas(b)     -> rng.Def = b

        var ret *ir.ReturnStmt
        ret.List()          -> ret.Results
        ret.PtrList()       -> &ret.Results
        ret.SetList(ns)     -> ret.Results = ns

        var sel *ir.SelectStmt
        sel.List()          -> sel.Cases
        sel.PtrList()       -> &sel.Cases
        sel.SetList(ns)     -> sel.Cases = ns
        sel.Sym()           -> sel.Label
        sel.SetSym(sym)     -> sel.Label = sym
        sel.HasBreak()      -> sel.HasBreak_
        sel.SetHasBreak(b)  -> sel.HasBreak_ = b
        sel.Body()          -> sel.Compiled
        sel.PtrBody()       -> &sel.Compiled
        sel.SetBody(ns)     -> sel.Compiled = ns

        var send *ir.SendStmt
        send.Left()         -> send.Chan
        send.SetLeft(n)     -> send.Chan = n
        send.Right()        -> send.Value
        send.SetRight(n)    -> send.Value = n

        var sw *ir.SwitchStmt
        sw.Left()           -> sw.Tag
        sw.SetLeft(n)       -> sw.Tag = n
        sw.List()           -> sw.Cases
        sw.PtrList()        -> &sw.Cases
        sw.SetList(ns)      -> sw.Cases = ns
        sw.Body()           -> sw.Compiled
        sw.PtrBody()        -> &sw.Compiled
        sw.SetBody(ns)      -> sw.Compiled = ns
        sw.Sym()            -> sw.Label
        sw.SetSym(sym)      -> sw.Label = sym
        sw.HasBreak()       -> sw.HasBreak_
        sw.SetHasBreak(b)   -> sw.HasBreak_ = b

        var tg *ir.TypeSwitchGuard
        tg.Left()           -> tg.Tag
        tg.SetLeft(nil)     -> tg.Tag = nil
        tg.SetLeft(n)       -> tg.Tag = n.(*ir.Ident)
        tg.Right()          -> tg.X
        tg.SetRight(n)      -> tg.X = n

        var adds *ir.AddStringExpr
        adds.List()         -> adds.List_
        adds.PtrList()      -> &adds.List_
        adds.SetList(ns)    -> adds.List_ = ns

        var addr *ir.AddrExpr
        addr.Left()         -> addr.X
        addr.SetLeft(n)     -> addr.X = n
        addr.Right()        -> addr.Alloc
        addr.SetRight(n)    -> addr.Alloc = n

        var bin *ir.BinaryExpr
        bin.Left()          -> bin.X
        bin.SetLeft(n)      -> bin.X = n
        bin.Right()         -> bin.Y
        bin.SetRight(n)     -> bin.Y = n

        var log *ir.LogicalExpr
        log.Left()          -> log.X
        log.SetLeft(n)      -> log.X = n
        log.Right()         -> log.Y
        log.SetRight(n)     -> log.Y = n

        var call *ir.CallExpr
        call.Left()         -> call.X
        call.SetLeft(n)     -> call.X = n
        call.List()         -> call.Args
        call.PtrList()      -> &call.Args
        call.SetList(ns)    -> call.Args = ns
        call.Rlist()        -> call.Rargs
        call.PtrRlist()     -> &call.Rargs
        call.SetRlist(ns)   -> call.Rargs = ns
        call.IsDDD()        -> call.DDD
        call.SetIsDDD(b)    -> call.DDD = b
        call.NoInline()     -> call.NoInline_
        call.SetNoInline(b) -> call.NoInline_ = b
        call.Body()         -> call.Body_
        call.PtrBody()      -> &call.Body_
        call.SetBody(ns)    -> call.Body_ = ns

        var cp *ir.CallPartExpr
        cp.Func()           -> cp.Func_
        cp.Left()           -> cp.X
        cp.SetLeft(n)       -> cp.X = n
        cp.Sym()            -> cp.Method.Sym

        var clo *ir.ClosureExpr
        clo.Func()          -> clo.Func_

        var cr *ir.ClosureReadExpr
        cr.Offset()         -> cr.Offset_

        var cl *ir.CompLitExpr
        cl.Right()          -> cl.Ntype
        cl.SetRight(nil)    -> cl.Ntype = nil
        cl.SetRight(n)      -> cl.Ntype = ir.Node(n).(ir.Ntype)
        cl.List()           -> cl.List_
        cl.PtrList()        -> &cl.List_
        cl.SetList(ns)      -> cl.List_ = ns

        var conv *ir.ConvExpr
        conv.Left()         -> conv.X
        conv.SetLeft(n)     -> conv.X = n

        var ix *ir.IndexExpr
        ix.Left()           -> ix.X
        ix.SetLeft(n)       -> ix.X = n
        ix.Right()          -> ix.Index
        ix.SetRight(n)      -> ix.Index = n
        ix.IndexMapLValue() -> ix.Assigned
        ix.SetIndexMapLValue(b) -> ix.Assigned = b

        var kv *ir.KeyExpr
        kv.Left()           -> kv.Key
        kv.SetLeft(n)       -> kv.Key = n
        kv.Right()          -> kv.Value
        kv.SetRight(n)      -> kv.Value = n

        var sk *ir.StructKeyExpr
        sk.Sym()            -> sk.Field
        sk.SetSym(sym)      -> sk.Field = sym
        sk.Left()           -> sk.Value
        sk.SetLeft(n)       -> sk.Value = n
        sk.Offset()         -> sk.Offset_
        sk.SetOffset(i64)   -> sk.Offset_ = i64

        var ic *ir.InlinedCallExpr
        ic.Body()           -> ic.Body_
        ic.PtrBody()        -> &ic.Body_
        ic.SetBody(ns)      -> ic.Body_ = ns
        ic.Rlist()          -> ic.ReturnVars
        ic.PtrRlist()       -> &ic.ReturnVars
        ic.SetRlist(ns)     -> ic.ReturnVars = ns

        var mak *ir.MakeExpr
        mak.Left()          -> mak.Len
        mak.SetLeft(n)      -> mak.Len = n
        mak.Right()         -> mak.Cap
        mak.SetRight(n)     -> mak.Cap = n

        var par *ir.ParenExpr
        par.Left()          -> par.X
        par.SetLeft(n)      -> par.X = n

        var res *ir.ResultExpr
        res.Offset()        -> res.Offset_
        res.SetOffset(i64)  -> res.Offset_ = i64

        var dot *ir.SelectorExpr
        dot.Left()          -> dot.X
        dot.SetLeft(n)      -> dot.X = n
        dot.Sym()           -> dot.Sel
        dot.SetSym(sym)     -> dot.Sel = sym
        dot.Offset()        -> dot.Offset_
        dot.SetOffset(i64)  -> dot.Offset_ = i64

        var sl *ir.SliceExpr
        sl.Left()           -> sl.X
        sl.SetLeft(n)       -> sl.X = n
        sl.List()           -> sl.List_
        sl.PtrList()        -> &sl.List_
        sl.SetList(ns)      -> sl.List_ = ns

        var sh *ir.SliceHeaderExpr
        sh.Left()           -> sh.Ptr
        sh.SetLeft(n)       -> sh.Ptr = n
        sh.List()           -> sh.LenCap_
        sh.PtrList()        -> &sh.LenCap_
        sh.SetList(ns)      -> sh.LenCap_ = ns

        var st *ir.StarExpr
        st.Left()           -> st.X
        st.SetLeft(n)       -> st.X = n

        var ta *ir.TypeAssertExpr
        ta.Left()           -> ta.X
        ta.SetLeft(n)       -> ta.X = n
        ta.Right()          -> ta.Ntype
        ta.SetRight(n)    -> ta.Ntype = n
        ta.List()           -> ta.Itab
        ta.PtrList()        -> &ta.Itab
        ta.SetList(ns)      -> ta.Itab = ns

        var u *ir.UnaryExpr
        u.Left()            -> u.X
        u.SetLeft(n)        -> u.X = n

        var fn *ir.Func
        fn.Body()           -> fn.Body_
        fn.PtrBody()        -> &fn.Body_
        fn.SetBody(ns)      -> fn.Body_ = ns
        fn.Iota()           -> fn.Iota_
        fn.SetIota(i64)     -> fn.Iota_ = i64
        fn.Func()           -> fn

        var nam *ir.Name
        nam.SubOp()         -> nam.BuiltinOp
        nam.SetSubOp(op)    -> nam.BuiltinOp = op
        nam.Class()         -> nam.Class_
        nam.SetClass(class) -> nam.Class_ = class
        nam.Func()          -> nam.Func_
        nam.Offset()        -> nam.Offset_
        nam.SetOffset(i64)  -> nam.Offset_ = i64
}

ex . ../ir {
        import "cmd/compile/internal/ir"

        var n ir.Nodes

        (&n).Append         -> n.Append
        (&n).AppendNodes    -> n.AppendNodes
        (&n).MoveNodes      -> n.MoveNodes
        (&n).Prepend        -> n.Prepend
        (&n).Set            -> n.Set
        (&n).Set1           -> n.Set1
        (&n).Set2           -> n.Set2
        (&n).Set3           -> n.Set3

        var ntype ir.Ntype
        ir.Node(ntype).(ir.Ntype) -> ntype
}
'

cd ../ir
rf '
rm \
        Decl.Left Decl.SetLeft \
        AssignListStmt.List AssignListStmt.PtrList AssignListStmt.SetList \
        AssignListStmt.Rlist AssignListStmt.PtrRlist AssignListStmt.SetRlist \
        AssignListStmt.Colas AssignListStmt.SetColas \
        AssignStmt.Left AssignStmt.SetLeft \
        AssignStmt.Right AssignStmt.SetRight \
        AssignStmt.Colas AssignStmt.SetColas \
        AssignOpStmt.Left AssignOpStmt.SetLeft \
        AssignOpStmt.Right AssignOpStmt.SetRight \
        AssignOpStmt.SubOp AssignOpStmt.SetSubOp \
        AssignOpStmt.Implicit AssignOpStmt.SetImplicit \
        BlockStmt.List BlockStmt.PtrList BlockStmt.SetList \
        BranchStmt.SetSym \
        CaseStmt.List CaseStmt.PtrList CaseStmt.SetList \
        CaseStmt.Body CaseStmt.PtrBody CaseStmt.SetBody \
        CaseStmt.Rlist CaseStmt.PtrRlist CaseStmt.SetRlist \
        CaseStmt.Left CaseStmt.SetLeft \
        ForStmt.Left ForStmt.SetLeft \
        ForStmt.Right ForStmt.SetRight \
        ForStmt.Body ForStmt.PtrBody ForStmt.SetBody \
        ForStmt.List ForStmt.PtrList ForStmt.SetList \
        ForStmt.HasBreak ForStmt.SetHasBreak \
        ForStmt.Sym ForStmt.SetSym \
        GoDeferStmt.Left GoDeferStmt.SetLeft \
        IfStmt.Left IfStmt.SetLeft \
        IfStmt.Body IfStmt.PtrBody IfStmt.SetBody \
        IfStmt.Rlist IfStmt.PtrRlist IfStmt.SetRlist \
        IfStmt.Likely IfStmt.SetLikely \
        LabelStmt.SetSym \
        RangeStmt.Right RangeStmt.SetRight \
        RangeStmt.Body RangeStmt.PtrBody RangeStmt.SetBody \
        RangeStmt.List RangeStmt.PtrList RangeStmt.SetList \
        RangeStmt.HasBreak RangeStmt.SetHasBreak \
        RangeStmt.Colas RangeStmt.SetColas \
        RangeStmt.Sym RangeStmt.SetSym \
        ReturnStmt.List ReturnStmt.PtrList ReturnStmt.SetList \
        SelectStmt.List SelectStmt.PtrList SelectStmt.SetList \
        SelectStmt.HasBreak SelectStmt.SetHasBreak \
        SelectStmt.Body SelectStmt.PtrBody SelectStmt.SetBody \
        SelectStmt.Sym SelectStmt.SetSym \
        SendStmt.Left SendStmt.SetLeft \
        SendStmt.Right SendStmt.SetRight \
        SwitchStmt.Left SwitchStmt.SetLeft \
        SwitchStmt.List SwitchStmt.PtrList SwitchStmt.SetList \
        SwitchStmt.Body SwitchStmt.PtrBody SwitchStmt.SetBody \
        SwitchStmt.HasBreak SwitchStmt.SetHasBreak \
        SwitchStmt.Sym SwitchStmt.SetSym \
        TypeSwitchGuard.Left TypeSwitchGuard.SetLeft \
        TypeSwitchGuard.Right TypeSwitchGuard.SetRight \
        AddStringExpr.List AddStringExpr.PtrList AddStringExpr.SetList \
        AddrExpr.Left AddrExpr.SetLeft \
        AddrExpr.Right AddrExpr.SetRight \
        BinaryExpr.Left BinaryExpr.SetLeft \
        BinaryExpr.Right BinaryExpr.SetRight \
        LogicalExpr.Left LogicalExpr.SetLeft \
        LogicalExpr.Right LogicalExpr.SetRight \
        CallExpr.Left CallExpr.SetLeft \
        CallExpr.List CallExpr.PtrList CallExpr.SetList \
        CallExpr.Rlist CallExpr.PtrRlist CallExpr.SetRlist \
        CallExpr.NoInline CallExpr.SetNoInline \
        CallExpr.Body CallExpr.PtrBody CallExpr.SetBody \
        CallExpr.IsDDD CallExpr.SetIsDDD \
        CallPartExpr.Left CallPartExpr.SetLeft \
        ClosureReadExpr.Offset \
        ClosureReadExpr.Type \ # provided by miniExpr already
        CompLitExpr.Right CompLitExpr.SetRight \
        CompLitExpr.List CompLitExpr.PtrList CompLitExpr.SetList \
        ConvExpr.Left ConvExpr.SetLeft \
        IndexExpr.Left IndexExpr.SetLeft \
        IndexExpr.Right IndexExpr.SetRight \
        IndexExpr.IndexMapLValue IndexExpr.SetIndexMapLValue \
        KeyExpr.Left KeyExpr.SetLeft \
        KeyExpr.Right KeyExpr.SetRight \
        StructKeyExpr.Left StructKeyExpr.SetLeft \
        StructKeyExpr.Offset StructKeyExpr.SetOffset \
        StructKeyExpr.SetSym \
        InlinedCallExpr.Body InlinedCallExpr.PtrBody InlinedCallExpr.SetBody \
        InlinedCallExpr.Rlist InlinedCallExpr.PtrRlist InlinedCallExpr.SetRlist \
        MakeExpr.Left MakeExpr.SetLeft \
        MakeExpr.Right MakeExpr.SetRight \
        MethodExpr.Left MethodExpr.SetLeft \
        MethodExpr.Right MethodExpr.SetRight \
        MethodExpr.Offset MethodExpr.SetOffset \
        MethodExpr.Class MethodExpr.SetClass \
        ParenExpr.Left ParenExpr.SetLeft \
        ResultExpr.Offset ResultExpr.SetOffset \
        ReturnStmt.IsDDD \
        SelectorExpr.Left SelectorExpr.SetLeft \
        SelectorExpr.Offset SelectorExpr.SetOffset \
        SelectorExpr.SetSym \
        SliceExpr.Left SliceExpr.SetLeft \
        SliceExpr.List SliceExpr.PtrList SliceExpr.SetList \
        SliceHeaderExpr.Left SliceHeaderExpr.SetLeft \
        SliceHeaderExpr.List SliceHeaderExpr.PtrList SliceHeaderExpr.SetList \
        StarExpr.Left StarExpr.SetLeft \
        TypeAssertExpr.Left TypeAssertExpr.SetLeft \
        TypeAssertExpr.Right TypeAssertExpr.SetRight \
        TypeAssertExpr.List TypeAssertExpr.PtrList TypeAssertExpr.SetList \
        UnaryExpr.Left UnaryExpr.SetLeft \
        Func.Body Func.PtrBody Func.SetBody \
        Func.Iota Func.SetIota \
        CallPartExpr.Func ClosureExpr.Func Func.Func Name.Func \

mv BlockStmt.List_ BlockStmt.List
mv CaseStmt.List_ CaseStmt.List
mv CaseStmt.Body_ CaseStmt.Body
mv ForStmt.Body_ ForStmt.Body
mv ForStmt.HasBreak_ ForStmt.HasBreak
mv Func.Iota_ Func.Iota
mv IfStmt.Body_ IfStmt.Body
mv IfStmt.Likely_ IfStmt.Likely
mv RangeStmt.Body_ RangeStmt.Body
mv RangeStmt.HasBreak_ RangeStmt.HasBreak
mv SelectStmt.HasBreak_ SelectStmt.HasBreak
mv SwitchStmt.HasBreak_ SwitchStmt.HasBreak
mv AddStringExpr.List_ AddStringExpr.List
mv CallExpr.NoInline_ CallExpr.NoInline
mv CallExpr.Body_ CallExpr.Body # TODO what is this?
mv CallExpr.DDD CallExpr.IsDDD
mv ClosureReadExpr.Offset_ ClosureReadExpr.Offset
mv CompLitExpr.List_ CompLitExpr.List
mv StructKeyExpr.Offset_ StructKeyExpr.Offset
mv InlinedCallExpr.Body_ InlinedCallExpr.Body
mv ResultExpr.Offset_ ResultExpr.Offset
mv SelectorExpr.Offset_ SelectorExpr.Offset
mv SliceExpr.List_ SliceExpr.List
mv SliceHeaderExpr.LenCap_ SliceHeaderExpr.LenCap
mv Func.Body_ Func.Body
mv CallPartExpr.Func_ CallPartExpr.Func
mv ClosureExpr.Func_ ClosureExpr.Func
mv Name.Func_ Name.Func
'

Change-Id: Ia2ee59649674f83eb123e63fda7a7781cf91cc56
Reviewed-on: https://go-review.googlesource.com/c/go/+/277935
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-12-23 06:37:41 +00:00
Russ Cox
51ba53f5c2 [dev.regabi] cmd/compile: separate misc for gc split
Misc cleanup for splitting package gc: API tweaks
and boundary adjustments.

The change in ir.NewBlockStmt makes it a drop-in
replacement for liststmt.

Change-Id: I9455fe8ccae7d71fe8ccf390ac96672389bf4f3d
Reviewed-on: https://go-review.googlesource.com/c/go/+/279305
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-12-22 19:32:16 +00:00
Russ Cox
7c8f5356ab [dev.regabi] cmd/compile: separate dowidth better
Having a global MaxWidth lets us avoid needing to
refer to thearch from split-out packages when all
they need is thearch.MAXWIDTH.

And make a couple interface changes to let dowidth
avoid importing package ir directly.
Then it can move into package types.

Change-Id: I2c12e8e22252597530e648848320e19bdd490a01
Reviewed-on: https://go-review.googlesource.com/c/go/+/279302
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-12-22 19:31:57 +00:00
Russ Cox
9c384e881e [dev.regabi] cmd/compile: cleanup for concrete types - mop-up
An automated rewrite will add concrete type assertions after
a test of n.Op(), when n can be safely type-asserted
(meaning, n is not reassigned a different type, n is not reassigned
and then used outside the scope of the type assertion,
and so on).

This sequence of CLs handles the code that the automated
rewrite does not: adding specific types to function arguments,
adjusting code not to call n.Left() etc when n may have multiple
representations, and so on.

This CL handles all the little files that are left.

Passes buildall w/ toolstash -cmp.

Change-Id: I6588c92dbbdd37342a77b365d70e02134a033d2a
Reviewed-on: https://go-review.googlesource.com/c/go/+/277932
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-12-17 04:43:53 +00:00
Keith Randall
fea898a4b0 [dev.regabi] cmd/compile: intercept the making of OADDR nodes
This is a mechanical change to intercept the construction of
all OADDR nodes. We will use the new nodAddr and nodAddrAt
functions to compute the Addrtaken bit.

Change-Id: I90ee3acb8e32540a198a9999284573418729f422
Reviewed-on: https://go-review.googlesource.com/c/go/+/275694
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Keith Randall <khr@golang.org>
Trust: Dan Scales <danscales@google.com>
Reviewed-by: Dan Scales <danscales@google.com>
2020-12-14 23:35:06 +00:00
Russ Cox
bb4a37bd93 [dev.regabi] cmd/compile: move Type, Sym printing to package types [generated]
Move the printing of types.Type and types.Sym out of ir
into package types, where it properly belongs. This wasn't
done originally (when the code was in gc) because the Type
and Sym printing was a bit tangled up with the Node printing.
But now they are untangled and can move into the correct
package.

This CL is automatically generated.
A followup CL will clean up a little bit more by hand.

Passes buildall w/ toolstash -cmp.

[git-generate]
cd src/cmd/compile/internal/ir
rf '
	mv FmtMode fmtMode
	mv FErr fmtGo
	mv FDbg fmtDebug
	mv FTypeId fmtTypeID
	mv FTypeIdName fmtTypeIDName
	mv methodSymName SymMethodName

	mv BuiltinPkg LocalPkg BlankSym OrigSym NumImport \
		fmtMode fmtGo symFormat sconv sconv2 symfmt SymMethodName \
		BasicTypeNames fmtBufferPool InstallTypeFormats typeFormat tconv tconv2 fldconv FmtConst \
		typefmt.go

	mv typefmt.go cmd/compile/internal/types
'
cd ../types
mv typefmt.go fmt.go

Change-Id: I6f3fd818323733ab8446f00594937c1628760b27
Reviewed-on: https://go-review.googlesource.com/c/go/+/275779
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-12-07 20:41:11 +00:00
Matthew Dempsky
c10b0ad628 [dev.regabi] cmd/compile: add Pkg parameter to type constructors
Allows getting rid of the SetPkg method and also addresses a
long-standing TODO in the exporter. Suggested by rsc@.

Passes buildall w/ toolstash -cmp.

Change-Id: Ib294f75f1350572efb2e0d993d49efef884de3d4
Reviewed-on: https://go-review.googlesource.com/c/go/+/274440
Trust: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
2020-12-02 08:50:26 +00:00
Matthew Dempsky
77a71e0057 [dev.regabi] cmd/compile: add Interface, Signature, and Struct constructors
This CL adds the remaining constructors needed to abstract away
construction of Types, and updates the compiler to use them
throughout. There's now just a couple uses within test cases to
remove.

While at it, I also replace the Func.Outnamed field with a simple
helper function, which reduces the size of function types somewhat.

Passes toolstash/buildall.

Change-Id: If1aa1095c98ae34b00380d0b3531bd63c10ce885
Reviewed-on: https://go-review.googlesource.com/c/go/+/274713
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
2020-12-02 06:42:17 +00:00
Matthew Dempsky
15085f8974 [dev.regabi] cmd/compile: tweak hash bucket type descriptor
There's no need for the bucket type to be precise. The compiler
doesn't actually generate code that references these fields; it just
needs it for size and GC bitmap calculations.

However, changing the type field does alter the runtime type
descriptor and relocations emitted by the compiler, so this change
isn't safe for toolstash.

Change-Id: Icf79d6c4326515889b13435a575d618e3bbfbcd7
Reviewed-on: https://go-review.googlesource.com/c/go/+/274712
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
2020-12-02 06:37:47 +00:00
Matthew Dempsky
1408d26ccc [dev.regabi] cmd/compile: cleanup some leftover cruft
Just clearing away some scaffolding artifacts from previous
refactorings.

[git-generate]
cd src/cmd/compile/internal/gc
rf '
ex {
  import "cmd/compile/internal/ir"
  import "cmd/compile/internal/types"

  var n *ir.Name; n.Name() -> n
  var f *ir.Func; f.Func() -> f

  var o types.Object
  ir.AsNode(o).Sym() -> o.Sym()
  ir.AsNode(o).Type() -> o.Type()
  ir.AsNode(o).(*ir.Name) -> o.(*ir.Name)
  ir.AsNode(o).(*ir.Func) -> o.(*ir.Func)

  var x ir.Node
  ir.AsNode(o) != x -> o != x
}
'

Change-Id: I946ec344bd7ee274900a392da53b95308ceaade4
Reviewed-on: https://go-review.googlesource.com/c/go/+/274592
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
2020-12-01 22:09:25 +00:00
Matthew Dempsky
5ffa275f3c [dev.regabi] cmd/compile: first pass at abstracting Type
Passes toolstash/buildall.

[git-generate]
cd src/cmd/compile/internal/ssa
rf '
ex . ../ir ../gc {
  import "cmd/compile/internal/types"
  var t *types.Type
  t.Etype -> t.Kind()
  t.Sym -> t.GetSym()
  t.Orig -> t.Underlying()
}
'

cd ../types
rf '
mv EType Kind
mv IRNode Object

mv Type.Etype Type.kind
mv Type.Sym Type.sym
mv Type.Orig Type.underlying
mv Type.Cache Type.cache

mv Type.GetSym Type.Sym

mv Bytetype ByteType
mv Runetype RuneType
mv Errortype ErrorType
'

cd ../gc
sed -i 's/Bytetype/ByteType/; s/Runetype/RuneType/' mkbuiltin.go

git codereview gofmt
go install cmd/compile/internal/...
go test cmd/compile -u || go test cmd/compile

Change-Id: Ibecb2d7100d3318a49238eb4a78d70acb49eedca
Reviewed-on: https://go-review.googlesource.com/c/go/+/274437
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Russ Cox <rsc@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
2020-12-01 19:24:00 +00:00
Russ Cox
4e7685ef1a [dev.regabi] cmd/compile: add custom type syntax Node implementations
The type syntax is reused to stand in for the actual type once typechecked,
to avoid updating all the possible references to the original type syntax.
So all these implementations allow changing their Op from the raw syntax
like OTMAP to the finished form OTYPE, even though obviously the
representation does not change.

Passes buildall w/ toolstash -cmp.

Change-Id: I4acca1a5b35fa2f48ee08e8f1e5a330a004c284b
Reviewed-on: https://go-review.googlesource.com/c/go/+/274103
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
2020-11-30 19:45:21 +00:00
Russ Cox
41f3af9d04 [dev.regabi] cmd/compile: replace *Node type with an interface Node [generated]
The plan is to introduce a Node interface that replaces the old *Node pointer-to-struct.

The previous CL defined an interface INode modeling a *Node.

This CL:
 - Changes all references outside internal/ir to use INode,
   along with many references inside internal/ir as well.
 - Renames Node to node.
 - Renames INode to Node

So now ir.Node is an interface implemented by *ir.node, which is otherwise inaccessible,
and the code outside package ir is now (clearly) using only the interface.

The usual rule is never to redefine an existing name with a new meaning,
so that old code that hasn't been updated gets a "unknown name" error
instead of more mysterious errors or silent misbehavior. That rule would
caution against replacing Node-the-struct with Node-the-interface,
as in this CL, because code that says *Node would now be using a pointer
to an interface. But this CL is being landed at the same time as another that
moves Node from gc to ir. So the net effect is to replace *gc.Node with ir.Node,
which does follow the rule: any lingering references to gc.Node will be told
it's gone, not silently start using pointers to interfaces. So the rule is followed
by the CL sequence, just not this specific CL.

Overall, the loss of inlining caused by using interfaces cuts the compiler speed
by about 6%, a not insignificant amount. However, as we convert the representation
to concrete structs that are not the giant Node over the next weeks, that speed
should come back as more of the compiler starts operating directly on concrete types
and the memory taken up by the graph of Nodes drops due to the more precise
structs. Honestly, I was expecting worse.

% benchstat bench.old bench.new
name                      old time/op       new time/op       delta
Template                        168ms ± 4%        182ms ± 2%   +8.34%  (p=0.000 n=9+9)
Unicode                        72.2ms ±10%       82.5ms ± 6%  +14.38%  (p=0.000 n=9+9)
GoTypes                         563ms ± 8%        598ms ± 2%   +6.14%  (p=0.006 n=9+9)
Compiler                        2.89s ± 4%        3.04s ± 2%   +5.37%  (p=0.000 n=10+9)
SSA                             6.45s ± 4%        7.25s ± 5%  +12.41%  (p=0.000 n=9+10)
Flate                           105ms ± 2%        115ms ± 1%   +9.66%  (p=0.000 n=10+8)
GoParser                        144ms ±10%        152ms ± 2%   +5.79%  (p=0.011 n=9+8)
Reflect                         345ms ± 9%        370ms ± 4%   +7.28%  (p=0.001 n=10+9)
Tar                             149ms ± 9%        161ms ± 5%   +8.05%  (p=0.001 n=10+9)
XML                             190ms ± 3%        209ms ± 2%   +9.54%  (p=0.000 n=9+8)
LinkCompiler                    327ms ± 2%        325ms ± 2%     ~     (p=0.382 n=8+8)
ExternalLinkCompiler            1.77s ± 4%        1.73s ± 6%     ~     (p=0.113 n=9+10)
LinkWithoutDebugCompiler        214ms ± 4%        211ms ± 2%     ~     (p=0.360 n=10+8)
StdCmd                          14.8s ± 3%        15.9s ± 1%   +6.98%  (p=0.000 n=10+9)
[Geo mean]                      480ms             510ms        +6.31%

name                      old user-time/op  new user-time/op  delta
Template                        223ms ± 3%        237ms ± 3%   +6.16%  (p=0.000 n=9+10)
Unicode                         103ms ± 6%        113ms ± 3%   +9.53%  (p=0.000 n=9+9)
GoTypes                         758ms ± 8%        800ms ± 2%   +5.55%  (p=0.003 n=10+9)
Compiler                        3.95s ± 2%        4.12s ± 2%   +4.34%  (p=0.000 n=10+9)
SSA                             9.43s ± 1%        9.74s ± 4%   +3.25%  (p=0.000 n=8+10)
Flate                           132ms ± 2%        141ms ± 2%   +6.89%  (p=0.000 n=9+9)
GoParser                        177ms ± 9%        183ms ± 4%     ~     (p=0.050 n=9+9)
Reflect                         467ms ±10%        495ms ± 7%   +6.17%  (p=0.029 n=10+10)
Tar                             183ms ± 9%        197ms ± 5%   +7.92%  (p=0.001 n=10+10)
XML                             249ms ± 5%        268ms ± 4%   +7.82%  (p=0.000 n=10+9)
LinkCompiler                    544ms ± 5%        544ms ± 6%     ~     (p=0.863 n=9+9)
ExternalLinkCompiler            1.79s ± 4%        1.75s ± 6%     ~     (p=0.075 n=10+10)
LinkWithoutDebugCompiler        248ms ± 6%        246ms ± 2%     ~     (p=0.965 n=10+8)
[Geo mean]                      483ms             504ms        +4.41%

[git-generate]
cd src/cmd/compile/internal/ir
: # We need to do the conversion in multiple steps, so we introduce
: # a temporary type alias that will start out meaning the pointer-to-struct
: # and then change to mean the interface.
rf '
	mv Node OldNode

	add node.go \
		type Node = *OldNode
'

: # It should work to do this ex in ir, but it misses test files, due to a bug in rf.
: # Run the command in gc to handle gc's tests, and then again in ssa for ssa's tests.
cd ../gc
rf '
        ex .  ../arm ../riscv64 ../arm64 ../mips64 ../ppc64 ../mips ../wasm {
                import "cmd/compile/internal/ir"
                *ir.OldNode -> ir.Node
        }
'
cd ../ssa
rf '
        ex {
                import "cmd/compile/internal/ir"
                *ir.OldNode -> ir.Node
        }
'

: # Back in ir, finish conversion clumsily with sed,
: # because type checking and circular aliases do not mix.
cd ../ir
sed -i '' '
	/type Node = \*OldNode/d
	s/\*OldNode/Node/g
	s/^func (n Node)/func (n *OldNode)/
	s/OldNode/node/g
	s/type INode interface/type Node interface/
	s/var _ INode = (Node)(nil)/var _ Node = (*node)(nil)/
' *.go
gofmt -w *.go

sed -i '' '
	s/{Func{}, 136, 248}/{Func{}, 152, 280}/
	s/{Name{}, 32, 56}/{Name{}, 44, 80}/
	s/{Param{}, 24, 48}/{Param{}, 44, 88}/
	s/{node{}, 76, 128}/{node{}, 88, 152}/
' sizeof_test.go

cd ../ssa
sed -i '' '
	s/{LocalSlot{}, 28, 40}/{LocalSlot{}, 32, 48}/
' sizeof_test.go

cd ../gc
sed -i '' 's/\*ir.Node/ir.Node/' mkbuiltin.go

cd ../../../..
go install std cmd
cd cmd/compile
go test -u || go test -u

Change-Id: I196bbe3b648e4701662e4a2bada40bf155e2a553
Reviewed-on: https://go-review.googlesource.com/c/go/+/272935
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-11-25 17:30:43 +00:00
Russ Cox
c26aead50c [dev.regabi] cmd/compile: convert types.Node (a pointer) to types.IRNode (an interface)
The pointer hack was nice and saved a word, but it's untenable
in a world where nodes are themselves interfaces with different
underlying types. Bite the bullet and use an interface to hold the
Node when in types.Sym and types.Type.

This has the nice benefit of removing AsTypesNode entirely.
AsNode is still useful because of its nil handling.

Change-Id: I298cba9ff788b956ee287283bec78010e8b601e5
Reviewed-on: https://go-review.googlesource.com/c/go/+/272933
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-11-25 17:30:40 +00:00
Russ Cox
acb4d1cef1 [dev.regabi] cmd/compile: use Node getters and setters [generated]
Now that we have all the getters and setters defined, use them
and unexport all the actual Node fields. This is the next step
toward replacing Node with an interface.

[git-generate]
cd src/cmd/compile/internal/gc
rf '
        ex . ../ir ../ssa {
                import "cmd/compile/internal/ir"
                import "cmd/compile/internal/types"
                import "cmd/internal/src"
                var n, x *ir.Node
                var op ir.Op
                var t *types.Type
                var f *ir.Func
                var m *ir.Name
                var s *types.Sym
                var p src.XPos
                var i int64
                var e uint16
                var nodes ir.Nodes

                n.Op = op    -> n.SetOp(op)
                n.Left = x   -> n.SetLeft(x)
                n.Right = x  -> n.SetRight(x)
                n.Orig = x -> n.SetOrig(x)
                n.Type = t -> n.SetType(t)
                n.Func = f -> n.SetFunc(f)
                n.Name = m -> n.SetName(m)
                n.Sym = s -> n.SetSym(s)
                n.Pos = p -> n.SetPos(p)
                n.Xoffset = i -> n.SetXoffset(i)
                n.Esc = e -> n.SetEsc(e)

                n.Ninit.Append -> n.PtrNinit().Append
                n.Ninit.AppendNodes -> n.PtrNinit().AppendNodes
                n.Ninit.MoveNodes -> n.PtrNinit().MoveNodes
                n.Ninit.Prepend -> n.PtrNinit().Prepend
                n.Ninit.Set -> n.PtrNinit().Set
                n.Ninit.Set1 -> n.PtrNinit().Set1
                n.Ninit.Set2 -> n.PtrNinit().Set2
                n.Ninit.Set3 -> n.PtrNinit().Set3
                &n.Ninit -> n.PtrNinit()
                n.Ninit = nodes -> n.SetNinit(nodes)

                n.Nbody.Append -> n.PtrNbody().Append
                n.Nbody.AppendNodes -> n.PtrNbody().AppendNodes
                n.Nbody.MoveNodes -> n.PtrNbody().MoveNodes
                n.Nbody.Prepend -> n.PtrNbody().Prepend
                n.Nbody.Set -> n.PtrNbody().Set
                n.Nbody.Set1 -> n.PtrNbody().Set1
                n.Nbody.Set2 -> n.PtrNbody().Set2
                n.Nbody.Set3 -> n.PtrNbody().Set3
                &n.Nbody -> n.PtrNbody()
                n.Nbody = nodes -> n.SetNbody(nodes)

                n.List.Append -> n.PtrList().Append
                n.List.AppendNodes -> n.PtrList().AppendNodes
                n.List.MoveNodes -> n.PtrList().MoveNodes
                n.List.Prepend -> n.PtrList().Prepend
                n.List.Set -> n.PtrList().Set
                n.List.Set1 -> n.PtrList().Set1
                n.List.Set2 -> n.PtrList().Set2
                n.List.Set3 -> n.PtrList().Set3
                &n.List -> n.PtrList()
                n.List = nodes -> n.SetList(nodes)

                n.Rlist.Append -> n.PtrRlist().Append
                n.Rlist.AppendNodes -> n.PtrRlist().AppendNodes
                n.Rlist.MoveNodes -> n.PtrRlist().MoveNodes
                n.Rlist.Prepend -> n.PtrRlist().Prepend
                n.Rlist.Set -> n.PtrRlist().Set
                n.Rlist.Set1 -> n.PtrRlist().Set1
                n.Rlist.Set2 -> n.PtrRlist().Set2
                n.Rlist.Set3 -> n.PtrRlist().Set3
                &n.Rlist -> n.PtrRlist()
                n.Rlist = nodes -> n.SetRlist(nodes)
        }
        ex . ../ir ../ssa {
                import "cmd/compile/internal/ir"

                var n *ir.Node
                n.Op         -> n.GetOp()
                n.Left       -> n.GetLeft()
                n.Right      -> n.GetRight()
                n.Orig -> n.GetOrig()
                n.Type -> n.GetType()
                n.Func -> n.GetFunc()
                n.Name -> n.GetName()
                n.Sym -> n.GetSym()
                n.Pos -> n.GetPos()
                n.Xoffset -> n.GetXoffset()
                n.Esc -> n.GetEsc()

                avoid (*ir.Node).PtrNinit
                avoid (*ir.Node).PtrNbody
                avoid (*ir.Node).PtrList
                avoid (*ir.Node).PtrRlist

                n.Ninit -> n.GetNinit()
                n.Nbody -> n.GetNbody()
                n.List -> n.GetList()
                n.Rlist -> n.GetRlist()
        }
'

cd ../ir
rf '
        mv Node.Op Node.op
        mv Node.GetOp Node.Op

        mv Node.Left Node.left
        mv Node.GetLeft Node.Left

        mv Node.Right Node.right
        mv Node.GetRight Node.Right

        mv Node.Orig Node.orig
        mv Node.GetOrig Node.Orig

        mv Node.Type Node.typ
        mv Node.GetType Node.Type

        mv Node.Func Node.fn
        mv Node.GetFunc Node.Func

        mv Node.Name Node.name
        mv Node.GetName Node.Name

        # All uses are in other Node methods already.
        mv Node.E Node.e

        mv Node.Sym Node.sym
        mv Node.GetSym Node.Sym

        mv Node.Pos Node.pos
        mv Node.GetPos Node.Pos

        mv Node.Esc Node.esc
        mv Node.GetEsc Node.Esc

	# While we are here, rename Xoffset to more idiomatic Offset.
        mv Node.Xoffset Node.offset
        mv Node.GetXoffset Node.Offset
	mv Node.SetXoffset Node.SetOffset

        # While we are here, rename Ninit, Nbody to more idiomatic Init, Body.
        mv Node.Ninit Node.init
        mv Node.GetNinit Node.Init
        mv Node.PtrNinit Node.PtrInit
        mv Node.SetNinit Node.SetInit
        mv Node.Nbody Node.body
        mv Node.GetNbody Node.Body
        mv Node.PtrNbody Node.PtrBody
        mv Node.SetNbody Node.SetBody
        mv Node.List Node.list
        mv Node.GetList Node.List
        mv Node.Rlist Node.rlist
        mv Node.GetRlist Node.Rlist

        # Unexport these
        mv Node.SetHasOpt Node.setHasOpt
        mv Node.SetHasVal Node.setHasVal
'

Change-Id: I9894f633375c5237a29b6d6d7b89ba181b56ca3a
Reviewed-on: https://go-review.googlesource.com/c/go/+/273009
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-11-25 17:30:39 +00:00
Russ Cox
84e2bd611f [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-25 16:53:33 +00:00
Russ Cox
26b66fd60b [dev.regabi] cmd/compile: introduce cmd/compile/internal/base [generated]
Move Flag, Debug, Ctxt, Exit, and error messages to
new package cmd/compile/internal/base.

These are the core functionality that everything in gc uses
and which otherwise prevent splitting any other code
out of gc into different packages.

A minor milestone: the compiler source code
no longer contains the string "yy".

[git-generate]
cd src/cmd/compile/internal/gc
rf '
        mv atExit AtExit
        mv Ctxt atExitFuncs AtExit Exit base.go

        mv lineno Pos
        mv linestr FmtPos
        mv flusherrors FlushErrors
        mv yyerror Errorf
        mv yyerrorl ErrorfAt
        mv yyerrorv ErrorfVers
        mv noder.yyerrorpos noder.errorAt
        mv Warnl WarnfAt
        mv errorexit ErrorExit

        mv base.go debug.go flag.go print.go cmd/compile/internal/base
'

: # update comments
sed -i '' 's/yyerrorl/ErrorfAt/g; s/yyerror/Errorf/g' *.go

: # bootstrap.go is not built by default so invisible to rf
sed -i '' 's/Fatalf/base.Fatalf/' bootstrap.go
goimports -w bootstrap.go

: # update cmd/dist to add internal/base
cd ../../../dist
sed -i '' '/internal.amd64/a\
	"cmd/compile/internal/base",
' buildtool.go
gofmt -w buildtool.go

Change-Id: I59903c7084222d6eaee38823fd222159ba24a31a
Reviewed-on: https://go-review.googlesource.com/c/go/+/272250
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-11-25 16:39:54 +00:00
Russ Cox
3c240f5d17 [dev.regabi] cmd/compile: clean up debug flag (-d) handling [generated]
The debug table is not as haphazard as flags, but there are still
a few mismatches between command-line names and variable names.
This CL moves them all into a consistent home (var Debug, like var Flag).

Code updated automatically using the rf command below.
A followup CL will make a few manual cleanups, leaving this CL
completely automated and easier to regenerate during merge
conflicts.

[git-generate]
cd src/cmd/compile/internal/gc
rf '
	add main.go var Debug struct{}
	mv Debug_append Debug.Append
	mv Debug_checkptr Debug.Checkptr
	mv Debug_closure Debug.Closure
	mv Debug_compilelater Debug.CompileLater
	mv disable_checknil Debug.DisableNil
	mv debug_dclstack Debug.DclStack
	mv Debug_gcprog Debug.GCProg
	mv Debug_libfuzzer Debug.Libfuzzer
	mv Debug_checknil Debug.Nil
	mv Debug_panic Debug.Panic
	mv Debug_slice Debug.Slice
	mv Debug_typeassert Debug.TypeAssert
	mv Debug_wb Debug.WB
	mv Debug_export Debug.Export
	mv Debug_pctab Debug.PCTab
	mv Debug_locationlist Debug.LocationLists
	mv Debug_typecheckinl Debug.TypecheckInl
	mv Debug_gendwarfinl Debug.DwarfInl
	mv Debug_softfloat Debug.SoftFloat
	mv Debug_defer Debug.Defer
	mv Debug_dumpptrs Debug.DumpPtrs

	mv flag.go:/parse.-d/-1,/unknown.debug/+2 parseDebug

	mv debugtab Debug parseDebug \
		debugHelpHeader debugHelpFooter \
		debug.go

	# Remove //go:generate line copied from main.go
	rm debug.go:/go:generate/-+
'

Change-Id: I625761ca5659be4052f7161a83baa00df75cca91
Reviewed-on: https://go-review.googlesource.com/c/go/+/272246
Trust: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-11-25 16:39:42 +00:00
Russ Cox
18573aea3c [dev.regabi] cmd/compile: clean up flag handling [generated]
The flag values have grown fairly haphazard, with no organization
or even common naming convention. This CL moves all flag values
into the Flag struct (formerly misnamed Debug), except for a few
that live in Ctxt fields instead.

This CL is entirely automated changes.
A followup CL will make a few manual cleanups, leaving this CL
completely automated and easier to regenerate during merge
conflicts.

Cleaning up flags is necessary because the printing routines
look at some of them, and the printing routines need to move
out of package gc to a new package shared by gc and any
other packages that split out of gc.

[git-generate]

cd src/cmd/compile/internal/gc
rf '
	mv Debug Flag
	mv DebugFlags Flags
	mv Flags.e Flags.LowerE
	mv Flags.h Flags.LowerH
	mv Flags.j Flags.LowerJ
	mv Flags.l Flags.LowerL
	mv Flags.m Flags.LowerM
	mv Flags.r Flags.LowerR
	mv Flags.w Flags.LowerW
	mv Flags.P Flags.Percent
	mv compiling_runtime Flag.CompilingRuntime
	mv compiling_std Flag.Std
	mv localimport Flag.D
	mv asmhdr Flag.AsmHdr
	mv buildid Flag.BuildID
	mv nBackendWorkers Flag.LowerC
	mv pure_go Flag.Complete
	mv debugstr Flag.LowerD
	mv flagDWARF Flag.Dwarf
	mv genDwarfInline Flag.GenDwarfInl
	mv flag_installsuffix Flag.InstallSuffix
	mv flag_lang Flag.Lang
	mv linkobj Flag.LinkObj
	mv debuglive Flag.Live
	mv flag_msan Flag.MSan
	mv nolocalimports Flag.NoLocalImports
	mv outfile Flag.LowerO
	mv myimportpath Ctxt.Pkgpath
	mv writearchive Flag.Pack
	mv flag_race Flag.Race
	mv spectre Flag.Spectre
	mv trace Flag.LowerT
	mv pathPrefix Flag.TrimPath
	mv Debug_vlog Ctxt.Debugvlog
	mv use_writebarrier Flag.WB
	mv Main.flag_shared Flag.Shared
	mv Main.flag_dynlink Flag.Dynlink
	mv Main.goversion Flag.GoVersion
	mv Main.symabisPath Flag.SymABIs
	mv cpuprofile Flag.CPUProfile
	mv memprofile Flag.MemProfile
	mv traceprofile Flag.TraceProfile
	mv blockprofile Flag.BlockProfile
	mv mutexprofile Flag.MutexProfile
	mv benchfile Flag.Bench
	mv Main.smallFrames Flag.SmallFrames
	mv Main.jsonLogOpt Flag.JSON

	add Flag:$ \
		Cfg struct{}
	mv embedCfg Flag.Cfg.Embed
	mv idirs Flag.Cfg.ImportDirs
	mv importMap Flag.Cfg.ImportMap
	mv packageFile Flag.Cfg.PackageFile
	mv spectreIndex Flag.Cfg.SpectreIndex

	mv addidir addImportDir

	mv main.go:/Wasm/-0,/ssaDump/-3 ParseFlags

	mv usage Flag Flags ParseFlags \
		concurrentFlagOk concurrentBackendAllowed \
		addImportDir addImportMap \
		readImportCfg readEmbedCfg \
		flag.go

	# Remove //go:generate line copied from main.go
	# along with two self-assignments from the merge.
	rm flag.go:/go:generate/-+ \
		flag.go:/Ctxt.Pkgpath = Ctxt.Pkgpath/-+ \
		flag.go:/Ctxt.Debugvlog = Ctxt.Debugvlog/-+
'

Change-Id: I10431c15fe7d9f48024d53141d4224d957dbf334
Reviewed-on: https://go-review.googlesource.com/c/go/+/271667
Trust: Russ Cox <rsc@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-11-25 15:08:55 +00:00
Matthew Dempsky
c754f25241 [dev.regabi] cmd/compile/internal/types: remove Func.Nname
Now that there's no code remaining that uses Func.Nname, we can get
rid of it along with the remaining code that uselessly assigns to it.

Passes toolstash-check.

Change-Id: I104ab3bb5122fb824c741bc6e4d9d54fefe5646e
Reviewed-on: https://go-review.googlesource.com/c/go/+/272390
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-11-24 01:34:39 +00:00
Matthew Dempsky
e1047302bd [dev.regabi] cmd/compile/internal/types: add pos/sym/typ params to NewField
These are almost always set, so might as well expect callers to
provide them. They're also all required by go/types's corresponding
New{Field,Func,Param,Var} functions, so this eases API compatibility.

Passes toolstash-check.

Change-Id: Ib3fa355d4961243cd285b41915e87652ae2c22f6
Reviewed-on: https://go-review.googlesource.com/c/go/+/272386
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-11-24 01:33:25 +00:00
Cherry Zhang
86954d5246 cmd/compile: mark plugin-exported types as used in interface
Plugin exports symbols as interfaces. Mark their types as used in
interfaces, so their methods will be kept alive by the linker.

Fixes #42579.

Change-Id: If1b5aacc21510c20c25f88bb131bca61db6f1d56
Reviewed-on: https://go-review.googlesource.com/c/go/+/269819
Trust: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
2020-11-13 22:01:37 +00:00
Cuong Manh Le
642329fdd5 Revert "cmd/compile: split exported/non-exported methods for interface type"
This reverts commit 8f26b57f9a.

Reason for revert: break a bunch of code, include standard library.

Fixes #42123

Change-Id: Ife90ecbafd2cb395623d1db555fbfc9c1b0098e0
Reviewed-on: https://go-review.googlesource.com/c/go/+/264026
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
2020-10-28 17:10:08 +00:00
Cuong Manh Le
8f26b57f9a cmd/compile: split exported/non-exported methods for interface type
Currently, mhdr/methods is emitted with the same len/cap. There's no way
to distinguish between exported and non-exported methods statically.

This CL splits mhdr/methods into two parts, use "len" for number of
exported methods, and "cap" for all methods. This fixes the bug in
issue #22075, which intends to return the number of exported methods but
currently return all methods.

Note that with this encoding, we still can access either
all/exported-only/non-exported-only methods:

	mhdr[:cap(mhdr)]          // all methods
	mhdr                      // exported methods
	mhdr[len(mhdr):cap(mhdr)] // non-exported methods

Thank to Matthew Dempsky (@mdempsky) for suggesting this encoding.

Fixes #22075

Change-Id: If662adb03ccff27407d55a5578a0ed05a15e7cdd
Reviewed-on: https://go-review.googlesource.com/c/go/+/259237
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-10-09 02:14:32 +00:00
Cherry Zhang
66770f4b1d cmd/compile: mark type namedata symbols content-addressable
Type namedata symbols are for type/field/method names and package
paths. We can use content-addressable symbol mechanism for them.

Change-Id: I923fda17b7094c7a0e46aad7c450622eb3826294
Reviewed-on: https://go-review.googlesource.com/c/go/+/257960
Trust: Cherry Zhang <cherryyz@google.com>
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
2020-09-29 17:25:24 +00:00
Cherry Zhang
39dde09126 cmd/link: retain only used interface methods
Currently, in the linker's deadcode pass, when an interface type
is live, the linker thinks all its methods are live, and uses
them to match methods on concrete types. The interface method may
never be used, though.

This CL changes it to only keep used interface methods, for
matching concrete type methods. To do that, when an interface
method is used, the compiler generates a mark relocation. The
linker uses the marker relocations to mark used interface
methods, and only the used ones.

binary size    before      after
cmd/compile   18887400   18812200
cmd/go        13470652   13470492

Change-Id: I3cfd9df4a53783330ba87735853f2a0ec3c42802
Reviewed-on: https://go-review.googlesource.com/c/go/+/256798
Trust: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
2020-09-29 16:30:26 +00:00
Keith Randall
623652e73f cmd/compile: make Haspointers a method instead of a function
More ergonomic that way. Also change Haspointers to HasPointers
while we are here.

Change-Id: I45bedc294c1a8c2bd01dc14bd04615ae77555375
Reviewed-on: https://go-review.googlesource.com/c/go/+/249959
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2020-08-23 18:33:55 +00:00
Cherry Zhang
db924fd99e [dev.link] cmd/compile, cmd/link: generate itablink at link time
Currently, at compile time, for each itab symbol, we create an
"itablink" symbol which holds solely the address of the itab
symbol. At link time, all the itablink symbols are grouped
together to form the itablinks slice.

This CL removes the itablink symbols, and directly generate the
itablinks slice in the linker. This removes a number of symbols,
which are dupOK and generally have long names. And also removes
a special handling of itablink symbols in the deadcode pass which
iterates through all symbols.

Change-Id: I475c3c8899e9fbeec9abc7647b1e4a69aa5c3c5a
Reviewed-on: https://go-review.googlesource.com/c/go/+/245901
Reviewed-by: Jeremy Faller <jeremy@golang.org>
2020-08-03 21:13:25 +00:00
Cherry Zhang
cecb7a1cf3 [dev.link] cmd/compile, cmd/link: make itab symbols content-addressable
Extend the content-addressable symbol mechanism to itab symbols.
Itab symbols require global uniqueness (as at run time we compare
pointers), so it needs to be reliably deduplicated. Currently the
content hash depends on symbol name expansion, so we can only do
this when all Go packages are built with know package paths. Fall
back to checking names if any Go package is built with unknown
package path.

Change-Id: Icf5e8873755050c20e5fc6549f6de1c883254c89
Reviewed-on: https://go-review.googlesource.com/c/go/+/245719
Reviewed-by: Jeremy Faller <jeremy@golang.org>
2020-08-03 21:12:28 +00:00
Cherry Zhang
69748f0ce4 [dev.link] cmd/compile, cmd/link: reference type symbol of defined type by index
The type descriptor symbol of a defined (named) type (and pointer
to it) is defined only in the package that defines the type. It
is not dupOK, unlike other type descriptors. So it can be
referenced by index. Currently it is referenced by name for
cross-package references, because the index is not exported and
so not known to the referencing package.

This CL passes the index through the export data, so the symbol
can be referenced by index, and does not need to be looked up by
name. This also makes such symbol references consistent: it is
referenced by index within the defining package and also cross-
package, which makes it easier for content hashing (in later CLs).

One complication is that we need to set flags on referenced
symbols (specifically, the UsedInIface flag). Before, they are
non-package refs, which naturally carry flags in the object file.
For indexed refs, we currently don't put their flags in the
object file. Introduce a new block for this.

Change-Id: I8126f8e318ac4e6609eb2ac136201fd6c264c256
Reviewed-on: https://go-review.googlesource.com/c/go/+/245718
Reviewed-by: Jeremy Faller <jeremy@golang.org>
2020-08-03 21:11:33 +00:00
Cherry Zhang
17344d55d6 [dev.link] cmd/compile: make GC map symbols content-addressable
Change-Id: I20e5b580b3e0505473816fe7f277a74e13d33e64
Reviewed-on: https://go-review.googlesource.com/c/go/+/242080
Reviewed-by: Jeremy Faller <jeremy@golang.org>
2020-07-16 18:44:15 +00:00
Dan Scales
be64a19d99 cmd/compile, cmd/link, runtime: make defers low-cost through inline code and extra funcdata
Generate inline code at defer time to save the args of defer calls to unique
(autotmp) stack slots, and generate inline code at exit time to check which defer
calls were made and make the associated function/method/interface calls. We
remember that a particular defer statement was reached by storing in the deferBits
variable (always stored on the stack). At exit time, we check the bits of the
deferBits variable to determine which defer function calls to make (in reverse
order). These low-cost defers are only used for functions where no defers
appear in loops. In addition, we don't do these low-cost defers if there are too
many defer statements or too many exits in a function (to limit code increase).

When a function uses open-coded defers, we produce extra
FUNCDATA_OpenCodedDeferInfo information that specifies the number of defers, and
for each defer, the stack slots where the closure and associated args have been
stored. The funcdata also includes the location of the deferBits variable.
Therefore, for panics, we can use this funcdata to determine exactly which defers
are active, and call the appropriate functions/methods/closures with the correct
arguments for each active defer.

In order to unwind the stack correctly after a recover(), we need to add an extra
code segment to functions with open-coded defers that simply calls deferreturn()
and returns. This segment is not reachable by the normal function, but is returned
to by the runtime during recovery. We set the liveness information of this
deferreturn() to be the same as the liveness at the first function call during the
last defer exit code (so all return values and all stack slots needed by the defer
calls will be live).

I needed to increase the stackguard constant from 880 to 896, because of a small
amount of new code in deferreturn().

The -N flag disables open-coded defers. '-d defer' prints out the kind of defer
being used at each defer statement (heap-allocated, stack-allocated, or
open-coded).

Cost of defer statement  [ go test -run NONE -bench BenchmarkDefer$ runtime ]
  With normal (stack-allocated) defers only:         35.4  ns/op
  With open-coded defers:                             5.6  ns/op
  Cost of function call alone (remove defer keyword): 4.4  ns/op

Text size increase (including funcdata) for go binary without/with open-coded defers:  0.09%

The average size increase (including funcdata) for only the functions that use
open-coded defers is 1.1%.

The cost of a panic followed by a recover got noticeably slower, since panic
processing now requires a scan of the stack for open-coded defer frames. This scan
is required, even if no frames are using open-coded defers:

Cost of panic and recover [ go test -run NONE -bench BenchmarkPanicRecover runtime ]
  Without open-coded defers:        62.0 ns/op
  With open-coded defers:           255  ns/op

A CGO Go-to-C-to-Go benchmark got noticeably faster because of open-coded defers:

CGO Go-to-C-to-Go benchmark [cd misc/cgo/test; go test -run NONE -bench BenchmarkCGoCallback ]
  Without open-coded defers:        443 ns/op
  With open-coded defers:           347 ns/op

Updates #14939 (defer performance)
Updates #34481 (design doc)

Change-Id: I63b1a60d1ebf28126f55ee9fd7ecffe9cb23d1ff
Reviewed-on: https://go-review.googlesource.com/c/go/+/202340
Reviewed-by: Austin Clements <austin@google.com>
2019-10-24 13:54:11 +00:00
Cuong Manh Le
ba97d0d84d cmd/compile: remove overflow pointer padding for nacl
CL 200077 removed nacl bits in the toolchain, but it misses the code to
add pointer overflow padding, which is specific for nacl.

This CL removes that part.

Passes toolstash-check.

Updates #30439

Change-Id: I1e77cade9f31690e16cd13d3445a98b500671252
Reviewed-on: https://go-review.googlesource.com/c/go/+/202159
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2019-10-21 19:04:47 +00:00
Bryan C. Mills
b76e6f8825 Revert "cmd/compile, cmd/link, runtime: make defers low-cost through inline code and extra funcdata"
This reverts CL 190098.

Reason for revert: broke several builders.

Change-Id: I69161352f9ded02537d8815f259c4d391edd9220
Reviewed-on: https://go-review.googlesource.com/c/go/+/201519
Run-TryBot: Bryan C. Mills <bcmills@google.com>
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: Dan Scales <danscales@google.com>
2019-10-16 20:59:53 +00:00
Dan Scales
dad616375f cmd/compile, cmd/link, runtime: make defers low-cost through inline code and extra funcdata
Generate inline code at defer time to save the args of defer calls to unique
(autotmp) stack slots, and generate inline code at exit time to check which defer
calls were made and make the associated function/method/interface calls. We
remember that a particular defer statement was reached by storing in the deferBits
variable (always stored on the stack). At exit time, we check the bits of the
deferBits variable to determine which defer function calls to make (in reverse
order). These low-cost defers are only used for functions where no defers
appear in loops. In addition, we don't do these low-cost defers if there are too
many defer statements or too many exits in a function (to limit code increase).

When a function uses open-coded defers, we produce extra
FUNCDATA_OpenCodedDeferInfo information that specifies the number of defers, and
for each defer, the stack slots where the closure and associated args have been
stored. The funcdata also includes the location of the deferBits variable.
Therefore, for panics, we can use this funcdata to determine exactly which defers
are active, and call the appropriate functions/methods/closures with the correct
arguments for each active defer.

In order to unwind the stack correctly after a recover(), we need to add an extra
code segment to functions with open-coded defers that simply calls deferreturn()
and returns. This segment is not reachable by the normal function, but is returned
to by the runtime during recovery. We set the liveness information of this
deferreturn() to be the same as the liveness at the first function call during the
last defer exit code (so all return values and all stack slots needed by the defer
calls will be live).

I needed to increase the stackguard constant from 880 to 896, because of a small
amount of new code in deferreturn().

The -N flag disables open-coded defers. '-d defer' prints out the kind of defer
being used at each defer statement (heap-allocated, stack-allocated, or
open-coded).

Cost of defer statement  [ go test -run NONE -bench BenchmarkDefer$ runtime ]
  With normal (stack-allocated) defers only:         35.4  ns/op
  With open-coded defers:                             5.6  ns/op
  Cost of function call alone (remove defer keyword): 4.4  ns/op

Text size increase (including funcdata) for go cmd without/with open-coded defers:  0.09%

The average size increase (including funcdata) for only the functions that use
open-coded defers is 1.1%.

The cost of a panic followed by a recover got noticeably slower, since panic
processing now requires a scan of the stack for open-coded defer frames. This scan
is required, even if no frames are using open-coded defers:

Cost of panic and recover [ go test -run NONE -bench BenchmarkPanicRecover runtime ]
  Without open-coded defers:        62.0 ns/op
  With open-coded defers:           255  ns/op

A CGO Go-to-C-to-Go benchmark got noticeably faster because of open-coded defers:

CGO Go-to-C-to-Go benchmark [cd misc/cgo/test; go test -run NONE -bench BenchmarkCGoCallback ]
  Without open-coded defers:        443 ns/op
  With open-coded defers:           347 ns/op

Updates #14939 (defer performance)
Updates #34481 (design doc)

Change-Id: I51a389860b9676cfa1b84722f5fb84d3c4ee9e28
Reviewed-on: https://go-review.googlesource.com/c/go/+/190098
Reviewed-by: Austin Clements <austin@google.com>
2019-10-16 18:27:16 +00:00
Matthew Dempsky
46be01f4e0 cmd/compile: remove Addable flag
This flag is supposed to indicate whether the expression is
"addressable"; but in practice, we infer this from other
attributes about the expression (e.g., n.Op and n.Class()).

Passes toolstash-check.

Change-Id: I19352ca07ab5646e232d98e8a7c1c9aec822ddd0
Reviewed-on: https://go-review.googlesource.com/c/go/+/200897
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2019-10-13 01:48:30 +00:00
Keith Randall
36f30ba289 cmd/compile,runtime: generate hash functions only for types which are map keys
Right now we generate hash functions for all types, just in case they
are used as map keys. That's a lot of wasted effort and binary size
for types which will never be used as a map key. Instead, generate
hash functions only for types that we know are map keys.

Just doing that is a bit too simple, since maps with an interface type
as a key might have to hash any concrete key type that implements that
interface. So for that case, implement hashing of such types at
runtime (instead of with generated code). It will be slower, but only
for maps with interface types as keys, and maybe only a bit slower as
the aeshash time probably dominates the dispatch time.

Reorg where we keep the equals and hash functions. Move the hash function
from the key type to the map type, saving a field in every non-map type.
That leaves only one function in the alg structure, so get rid of that and
just keep the equal function in the type descriptor itself.

cmd/go now has 10 generated hash functions, instead of 504. Makes
cmd/go 1.0% smaller. Update #6853.

Speed on non-interface keys is unchanged. Speed on interface keys
is ~20% slower:

name                  old time/op  new time/op  delta
MapInterfaceString-8  23.0ns ±21%  27.6ns ±14%  +20.01%  (p=0.002 n=10+10)
MapInterfacePtr-8     19.4ns ±16%  23.7ns ± 7%  +22.48%   (p=0.000 n=10+8)

Change-Id: I7c2e42292a46b5d4e288aaec4029bdbb01089263
Reviewed-on: https://go-review.googlesource.com/c/go/+/191198
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Martin Möhrmann <moehrmann@google.com>
2019-09-03 20:41:29 +00:00
Keith Randall
fbde753a58 cmd/compile: make duplicate anonymous interface output deterministic
Taking over CL 162240, the original CL hasn't been making progress.
I just took the parts that fix the immediate issue. I left the
signatslice changes out, I don't think they are necessary.

Fixes #30202

Change-Id: I5b347605f0841dd925d5a73150b8bf269fa82464
Reviewed-on: https://go-review.googlesource.com/c/go/+/183852
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2019-07-02 13:52:21 +00:00
Keith Randall
343b7fa626 cmd/compile: don't mark argument array as noalg
It ends up making two similar types, [N]uint8 of both
alg and noalg varieties. Comparsions between the two then
don't come out equal when they should.
In particular, the type *[N]uint8 has an Elem pointer which
must point to one of the above two types; it can't point to both.
Thus allocating a *[N]uint8 and dereferencing it might be a
different type than a [N]uint8.

The fix is easy. Making a small test for this is really hard. It
requires that both a argless defer and the test be imported by a
common parent package. This is why a main binary doesn't see this
issue, but a test does (as Agniva noticed), because there's a wrapper
package that imports both the test and the defer.

Types like [N]uint8 don't really need to be marked noalg anyway,
as the generated code (if any) will be shared among all
vanilla memory types of the same size.

Fixes #32595

Change-Id: If7b77fa6ed56cd4495601c3f90170682d853b82f
Reviewed-on: https://go-review.googlesource.com/c/go/+/182357
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Emmanuel Odeke <emm.odeke@gmail.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2019-06-25 21:30:39 +00:00
Keith Randall
8f296f59de Revert "Revert "cmd/compile,runtime: allocate defer records on the stack""
This reverts CL 180761

Reason for revert: Reinstate the stack-allocated defer CL.

There was nothing wrong with the CL proper, but stack allocation of defers exposed two other issues.

Issue #32477: Fix has been submitted as CL 181258.
Issue #32498: Possible fix is CL 181377 (not submitted yet).

Change-Id: I32b3365d5026600069291b068bbba6cb15295eb3
Reviewed-on: https://go-review.googlesource.com/c/go/+/181378
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2019-06-10 16:19:39 +00:00
Keith Randall
49200e3f3e Revert "cmd/compile,runtime: allocate defer records on the stack"
This reverts commit fff4f599fe.

Reason for revert: Seems to still have issues around GC.

Fixes #32452

Change-Id: Ibe7af629f9ad6a3d5312acd7b066123f484da7f0
Reviewed-on: https://go-review.googlesource.com/c/go/+/180761
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
2019-06-05 19:50:09 +00:00
Keith Randall
fff4f599fe cmd/compile,runtime: allocate defer records on the stack
When a defer is executed at most once in a function body,
we can allocate the defer record for it on the stack instead
of on the heap.

This should make defers like this (which are very common) faster.

This optimization applies to 363 out of the 370 static defer sites
in the cmd/go binary.

name     old time/op  new time/op  delta
Defer-4  52.2ns ± 5%  36.2ns ± 3%  -30.70%  (p=0.000 n=10+10)

Fixes #6980
Update #14939

Change-Id: I697109dd7aeef9e97a9eeba2ef65ff53d3ee1004
Reviewed-on: https://go-review.googlesource.com/c/go/+/171758
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2019-06-04 17:35:20 +00:00
Josh Bleecher Snyder
73cb9a1cb3 all: refer to map elements as elements instead of values
The spec carefully and consistently uses "key" and "element"
as map terminology. The implementation, not so much.

This change attempts to make the implementation consistently
hew to the spec's terminology. Beyond consistency, this has
the advantage of avoid some confusion and naming collisions,
since v and value are very generic and commonly used terms.

I believe that I found all everything, but there are a lot of
non-obvious places for these to hide, and grepping for them is hard.
Hopefully this change changes enough of them that we will start using
elem going forward. Any remaining hidden cases can be removed ad hoc
as they are discovered.

The only externally-facing part of this change is in package reflect,
where there is a minor doc change and a function parameter name change.

Updates #27167

Change-Id: I2f2d78f16c360dc39007b9966d5c2046a29d3701
Reviewed-on: https://go-review.googlesource.com/c/go/+/174523
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2019-04-30 18:18:12 +00:00
Keith Randall
db16de9203 runtime: remove kindNoPointers
We already have the ptrdata field in a type, which encodes exactly
the same information that kindNoPointers does.

My problem with kindNoPointers is that it often leads to
double-negative code like:

   t.kind & kindNoPointers != 0

Much clearer is:

   t.ptrdata == 0

Update #27167

Change-Id: I92307d7f018a6bbe3daca4a4abb4225e359349b1
Reviewed-on: https://go-review.googlesource.com/c/go/+/169157
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
2019-03-25 20:46:35 +00:00
Daniel Martí
49662bc6b0 all: simplify multiple for loops
If a for loop has a simple condition and begins with a simple
"if x { break; }"; we can simply add "!x" to the loop's condition.

While at it, simplify a few assignments to use the common pattern
"x := staticDefault; if cond { x = otherValue(); }".

Finally, simplify a couple of var declarations.

Change-Id: I413982c6abd32905adc85a9a666cb3819139c19f
Reviewed-on: https://go-review.googlesource.com/c/go/+/165342
Run-TryBot: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2019-03-08 14:29:19 +00:00