]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.regabi] cmd/compile: fix package-initialization order
authorMatthew Dempsky <mdempsky@google.com>
Fri, 1 Jan 2021 07:45:36 +0000 (23:45 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Fri, 1 Jan 2021 10:52:33 +0000 (10:52 +0000)
This CL fixes package initialization order by creating the init task
before the general deadcode-removal pass.

It also changes noder to emit zero-initialization assignments (i.e.,
OAS with nil RHS) for package-block variables, so that initOrder can
tell the variables still need initialization. To allow this, we need
to also extend the static-init code to recognize zero-initialization
assignments.

This doesn't pass toolstash -cmp, because it reorders some package
initialization routines.

Fixes #43444.

Change-Id: I0da7996a62c85e15e97ce965298127e075390a7e
Reviewed-on: https://go-review.googlesource.com/c/go/+/280976
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/noder/noder.go
src/cmd/compile/internal/pkginit/init.go
src/cmd/compile/internal/staticinit/sched.go
test/fixedbugs/issue43444.go [new file with mode: 0644]
test/fixedbugs/issue43444.out [new file with mode: 0644]

index df6a9d8e4518f601bcfc762dea90905ce7f08f37..c1f51e4f1dee36a0d8a99dadf0ddc96dbdd176b6 100644 (file)
@@ -208,6 +208,11 @@ func Main(archInit func(*ssagen.ArchInfo)) {
        dwarfgen.RecordPackageName()
        ssagen.CgoSymABIs()
 
+       // Build init task.
+       if initTask := pkginit.Task(); initTask != nil {
+               typecheck.Export(initTask)
+       }
+
        // Compute Addrtaken for names.
        // We need to wait until typechecking is done so that when we see &x[i]
        // we know that x has its address taken if x is an array, but not if x is a slice.
@@ -249,11 +254,6 @@ func Main(archInit func(*ssagen.ArchInfo)) {
                typecheck.AllImportedBodies()
        }
 
-       // Build init task.
-       if initTask := pkginit.Task(); initTask != nil {
-               typecheck.Export(initTask)
-       }
-
        // Inlining
        base.Timer.Start("fe", "inlining")
        if base.Flag.LowerL != 0 {
index 29bfde3ff23cc0cea3c2150fd98ed150cf345466..cc8a1c7c89a4f9faff4b5250d00786f6fa107567 100644 (file)
@@ -474,24 +474,15 @@ func (p *noder) varDecl(decl *syntax.VarDecl) []ir.Node {
                p.checkUnused(pragma)
        }
 
-       p.setlineno(decl)
-       return DeclVars(names, typ, exprs)
-}
-
-// declare variables from grammar
-// new_name_list (type | [type] = expr_list)
-func DeclVars(vl []*ir.Name, t ir.Ntype, el []ir.Node) []ir.Node {
        var init []ir.Node
-       doexpr := len(el) > 0
+       p.setlineno(decl)
 
-       if len(el) == 1 && len(vl) > 1 {
-               e := el[0]
-               as2 := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, nil)
-               as2.Rhs = []ir.Node{e}
-               for _, v := range vl {
+       if len(names) > 1 && len(exprs) == 1 {
+               as2 := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, exprs)
+               for _, v := range names {
                        as2.Lhs.Append(v)
                        typecheck.Declare(v, typecheck.DeclContext)
-                       v.Ntype = t
+                       v.Ntype = typ
                        v.Defn = as2
                        if ir.CurFunc != nil {
                                init = append(init, ir.NewDecl(base.Pos, ir.ODCL, v))
@@ -501,34 +492,29 @@ func DeclVars(vl []*ir.Name, t ir.Ntype, el []ir.Node) []ir.Node {
                return append(init, as2)
        }
 
-       for i, v := range vl {
+       for i, v := range names {
                var e ir.Node
-               if doexpr {
-                       if i >= len(el) {
-                               base.Errorf("assignment mismatch: %d variables but %d values", len(vl), len(el))
-                               break
-                       }
-                       e = el[i]
+               if i < len(exprs) {
+                       e = exprs[i]
                }
 
                typecheck.Declare(v, typecheck.DeclContext)
-               v.Ntype = t
+               v.Ntype = typ
 
-               if e != nil || ir.CurFunc != nil || ir.IsBlank(v) {
-                       if ir.CurFunc != nil {
-                               init = append(init, ir.NewDecl(base.Pos, ir.ODCL, v))
-                       }
-                       as := ir.NewAssignStmt(base.Pos, v, e)
-                       init = append(init, as)
-                       if e != nil {
-                               v.Defn = as
-                       }
+               if ir.CurFunc != nil {
+                       init = append(init, ir.NewDecl(base.Pos, ir.ODCL, v))
+               }
+               as := ir.NewAssignStmt(base.Pos, v, e)
+               init = append(init, as)
+               if e != nil || ir.CurFunc == nil {
+                       v.Defn = as
                }
        }
 
-       if len(el) > len(vl) {
-               base.Errorf("assignment mismatch: %d variables but %d values", len(vl), len(el))
+       if len(exprs) != 0 && len(names) != len(exprs) {
+               base.Errorf("assignment mismatch: %d variables but %d values", len(names), len(exprs))
        }
+
        return init
 }
 
index f1ffbb5933db1e10c2861b207b2ee3b893c57f18..24fe1a76280d814d9a0f31e9b3509c2ec4df97a7 100644 (file)
@@ -6,6 +6,7 @@ package pkginit
 
 import (
        "cmd/compile/internal/base"
+       "cmd/compile/internal/deadcode"
        "cmd/compile/internal/ir"
        "cmd/compile/internal/objw"
        "cmd/compile/internal/typecheck"
@@ -68,6 +69,9 @@ func Task() *ir.Name {
 
        // Record user init functions.
        for _, fn := range typecheck.Target.Inits {
+               // Must happen after initOrder; see #43444.
+               deadcode.Func(fn)
+
                // Skip init functions with empty bodies.
                if len(fn.Body) == 1 {
                        if stmt := fn.Body[0]; stmt.Op() == ir.OBLOCK && len(stmt.(*ir.BlockStmt).List) == 0 {
index 1b0af1b05d4ae610a79585588fa35710c29cf73d..8e4ce559548166efbeaf04d2053342bb065a6e68 100644 (file)
@@ -86,17 +86,22 @@ func (s *Schedule) staticcopy(l *ir.Name, loff int64, rn *ir.Name, typ *types.Ty
        if rn.Class_ != ir.PEXTERN || rn.Sym().Pkg != types.LocalPkg {
                return false
        }
-       if rn.Defn == nil { // probably zeroed but perhaps supplied externally and of unknown value
-               return false
-       }
        if rn.Defn.Op() != ir.OAS {
                return false
        }
        if rn.Type().IsString() { // perhaps overwritten by cmd/link -X (#34675)
                return false
        }
+       if rn.Embed != nil {
+               return false
+       }
        orig := rn
        r := rn.Defn.(*ir.AssignStmt).Y
+       if r == nil {
+               // No explicit initialization value. Probably zeroed but perhaps
+               // supplied externally and of unknown value.
+               return false
+       }
 
        for r.Op() == ir.OCONVNOP && !types.Identical(r.Type(), typ) {
                r = r.(*ir.ConvExpr).X
@@ -185,6 +190,11 @@ func (s *Schedule) staticcopy(l *ir.Name, loff int64, rn *ir.Name, typ *types.Ty
 }
 
 func (s *Schedule) StaticAssign(l *ir.Name, loff int64, r ir.Node, typ *types.Type) bool {
+       if r == nil {
+               // No explicit initialization value. Either zero or supplied
+               // externally.
+               return true
+       }
        for r.Op() == ir.OCONVNOP {
                r = r.(*ir.ConvExpr).X
        }
diff --git a/test/fixedbugs/issue43444.go b/test/fixedbugs/issue43444.go
new file mode 100644 (file)
index 0000000..c430e1b
--- /dev/null
@@ -0,0 +1,28 @@
+// run
+
+package main
+
+var sp = ""
+
+func f(name string, _ ...interface{}) int {
+       print(sp, name)
+       sp = " "
+       return 0
+}
+
+var a = f("a", x)
+var b = f("b", y)
+var c = f("c", z)
+var d = func() int {
+       if false {
+               _ = z
+       }
+       return f("d")
+}()
+var e = f("e")
+
+var x int
+var y int = 42
+var z int = func() int { return 42 }()
+
+func main() { println() }
diff --git a/test/fixedbugs/issue43444.out b/test/fixedbugs/issue43444.out
new file mode 100644 (file)
index 0000000..22d6a0d
--- /dev/null
@@ -0,0 +1 @@
+e a b c d