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.OGETCALLERPC, 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 e.discard(n.Index)
94 case ir.OSLICE, ir.OSLICEARR, ir.OSLICE3, ir.OSLICE3ARR, ir.OSLICESTR:
95 n := n.(*ir.SliceExpr)
96 e.expr(k.note(n, "slice"), n.X)
97 e.discard(n.Low)
98 e.discard(n.High)
99 e.discard(n.Max)
100
101 case ir.OCONV, ir.OCONVNOP:
102 n := n.(*ir.ConvExpr)
103 if (ir.ShouldCheckPtr(e.curfn, 2) || ir.ShouldAsanCheckPtr(e.curfn)) && n.Type().IsUnsafePtr() && n.X.Type().IsPtr() {
104
105
106
107
108
109
110 e.assignHeap(n.X, "conversion to unsafe.Pointer", n)
111 } else if n.Type().IsUnsafePtr() && n.X.Type().IsUintptr() {
112 e.unsafeValue(k, n.X)
113 } else {
114 e.expr(k, n.X)
115 }
116 case ir.OCONVIFACE:
117 n := n.(*ir.ConvExpr)
118 if !n.X.Type().IsInterface() && !types.IsDirectIface(n.X.Type()) {
119 k = e.spill(k, n)
120 }
121 e.expr(k.note(n, "interface-converted"), n.X)
122 case ir.OMAKEFACE:
123 n := n.(*ir.BinaryExpr)
124
125 e.expr(k, n.Y)
126 case ir.OITAB, ir.OIDATA, ir.OSPTR:
127 n := n.(*ir.UnaryExpr)
128 e.expr(k, n.X)
129 case ir.OSLICE2ARR:
130
131 n := n.(*ir.ConvExpr)
132 e.expr(k.deref(n, "slice-to-array"), n.X)
133 case ir.OSLICE2ARRPTR:
134
135 n := n.(*ir.ConvExpr)
136 e.expr(k, n.X)
137 case ir.ORECV:
138 n := n.(*ir.UnaryExpr)
139 e.discard(n.X)
140
141 case ir.OCALLMETH, ir.OCALLFUNC, ir.OCALLINTER, ir.OINLCALL,
142 ir.OLEN, ir.OCAP, ir.OMIN, ir.OMAX, ir.OCOMPLEX, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.OCOPY, ir.ORECOVERFP,
143 ir.OUNSAFEADD, ir.OUNSAFESLICE, ir.OUNSAFESTRING, ir.OUNSAFESTRINGDATA, ir.OUNSAFESLICEDATA:
144 e.call([]hole{k}, n)
145
146 case ir.ONEW:
147 n := n.(*ir.UnaryExpr)
148 e.spill(k, n)
149
150 case ir.OMAKESLICE:
151 n := n.(*ir.MakeExpr)
152 e.spill(k, n)
153 e.discard(n.Len)
154 e.discard(n.Cap)
155 case ir.OMAKECHAN:
156 n := n.(*ir.MakeExpr)
157 e.discard(n.Len)
158 case ir.OMAKEMAP:
159 n := n.(*ir.MakeExpr)
160 e.spill(k, n)
161 e.discard(n.Len)
162
163 case ir.OMETHVALUE:
164
165
166
167 n := n.(*ir.SelectorExpr)
168 closureK := e.spill(k, n)
169
170 m := n.Selection
171
172
173
174
175
176
177
178 var ks []hole
179 for i := m.Type.NumResults(); i > 0; i-- {
180 ks = append(ks, e.heapHole())
181 }
182 name, _ := m.Nname.(*ir.Name)
183 paramK := e.tagHole(ks, name, m.Type.Recv())
184
185 e.expr(e.teeHole(paramK, closureK), n.X)
186
187 case ir.OPTRLIT:
188 n := n.(*ir.AddrExpr)
189 e.expr(e.spill(k, n), n.X)
190
191 case ir.OARRAYLIT:
192 n := n.(*ir.CompLitExpr)
193 for _, elt := range n.List {
194 if elt.Op() == ir.OKEY {
195 elt = elt.(*ir.KeyExpr).Value
196 }
197 e.expr(k.note(n, "array literal element"), elt)
198 }
199
200 case ir.OSLICELIT:
201 n := n.(*ir.CompLitExpr)
202 k = e.spill(k, n)
203
204 for _, elt := range n.List {
205 if elt.Op() == ir.OKEY {
206 elt = elt.(*ir.KeyExpr).Value
207 }
208 e.expr(k.note(n, "slice-literal-element"), elt)
209 }
210
211 case ir.OSTRUCTLIT:
212 n := n.(*ir.CompLitExpr)
213 for _, elt := range n.List {
214 e.expr(k.note(n, "struct literal element"), elt.(*ir.StructKeyExpr).Value)
215 }
216
217 case ir.OMAPLIT:
218 n := n.(*ir.CompLitExpr)
219 e.spill(k, n)
220
221
222 for _, elt := range n.List {
223 elt := elt.(*ir.KeyExpr)
224 e.assignHeap(elt.Key, "map literal key", n)
225 e.assignHeap(elt.Value, "map literal value", n)
226 }
227
228 case ir.OCLOSURE:
229 n := n.(*ir.ClosureExpr)
230 k = e.spill(k, n)
231 e.closures = append(e.closures, closure{k, n})
232
233 if fn := n.Func; fn.IsHiddenClosure() {
234 for _, cv := range fn.ClosureVars {
235 if loc := e.oldLoc(cv); !loc.captured {
236 loc.captured = true
237
238
239
240 if loc.loopDepth == e.loopDepth {
241 loc.reassigned = false
242 }
243 }
244 }
245
246 for _, n := range fn.Dcl {
247
248
249
250
251
252 if n.Op() == ir.ONAME && n.Opt == nil {
253 e.with(fn).newLoc(n, true)
254 }
255 }
256 e.walkFunc(fn)
257 }
258
259 case ir.ORUNES2STR, ir.OBYTES2STR, ir.OSTR2RUNES, ir.OSTR2BYTES, ir.ORUNESTR:
260 n := n.(*ir.ConvExpr)
261 e.spill(k, n)
262 e.discard(n.X)
263
264 case ir.OADDSTR:
265 n := n.(*ir.AddStringExpr)
266 e.spill(k, n)
267
268
269
270 e.discards(n.List)
271
272 case ir.ODYNAMICTYPE:
273
274 }
275 }
276
277
278
279 func (e *escape) unsafeValue(k hole, n ir.Node) {
280 if n.Type().Kind() != types.TUINTPTR {
281 base.Fatalf("unexpected type %v for %v", n.Type(), n)
282 }
283 if k.addrtaken {
284 base.Fatalf("unexpected addrtaken")
285 }
286
287 e.stmts(n.Init())
288
289 switch n.Op() {
290 case ir.OCONV, ir.OCONVNOP:
291 n := n.(*ir.ConvExpr)
292 if n.X.Type().IsUnsafePtr() {
293 e.expr(k, n.X)
294 } else {
295 e.discard(n.X)
296 }
297 case ir.ODOTPTR:
298 n := n.(*ir.SelectorExpr)
299 if ir.IsReflectHeaderDataField(n) {
300 e.expr(k.deref(n, "reflect.Header.Data"), n.X)
301 } else {
302 e.discard(n.X)
303 }
304 case ir.OPLUS, ir.ONEG, ir.OBITNOT:
305 n := n.(*ir.UnaryExpr)
306 e.unsafeValue(k, n.X)
307 case ir.OADD, ir.OSUB, ir.OOR, ir.OXOR, ir.OMUL, ir.ODIV, ir.OMOD, ir.OAND, ir.OANDNOT:
308 n := n.(*ir.BinaryExpr)
309 e.unsafeValue(k, n.X)
310 e.unsafeValue(k, n.Y)
311 case ir.OLSH, ir.ORSH:
312 n := n.(*ir.BinaryExpr)
313 e.unsafeValue(k, n.X)
314
315
316 e.discard(n.Y)
317 default:
318 e.exprSkipInit(e.discardHole(), n)
319 }
320 }
321
322
323
324 func (e *escape) discard(n ir.Node) {
325 e.expr(e.discardHole(), n)
326 }
327
328 func (e *escape) discards(l ir.Nodes) {
329 for _, n := range l {
330 e.discard(n)
331 }
332 }
333
334
335
336
337 func (e *escape) spill(k hole, n ir.Node) hole {
338 loc := e.newLoc(n, false)
339 e.flow(k.addr(n, "spill"), loc)
340 return loc.asHole()
341 }
342
View as plain text