1
2
3
4
5 package escape
6
7 import (
8 "cmd/compile/internal/ir"
9 "cmd/compile/internal/typecheck"
10 )
11
12 func isSliceSelfAssign(dst, src ir.Node) bool {
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 var dstX ir.Node
30 switch dst.Op() {
31 default:
32 return false
33 case ir.ODEREF:
34 dst := dst.(*ir.StarExpr)
35 dstX = dst.X
36 case ir.ODOTPTR:
37 dst := dst.(*ir.SelectorExpr)
38 dstX = dst.X
39 }
40 if dstX.Op() != ir.ONAME {
41 return false
42 }
43
44 switch src.Op() {
45 case ir.OSLICE, ir.OSLICE3, ir.OSLICESTR:
46
47 case ir.OSLICEARR, ir.OSLICE3ARR:
48
49
50
51
52
53
54
55
56
57 src := src.(*ir.SliceExpr)
58 if src.X.Op() == ir.OADDR {
59 return false
60 }
61 default:
62 return false
63 }
64
65 var baseX ir.Node
66 switch base := src.(*ir.SliceExpr).X; base.Op() {
67 default:
68 return false
69 case ir.ODEREF:
70 base := base.(*ir.StarExpr)
71 baseX = base.X
72 case ir.ODOTPTR:
73 base := base.(*ir.SelectorExpr)
74 baseX = base.X
75 }
76 if baseX.Op() != ir.ONAME {
77 return false
78 }
79
80 return dstX.(*ir.Name) == baseX.(*ir.Name)
81 }
82
83
84
85 func isSelfAssign(dst, src ir.Node) bool {
86 if isSliceSelfAssign(dst, src) {
87 return true
88 }
89
90
91
92
93
94
95
96
97
98
99
100 if dst == nil || src == nil || dst.Op() != src.Op() {
101 return false
102 }
103
104
105 switch dst.Op() {
106 case ir.ODOT, ir.ODOTPTR:
107
108 dst := dst.(*ir.SelectorExpr)
109 src := src.(*ir.SelectorExpr)
110 return ir.SameSafeExpr(dst.X, src.X)
111 case ir.OINDEX:
112 dst := dst.(*ir.IndexExpr)
113 src := src.(*ir.IndexExpr)
114 if mayAffectMemory(dst.Index) || mayAffectMemory(src.Index) {
115 return false
116 }
117 return ir.SameSafeExpr(dst.X, src.X)
118 default:
119 return false
120 }
121 }
122
123
124
125
126 func mayAffectMemory(n ir.Node) bool {
127
128
129
130
131
132
133
134
135
136
137 switch n.Op() {
138 case ir.ONAME, ir.OLITERAL, ir.ONIL:
139 return false
140
141 case ir.OADD, ir.OSUB, ir.OOR, ir.OXOR, ir.OMUL, ir.OLSH, ir.ORSH, ir.OAND, ir.OANDNOT, ir.ODIV, ir.OMOD:
142 n := n.(*ir.BinaryExpr)
143 return mayAffectMemory(n.X) || mayAffectMemory(n.Y)
144
145 case ir.OINDEX:
146 n := n.(*ir.IndexExpr)
147 return mayAffectMemory(n.X) || mayAffectMemory(n.Index)
148
149 case ir.OCONVNOP, ir.OCONV:
150 n := n.(*ir.ConvExpr)
151 return mayAffectMemory(n.X)
152
153 case ir.OLEN, ir.OCAP, ir.ONOT, ir.OBITNOT, ir.OPLUS, ir.ONEG, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF:
154 n := n.(*ir.UnaryExpr)
155 return mayAffectMemory(n.X)
156
157 case ir.ODOT, ir.ODOTPTR:
158 n := n.(*ir.SelectorExpr)
159 return mayAffectMemory(n.X)
160
161 case ir.ODEREF:
162 n := n.(*ir.StarExpr)
163 return mayAffectMemory(n.X)
164
165 default:
166 return true
167 }
168 }
169
170
171
172 func HeapAllocReason(n ir.Node) string {
173 if n == nil || n.Type() == nil {
174 return ""
175 }
176
177
178 if n.Op() == ir.ONAME {
179 n := n.(*ir.Name)
180 if n.Class == ir.PPARAM || n.Class == ir.PPARAMOUT {
181 return ""
182 }
183 }
184
185 if n.Type().Size() > ir.MaxStackVarSize {
186 return "too large for stack"
187 }
188
189 if (n.Op() == ir.ONEW || n.Op() == ir.OPTRLIT) && n.Type().Elem().Size() > ir.MaxImplicitStackVarSize {
190 return "too large for stack"
191 }
192
193 if n.Op() == ir.OCLOSURE && typecheck.ClosureType(n.(*ir.ClosureExpr)).Size() > ir.MaxImplicitStackVarSize {
194 return "too large for stack"
195 }
196 if n.Op() == ir.OMETHVALUE && typecheck.MethodValueType(n.(*ir.SelectorExpr)).Size() > ir.MaxImplicitStackVarSize {
197 return "too large for stack"
198 }
199
200 if n.Op() == ir.OMAKESLICE {
201 n := n.(*ir.MakeExpr)
202 r := n.Cap
203 if r == nil {
204 r = n.Len
205 }
206 if !ir.IsSmallIntConst(r) {
207 return "non-constant size"
208 }
209 if t := n.Type(); t.Elem().Size() != 0 && ir.Int64Val(r) > ir.MaxImplicitStackVarSize/t.Elem().Size() {
210 return "too large for stack"
211 }
212 }
213
214 return ""
215 }
216
View as plain text