diff options
| author | Matthew Dempsky <mdempsky@google.com> | 2022-02-11 11:55:27 -0800 |
|---|---|---|
| committer | Matthew Dempsky <mdempsky@google.com> | 2022-03-01 06:01:28 +0000 |
| commit | 4f04e1d99fac7abf067b6bd3a299f1fbc9a59414 (patch) | |
| tree | b70fa443fb8a30308fe140cde09aee0522fcaf7d /src/cmd/compile/internal/noder | |
| parent | 936c7fbc1c154964b6e3e8a7523bdf0c29b4e1b3 (diff) | |
| download | go-4f04e1d99fac7abf067b6bd3a299f1fbc9a59414.tar.xz | |
cmd/compile: remove unified IR quirks mode
Unified IR quirks mode existed to help bootstrap unified IR by forcing
it to produce bit-for-bit identical output to the original gc noder
and typechecker. However, I believe it's far enough along now to stand
on its own, plus we have good test coverage of generics already for
-G=3 mode.
Change-Id: I8bf412c8bb5d720eadeac3fe31f49dc73679da70
Reviewed-on: https://go-review.googlesource.com/c/go/+/385998
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Diffstat (limited to 'src/cmd/compile/internal/noder')
| -rw-r--r-- | src/cmd/compile/internal/noder/quirks.go | 369 | ||||
| -rw-r--r-- | src/cmd/compile/internal/noder/reader.go | 57 | ||||
| -rw-r--r-- | src/cmd/compile/internal/noder/unified.go | 6 | ||||
| -rw-r--r-- | src/cmd/compile/internal/noder/unified_test.go | 160 | ||||
| -rw-r--r-- | src/cmd/compile/internal/noder/writer.go | 84 |
5 files changed, 6 insertions, 670 deletions
diff --git a/src/cmd/compile/internal/noder/quirks.go b/src/cmd/compile/internal/noder/quirks.go index 914c5d2bd7..c4cb9b9a2c 100644 --- a/src/cmd/compile/internal/noder/quirks.go +++ b/src/cmd/compile/internal/noder/quirks.go @@ -9,254 +9,13 @@ package noder import ( "fmt" - "cmd/compile/internal/base" - "cmd/compile/internal/ir" "cmd/compile/internal/syntax" - "cmd/compile/internal/types2" - "cmd/internal/src" ) // This file defines helper functions useful for satisfying toolstash // -cmp when compared against the legacy frontend behavior, but can be // removed after that's no longer a concern. -// quirksMode controls whether behavior specific to satisfying -// toolstash -cmp is used. -func quirksMode() bool { - return base.Debug.UnifiedQuirks != 0 -} - -// posBasesOf returns all of the position bases in the source files, -// as seen in a straightforward traversal. -// -// This is necessary to ensure position bases (and thus file names) -// get registered in the same order as noder would visit them. -func posBasesOf(noders []*noder) []*syntax.PosBase { - seen := make(map[*syntax.PosBase]bool) - var bases []*syntax.PosBase - - for _, p := range noders { - syntax.Crawl(p.file, func(n syntax.Node) bool { - if b := n.Pos().Base(); !seen[b] { - bases = append(bases, b) - seen[b] = true - } - return false - }) - } - - return bases -} - -// importedObjsOf returns the imported objects (i.e., referenced -// objects not declared by curpkg) from the parsed source files, in -// the order that typecheck used to load their definitions. -// -// This is needed because loading the definitions for imported objects -// can also add file names. -func importedObjsOf(curpkg *types2.Package, info *types2.Info, noders []*noder) []types2.Object { - // This code is complex because it matches the precise order that - // typecheck recursively and repeatedly traverses the IR. It's meant - // to be thrown away eventually anyway. - - seen := make(map[types2.Object]bool) - var objs []types2.Object - - var phase int - - decls := make(map[types2.Object]syntax.Decl) - assoc := func(decl syntax.Decl, names ...*syntax.Name) { - for _, name := range names { - obj, ok := info.Defs[name] - assert(ok) - decls[obj] = decl - } - } - - for _, p := range noders { - syntax.Crawl(p.file, func(n syntax.Node) bool { - switch n := n.(type) { - case *syntax.ConstDecl: - assoc(n, n.NameList...) - case *syntax.FuncDecl: - assoc(n, n.Name) - case *syntax.TypeDecl: - assoc(n, n.Name) - case *syntax.VarDecl: - assoc(n, n.NameList...) - case *syntax.BlockStmt: - return true - } - return false - }) - } - - var visited map[syntax.Decl]bool - - var resolveDecl func(n syntax.Decl) - var resolveNode func(n syntax.Node, top bool) - - resolveDecl = func(n syntax.Decl) { - if visited[n] { - return - } - visited[n] = true - - switch n := n.(type) { - case *syntax.ConstDecl: - resolveNode(n.Type, true) - resolveNode(n.Values, true) - - case *syntax.FuncDecl: - if n.Recv != nil { - resolveNode(n.Recv, true) - } - resolveNode(n.Type, true) - - case *syntax.TypeDecl: - resolveNode(n.Type, true) - - case *syntax.VarDecl: - if n.Type != nil { - resolveNode(n.Type, true) - } else { - resolveNode(n.Values, true) - } - } - } - - resolveObj := func(pos syntax.Pos, obj types2.Object) { - switch obj.Pkg() { - case nil: - // builtin; nothing to do - - case curpkg: - if decl, ok := decls[obj]; ok { - resolveDecl(decl) - } - - default: - if obj.Parent() == obj.Pkg().Scope() && !seen[obj] { - seen[obj] = true - objs = append(objs, obj) - } - } - } - - checkdefat := func(pos syntax.Pos, n *syntax.Name) { - if n.Value == "_" { - return - } - obj, ok := info.Uses[n] - if !ok { - obj, ok = info.Defs[n] - if !ok { - return - } - } - if obj == nil { - return - } - resolveObj(pos, obj) - } - checkdef := func(n *syntax.Name) { checkdefat(n.Pos(), n) } - - var later []syntax.Node - - resolveNode = func(n syntax.Node, top bool) { - if n == nil { - return - } - syntax.Crawl(n, func(n syntax.Node) bool { - switch n := n.(type) { - case *syntax.Name: - checkdef(n) - - case *syntax.SelectorExpr: - if name, ok := n.X.(*syntax.Name); ok { - if _, isPkg := info.Uses[name].(*types2.PkgName); isPkg { - checkdefat(n.X.Pos(), n.Sel) - return true - } - } - - case *syntax.AssignStmt: - resolveNode(n.Rhs, top) - resolveNode(n.Lhs, top) - return true - - case *syntax.VarDecl: - resolveNode(n.Values, top) - - case *syntax.FuncLit: - if top { - resolveNode(n.Type, top) - later = append(later, n.Body) - return true - } - - case *syntax.BlockStmt: - if phase >= 3 { - for _, stmt := range n.List { - resolveNode(stmt, false) - } - } - return true - } - - return false - }) - } - - for phase = 1; phase <= 5; phase++ { - visited = map[syntax.Decl]bool{} - - for _, p := range noders { - for _, decl := range p.file.DeclList { - switch decl := decl.(type) { - case *syntax.ConstDecl: - resolveDecl(decl) - - case *syntax.FuncDecl: - resolveDecl(decl) - if phase >= 3 && decl.Body != nil { - resolveNode(decl.Body, true) - } - - case *syntax.TypeDecl: - if !decl.Alias || phase >= 2 { - resolveDecl(decl) - } - - case *syntax.VarDecl: - if phase >= 2 { - resolveNode(decl.Values, true) - resolveDecl(decl) - } - } - } - - if phase >= 5 { - syntax.Crawl(p.file, func(n syntax.Node) bool { - if name, ok := n.(*syntax.Name); ok { - if obj, ok := info.Uses[name]; ok { - resolveObj(name.Pos(), obj) - } - } - return false - }) - } - } - - for i := 0; i < len(later); i++ { - resolveNode(later[i], true) - } - later = nil - } - - return objs -} - // typeExprEndPos returns the position that noder would leave base.Pos // after parsing the given type expression. func typeExprEndPos(expr0 syntax.Expr) syntax.Pos { @@ -320,131 +79,3 @@ func lastFieldType(fields []*syntax.Field) syntax.Expr { } return fields[len(fields)-1].Type } - -// sumPos returns the position that noder.sum would produce for -// constant expression x. -func sumPos(x syntax.Expr) syntax.Pos { - orig := x - for { - switch x1 := x.(type) { - case *syntax.BasicLit: - assert(x1.Kind == syntax.StringLit) - return x1.Pos() - case *syntax.Operation: - assert(x1.Op == syntax.Add && x1.Y != nil) - if r, ok := x1.Y.(*syntax.BasicLit); ok { - assert(r.Kind == syntax.StringLit) - x = x1.X - continue - } - } - return orig.Pos() - } -} - -// funcParamsEndPos returns the value of base.Pos left by noder after -// processing a function signature. -func funcParamsEndPos(fn *ir.Func) src.XPos { - sig := fn.Nname.Type() - - fields := sig.Results().FieldSlice() - if len(fields) == 0 { - fields = sig.Params().FieldSlice() - if len(fields) == 0 { - fields = sig.Recvs().FieldSlice() - if len(fields) == 0 { - if fn.OClosure != nil { - return fn.Nname.Ntype.Pos() - } - return fn.Pos() - } - } - } - - return fields[len(fields)-1].Pos -} - -type dupTypes struct { - origs map[types2.Type]types2.Type -} - -func (d *dupTypes) orig(t types2.Type) types2.Type { - if orig, ok := d.origs[t]; ok { - return orig - } - return t -} - -func (d *dupTypes) add(t, orig types2.Type) { - if t == orig { - return - } - - if d.origs == nil { - d.origs = make(map[types2.Type]types2.Type) - } - assert(d.origs[t] == nil) - d.origs[t] = orig - - switch t := t.(type) { - case *types2.Pointer: - orig := orig.(*types2.Pointer) - d.add(t.Elem(), orig.Elem()) - - case *types2.Slice: - orig := orig.(*types2.Slice) - d.add(t.Elem(), orig.Elem()) - - case *types2.Map: - orig := orig.(*types2.Map) - d.add(t.Key(), orig.Key()) - d.add(t.Elem(), orig.Elem()) - - case *types2.Array: - orig := orig.(*types2.Array) - assert(t.Len() == orig.Len()) - d.add(t.Elem(), orig.Elem()) - - case *types2.Chan: - orig := orig.(*types2.Chan) - assert(t.Dir() == orig.Dir()) - d.add(t.Elem(), orig.Elem()) - - case *types2.Struct: - orig := orig.(*types2.Struct) - assert(t.NumFields() == orig.NumFields()) - for i := 0; i < t.NumFields(); i++ { - d.add(t.Field(i).Type(), orig.Field(i).Type()) - } - - case *types2.Interface: - orig := orig.(*types2.Interface) - assert(t.NumExplicitMethods() == orig.NumExplicitMethods()) - assert(t.NumEmbeddeds() == orig.NumEmbeddeds()) - for i := 0; i < t.NumExplicitMethods(); i++ { - d.add(t.ExplicitMethod(i).Type(), orig.ExplicitMethod(i).Type()) - } - for i := 0; i < t.NumEmbeddeds(); i++ { - d.add(t.EmbeddedType(i), orig.EmbeddedType(i)) - } - - case *types2.Signature: - orig := orig.(*types2.Signature) - assert((t.Recv() == nil) == (orig.Recv() == nil)) - if t.Recv() != nil { - d.add(t.Recv().Type(), orig.Recv().Type()) - } - d.add(t.Params(), orig.Params()) - d.add(t.Results(), orig.Results()) - - case *types2.Tuple: - orig := orig.(*types2.Tuple) - assert(t.Len() == orig.Len()) - for i := 0; i < t.Len(); i++ { - d.add(t.At(i).Type(), orig.At(i).Type()) - } - - default: - assert(types2.Identical(t, orig)) - } -} diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 5d17c534c1..60b0b7b40a 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -968,11 +968,7 @@ func (r *reader) funcBody(fn *ir.Func) { body := r.stmts() if body == nil { - pos := src.NoXPos - if quirksMode() { - pos = funcParamsEndPos(fn) - } - body = []ir.Node{typecheck.Stmt(ir.NewBlockStmt(pos, nil))} + body = []ir.Node{typecheck.Stmt(ir.NewBlockStmt(src.NoXPos, nil))} } fn.Body = body fn.Endlineno = r.pos() @@ -1291,18 +1287,6 @@ func (r *reader) stmt1(tag codeStmt, out *ir.Nodes) ir.Node { case stmtSwitch: return r.switchStmt(label) - - case stmtTypeDeclHack: - // fake "type _ = int" declaration to prevent inlining in quirks mode. - assert(quirksMode()) - - name := ir.NewDeclNameAt(src.NoXPos, ir.OTYPE, ir.BlankNode.Sym()) - name.SetAlias(true) - setType(name, types.Types[types.TINT]) - - n := ir.NewDecl(src.NoXPos, ir.ODCLTYPE, name) - n.SetTypecheck(1) - return n } } @@ -1712,22 +1696,15 @@ func (r *reader) funcLit() ir.Node { r.sync(syncFuncLit) pos := r.pos() - typPos := r.pos() xtype2 := r.signature(types.LocalPkg, nil) opos := pos - if quirksMode() { - opos = r.origPos(pos) - } fn := ir.NewClosureFunc(opos, r.curfn != nil) clo := fn.OClosure ir.NameClosure(clo, r.curfn) setType(fn.Nname, xtype2) - if quirksMode() { - fn.Nname.Ntype = ir.TypeNodeAt(typPos, xtype2) - } typecheck.Func(fn) setType(clo, fn.Type()) @@ -1767,23 +1744,6 @@ func (r *reader) op() ir.Op { // @@@ Package initialization func (r *reader) pkgInit(self *types.Pkg, target *ir.Package) { - if quirksMode() { - for i, n := 0, r.len(); i < n; i++ { - // Eagerly register position bases, so their filenames are - // assigned stable indices. - posBase := r.posBase() - _ = base.Ctxt.PosTable.XPos(src.MakePos(posBase, 0, 0)) - } - - for i, n := 0, r.len(); i < n; i++ { - // Eagerly resolve imported objects, so any filenames registered - // in the process are assigned stable indices too. - _, sym := r.qualifiedIdent() - typecheck.Resolve(ir.NewIdent(src.NoXPos, sym)) - assert(sym.Def != nil) - } - } - cgoPragmas := make([][]string, r.len()) for i := range cgoPragmas { cgoPragmas[i] = r.strings() @@ -2027,17 +1987,6 @@ func InlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExp body := ir.Nodes(r.curfn.Body) - // Quirk: If deadcode elimination turned a non-empty function into - // an empty one, we need to set the position for the empty block - // left behind to the inlined position for src.NoXPos, so that - // an empty string gets added into the DWARF file name listing at - // the appropriate index. - if quirksMode() && len(body) == 1 { - if block, ok := body[0].(*ir.BlockStmt); ok && len(block.List) == 0 { - block.SetPos(r.updatePos(src.NoXPos)) - } - } - // Quirkish: We need to eagerly prune variables added during // inlining, but removed by deadcode.FuncBody above. Unused // variables will get removed during stack frame layout anyway, but @@ -2218,8 +2167,8 @@ func (r *reader) importedDef() bool { } func MakeWrappers(target *ir.Package) { - // Only unified IR in non-quirks mode emits its own wrappers. - if base.Debug.Unified == 0 || quirksMode() { + // Only unified IR emits its own wrappers. + if base.Debug.Unified == 0 { return } diff --git a/src/cmd/compile/internal/noder/unified.go b/src/cmd/compile/internal/noder/unified.go index ec0012db4c..57bec43890 100644 --- a/src/cmd/compile/internal/noder/unified.go +++ b/src/cmd/compile/internal/noder/unified.go @@ -72,11 +72,7 @@ var localPkgReader *pkgReader func unified(noders []*noder) { inline.NewInline = InlineCall - if !quirksMode() { - writeNewExportFunc = writeNewExport - } else if base.Flag.G != 0 { - base.Errorf("cannot use -G and -d=quirksmode together") - } + writeNewExportFunc = writeNewExport newReadImportFunc = func(data string, pkg1 *types.Pkg, ctxt *types2.Context, packages map[string]*types2.Package) (pkg2 *types2.Package, err error) { pr := newPkgDecoder(pkg1.Path, data) diff --git a/src/cmd/compile/internal/noder/unified_test.go b/src/cmd/compile/internal/noder/unified_test.go deleted file mode 100644 index d7334df282..0000000000 --- a/src/cmd/compile/internal/noder/unified_test.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2021 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 noder_test - -import ( - "encoding/json" - "flag" - exec "internal/execabs" - "os" - "reflect" - "runtime" - "strings" - "testing" -) - -var ( - flagCmp = flag.Bool("cmp", false, "enable TestUnifiedCompare") - flagPkgs = flag.String("pkgs", "std", "list of packages to compare (ignored in -short mode)") - flagAll = flag.Bool("all", false, "enable testing of all GOOS/GOARCH targets") - flagParallel = flag.Bool("parallel", false, "test GOOS/GOARCH targets in parallel") -) - -// TestUnifiedCompare implements a test similar to running: -// -// $ go build -toolexec="toolstash -cmp" std -// -// The -pkgs flag controls the list of packages tested. -// -// By default, only the native GOOS/GOARCH target is enabled. The -all -// flag enables testing of non-native targets. The -parallel flag -// additionally enables testing of targets in parallel. -// -// Caution: Testing all targets is very resource intensive! On an IBM -// P920 (dual Intel Xeon Gold 6154 CPUs; 36 cores, 192GB RAM), testing -// all targets in parallel takes about 5 minutes. Using the 'go test' -// command's -run flag for subtest matching is recommended for less -// powerful machines. -func TestUnifiedCompare(t *testing.T) { - // TODO(mdempsky): Either re-enable or delete. Disabled for now to - // avoid impeding others' forward progress. - if !*flagCmp { - t.Skip("skipping TestUnifiedCompare (use -cmp to enable)") - } - - targets, err := exec.Command("go", "tool", "dist", "list").Output() - if err != nil { - t.Fatal(err) - } - - for _, target := range strings.Fields(string(targets)) { - t.Run(target, func(t *testing.T) { - parts := strings.Split(target, "/") - goos, goarch := parts[0], parts[1] - - if !(*flagAll || goos == runtime.GOOS && goarch == runtime.GOARCH) { - t.Skip("skipping non-native target (use -all to enable)") - } - if *flagParallel { - t.Parallel() - } - - pkgs1 := loadPackages(t, goos, goarch, "-d=unified=0 -d=inlfuncswithclosures=0 -d=unifiedquirks=1 -G=0") - pkgs2 := loadPackages(t, goos, goarch, "-d=unified=1 -d=inlfuncswithclosures=0 -d=unifiedquirks=1 -G=0") - - if len(pkgs1) != len(pkgs2) { - t.Fatalf("length mismatch: %v != %v", len(pkgs1), len(pkgs2)) - } - - for i := range pkgs1 { - pkg1 := pkgs1[i] - pkg2 := pkgs2[i] - - path := pkg1.ImportPath - if path != pkg2.ImportPath { - t.Fatalf("mismatched paths: %q != %q", path, pkg2.ImportPath) - } - - // Packages that don't have any source files (e.g., packages - // unsafe, embed/internal/embedtest, and cmd/internal/moddeps). - if pkg1.Export == "" && pkg2.Export == "" { - continue - } - - if pkg1.BuildID == pkg2.BuildID { - t.Errorf("package %q: build IDs unexpectedly matched", path) - } - - // Unlike toolstash -cmp, we're comparing the same compiler - // binary against itself, just with different flags. So we - // don't need to worry about skipping over mismatched version - // strings, but we do need to account for differing build IDs. - // - // Fortunately, build IDs are cryptographic 256-bit hashes, - // and cmd/go provides us with them up front. So we can just - // use them as delimeters to split the files, and then check - // that the substrings are all equal. - file1 := strings.Split(readFile(t, pkg1.Export), pkg1.BuildID) - file2 := strings.Split(readFile(t, pkg2.Export), pkg2.BuildID) - if !reflect.DeepEqual(file1, file2) { - t.Errorf("package %q: compile output differs", path) - } - } - }) - } -} - -type pkg struct { - ImportPath string - Export string - BuildID string - Incomplete bool -} - -func loadPackages(t *testing.T, goos, goarch, gcflags string) []pkg { - args := []string{"list", "-e", "-export", "-json", "-gcflags=all=" + gcflags, "--"} - if testing.Short() { - t.Log("short testing mode; only testing package runtime") - args = append(args, "runtime") - } else { - args = append(args, strings.Fields(*flagPkgs)...) - } - - cmd := exec.Command("go", args...) - cmd.Env = append(os.Environ(), "GOOS="+goos, "GOARCH="+goarch) - cmd.Stderr = os.Stderr - t.Logf("running %v", cmd) - stdout, err := cmd.StdoutPipe() - if err != nil { - t.Fatal(err) - } - if err := cmd.Start(); err != nil { - t.Fatal(err) - } - - var res []pkg - for dec := json.NewDecoder(stdout); dec.More(); { - var pkg pkg - if err := dec.Decode(&pkg); err != nil { - t.Fatal(err) - } - if pkg.Incomplete { - t.Fatalf("incomplete package: %q", pkg.ImportPath) - } - res = append(res, pkg) - } - if err := cmd.Wait(); err != nil { - t.Fatal(err) - } - return res -} - -func readFile(t *testing.T, name string) string { - buf, err := os.ReadFile(name) - if err != nil { - t.Fatal(err) - } - return string(buf) -} diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 46e8339120..97b3d878d0 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -8,7 +8,6 @@ package noder import ( "fmt" - "go/constant" "cmd/compile/internal/base" "cmd/compile/internal/ir" @@ -33,8 +32,6 @@ type pkgWriter struct { linknames map[types2.Object]string cgoPragmas [][]string - - dups dupTypes } func newPkgWriter(m posMap, pkg *types2.Package, info *types2.Info) *pkgWriter { @@ -251,10 +248,6 @@ func (w *writer) typInfo(info typeInfo) { // typIdx also reports whether typ is a derived type; that is, whether // its identity depends on type parameters. func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo { - if quirksMode() { - typ = pw.dups.orig(typ) - } - if idx, ok := pw.typsIdx[typ]; ok { return typeInfo{idx: idx, derived: false} } @@ -999,36 +992,9 @@ func (w *writer) declStmt(decl syntax.Decl) { default: w.p.unexpected("declaration", decl) - case *syntax.ConstDecl: - - case *syntax.TypeDecl: - // Quirk: The legacy inliner doesn't support inlining functions - // with type declarations. Unified IR doesn't have any need to - // write out type declarations explicitly (they're always looked - // up via global index tables instead), so we just write out a - // marker so the reader knows to synthesize a fake declaration to - // prevent inlining. - if quirksMode() { - w.code(stmtTypeDeclHack) - } + case *syntax.ConstDecl, *syntax.TypeDecl: case *syntax.VarDecl: - values := unpackListExpr(decl.Values) - - // Quirk: When N variables are declared with N initialization - // values, we need to decompose that into N interleaved - // declarations+initializations, because it leads to different - // (albeit semantically equivalent) code generation. - if quirksMode() && len(decl.NameList) == len(values) { - for i, name := range decl.NameList { - w.code(stmtAssign) - w.pos(decl) - w.exprList(values[i]) - w.assignList(name) - } - break - } - w.code(stmtAssign) w.pos(decl) w.exprList(decl.Values) @@ -1184,21 +1150,8 @@ func (w *writer) expr(expr syntax.Expr) { } if tv.Value != nil { - pos := expr.Pos() - if quirksMode() { - if obj != nil { - // Quirk: IR (and thus iexport) doesn't track position - // information for uses of declared objects. - pos = syntax.Pos{} - } else if tv.Value.Kind() == constant.String { - // Quirk: noder.sum picks a particular position for certain - // string concatenations. - pos = sumPos(expr) - } - } - w.code(exprConst) - w.pos(pos) + w.pos(expr.Pos()) w.typ(tv.Type) w.value(tv.Value) @@ -1377,15 +1330,11 @@ func (w *writer) funcLit(expr *syntax.FuncLit) { w.sync(syncFuncLit) w.pos(expr) - w.pos(expr.Type) // for QuirksMode w.signature(sig) w.len(len(closureVars)) for _, cv := range closureVars { w.pos(cv.pos) - if quirksMode() { - cv.pos = expr.Body.Rbrace - } w.useLocal(cv.pos, cv.obj) } @@ -1538,21 +1487,6 @@ func (c *declCollector) Visit(n syntax.Node) syntax.Visitor { } } - // Workaround for #46208. For variable declarations that - // declare multiple variables and have an explicit type - // expression, the type expression is evaluated multiple - // times. This affects toolstash -cmp, because iexport is - // sensitive to *types.Type pointer identity. - if quirksMode() && n.Type != nil { - tv, ok := pw.info.Types[n.Type] - assert(ok) - assert(tv.IsType()) - for _, name := range n.NameList { - obj := pw.info.Defs[name].(*types2.Var) - pw.dups.add(obj.Type(), tv.Type) - } - } - case *syntax.BlockStmt: if !c.withinFunc { copy := *c @@ -1621,20 +1555,6 @@ func (pw *pkgWriter) checkPragmas(p syntax.Pragma, allowed ir.PragmaFlag, embedO } func (w *writer) pkgInit(noders []*noder) { - if quirksMode() { - posBases := posBasesOf(noders) - w.len(len(posBases)) - for _, posBase := range posBases { - w.posBase(posBase) - } - - objs := importedObjsOf(w.p.curpkg, w.p.info, noders) - w.len(len(objs)) - for _, obj := range objs { - w.qualifiedIdent(obj) - } - } - w.len(len(w.p.cgoPragmas)) for _, cgoPragma := range w.p.cgoPragmas { w.strings(cgoPragma) |
