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