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