1
2
3
4
5 package escape
6
7 import (
8 "cmd/compile/internal/base"
9 "cmd/compile/internal/ir"
10 "cmd/compile/internal/types"
11 )
12
13
14
15 func (e *escape) expr(k hole, n ir.Node) {
16 if n == nil {
17 return
18 }
19 e.stmts(n.Init())
20 e.exprSkipInit(k, n)
21 }
22
23 func (e *escape) exprSkipInit(k hole, n ir.Node) {
24 if n == nil {
25 return
26 }
27
28 lno := ir.SetPos(n)
29 defer func() {
30 base.Pos = lno
31 }()
32
33 if k.derefs >= 0 && !n.Type().IsUntyped() && !n.Type().HasPointers() {
34 k.dst = &e.blankLoc
35 }
36
37 switch n.Op() {
38 default:
39 base.Fatalf("unexpected expr: %s %v", n.Op().String(), n)
40
41 case ir.OLITERAL, ir.ONIL, ir.OGETG, ir.OGETCALLERSP, ir.OTYPE, ir.OMETHEXPR, ir.OLINKSYMOFFSET:
42
43
44 case ir.ONAME:
45 n := n.(*ir.Name)
46 if n.Class == ir.PFUNC || n.Class == ir.PEXTERN {
47 return
48 }
49 e.flow(k, e.oldLoc(n))
50
51 case ir.OPLUS, ir.ONEG, ir.OBITNOT, ir.ONOT:
52 n := n.(*ir.UnaryExpr)
53 e.discard(n.X)
54 case ir.OADD, ir.OSUB, ir.OOR, ir.OXOR, ir.OMUL, ir.ODIV, ir.OMOD, ir.OLSH, ir.ORSH, ir.OAND, ir.OANDNOT, ir.OEQ, ir.ONE, ir.OLT, ir.OLE, ir.OGT, ir.OGE:
55 n := n.(*ir.BinaryExpr)
56 e.discard(n.X)
57 e.discard(n.Y)
58 case ir.OANDAND, ir.OOROR:
59 n := n.(*ir.LogicalExpr)
60 e.discard(n.X)
61 e.discard(n.Y)
62 case ir.OADDR:
63 n := n.(*ir.AddrExpr)
64 e.expr(k.addr(n, "address-of"), n.X)
65 case ir.ODEREF:
66 n := n.(*ir.StarExpr)
67 e.expr(k.deref(n, "indirection"), n.X)
68 case ir.ODOT, ir.ODOTMETH, ir.ODOTINTER:
69 n := n.(*ir.SelectorExpr)
70 e.expr(k.note(n, "dot"), n.X)
71 case ir.ODOTPTR:
72 n := n.(*ir.SelectorExpr)
73 e.expr(k.deref(n, "dot of pointer"), n.X)
74 case ir.ODOTTYPE, ir.ODOTTYPE2:
75 n := n.(*ir.TypeAssertExpr)
76 e.expr(k.dotType(n.Type(), n, "dot"), n.X)
77 case ir.ODYNAMICDOTTYPE, ir.ODYNAMICDOTTYPE2:
78 n := n.(*ir.DynamicTypeAssertExpr)
79 e.expr(k.dotType(n.Type(), n, "dot"), n.X)
80
81 case ir.OINDEX:
82 n := n.(*ir.IndexExpr)
83 if n.X.Type().IsArray() {
84 e.expr(k.note(n, "fixed-array-index-of"), n.X)
85 } else {
86
87 e.expr(k.deref(n, "dot of pointer"), n.X)
88 }
89 e.discard(n.Index)
90 case ir.OINDEXMAP:
91 n := n.(*ir.IndexExpr)
92 e.discard(n.X)
93
94
95 e.discard(n.Index)
96 case ir.OSLICE, ir.OSLICEARR, ir.OSLICE3, ir.OSLICE3ARR, ir.OSLICESTR:
97 n := n.(*ir.SliceExpr)
98 e.expr(k.note(n, "slice"), n.X)
99 e.discard(n.Low)
100 e.discard(n.High)
101 e.discard(n.Max)
102
103 case ir.OCONV, ir.OCONVNOP:
104 n := n.(*ir.ConvExpr)
105 if (ir.ShouldCheckPtr(e.curfn, 2) || ir.ShouldAsanCheckPtr(e.curfn)) && n.Type().IsUnsafePtr() && n.X.Type().IsPtr() {
106
107
108
109
110
111
112 e.assignHeap(n.X, "conversion to unsafe.Pointer", n)
113 } else if n.Type().IsUnsafePtr() && n.X.Type().IsUintptr() {
114 e.unsafeValue(k, n.X)
115 } else {
116 e.expr(k, n.X)
117 }
118 case ir.OCONVIFACE:
119 n := n.(*ir.ConvExpr)
120 if !n.X.Type().IsInterface() && !types.IsDirectIface(n.X.Type()) {
121 k = e.spill(k, n)
122 }
123 e.expr(k.note(n, "interface-converted"), n.X)
124 case ir.OMAKEFACE:
125 n := n.(*ir.BinaryExpr)
126
127 e.expr(k, n.Y)
128 case ir.OITAB, ir.OIDATA, ir.OSPTR:
129 n := n.(*ir.UnaryExpr)
130 e.expr(k, n.X)
131 case ir.OSLICE2ARR:
132
133 n := n.(*ir.ConvExpr)
134 e.expr(k.deref(n, "slice-to-array"), n.X)
135 case ir.OSLICE2ARRPTR:
136
137 n := n.(*ir.ConvExpr)
138 e.expr(k, n.X)
139 case ir.ORECV:
140 n := n.(*ir.UnaryExpr)
141 e.discard(n.X)
142
143 case ir.OCALLMETH, ir.OCALLFUNC, ir.OCALLINTER, ir.OINLCALL,
144 ir.OLEN, ir.OCAP, ir.OMIN, ir.OMAX, ir.OCOMPLEX, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.OCOPY, ir.ORECOVER,
145 ir.OUNSAFEADD, ir.OUNSAFESLICE, ir.OUNSAFESTRING, ir.OUNSAFESTRINGDATA, ir.OUNSAFESLICEDATA:
146 e.call([]hole{k}, n)
147
148 case ir.ONEW:
149 n := n.(*ir.UnaryExpr)
150 e.spill(k, n)
151
152 case ir.OMAKESLICE:
153 n := n.(*ir.MakeExpr)
154 e.spill(k, n)
155 e.discard(n.Len)
156 e.discard(n.Cap)
157 case ir.OMAKECHAN:
158 n := n.(*ir.MakeExpr)
159 e.discard(n.Len)
160 case ir.OMAKEMAP:
161 n := n.(*ir.MakeExpr)
162 e.spill(k, n)
163 e.discard(n.Len)
164
165 case ir.OMETHVALUE:
166
167
168
169 n := n.(*ir.SelectorExpr)
170 closureK := e.spill(k, n)
171
172 m := n.Selection
173
174
175
176
177
178
179
180 var ks []hole
181 for i := m.Type.NumResults(); i > 0; i-- {
182 ks = append(ks, e.heapHole())
183 }
184 name, _ := m.Nname.(*ir.Name)
185 paramK := e.tagHole(ks, name, m.Type.Recv())
186
187 e.expr(e.teeHole(paramK, closureK), n.X)
188
189 case ir.OPTRLIT:
190 n := n.(*ir.AddrExpr)
191 e.expr(e.spill(k, n), n.X)
192
193 case ir.OARRAYLIT:
194 n := n.(*ir.CompLitExpr)
195 for _, elt := range n.List {
196 if elt.Op() == ir.OKEY {
197 elt = elt.(*ir.KeyExpr).Value
198 }
199 e.expr(k.note(n, "array literal element"), elt)
200 }
201
202 case ir.OSLICELIT:
203 n := n.(*ir.CompLitExpr)
204 k = e.spill(k, n)
205
206 for _, elt := range n.List {
207 if elt.Op() == ir.OKEY {
208 elt = elt.(*ir.KeyExpr).Value
209 }
210 e.expr(k.note(n, "slice-literal-element"), elt)
211 }
212
213 case ir.OSTRUCTLIT:
214 n := n.(*ir.CompLitExpr)
215 for _, elt := range n.List {
216 e.expr(k.note(n, "struct literal element"), elt.(*ir.StructKeyExpr).Value)
217 }
218
219 case ir.OMAPLIT:
220 n := n.(*ir.CompLitExpr)
221 e.spill(k, n)
222
223
224 for _, elt := range n.List {
225 elt := elt.(*ir.KeyExpr)
226 e.assignHeap(elt.Key, "map literal key", n)
227 e.assignHeap(elt.Value, "map literal value", n)
228 }
229
230 case ir.OCLOSURE:
231 n := n.(*ir.ClosureExpr)
232 k = e.spill(k, n)
233 e.closures = append(e.closures, closure{k, n})
234
235 if fn := n.Func; fn.IsClosure() {
236 for _, cv := range fn.ClosureVars {
237 if loc := e.oldLoc(cv); !loc.captured {
238 loc.captured = true
239
240
241
242 if loc.loopDepth == e.loopDepth {
243 loc.reassigned = false
244 }
245 }
246 }
247
248 for _, n := range fn.Dcl {
249
250
251
252
253
254 if n.Op() == ir.ONAME && n.Opt == nil {
255 e.with(fn).newLoc(n, true)
256 }
257 }
258 e.walkFunc(fn)
259 }
260
261 case ir.ORUNES2STR, ir.OBYTES2STR, ir.OSTR2RUNES, ir.OSTR2BYTES, ir.ORUNESTR:
262 n := n.(*ir.ConvExpr)
263 e.spill(k, n)
264 e.discard(n.X)
265
266 case ir.OADDSTR:
267 n := n.(*ir.AddStringExpr)
268 e.spill(k, n)
269
270
271
272 e.discards(n.List)
273
274 case ir.ODYNAMICTYPE:
275
276 }
277 }
278
279
280
281 func (e *escape) unsafeValue(k hole, n ir.Node) {
282 if n.Type().Kind() != types.TUINTPTR {
283 base.Fatalf("unexpected type %v for %v", n.Type(), n)
284 }
285 if k.addrtaken {
286 base.Fatalf("unexpected addrtaken")
287 }
288
289 e.stmts(n.Init())
290
291 switch n.Op() {
292 case ir.OCONV, ir.OCONVNOP:
293 n := n.(*ir.ConvExpr)
294 if n.X.Type().IsUnsafePtr() {
295 e.expr(k, n.X)
296 } else {
297 e.discard(n.X)
298 }
299 case ir.ODOTPTR:
300 n := n.(*ir.SelectorExpr)
301 if ir.IsReflectHeaderDataField(n) {
302 e.expr(k.deref(n, "reflect.Header.Data"), n.X)
303 } else {
304 e.discard(n.X)
305 }
306 case ir.OPLUS, ir.ONEG, ir.OBITNOT:
307 n := n.(*ir.UnaryExpr)
308 e.unsafeValue(k, n.X)
309 case ir.OADD, ir.OSUB, ir.OOR, ir.OXOR, ir.OMUL, ir.ODIV, ir.OMOD, ir.OAND, ir.OANDNOT:
310 n := n.(*ir.BinaryExpr)
311 e.unsafeValue(k, n.X)
312 e.unsafeValue(k, n.Y)
313 case ir.OLSH, ir.ORSH:
314 n := n.(*ir.BinaryExpr)
315 e.unsafeValue(k, n.X)
316
317
318 e.discard(n.Y)
319 default:
320 e.exprSkipInit(e.discardHole(), n)
321 }
322 }
323
324
325
326 func (e *escape) discard(n ir.Node) {
327 e.expr(e.discardHole(), n)
328 }
329
330 func (e *escape) discards(l ir.Nodes) {
331 for _, n := range l {
332 e.discard(n)
333 }
334 }
335
336
337
338
339 func (e *escape) spill(k hole, n ir.Node) hole {
340 loc := e.newLoc(n, false)
341 e.flow(k.addr(n, "spill"), loc)
342 return loc.asHole()
343 }
344
View as plain text