@@ -42,40 +42,42 @@ import (
4242 "cmd/compile/internal/reflectdata"
4343 "cmd/compile/internal/typecheck"
4444 "cmd/compile/internal/types"
45- "fmt "
45+ "cmd/internal/src "
4646)
4747
4848// getNameFromNode tries to iteratively peel down the node to
4949// get the name.
5050func getNameFromNode (n ir.Node ) * ir.Name {
51- var ret * ir.Name
52- if n .Op () == ir .ONAME {
53- ret = n .(* ir.Name )
54- } else {
55- // avoid infinite recursion on circular referencing nodes.
56- seen := map [ir.Node ]bool {n : true }
57- var findName func (ir.Node ) bool
58- findName = func (a ir.Node ) bool {
59- if a .Op () == ir .ONAME {
60- ret = a .(* ir.Name )
61- return true
62- }
63- if ! seen [a ] {
64- seen [a ] = true
65- return ir .DoChildren (a , findName )
66- }
67- return false
51+ // Tries to iteratively peel down the node to get the names.
52+ for n != nil {
53+ switch n .Op () {
54+ case ir .ONAME :
55+ // Found the name, stop the loop.
56+ return n .(* ir.Name )
57+ case ir .OSLICE , ir .OSLICE3 :
58+ n = n .(* ir.SliceExpr ).X
59+ case ir .ODOT :
60+ n = n .(* ir.SelectorExpr ).X
61+ case ir .OCONV , ir .OCONVIFACE , ir .OCONVNOP :
62+ n = n .(* ir.ConvExpr ).X
63+ case ir .OADDR :
64+ n = n .(* ir.AddrExpr ).X
65+ case ir .ODOTPTR :
66+ n = n .(* ir.SelectorExpr ).X
67+ case ir .OINDEX , ir .OINDEXMAP :
68+ n = n .(* ir.IndexExpr ).X
69+ default :
70+ n = nil
6871 }
69- ir .DoChildren (n , findName )
7072 }
71- return ret
73+ return nil
7274}
7375
7476// keepAliveAt returns a statement that is either curNode, or a
7577// block containing curNode followed by a call to runtime.keepAlive for each
76- // ONAME in ns. These calls ensure that names in ns will be live until
78+ // node in ns. These calls ensure that nodes in ns will be live until
7779// after curNode's execution.
78- func keepAliveAt (ns []* ir.Name , curNode ir.Node ) ir.Node {
80+ func keepAliveAt (ns []ir.Node , curNode ir.Node ) ir.Node {
7981 if len (ns ) == 0 {
8082 return curNode
8183 }
@@ -109,12 +111,12 @@ func keepAliveAt(ns []*ir.Name, curNode ir.Node) ir.Node {
109111 return ir .NewBlockStmt (pos , calls )
110112}
111113
112- func debugName (name * ir.Name , line string ) {
113- if base .Flag .LowerM > 0 {
114+ func debugName (name * ir.Name , pos src. XPos ) {
115+ if base .Flag .LowerM > 1 {
114116 if name .Linksym () != nil {
115- fmt . Printf ( "%v: % s will be kept alive\n " , line , name .Linksym ().Name )
117+ base . WarnfAt ( pos , "% s will be kept alive" , name .Linksym ().Name )
116118 } else {
117- fmt . Printf ( "%v: expr will be kept alive\n " , line )
119+ base . WarnfAt ( pos , " expr will be kept alive" )
118120 }
119121 }
120122}
@@ -129,29 +131,50 @@ func preserveStmt(curFn *ir.Func, stmt ir.Node) (ret ir.Node) {
129131 // Peel down struct and slice indexing to get the names
130132 name := getNameFromNode (n .X )
131133 if name != nil {
132- debugName (name , ir .Line (stmt ))
133- ret = keepAliveAt ([]* ir.Name {name }, n )
134+ debugName (name , n .Pos ())
135+ ret = keepAliveAt ([]ir.Node {name }, n )
136+ } else if deref := n .X .(* ir.StarExpr ); deref != nil {
137+ ret = keepAliveAt ([]ir.Node {deref }, n )
138+ if base .Flag .LowerM > 1 {
139+ base .WarnfAt (n .Pos (), "dereference will be kept alive" )
140+ }
141+ } else if base .Flag .LowerM > 1 {
142+ base .WarnfAt (n .Pos (), "expr is unknown to bloop pass" )
134143 }
135144 case * ir.AssignListStmt :
136- names := []* ir.Name {}
145+ ns := []ir.Node {}
137146 for _ , lhs := range n .Lhs {
138147 name := getNameFromNode (lhs )
139148 if name != nil {
140- debugName (name , ir .Line (stmt ))
141- names = append (names , name )
149+ debugName (name , n .Pos ())
150+ ns = append (ns , name )
151+ } else if deref := lhs .(* ir.StarExpr ); deref != nil {
152+ ns = append (ns , deref )
153+ if base .Flag .LowerM > 1 {
154+ base .WarnfAt (n .Pos (), "dereference will be kept alive" )
155+ }
156+ } else if base .Flag .LowerM > 1 {
157+ base .WarnfAt (n .Pos (), "expr is unknown to bloop pass" )
142158 }
143159 }
144- ret = keepAliveAt (names , n )
160+ ret = keepAliveAt (ns , n )
145161 case * ir.AssignOpStmt :
146162 name := getNameFromNode (n .X )
147163 if name != nil {
148- debugName (name , ir .Line (stmt ))
149- ret = keepAliveAt ([]* ir.Name {name }, n )
164+ debugName (name , n .Pos ())
165+ ret = keepAliveAt ([]ir.Node {name }, n )
166+ } else if deref := n .X .(* ir.StarExpr ); deref != nil {
167+ ret = keepAliveAt ([]ir.Node {deref }, n )
168+ if base .Flag .LowerM > 1 {
169+ base .WarnfAt (n .Pos (), "dereference will be kept alive" )
170+ }
171+ } else if base .Flag .LowerM > 1 {
172+ base .WarnfAt (n .Pos (), "expr is unknown to bloop pass" )
150173 }
151174 case * ir.CallExpr :
152- names := []* ir.Name {}
153175 curNode := stmt
154176 if n .Fun != nil && n .Fun .Type () != nil && n .Fun .Type ().NumResults () != 0 {
177+ ns := []ir.Node {}
155178 // This function's results are not assigned, assign them to
156179 // auto tmps and then keepAliveAt these autos.
157180 // Note: markStmt assumes the context that it's called - this CallExpr is
@@ -161,7 +184,7 @@ func preserveStmt(curFn *ir.Func, stmt ir.Node) (ret ir.Node) {
161184 for i , res := range results {
162185 tmp := typecheck .TempAt (n .Pos (), curFn , res .Type )
163186 lhs [i ] = tmp
164- names = append (names , tmp )
187+ ns = append (ns , tmp )
165188 }
166189
167190 // Create an assignment statement.
@@ -174,33 +197,35 @@ func preserveStmt(curFn *ir.Func, stmt ir.Node) (ret ir.Node) {
174197 if len (results ) > 1 {
175198 plural = "s"
176199 }
177- if base .Flag .LowerM > 0 {
178- fmt . Printf ( "%v: function result%s will be kept alive\n " , ir . Line ( stmt ) , plural )
200+ if base .Flag .LowerM > 1 {
201+ base . WarnfAt ( n . Pos (), " function result%s will be kept alive" , plural )
179202 }
203+ ret = keepAliveAt (ns , curNode )
180204 } else {
181205 // This function probably doesn't return anything, keep its args alive.
182206 argTmps := []ir.Node {}
207+ names := []ir.Node {}
183208 for i , a := range n .Args {
184209 if name := getNameFromNode (a ); name != nil {
185210 // If they are name, keep them alive directly.
186- debugName (name , ir . Line ( stmt ))
211+ debugName (name , n . Pos ( ))
187212 names = append (names , name )
188213 } else if a .Op () == ir .OSLICELIT {
189214 // variadic args are encoded as slice literal.
190215 s := a .(* ir.CompLitExpr )
191- ns := []* ir.Name {}
192- for i , n := range s .List {
193- if name := getNameFromNode (n ); name != nil {
194- debugName (name , ir . Line ( a ))
216+ ns := []ir.Node {}
217+ for i , elem := range s .List {
218+ if name := getNameFromNode (elem ); name != nil {
219+ debugName (name , n . Pos ( ))
195220 ns = append (ns , name )
196221 } else {
197222 // We need a temporary to save this arg.
198- tmp := typecheck .TempAt (n .Pos (), curFn , n .Type ())
199- argTmps = append (argTmps , typecheck .AssignExpr (ir .NewAssignStmt (n .Pos (), tmp , n )))
223+ tmp := typecheck .TempAt (elem .Pos (), curFn , elem .Type ())
224+ argTmps = append (argTmps , typecheck .AssignExpr (ir .NewAssignStmt (elem .Pos (), tmp , elem )))
200225 names = append (names , tmp )
201226 s .List [i ] = tmp
202- if base .Flag .LowerM > 0 {
203- fmt . Printf ( "%v: function arg will be kept alive\n " , ir . Line ( n ) )
227+ if base .Flag .LowerM > 1 {
228+ base . WarnfAt ( n . Pos (), " function arg will be kept alive" )
204229 }
205230 }
206231 }
@@ -212,17 +237,17 @@ func preserveStmt(curFn *ir.Func, stmt ir.Node) (ret ir.Node) {
212237 argTmps = append (argTmps , typecheck .AssignExpr (ir .NewAssignStmt (n .Pos (), tmp , a )))
213238 names = append (names , tmp )
214239 n .Args [i ] = tmp
215- if base .Flag .LowerM > 0 {
216- fmt . Printf ( "%v: function arg will be kept alive\n " , ir . Line ( stmt ) )
240+ if base .Flag .LowerM > 1 {
241+ base . WarnfAt ( n . Pos (), " function arg will be kept alive" )
217242 }
218243 }
219244 }
220245 if len (argTmps ) > 0 {
221246 argTmps = append (argTmps , n )
222247 curNode = ir .NewBlockStmt (n .Pos (), argTmps )
223248 }
249+ ret = keepAliveAt (names , curNode )
224250 }
225- ret = keepAliveAt (names , curNode )
226251 }
227252 return
228253}
@@ -282,6 +307,8 @@ func (e editor) edit(n ir.Node) ir.Node {
282307 preserveStmts (e .curFn , n .Body )
283308 case * ir.CommClause :
284309 preserveStmts (e .curFn , n .Body )
310+ case * ir.RangeStmt :
311+ preserveStmts (e .curFn , n .Body )
285312 }
286313 }
287314 return n
0 commit comments