mirror of
https://github.com/golang/go
synced 2024-11-26 02:07:57 -07:00
cmd: remove GOEXPERIMENT=nounified knob
This CL removes the GOEXPERIMENT=nounified knob, and any conditional statements that depend on that knob. Further CLs to remove unreachable code follow this one. Updates #57410. Change-Id: I39c147e1a83601c73f8316a001705778fee64a91 Reviewed-on: https://go-review.googlesource.com/c/go/+/458615 Run-TryBot: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Cherry Mui <cherryyz@google.com>
This commit is contained in:
parent
3d49b683c6
commit
4f467f1082
@ -47,7 +47,6 @@ type DebugFlags struct {
|
|||||||
SyncFrames int `help:"how many writer stack frames to include at sync points in unified export data"`
|
SyncFrames int `help:"how many writer stack frames to include at sync points in unified export data"`
|
||||||
TypeAssert int `help:"print information about type assertion inlining"`
|
TypeAssert int `help:"print information about type assertion inlining"`
|
||||||
TypecheckInl int `help:"eager typechecking of inline function bodies" concurrent:"ok"`
|
TypecheckInl int `help:"eager typechecking of inline function bodies" concurrent:"ok"`
|
||||||
Unified int `help:"enable unified IR construction"`
|
|
||||||
WB int `help:"print information about write barriers"`
|
WB int `help:"print information about write barriers"`
|
||||||
ABIWrap int `help:"print information about ABI wrapper generation"`
|
ABIWrap int `help:"print information about ABI wrapper generation"`
|
||||||
MayMoreStack string `help:"call named function before all stack growth checks" concurrent:"ok"`
|
MayMoreStack string `help:"call named function before all stack growth checks" concurrent:"ok"`
|
||||||
|
@ -167,9 +167,6 @@ func ParseFlags() {
|
|||||||
Debug.ConcurrentOk = true
|
Debug.ConcurrentOk = true
|
||||||
Debug.InlFuncsWithClosures = 1
|
Debug.InlFuncsWithClosures = 1
|
||||||
Debug.InlStaticInit = 1
|
Debug.InlStaticInit = 1
|
||||||
if buildcfg.Experiment.Unified {
|
|
||||||
Debug.Unified = 1
|
|
||||||
}
|
|
||||||
Debug.SyncFrames = -1 // disable sync markers by default
|
Debug.SyncFrames = -1 // disable sync markers by default
|
||||||
|
|
||||||
Debug.Checkptr = -1 // so we can tell whether it is set explicitly
|
Debug.Checkptr = -1 // so we can tell whether it is set explicitly
|
||||||
|
@ -57,58 +57,52 @@ func Call(call *ir.CallExpr) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if base.Debug.Unified != 0 {
|
// If typ is a shape type, then it was a type argument originally
|
||||||
// N.B., stencil.go converts shape-typed values to interface type
|
// and we'd need an indirect call through the dictionary anyway.
|
||||||
// using OEFACE instead of OCONVIFACE, so devirtualization fails
|
// We're unable to devirtualize this call.
|
||||||
// above instead. That's why this code is specific to unified IR.
|
if typ.IsShape() {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// If typ is a shape type, then it was a type argument originally
|
// If typ *has* a shape type, then it's an shaped, instantiated
|
||||||
// and we'd need an indirect call through the dictionary anyway.
|
// type like T[go.shape.int], and its methods (may) have an extra
|
||||||
// We're unable to devirtualize this call.
|
// dictionary parameter. We could devirtualize this call if we
|
||||||
if typ.IsShape() {
|
// could derive an appropriate dictionary argument.
|
||||||
return
|
//
|
||||||
|
// TODO(mdempsky): If typ has has a promoted non-generic method,
|
||||||
|
// then that method won't require a dictionary argument. We could
|
||||||
|
// still devirtualize those calls.
|
||||||
|
//
|
||||||
|
// TODO(mdempsky): We have the *runtime.itab in recv.TypeWord. It
|
||||||
|
// should be possible to compute the represented type's runtime
|
||||||
|
// dictionary from this (e.g., by adding a pointer from T[int]'s
|
||||||
|
// *runtime._type to .dict.T[int]; or by recognizing static
|
||||||
|
// references to go:itab.T[int],iface and constructing a direct
|
||||||
|
// reference to .dict.T[int]).
|
||||||
|
if typ.HasShape() {
|
||||||
|
if base.Flag.LowerM != 0 {
|
||||||
|
base.WarnfAt(call.Pos(), "cannot devirtualize %v: shaped receiver %v", call, typ)
|
||||||
}
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// If typ *has* a shape type, then it's an shaped, instantiated
|
// Further, if sel.X's type has a shape type, then it's a shaped
|
||||||
// type like T[go.shape.int], and its methods (may) have an extra
|
// interface type. In this case, the (non-dynamic) TypeAssertExpr
|
||||||
// dictionary parameter. We could devirtualize this call if we
|
// we construct below would attempt to create an itab
|
||||||
// could derive an appropriate dictionary argument.
|
// corresponding to this shaped interface type; but the actual
|
||||||
//
|
// itab pointer in the interface value will correspond to the
|
||||||
// TODO(mdempsky): If typ has has a promoted non-generic method,
|
// original (non-shaped) interface type instead. These are
|
||||||
// then that method won't require a dictionary argument. We could
|
// functionally equivalent, but they have distinct pointer
|
||||||
// still devirtualize those calls.
|
// identities, which leads to the type assertion failing.
|
||||||
//
|
//
|
||||||
// TODO(mdempsky): We have the *runtime.itab in recv.TypeWord. It
|
// TODO(mdempsky): We know the type assertion here is safe, so we
|
||||||
// should be possible to compute the represented type's runtime
|
// could instead set a flag so that walk skips the itab check. For
|
||||||
// dictionary from this (e.g., by adding a pointer from T[int]'s
|
// now, punting is easy and safe.
|
||||||
// *runtime._type to .dict.T[int]; or by recognizing static
|
if sel.X.Type().HasShape() {
|
||||||
// references to go:itab.T[int],iface and constructing a direct
|
if base.Flag.LowerM != 0 {
|
||||||
// reference to .dict.T[int]).
|
base.WarnfAt(call.Pos(), "cannot devirtualize %v: shaped interface %v", call, sel.X.Type())
|
||||||
if typ.HasShape() {
|
|
||||||
if base.Flag.LowerM != 0 {
|
|
||||||
base.WarnfAt(call.Pos(), "cannot devirtualize %v: shaped receiver %v", call, typ)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Further, if sel.X's type has a shape type, then it's a shaped
|
|
||||||
// interface type. In this case, the (non-dynamic) TypeAssertExpr
|
|
||||||
// we construct below would attempt to create an itab
|
|
||||||
// corresponding to this shaped interface type; but the actual
|
|
||||||
// itab pointer in the interface value will correspond to the
|
|
||||||
// original (non-shaped) interface type instead. These are
|
|
||||||
// functionally equivalent, but they have distinct pointer
|
|
||||||
// identities, which leads to the type assertion failing.
|
|
||||||
//
|
|
||||||
// TODO(mdempsky): We know the type assertion here is safe, so we
|
|
||||||
// could instead set a flag so that walk skips the itab check. For
|
|
||||||
// now, punting is easy and safe.
|
|
||||||
if sel.X.Type().HasShape() {
|
|
||||||
if base.Flag.LowerM != 0 {
|
|
||||||
base.WarnfAt(call.Pos(), "cannot devirtualize %v: shaped interface %v", call, sel.X.Type())
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
dt := ir.NewTypeAssertExpr(sel.Pos(), sel.X, nil)
|
dt := ir.NewTypeAssertExpr(sel.Pos(), sel.X, nil)
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"cmd/compile/internal/types2"
|
"cmd/compile/internal/types2"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/build"
|
"go/build"
|
||||||
"internal/goexperiment"
|
|
||||||
"internal/testenv"
|
"internal/testenv"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
@ -98,7 +97,7 @@ func TestImportTestdata(t *testing.T) {
|
|||||||
"exports.go": {"go/ast", "go/token"},
|
"exports.go": {"go/ast", "go/token"},
|
||||||
"generics.go": nil,
|
"generics.go": nil,
|
||||||
}
|
}
|
||||||
if goexperiment.Unified {
|
if true /* was goexperiment.Unified */ {
|
||||||
// TODO(mdempsky): Fix test below to flatten the transitive
|
// TODO(mdempsky): Fix test below to flatten the transitive
|
||||||
// Package.Imports graph. Unified IR is more precise about
|
// Package.Imports graph. Unified IR is more precise about
|
||||||
// recreating the package import graph.
|
// recreating the package import graph.
|
||||||
@ -343,8 +342,12 @@ func verifyInterfaceMethodRecvs(t *testing.T, named *types2.Named, level int) {
|
|||||||
// The unified IR importer always sets interface method receiver
|
// The unified IR importer always sets interface method receiver
|
||||||
// parameters to point to the Interface type, rather than the Named.
|
// parameters to point to the Interface type, rather than the Named.
|
||||||
// See #49906.
|
// See #49906.
|
||||||
|
//
|
||||||
|
// TODO(mdempsky): This is only true for the types2 importer. For
|
||||||
|
// the go/types importer, we duplicate the Interface and rewrite its
|
||||||
|
// receiver methods to match historical behavior.
|
||||||
var want types2.Type = named
|
var want types2.Type = named
|
||||||
if goexperiment.Unified {
|
if true /* was goexperiment.Unified */ {
|
||||||
want = iface
|
want = iface
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,15 +645,13 @@ func (v *hairyVisitor) doNode(n ir.Node) bool {
|
|||||||
// minimize impact to the existing inlining heuristics (in
|
// minimize impact to the existing inlining heuristics (in
|
||||||
// particular, to avoid breaking the existing inlinability regress
|
// particular, to avoid breaking the existing inlinability regress
|
||||||
// tests), we need to compensate for this here.
|
// tests), we need to compensate for this here.
|
||||||
if base.Debug.Unified != 0 {
|
if init := n.Rhs[0].Init(); len(init) == 1 {
|
||||||
if init := n.Rhs[0].Init(); len(init) == 1 {
|
if _, ok := init[0].(*ir.AssignListStmt); ok {
|
||||||
if _, ok := init[0].(*ir.AssignListStmt); ok {
|
// 4 for each value, because each temporary variable now
|
||||||
// 4 for each value, because each temporary variable now
|
// appears 3 times (DCL, LHS, RHS), plus an extra DCL node.
|
||||||
// appears 3 times (DCL, LHS, RHS), plus an extra DCL node.
|
//
|
||||||
//
|
// 1 for the extra "tmp1, tmp2 = f()" assignment statement.
|
||||||
// 1 for the extra "tmp1, tmp2 = f()" assignment statement.
|
v.budget += 4*int32(len(n.Lhs)) + 1
|
||||||
v.budget += 4*int32(len(n.Lhs)) + 1
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -958,49 +956,6 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlCalls *[]*ir.Inlin
|
|||||||
return n
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// The non-unified frontend has issues with inlining and shape parameters.
|
|
||||||
if base.Debug.Unified == 0 {
|
|
||||||
// Don't inline a function fn that has no shape parameters, but is passed at
|
|
||||||
// least one shape arg. This means we must be inlining a non-generic function
|
|
||||||
// fn that was passed into a generic function, and can be called with a shape
|
|
||||||
// arg because it matches an appropriate type parameters. But fn may include
|
|
||||||
// an interface conversion (that may be applied to a shape arg) that was not
|
|
||||||
// apparent when we first created the instantiation of the generic function.
|
|
||||||
// We can't handle this if we actually do the inlining, since we want to know
|
|
||||||
// all interface conversions immediately after stenciling. So, we avoid
|
|
||||||
// inlining in this case, see issue #49309. (1)
|
|
||||||
//
|
|
||||||
// See discussion on go.dev/cl/406475 for more background.
|
|
||||||
if !fn.Type().Params().HasShape() {
|
|
||||||
for _, arg := range n.Args {
|
|
||||||
if arg.Type().HasShape() {
|
|
||||||
if logopt.Enabled() {
|
|
||||||
logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", ir.FuncName(ir.CurFunc),
|
|
||||||
fmt.Sprintf("inlining function %v has no-shape params with shape args", ir.FuncName(fn)))
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Don't inline a function fn that has shape parameters, but is passed no shape arg.
|
|
||||||
// See comments (1) above, and issue #51909.
|
|
||||||
inlineable := len(n.Args) == 0 // Function has shape in type, with no arguments can always be inlined.
|
|
||||||
for _, arg := range n.Args {
|
|
||||||
if arg.Type().HasShape() {
|
|
||||||
inlineable = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !inlineable {
|
|
||||||
if logopt.Enabled() {
|
|
||||||
logopt.LogOpt(n.Pos(), "cannotInlineCall", "inline", ir.FuncName(ir.CurFunc),
|
|
||||||
fmt.Sprintf("inlining function %v has shape params with no-shape args", ir.FuncName(fn)))
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if base.Flag.Cfg.Instrumenting && types.IsRuntimePkg(fn.Sym().Pkg) {
|
if base.Flag.Cfg.Instrumenting && types.IsRuntimePkg(fn.Sym().Pkg) {
|
||||||
// Runtime package must not be instrumented.
|
// Runtime package must not be instrumented.
|
||||||
// Instrument skips runtime package. However, some runtime code can be
|
// Instrument skips runtime package. However, some runtime code can be
|
||||||
|
@ -10,19 +10,14 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
|
|
||||||
"cmd/compile/internal/base"
|
"cmd/compile/internal/base"
|
||||||
"cmd/compile/internal/typecheck"
|
|
||||||
"cmd/internal/bio"
|
"cmd/internal/bio"
|
||||||
)
|
)
|
||||||
|
|
||||||
func WriteExports(out *bio.Writer) {
|
func WriteExports(out *bio.Writer) {
|
||||||
var data bytes.Buffer
|
var data bytes.Buffer
|
||||||
|
|
||||||
if base.Debug.Unified != 0 {
|
data.WriteByte('u')
|
||||||
data.WriteByte('u')
|
writeUnifiedExport(&data)
|
||||||
writeUnifiedExport(&data)
|
|
||||||
} else {
|
|
||||||
typecheck.WriteExports(&data, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The linker also looks for the $$ marker - use char after $$ to distinguish format.
|
// The linker also looks for the $$ marker - use char after $$ to distinguish format.
|
||||||
out.WriteString("\n$$B\n") // indicate binary export format
|
out.WriteString("\n$$B\n") // indicate binary export format
|
||||||
|
@ -231,10 +231,6 @@ func readImportFile(path string, target *ir.Package, env *types2.Context, packag
|
|||||||
|
|
||||||
switch c {
|
switch c {
|
||||||
case 'u':
|
case 'u':
|
||||||
if !buildcfg.Experiment.Unified {
|
|
||||||
base.Fatalf("unexpected export data format")
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(mdempsky): This seems a bit clunky.
|
// TODO(mdempsky): This seems a bit clunky.
|
||||||
data = strings.TrimSuffix(data, "\n$$\n")
|
data = strings.TrimSuffix(data, "\n$$\n")
|
||||||
|
|
||||||
@ -244,20 +240,6 @@ func readImportFile(path string, target *ir.Package, env *types2.Context, packag
|
|||||||
readPackage(newPkgReader(pr), pkg1, false)
|
readPackage(newPkgReader(pr), pkg1, false)
|
||||||
pkg2 = importer.ReadPackage(env, packages, pr)
|
pkg2 = importer.ReadPackage(env, packages, pr)
|
||||||
|
|
||||||
case 'i':
|
|
||||||
if buildcfg.Experiment.Unified {
|
|
||||||
base.Fatalf("unexpected export data format")
|
|
||||||
}
|
|
||||||
|
|
||||||
typecheck.ReadImports(pkg1, data)
|
|
||||||
|
|
||||||
if packages != nil {
|
|
||||||
pkg2, err = importer.ImportData(packages, data, path)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Indexed format is distinguished by an 'i' byte,
|
// Indexed format is distinguished by an 'i' byte,
|
||||||
// whereas previous export formats started with 'c', 'd', or 'v'.
|
// whereas previous export formats started with 'c', 'd', or 'v'.
|
||||||
|
@ -73,13 +73,7 @@ func LoadPackage(filenames []string) {
|
|||||||
}
|
}
|
||||||
base.Timer.AddEvent(int64(lines), "lines")
|
base.Timer.AddEvent(int64(lines), "lines")
|
||||||
|
|
||||||
if base.Debug.Unified != 0 {
|
unified(noders)
|
||||||
unified(noders)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Use types2 to type-check and generate IR.
|
|
||||||
check2(noders)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *noder) errorAt(pos syntax.Pos, format string, args ...interface{}) {
|
func (p *noder) errorAt(pos syntax.Pos, format string, args ...interface{}) {
|
||||||
|
@ -3688,11 +3688,6 @@ func (r *reader) importedDef() bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func MakeWrappers(target *ir.Package) {
|
func MakeWrappers(target *ir.Package) {
|
||||||
// Only unified IR emits its own wrappers.
|
|
||||||
if base.Debug.Unified == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// always generate a wrapper for error.Error (#29304)
|
// always generate a wrapper for error.Error (#29304)
|
||||||
needWrapperTypes = append(needWrapperTypes, types.ErrorType)
|
needWrapperTypes = append(needWrapperTypes, types.ErrorType)
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ func hasRType(n, rtype ir.Node, fieldName string) bool {
|
|||||||
// gets confused by implicit conversions. Also, because
|
// gets confused by implicit conversions. Also, because
|
||||||
// package-scope statements can never be generic, so they'll never
|
// package-scope statements can never be generic, so they'll never
|
||||||
// require dictionary lookups.
|
// require dictionary lookups.
|
||||||
if base.Debug.Unified != 0 && ir.CurFunc.Nname.Sym().Name != "init" {
|
if ir.CurFunc.Nname.Sym().Name != "init" {
|
||||||
ir.Dump("CurFunc", ir.CurFunc)
|
ir.Dump("CurFunc", ir.CurFunc)
|
||||||
base.FatalfAt(n.Pos(), "missing %s in %v: %+v", fieldName, ir.CurFunc, n)
|
base.FatalfAt(n.Pos(), "missing %s in %v: %+v", fieldName, ir.CurFunc, n)
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,6 @@ import (
|
|||||||
"cmd/compile/internal/base"
|
"cmd/compile/internal/base"
|
||||||
"cmd/compile/internal/bitvec"
|
"cmd/compile/internal/bitvec"
|
||||||
"cmd/compile/internal/compare"
|
"cmd/compile/internal/compare"
|
||||||
"cmd/compile/internal/escape"
|
|
||||||
"cmd/compile/internal/inline"
|
|
||||||
"cmd/compile/internal/ir"
|
"cmd/compile/internal/ir"
|
||||||
"cmd/compile/internal/objw"
|
"cmd/compile/internal/objw"
|
||||||
"cmd/compile/internal/typebits"
|
"cmd/compile/internal/typebits"
|
||||||
@ -1868,199 +1866,14 @@ func NeedEmit(typ *types.Type) bool {
|
|||||||
//
|
//
|
||||||
// These wrappers are always fully stenciled.
|
// These wrappers are always fully stenciled.
|
||||||
func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSym {
|
func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSym {
|
||||||
orig := rcvr
|
|
||||||
if forItab && !types.IsDirectIface(rcvr) {
|
if forItab && !types.IsDirectIface(rcvr) {
|
||||||
rcvr = rcvr.PtrTo()
|
rcvr = rcvr.PtrTo()
|
||||||
}
|
}
|
||||||
|
|
||||||
generic := false
|
|
||||||
// We don't need a dictionary if we are reaching a method (possibly via an
|
|
||||||
// embedded field) which is an interface method.
|
|
||||||
if !types.IsInterfaceMethod(method.Type) {
|
|
||||||
rcvr1 := deref(rcvr)
|
|
||||||
if len(rcvr1.RParams()) > 0 {
|
|
||||||
// If rcvr has rparams, remember method as generic, which
|
|
||||||
// means we need to add a dictionary to the wrapper.
|
|
||||||
generic = true
|
|
||||||
if rcvr.HasShape() {
|
|
||||||
base.Fatalf("method on type instantiated with shapes, rcvr:%+v", rcvr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
newnam := ir.MethodSym(rcvr, method.Sym)
|
newnam := ir.MethodSym(rcvr, method.Sym)
|
||||||
lsym := newnam.Linksym()
|
lsym := newnam.Linksym()
|
||||||
|
|
||||||
// Unified IR creates its own wrappers.
|
// Unified IR creates its own wrappers.
|
||||||
if base.Debug.Unified != 0 {
|
|
||||||
return lsym
|
|
||||||
}
|
|
||||||
|
|
||||||
if newnam.Siggen() {
|
|
||||||
return lsym
|
|
||||||
}
|
|
||||||
newnam.SetSiggen(true)
|
|
||||||
|
|
||||||
methodrcvr := method.Type.Recv().Type
|
|
||||||
// For generic methods, we need to generate the wrapper even if the receiver
|
|
||||||
// types are identical, because we want to add the dictionary.
|
|
||||||
if !generic && types.Identical(rcvr, methodrcvr) {
|
|
||||||
return lsym
|
|
||||||
}
|
|
||||||
|
|
||||||
if !NeedEmit(rcvr) || rcvr.IsPtr() && !NeedEmit(rcvr.Elem()) {
|
|
||||||
return lsym
|
|
||||||
}
|
|
||||||
|
|
||||||
base.Pos = base.AutogeneratedPos
|
|
||||||
typecheck.DeclContext = ir.PEXTERN
|
|
||||||
|
|
||||||
// TODO(austin): SelectorExpr may have created one or more
|
|
||||||
// ir.Names for these already with a nil Func field. We should
|
|
||||||
// consolidate these and always attach a Func to the Name.
|
|
||||||
fn := typecheck.DeclFunc(newnam, ir.NewField(base.Pos, typecheck.Lookup(".this"), rcvr),
|
|
||||||
typecheck.NewFuncParams(method.Type.Params(), true),
|
|
||||||
typecheck.NewFuncParams(method.Type.Results(), false))
|
|
||||||
|
|
||||||
fn.SetDupok(true)
|
|
||||||
|
|
||||||
nthis := ir.AsNode(fn.Type().Recv().Nname)
|
|
||||||
|
|
||||||
indirect := rcvr.IsPtr() && rcvr.Elem() == methodrcvr
|
|
||||||
|
|
||||||
// generate nil pointer check for better error
|
|
||||||
if indirect {
|
|
||||||
// generating wrapper from *T to T.
|
|
||||||
n := ir.NewIfStmt(base.Pos, nil, nil, nil)
|
|
||||||
n.Cond = ir.NewBinaryExpr(base.Pos, ir.OEQ, nthis, typecheck.NodNil())
|
|
||||||
call := ir.NewCallExpr(base.Pos, ir.OCALL, typecheck.LookupRuntime("panicwrap"), nil)
|
|
||||||
n.Body = []ir.Node{call}
|
|
||||||
fn.Body.Append(n)
|
|
||||||
}
|
|
||||||
|
|
||||||
dot := typecheck.AddImplicitDots(ir.NewSelectorExpr(base.Pos, ir.OXDOT, nthis, method.Sym))
|
|
||||||
// generate call
|
|
||||||
// It's not possible to use a tail call when dynamic linking on ppc64le. The
|
|
||||||
// bad scenario is when a local call is made to the wrapper: the wrapper will
|
|
||||||
// call the implementation, which might be in a different module and so set
|
|
||||||
// the TOC to the appropriate value for that module. But if it returns
|
|
||||||
// directly to the wrapper's caller, nothing will reset it to the correct
|
|
||||||
// value for that function.
|
|
||||||
var call *ir.CallExpr
|
|
||||||
if !base.Flag.Cfg.Instrumenting && rcvr.IsPtr() && methodrcvr.IsPtr() && method.Embedded != 0 && !types.IsInterfaceMethod(method.Type) && !(base.Ctxt.Arch.Name == "ppc64le" && base.Ctxt.Flag_dynlink) && !generic {
|
|
||||||
call = ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil)
|
|
||||||
call.Args = ir.ParamNames(fn.Type())
|
|
||||||
call.IsDDD = fn.Type().IsVariadic()
|
|
||||||
fn.Body.Append(ir.NewTailCallStmt(base.Pos, call))
|
|
||||||
} else {
|
|
||||||
fn.SetWrapper(true) // ignore frame for panic+recover matching
|
|
||||||
|
|
||||||
if generic && dot.X != nthis {
|
|
||||||
// If there is embedding involved, then we should do the
|
|
||||||
// normal non-generic embedding wrapper below, which calls
|
|
||||||
// the wrapper for the real receiver type using dot as an
|
|
||||||
// argument. There is no need for generic processing (adding
|
|
||||||
// a dictionary) for this wrapper.
|
|
||||||
generic = false
|
|
||||||
}
|
|
||||||
|
|
||||||
if generic {
|
|
||||||
targs := deref(rcvr).RParams()
|
|
||||||
// The wrapper for an auto-generated pointer/non-pointer
|
|
||||||
// receiver method should share the same dictionary as the
|
|
||||||
// corresponding original (user-written) method.
|
|
||||||
baseOrig := orig
|
|
||||||
if baseOrig.IsPtr() && !methodrcvr.IsPtr() {
|
|
||||||
baseOrig = baseOrig.Elem()
|
|
||||||
} else if !baseOrig.IsPtr() && methodrcvr.IsPtr() {
|
|
||||||
baseOrig = types.NewPtr(baseOrig)
|
|
||||||
}
|
|
||||||
args := []ir.Node{getDictionary(ir.MethodSym(baseOrig, method.Sym), targs)}
|
|
||||||
if indirect {
|
|
||||||
args = append(args, ir.NewStarExpr(base.Pos, dot.X))
|
|
||||||
} else if methodrcvr.IsPtr() && methodrcvr.Elem() == dot.X.Type() {
|
|
||||||
// Case where method call is via a non-pointer
|
|
||||||
// embedded field with a pointer method.
|
|
||||||
args = append(args, typecheck.NodAddrAt(base.Pos, dot.X))
|
|
||||||
} else {
|
|
||||||
args = append(args, dot.X)
|
|
||||||
}
|
|
||||||
args = append(args, ir.ParamNames(fn.Type())...)
|
|
||||||
|
|
||||||
// Target method uses shaped names.
|
|
||||||
targs2 := make([]*types.Type, len(targs))
|
|
||||||
origRParams := deref(orig).OrigType().RParams()
|
|
||||||
for i, t := range targs {
|
|
||||||
targs2[i] = typecheck.Shapify(t, i, origRParams[i])
|
|
||||||
}
|
|
||||||
targs = targs2
|
|
||||||
|
|
||||||
sym := typecheck.MakeFuncInstSym(ir.MethodSym(methodrcvr, method.Sym), targs, false, true)
|
|
||||||
if sym.Def == nil {
|
|
||||||
// Currently we make sure that we have all the
|
|
||||||
// instantiations we need by generating them all in
|
|
||||||
// ../noder/stencil.go:instantiateMethods
|
|
||||||
// Extra instantiations because of an inlined function
|
|
||||||
// should have been exported, and so available via
|
|
||||||
// Resolve.
|
|
||||||
in := typecheck.Resolve(ir.NewIdent(src.NoXPos, sym))
|
|
||||||
if in.Op() == ir.ONONAME {
|
|
||||||
base.Fatalf("instantiation %s not found", sym.Name)
|
|
||||||
}
|
|
||||||
sym = in.Sym()
|
|
||||||
}
|
|
||||||
target := ir.AsNode(sym.Def)
|
|
||||||
call = ir.NewCallExpr(base.Pos, ir.OCALL, target, args)
|
|
||||||
// Fill-in the generic method node that was not filled in
|
|
||||||
// in instantiateMethod.
|
|
||||||
method.Nname = fn.Nname
|
|
||||||
} else {
|
|
||||||
call = ir.NewCallExpr(base.Pos, ir.OCALL, dot, nil)
|
|
||||||
call.Args = ir.ParamNames(fn.Type())
|
|
||||||
}
|
|
||||||
call.IsDDD = fn.Type().IsVariadic()
|
|
||||||
if method.Type.NumResults() > 0 {
|
|
||||||
ret := ir.NewReturnStmt(base.Pos, nil)
|
|
||||||
ret.Results = []ir.Node{call}
|
|
||||||
fn.Body.Append(ret)
|
|
||||||
} else {
|
|
||||||
fn.Body.Append(call)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typecheck.FinishFuncBody()
|
|
||||||
if base.Debug.DclStack != 0 {
|
|
||||||
types.CheckDclstack()
|
|
||||||
}
|
|
||||||
|
|
||||||
typecheck.Func(fn)
|
|
||||||
ir.CurFunc = fn
|
|
||||||
typecheck.Stmts(fn.Body)
|
|
||||||
|
|
||||||
if AfterGlobalEscapeAnalysis {
|
|
||||||
// Inlining the method may reveal closures, which require walking all function bodies
|
|
||||||
// to decide whether to capture free variables by value or by ref. So we only do inline
|
|
||||||
// if the method do not contain any closures, otherwise, the escape analysis may make
|
|
||||||
// dead variables resurrected, and causing liveness analysis confused, see issue #53702.
|
|
||||||
var canInline bool
|
|
||||||
switch x := call.X.(type) {
|
|
||||||
case *ir.Name:
|
|
||||||
canInline = len(x.Func.Closures) == 0
|
|
||||||
case *ir.SelectorExpr:
|
|
||||||
if x.Op() == ir.OMETHEXPR {
|
|
||||||
canInline = x.FuncName().Func != nil && len(x.FuncName().Func.Closures) == 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if canInline {
|
|
||||||
// TODO(prattmic): plumb PGO.
|
|
||||||
inline.InlineCalls(fn, nil)
|
|
||||||
}
|
|
||||||
escape.Batch([]*ir.Func{fn}, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
ir.CurFunc = nil
|
|
||||||
typecheck.Target.Decls = append(typecheck.Target.Decls, fn)
|
|
||||||
|
|
||||||
return lsym
|
return lsym
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"internal/buildcfg"
|
|
||||||
"internal/testenv"
|
"internal/testenv"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@ -84,7 +83,7 @@ func TestDebugLinesPushback(t *testing.T) {
|
|||||||
|
|
||||||
case "arm64", "amd64": // register ABI
|
case "arm64", "amd64": // register ABI
|
||||||
fn := "(*List[go.shape.int_0]).PushBack"
|
fn := "(*List[go.shape.int_0]).PushBack"
|
||||||
if buildcfg.Experiment.Unified {
|
if true /* was buildcfg.Experiment.Unified */ {
|
||||||
// Unified mangles differently
|
// Unified mangles differently
|
||||||
fn = "(*List[go.shape.int]).PushBack"
|
fn = "(*List[go.shape.int]).PushBack"
|
||||||
}
|
}
|
||||||
@ -101,7 +100,7 @@ func TestDebugLinesConvert(t *testing.T) {
|
|||||||
|
|
||||||
case "arm64", "amd64": // register ABI
|
case "arm64", "amd64": // register ABI
|
||||||
fn := "G[go.shape.int_0]"
|
fn := "G[go.shape.int_0]"
|
||||||
if buildcfg.Experiment.Unified {
|
if true /* was buildcfg.Experiment.Unified */ {
|
||||||
// Unified mangles differently
|
// Unified mangles differently
|
||||||
fn = "G[go.shape.int]"
|
fn = "G[go.shape.int]"
|
||||||
}
|
}
|
||||||
|
@ -333,7 +333,7 @@ func (s *Schedule) StaticAssign(l *ir.Name, loff int64, r ir.Node, typ *types.Ty
|
|||||||
return val.Op() == ir.ONIL
|
return val.Op() == ir.ONIL
|
||||||
}
|
}
|
||||||
|
|
||||||
if base.Debug.Unified != 0 && val.Type().HasShape() {
|
if val.Type().HasShape() {
|
||||||
// See comment in cmd/compile/internal/walk/convert.go:walkConvInterface
|
// See comment in cmd/compile/internal/walk/convert.go:walkConvInterface
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ package test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"internal/buildcfg"
|
|
||||||
"internal/goexperiment"
|
"internal/goexperiment"
|
||||||
"internal/testenv"
|
"internal/testenv"
|
||||||
"io"
|
"io"
|
||||||
@ -235,7 +234,7 @@ func TestIntendedInlining(t *testing.T) {
|
|||||||
// (*Bool).CompareAndSwap is just over budget on 32-bit systems (386, arm).
|
// (*Bool).CompareAndSwap is just over budget on 32-bit systems (386, arm).
|
||||||
want["sync/atomic"] = append(want["sync/atomic"], "(*Bool).CompareAndSwap")
|
want["sync/atomic"] = append(want["sync/atomic"], "(*Bool).CompareAndSwap")
|
||||||
}
|
}
|
||||||
if buildcfg.Experiment.Unified {
|
if true /* was buildcfg.Experiment.Unified */ {
|
||||||
// Non-unified IR does not report "inlining call ..." for atomic.Pointer[T]'s methods.
|
// Non-unified IR does not report "inlining call ..." for atomic.Pointer[T]'s methods.
|
||||||
// TODO(cuonglm): remove once non-unified IR frontend gone.
|
// TODO(cuonglm): remove once non-unified IR frontend gone.
|
||||||
want["sync/atomic"] = append(want["sync/atomic"], "(*Pointer[go.shape.int]).CompareAndSwap")
|
want["sync/atomic"] = append(want["sync/atomic"], "(*Pointer[go.shape.int]).CompareAndSwap")
|
||||||
|
@ -336,27 +336,6 @@ func (p *crawler) markInlBody(n *ir.Name) {
|
|||||||
} else {
|
} else {
|
||||||
p.checkForFullyInst(t)
|
p.checkForFullyInst(t)
|
||||||
}
|
}
|
||||||
if base.Debug.Unified == 0 {
|
|
||||||
// If a method of un-exported type is promoted and accessible by
|
|
||||||
// embedding in an exported type, it makes that type reachable.
|
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
//
|
|
||||||
// type t struct {}
|
|
||||||
// func (t) M() {}
|
|
||||||
//
|
|
||||||
// func F() interface{} { return struct{ t }{} }
|
|
||||||
//
|
|
||||||
// We generate the wrapper for "struct{ t }".M, and inline call
|
|
||||||
// to "struct{ t }".M, which makes "t.M" reachable.
|
|
||||||
if t.IsStruct() {
|
|
||||||
for _, f := range t.FieldSlice() {
|
|
||||||
if f.Embedded != 0 {
|
|
||||||
p.markEmbed(f.Type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch n.Op() {
|
switch n.Op() {
|
||||||
|
@ -382,7 +382,7 @@ func Assignop1(src, dst *types.Type) (ir.Op, string) {
|
|||||||
// don't have the methods for them.
|
// don't have the methods for them.
|
||||||
return ir.OCONVIFACE, ""
|
return ir.OCONVIFACE, ""
|
||||||
}
|
}
|
||||||
if base.Debug.Unified != 0 && src.HasShape() {
|
if src.HasShape() {
|
||||||
// Unified IR uses OCONVIFACE for converting all derived types
|
// Unified IR uses OCONVIFACE for converting all derived types
|
||||||
// to interface type, not just type arguments themselves.
|
// to interface type, not just type arguments themselves.
|
||||||
return ir.OCONVIFACE, ""
|
return ir.OCONVIFACE, ""
|
||||||
|
@ -217,7 +217,6 @@ func methodValueWrapper(dot *ir.SelectorExpr) *ir.Name {
|
|||||||
base.Fatalf("methodValueWrapper: unexpected %v (%v)", dot, dot.Op())
|
base.Fatalf("methodValueWrapper: unexpected %v (%v)", dot, dot.Op())
|
||||||
}
|
}
|
||||||
|
|
||||||
t0 := dot.Type()
|
|
||||||
meth := dot.Sel
|
meth := dot.Sel
|
||||||
rcvrtype := dot.X.Type()
|
rcvrtype := dot.X.Type()
|
||||||
sym := ir.MethodSymSuffix(rcvrtype, meth, "-fm")
|
sym := ir.MethodSymSuffix(rcvrtype, meth, "-fm")
|
||||||
@ -227,48 +226,6 @@ func methodValueWrapper(dot *ir.SelectorExpr) *ir.Name {
|
|||||||
}
|
}
|
||||||
sym.SetUniq(true)
|
sym.SetUniq(true)
|
||||||
|
|
||||||
if base.Debug.Unified != 0 {
|
base.FatalfAt(dot.Pos(), "missing wrapper for %v", meth)
|
||||||
base.FatalfAt(dot.Pos(), "missing wrapper for %v", meth)
|
panic("unreachable")
|
||||||
}
|
|
||||||
|
|
||||||
savecurfn := ir.CurFunc
|
|
||||||
saveLineNo := base.Pos
|
|
||||||
ir.CurFunc = nil
|
|
||||||
|
|
||||||
base.Pos = base.AutogeneratedPos
|
|
||||||
|
|
||||||
fn := typecheck.DeclFunc(sym, nil,
|
|
||||||
typecheck.NewFuncParams(t0.Params(), true),
|
|
||||||
typecheck.NewFuncParams(t0.Results(), false))
|
|
||||||
fn.SetDupok(true)
|
|
||||||
fn.SetWrapper(true)
|
|
||||||
|
|
||||||
// Declare and initialize variable holding receiver.
|
|
||||||
ptr := ir.NewHiddenParam(base.Pos, fn, typecheck.Lookup(".this"), rcvrtype)
|
|
||||||
|
|
||||||
call := ir.NewCallExpr(base.Pos, ir.OCALL, ir.NewSelectorExpr(base.Pos, ir.OXDOT, ptr, meth), nil)
|
|
||||||
call.Args = ir.ParamNames(fn.Type())
|
|
||||||
call.IsDDD = fn.Type().IsVariadic()
|
|
||||||
|
|
||||||
var body ir.Node = call
|
|
||||||
if t0.NumResults() != 0 {
|
|
||||||
ret := ir.NewReturnStmt(base.Pos, nil)
|
|
||||||
ret.Results = []ir.Node{call}
|
|
||||||
body = ret
|
|
||||||
}
|
|
||||||
|
|
||||||
fn.Body = []ir.Node{body}
|
|
||||||
typecheck.FinishFuncBody()
|
|
||||||
|
|
||||||
typecheck.Func(fn)
|
|
||||||
// Need to typecheck the body of the just-generated wrapper.
|
|
||||||
// typecheckslice() requires that Curfn is set when processing an ORETURN.
|
|
||||||
ir.CurFunc = fn
|
|
||||||
typecheck.Stmts(fn.Body)
|
|
||||||
sym.Def = fn.Nname
|
|
||||||
typecheck.Target.Decls = append(typecheck.Target.Decls, fn)
|
|
||||||
ir.CurFunc = savecurfn
|
|
||||||
base.Pos = saveLineNo
|
|
||||||
|
|
||||||
return fn.Nname
|
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ func walkConvInterface(n *ir.ConvExpr, init *ir.Nodes) ir.Node {
|
|||||||
toType := n.Type()
|
toType := n.Type()
|
||||||
if !fromType.IsInterface() && !ir.IsBlank(ir.CurFunc.Nname) {
|
if !fromType.IsInterface() && !ir.IsBlank(ir.CurFunc.Nname) {
|
||||||
// skip unnamed functions (func _())
|
// skip unnamed functions (func _())
|
||||||
if base.Debug.Unified != 0 && fromType.HasShape() {
|
if fromType.HasShape() {
|
||||||
// Unified IR uses OCONVIFACE for converting all derived types
|
// Unified IR uses OCONVIFACE for converting all derived types
|
||||||
// to interface type. Avoid assertion failure in
|
// to interface type. Avoid assertion failure in
|
||||||
// MarkTypeUsedInInterface, because we've marked used types
|
// MarkTypeUsedInInterface, because we've marked used types
|
||||||
|
@ -8,7 +8,6 @@ import (
|
|||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"debug/macho"
|
"debug/macho"
|
||||||
"internal/buildcfg"
|
|
||||||
"internal/platform"
|
"internal/platform"
|
||||||
"internal/testenv"
|
"internal/testenv"
|
||||||
"os"
|
"os"
|
||||||
@ -1094,7 +1093,7 @@ func TestUnlinkableObj(t *testing.T) {
|
|||||||
testenv.MustHaveGoBuild(t)
|
testenv.MustHaveGoBuild(t)
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
if buildcfg.Experiment.Unified {
|
if true /* was buildcfg.Experiment.Unified */ {
|
||||||
t.Skip("TODO(mdempsky): Fix ICE when importing unlinkable objects for GOEXPERIMENT=unified")
|
t.Skip("TODO(mdempsky): Fix ICE when importing unlinkable objects for GOEXPERIMENT=unified")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ package importer
|
|||||||
import (
|
import (
|
||||||
"go/build"
|
"go/build"
|
||||||
"go/token"
|
"go/token"
|
||||||
"internal/buildcfg"
|
|
||||||
"internal/testenv"
|
"internal/testenv"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
@ -68,7 +67,7 @@ func TestForCompiler(t *testing.T) {
|
|||||||
// support for it in unified IR. It's not clear that we actually
|
// support for it in unified IR. It's not clear that we actually
|
||||||
// need to support importing "math/big" as "math/bigger", for
|
// need to support importing "math/big" as "math/bigger", for
|
||||||
// example. cmd/link no longer supports that.
|
// example. cmd/link no longer supports that.
|
||||||
if buildcfg.Experiment.Unified {
|
if true /* was buildcfg.Experiment.Unified */ {
|
||||||
t.Skip("not supported by GOEXPERIMENT=unified; see go.dev/cl/406319")
|
t.Skip("not supported by GOEXPERIMENT=unified; see go.dev/cl/406319")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@ package gcimporter_test
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"internal/goexperiment"
|
|
||||||
"internal/goroot"
|
"internal/goroot"
|
||||||
"internal/testenv"
|
"internal/testenv"
|
||||||
"os"
|
"os"
|
||||||
@ -108,7 +107,7 @@ func TestImportTestdata(t *testing.T) {
|
|||||||
"exports.go": {"go/ast", "go/token"},
|
"exports.go": {"go/ast", "go/token"},
|
||||||
"generics.go": nil,
|
"generics.go": nil,
|
||||||
}
|
}
|
||||||
if goexperiment.Unified {
|
if true /* was goexperiment.Unified */ {
|
||||||
// TODO(mdempsky): Fix test below to flatten the transitive
|
// TODO(mdempsky): Fix test below to flatten the transitive
|
||||||
// Package.Imports graph. Unified IR is more precise about
|
// Package.Imports graph. Unified IR is more precise about
|
||||||
// recreating the package import graph.
|
// recreating the package import graph.
|
||||||
@ -168,17 +167,6 @@ func TestImportTypeparamTests(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var skip map[string]string
|
|
||||||
if !goexperiment.Unified {
|
|
||||||
// The Go 1.18 frontend still fails several cases.
|
|
||||||
skip = map[string]string{
|
|
||||||
"equal.go": "inconsistent embedded sorting", // TODO(rfindley): investigate this.
|
|
||||||
"nested.go": "fails to compile", // TODO(rfindley): investigate this.
|
|
||||||
"issue47631.go": "can not handle local type declarations",
|
|
||||||
"issue55101.go": "fails to compile",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, entry := range list {
|
for _, entry := range list {
|
||||||
if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".go") {
|
if entry.IsDir() || !strings.HasSuffix(entry.Name(), ".go") {
|
||||||
// For now, only consider standalone go files.
|
// For now, only consider standalone go files.
|
||||||
@ -186,10 +174,6 @@ func TestImportTypeparamTests(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
t.Run(entry.Name(), func(t *testing.T) {
|
t.Run(entry.Name(), func(t *testing.T) {
|
||||||
if reason, ok := skip[entry.Name()]; ok {
|
|
||||||
t.Skip(reason)
|
|
||||||
}
|
|
||||||
|
|
||||||
filename := filepath.Join(rootDir, entry.Name())
|
filename := filepath.Join(rootDir, entry.Name())
|
||||||
src, err := os.ReadFile(filename)
|
src, err := os.ReadFile(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -70,7 +70,6 @@ func ParseGOEXPERIMENT(goos, goarch, goexp string) (*ExperimentFlags, error) {
|
|||||||
baseline := goexperiment.Flags{
|
baseline := goexperiment.Flags{
|
||||||
RegabiWrappers: regabiSupported,
|
RegabiWrappers: regabiSupported,
|
||||||
RegabiArgs: regabiSupported,
|
RegabiArgs: regabiSupported,
|
||||||
Unified: true,
|
|
||||||
CoverageRedesign: true,
|
CoverageRedesign: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +0,0 @@
|
|||||||
// Code generated by mkconsts.go. DO NOT EDIT.
|
|
||||||
|
|
||||||
//go:build !goexperiment.unified
|
|
||||||
// +build !goexperiment.unified
|
|
||||||
|
|
||||||
package goexperiment
|
|
||||||
|
|
||||||
const Unified = false
|
|
||||||
const UnifiedInt = 0
|
|
@ -1,9 +0,0 @@
|
|||||||
// Code generated by mkconsts.go. DO NOT EDIT.
|
|
||||||
|
|
||||||
//go:build goexperiment.unified
|
|
||||||
// +build goexperiment.unified
|
|
||||||
|
|
||||||
package goexperiment
|
|
||||||
|
|
||||||
const Unified = true
|
|
||||||
const UnifiedInt = 1
|
|
@ -60,10 +60,6 @@ type Flags struct {
|
|||||||
StaticLockRanking bool
|
StaticLockRanking bool
|
||||||
BoringCrypto bool
|
BoringCrypto bool
|
||||||
|
|
||||||
// Unified enables the compiler's unified IR construction
|
|
||||||
// experiment.
|
|
||||||
Unified bool
|
|
||||||
|
|
||||||
// Regabi is split into several sub-experiments that can be
|
// Regabi is split into several sub-experiments that can be
|
||||||
// enabled individually. Not all combinations work.
|
// enabled individually. Not all combinations work.
|
||||||
// The "regabi" GOEXPERIMENT is an alias for all "working"
|
// The "regabi" GOEXPERIMENT is an alias for all "working"
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
// errorcheck -0 -m -l
|
|
||||||
//go:build !goexperiment.unified
|
|
||||||
// +build !goexperiment.unified
|
|
||||||
|
|
||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package escape
|
|
||||||
|
|
||||||
var sink interface{}
|
|
||||||
|
|
||||||
func dotTypeEscape2() { // #13805, #15796
|
|
||||||
{
|
|
||||||
i := 0
|
|
||||||
j := 0
|
|
||||||
var ok bool
|
|
||||||
var x interface{} = i // ERROR "i does not escape"
|
|
||||||
var y interface{} = j // ERROR "j does not escape"
|
|
||||||
|
|
||||||
sink = x.(int) // ERROR "x.\(int\) escapes to heap"
|
|
||||||
// BAD: should be "y.\(int\) escapes to heap" too
|
|
||||||
sink, *(&ok) = y.(int)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,6 +1,4 @@
|
|||||||
// errorcheck -0 -m -l
|
// errorcheck -0 -m -l
|
||||||
//go:build goexperiment.unified
|
|
||||||
// +build goexperiment.unified
|
|
||||||
|
|
||||||
// Copyright 2015 The Go Authors. All rights reserved.
|
// Copyright 2015 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
// run
|
// run
|
||||||
//go:build goexperiment.unified && cgo
|
//go:build cgo
|
||||||
|
|
||||||
// TODO(mdempsky): Enable test unconditionally. This test should pass
|
|
||||||
// for non-unified mode too.
|
|
||||||
|
|
||||||
// Copyright 2021 The Go Authors. All rights reserved.
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
// compile
|
// compile
|
||||||
//go:build goexperiment.unified
|
|
||||||
|
|
||||||
// Copyright 2022 The Go Authors. All rights reserved.
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
// errorcheckwithauto -0 -m -d=inlfuncswithclosures=1
|
|
||||||
//go:build !goexperiment.unified
|
|
||||||
// +build !goexperiment.unified
|
|
||||||
|
|
||||||
// Copyright 2022 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package foo
|
|
||||||
|
|
||||||
func r(z int) int {
|
|
||||||
foo := func(x int) int { // ERROR "can inline r.func1" "func literal does not escape"
|
|
||||||
return x + z
|
|
||||||
}
|
|
||||||
bar := func(x int) int { // ERROR "func literal does not escape" "can inline r.func2"
|
|
||||||
return x + func(y int) int { // ERROR "can inline r.func2.1" "can inline r.func3"
|
|
||||||
return 2*y + x*z
|
|
||||||
}(x) // ERROR "inlining call to r.func2.1"
|
|
||||||
}
|
|
||||||
return foo(42) + bar(42) // ERROR "inlining call to r.func1" "inlining call to r.func2" "inlining call to r.func3"
|
|
||||||
}
|
|
@ -1,6 +1,4 @@
|
|||||||
// errorcheckwithauto -0 -m -d=inlfuncswithclosures=1
|
// errorcheckwithauto -0 -m -d=inlfuncswithclosures=1
|
||||||
//go:build goexperiment.unified
|
|
||||||
// +build goexperiment.unified
|
|
||||||
|
|
||||||
// Copyright 2022 The Go Authors. All rights reserved.
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
|
28
test/run.go
28
test/run.go
@ -76,15 +76,6 @@ var env = func() (res envVars) {
|
|||||||
return
|
return
|
||||||
}()
|
}()
|
||||||
|
|
||||||
var unifiedEnabled = func() bool {
|
|
||||||
for _, tag := range build.Default.ToolTags {
|
|
||||||
if tag == "goexperiment.unified" {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}()
|
|
||||||
|
|
||||||
// defaultAllCodeGen returns the default value of the -all_codegen
|
// defaultAllCodeGen returns the default value of the -all_codegen
|
||||||
// flag. By default, we prefer to be fast (returning false), except on
|
// flag. By default, we prefer to be fast (returning false), except on
|
||||||
// the linux-amd64 builder that's already very fast, so we get more
|
// the linux-amd64 builder that's already very fast, so we get more
|
||||||
@ -374,10 +365,6 @@ func (t *test) initExpectFail() {
|
|||||||
failureSets = append(failureSets, types2Failures32Bit)
|
failureSets = append(failureSets, types2Failures32Bit)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !unifiedEnabled {
|
|
||||||
failureSets = append(failureSets, go118Failures)
|
|
||||||
}
|
|
||||||
|
|
||||||
filename := strings.Replace(t.goFileName(), "\\", "/", -1) // goFileName() uses \ on Windows
|
filename := strings.Replace(t.goFileName(), "\\", "/", -1) // goFileName() uses \ on Windows
|
||||||
|
|
||||||
for _, set := range failureSets {
|
for _, set := range failureSets {
|
||||||
@ -2037,21 +2024,6 @@ var types2Failures32Bit = setOf(
|
|||||||
"fixedbugs/issue23305.go", // large untyped int passed to println (32-bit)
|
"fixedbugs/issue23305.go", // large untyped int passed to println (32-bit)
|
||||||
)
|
)
|
||||||
|
|
||||||
var go118Failures = setOf(
|
|
||||||
"fixedbugs/issue54343.go", // 1.18 compiler assigns receiver parameter to global variable
|
|
||||||
"fixedbugs/issue56280.go", // 1.18 compiler doesn't support inlining generic functions
|
|
||||||
"typeparam/nested.go", // 1.18 compiler doesn't support function-local types with generics
|
|
||||||
"typeparam/issue47631.go", // 1.18 can not handle local type declarations
|
|
||||||
"typeparam/issue51521.go", // 1.18 compiler produces bad panic message and link error
|
|
||||||
"typeparam/issue54456.go", // 1.18 compiler fails to distinguish local generic types
|
|
||||||
"typeparam/issue54497.go", // 1.18 compiler is more conservative about inlining due to repeated issues
|
|
||||||
"typeparam/issue55101.go", // 1.18 compiler ICEs writing export data
|
|
||||||
"typeparam/mdempsky/16.go", // 1.18 compiler uses interface shape type in failed type assertions
|
|
||||||
"typeparam/mdempsky/17.go", // 1.18 compiler mishandles implicit conversions from range loops
|
|
||||||
"typeparam/mdempsky/18.go", // 1.18 compiler mishandles implicit conversions in select statements
|
|
||||||
"typeparam/mdempsky/20.go", // 1.18 compiler crashes on method expressions promoted to derived types
|
|
||||||
)
|
|
||||||
|
|
||||||
// In all of these cases, the 1.17 compiler reports reasonable errors, but either the
|
// In all of these cases, the 1.17 compiler reports reasonable errors, but either the
|
||||||
// 1.17 or 1.18 compiler report extra errors, so we can't match correctly on both. We
|
// 1.17 or 1.18 compiler report extra errors, so we can't match correctly on both. We
|
||||||
// now set the patterns to match correctly on all the 1.18 errors.
|
// now set the patterns to match correctly on all the 1.18 errors.
|
||||||
|
Loading…
Reference in New Issue
Block a user