1// asmcheck
2
3// Copyright 2018 The Go Authors. All rights reserved.
4// Use of this source code is governed by a BSD-style
5// license that can be found in the LICENSE file.
6
7package codegen
8
9import "unsafe"
10
11// This file contains code generation tests related to the handling of
12// slice types.
13
14// ------------------ //
15//      Clear         //
16// ------------------ //
17
18// Issue #5373 optimize memset idiom
19// Some of the clears get inlined, see #56997
20
21func SliceClear(s []int) []int {
22	// amd64:`.*memclrNoHeapPointers`
23	// ppc64x:`.*memclrNoHeapPointers`
24	for i := range s {
25		s[i] = 0
26	}
27	return s
28}
29
30func SliceClearPointers(s []*int) []*int {
31	// amd64:`.*memclrHasPointers`
32	// ppc64x:`.*memclrHasPointers`
33	for i := range s {
34		s[i] = nil
35	}
36	return s
37}
38
39// ------------------ //
40//      Extension     //
41// ------------------ //
42
43// Issue #21266 - avoid makeslice in append(x, make([]T, y)...)
44
45func SliceExtensionConst(s []int) []int {
46	// amd64:-`.*runtime\.memclrNoHeapPointers`
47	// amd64:-`.*runtime\.makeslice`
48	// amd64:-`.*runtime\.panicmakeslicelen`
49	// amd64:"MOVUPS\tX15"
50	// ppc64x:-`.*runtime\.memclrNoHeapPointers`
51	// ppc64x:-`.*runtime\.makeslice`
52	// ppc64x:-`.*runtime\.panicmakeslicelen`
53	return append(s, make([]int, 1<<2)...)
54}
55
56func SliceExtensionConstInt64(s []int) []int {
57	// amd64:-`.*runtime\.memclrNoHeapPointers`
58	// amd64:-`.*runtime\.makeslice`
59	// amd64:-`.*runtime\.panicmakeslicelen`
60	// amd64:"MOVUPS\tX15"
61	// ppc64x:-`.*runtime\.memclrNoHeapPointers`
62	// ppc64x:-`.*runtime\.makeslice`
63	// ppc64x:-`.*runtime\.panicmakeslicelen`
64	return append(s, make([]int, int64(1<<2))...)
65}
66
67func SliceExtensionConstUint64(s []int) []int {
68	// amd64:-`.*runtime\.memclrNoHeapPointers`
69	// amd64:-`.*runtime\.makeslice`
70	// amd64:-`.*runtime\.panicmakeslicelen`
71	// amd64:"MOVUPS\tX15"
72	// ppc64x:-`.*runtime\.memclrNoHeapPointers`
73	// ppc64x:-`.*runtime\.makeslice`
74	// ppc64x:-`.*runtime\.panicmakeslicelen`
75	return append(s, make([]int, uint64(1<<2))...)
76}
77
78func SliceExtensionConstUint(s []int) []int {
79	// amd64:-`.*runtime\.memclrNoHeapPointers`
80	// amd64:-`.*runtime\.makeslice`
81	// amd64:-`.*runtime\.panicmakeslicelen`
82	// amd64:"MOVUPS\tX15"
83	// ppc64x:-`.*runtime\.memclrNoHeapPointers`
84	// ppc64x:-`.*runtime\.makeslice`
85	// ppc64x:-`.*runtime\.panicmakeslicelen`
86	return append(s, make([]int, uint(1<<2))...)
87}
88
89// On ppc64x continue to use memclrNoHeapPointers
90// for sizes >= 512.
91func SliceExtensionConst512(s []int) []int {
92	// amd64:-`.*runtime\.memclrNoHeapPointers`
93	// ppc64x:`.*runtime\.memclrNoHeapPointers`
94	return append(s, make([]int, 1<<9)...)
95}
96
97func SliceExtensionPointer(s []*int, l int) []*int {
98	// amd64:`.*runtime\.memclrHasPointers`
99	// amd64:-`.*runtime\.makeslice`
100	// ppc64x:`.*runtime\.memclrHasPointers`
101	// ppc64x:-`.*runtime\.makeslice`
102	return append(s, make([]*int, l)...)
103}
104
105func SliceExtensionVar(s []byte, l int) []byte {
106	// amd64:`.*runtime\.memclrNoHeapPointers`
107	// amd64:-`.*runtime\.makeslice`
108	// ppc64x:`.*runtime\.memclrNoHeapPointers`
109	// ppc64x:-`.*runtime\.makeslice`
110	return append(s, make([]byte, l)...)
111}
112
113func SliceExtensionVarInt64(s []byte, l int64) []byte {
114	// amd64:`.*runtime\.memclrNoHeapPointers`
115	// amd64:-`.*runtime\.makeslice`
116	// amd64:`.*runtime\.panicmakeslicelen`
117	return append(s, make([]byte, l)...)
118}
119
120func SliceExtensionVarUint64(s []byte, l uint64) []byte {
121	// amd64:`.*runtime\.memclrNoHeapPointers`
122	// amd64:-`.*runtime\.makeslice`
123	// amd64:`.*runtime\.panicmakeslicelen`
124	return append(s, make([]byte, l)...)
125}
126
127func SliceExtensionVarUint(s []byte, l uint) []byte {
128	// amd64:`.*runtime\.memclrNoHeapPointers`
129	// amd64:-`.*runtime\.makeslice`
130	// amd64:`.*runtime\.panicmakeslicelen`
131	return append(s, make([]byte, l)...)
132}
133
134func SliceExtensionInt64(s []int, l64 int64) []int {
135	// 386:`.*runtime\.makeslice`
136	// 386:-`.*runtime\.memclr`
137	return append(s, make([]int, l64)...)
138}
139
140// ------------------ //
141//      Make+Copy     //
142// ------------------ //
143
144// Issue #26252 - avoid memclr for make+copy
145
146func SliceMakeCopyLen(s []int) []int {
147	// amd64:`.*runtime\.mallocgc`
148	// amd64:`.*runtime\.memmove`
149	// amd64:-`.*runtime\.makeslice`
150	// ppc64x:`.*runtime\.mallocgc`
151	// ppc64x:`.*runtime\.memmove`
152	// ppc64x:-`.*runtime\.makeslice`
153	a := make([]int, len(s))
154	copy(a, s)
155	return a
156}
157
158func SliceMakeCopyLenPtr(s []*int) []*int {
159	// amd64:`.*runtime\.makeslicecopy`
160	// amd64:-`.*runtime\.makeslice\(`
161	// amd64:-`.*runtime\.typedslicecopy
162	// ppc64x:`.*runtime\.makeslicecopy`
163	// ppc64x:-`.*runtime\.makeslice\(`
164	// ppc64x:-`.*runtime\.typedslicecopy
165	a := make([]*int, len(s))
166	copy(a, s)
167	return a
168}
169
170func SliceMakeCopyConst(s []int) []int {
171	// amd64:`.*runtime\.makeslicecopy`
172	// amd64:-`.*runtime\.makeslice\(`
173	// amd64:-`.*runtime\.memmove`
174	a := make([]int, 4)
175	copy(a, s)
176	return a
177}
178
179func SliceMakeCopyConstPtr(s []*int) []*int {
180	// amd64:`.*runtime\.makeslicecopy`
181	// amd64:-`.*runtime\.makeslice\(`
182	// amd64:-`.*runtime\.typedslicecopy
183	a := make([]*int, 4)
184	copy(a, s)
185	return a
186}
187
188func SliceMakeCopyNoOptNoDeref(s []*int) []*int {
189	a := new([]*int)
190	// amd64:-`.*runtime\.makeslicecopy`
191	// amd64:`.*runtime\.makeslice\(`
192	*a = make([]*int, 4)
193	// amd64:-`.*runtime\.makeslicecopy`
194	// amd64:`.*runtime\.typedslicecopy`
195	copy(*a, s)
196	return *a
197}
198
199func SliceMakeCopyNoOptNoVar(s []*int) []*int {
200	a := make([][]*int, 1)
201	// amd64:-`.*runtime\.makeslicecopy`
202	// amd64:`.*runtime\.makeslice\(`
203	a[0] = make([]*int, 4)
204	// amd64:-`.*runtime\.makeslicecopy`
205	// amd64:`.*runtime\.typedslicecopy`
206	copy(a[0], s)
207	return a[0]
208}
209
210func SliceMakeCopyNoOptBlank(s []*int) []*int {
211	var a []*int
212	// amd64:-`.*runtime\.makeslicecopy`
213	_ = make([]*int, 4)
214	// amd64:-`.*runtime\.makeslicecopy`
215	// amd64:`.*runtime\.typedslicecopy`
216	copy(a, s)
217	return a
218}
219
220func SliceMakeCopyNoOptNoMake(s []*int) []*int {
221	// amd64:-`.*runtime\.makeslicecopy`
222	// amd64:-`.*runtime\.objectnew`
223	a := *new([]*int)
224	// amd64:-`.*runtime\.makeslicecopy`
225	// amd64:`.*runtime\.typedslicecopy`
226	copy(a, s)
227	return a
228}
229
230func SliceMakeCopyNoOptNoHeapAlloc(s []*int) int {
231	// amd64:-`.*runtime\.makeslicecopy`
232	a := make([]*int, 4)
233	// amd64:-`.*runtime\.makeslicecopy`
234	// amd64:`.*runtime\.typedslicecopy`
235	copy(a, s)
236	return cap(a)
237}
238
239func SliceMakeCopyNoOptNoCap(s []*int) []*int {
240	// amd64:-`.*runtime\.makeslicecopy`
241	// amd64:`.*runtime\.makeslice\(`
242	a := make([]*int, 0, 4)
243	// amd64:-`.*runtime\.makeslicecopy`
244	// amd64:`.*runtime\.typedslicecopy`
245	copy(a, s)
246	return a
247}
248
249func SliceMakeCopyNoOptNoCopy(s []*int) []*int {
250	copy := func(x, y []*int) {}
251	// amd64:-`.*runtime\.makeslicecopy`
252	// amd64:`.*runtime\.makeslice\(`
253	a := make([]*int, 4)
254	// amd64:-`.*runtime\.makeslicecopy`
255	copy(a, s)
256	return a
257}
258
259func SliceMakeCopyNoOptWrongOrder(s []*int) []*int {
260	// amd64:-`.*runtime\.makeslicecopy`
261	// amd64:`.*runtime\.makeslice\(`
262	a := make([]*int, 4)
263	// amd64:`.*runtime\.typedslicecopy`
264	// amd64:-`.*runtime\.makeslicecopy`
265	copy(s, a)
266	return a
267}
268
269func SliceMakeCopyNoOptWrongAssign(s []*int) []*int {
270	var a []*int
271	// amd64:-`.*runtime\.makeslicecopy`
272	// amd64:`.*runtime\.makeslice\(`
273	s = make([]*int, 4)
274	// amd64:`.*runtime\.typedslicecopy`
275	// amd64:-`.*runtime\.makeslicecopy`
276	copy(a, s)
277	return s
278}
279
280func SliceMakeCopyNoOptCopyLength(s []*int) (int, []*int) {
281	// amd64:-`.*runtime\.makeslicecopy`
282	// amd64:`.*runtime\.makeslice\(`
283	a := make([]*int, 4)
284	// amd64:`.*runtime\.typedslicecopy`
285	// amd64:-`.*runtime\.makeslicecopy`
286	n := copy(a, s)
287	return n, a
288}
289
290func SliceMakeCopyNoOptSelfCopy(s []*int) []*int {
291	// amd64:-`.*runtime\.makeslicecopy`
292	// amd64:`.*runtime\.makeslice\(`
293	a := make([]*int, 4)
294	// amd64:`.*runtime\.typedslicecopy`
295	// amd64:-`.*runtime\.makeslicecopy`
296	copy(a, a)
297	return a
298}
299
300func SliceMakeCopyNoOptTargetReference(s []*int) []*int {
301	// amd64:-`.*runtime\.makeslicecopy`
302	// amd64:`.*runtime\.makeslice\(`
303	a := make([]*int, 4)
304	// amd64:`.*runtime\.typedslicecopy`
305	// amd64:-`.*runtime\.makeslicecopy`
306	copy(a, s[:len(a)])
307	return a
308}
309
310func SliceMakeCopyNoOptCap(s []int) []int {
311	// amd64:-`.*runtime\.makeslicecopy`
312	// amd64:`.*runtime\.makeslice\(`
313	a := make([]int, len(s), 9)
314	// amd64:-`.*runtime\.makeslicecopy`
315	// amd64:`.*runtime\.memmove`
316	copy(a, s)
317	return a
318}
319
320func SliceMakeCopyNoMemmoveDifferentLen(s []int) []int {
321	// amd64:`.*runtime\.makeslicecopy`
322	// amd64:-`.*runtime\.memmove`
323	a := make([]int, len(s)-1)
324	// amd64:-`.*runtime\.memmove`
325	copy(a, s)
326	return a
327}
328
329func SliceMakeEmptyPointerToZerobase() []int {
330	// amd64:`LEAQ.+runtime\.zerobase`
331	// amd64:-`.*runtime\.makeslice`
332	return make([]int, 0)
333}
334
335// ---------------------- //
336//   Nil check of &s[0]   //
337// ---------------------- //
338// See issue 30366
339func SliceNilCheck(s []int) {
340	p := &s[0]
341	// amd64:-`TESTB`
342	_ = *p
343}
344
345// ---------------------- //
346//   Init slice literal   //
347// ---------------------- //
348// See issue 21561
349func InitSmallSliceLiteral() []int {
350	// amd64:`MOVQ\t[$]42`
351	return []int{42}
352}
353
354func InitNotSmallSliceLiteral() []int {
355	// amd64:`LEAQ\t.*stmp_`
356	return []int{
357		42,
358		42,
359		42,
360		42,
361		42,
362		42,
363		42,
364		42,
365		42,
366		42,
367		42,
368		42,
369		42,
370		42,
371		42,
372		42,
373		42,
374		42,
375		42,
376		42,
377		42,
378		42,
379		42,
380		42,
381		42,
382		42,
383		42,
384		42,
385		42,
386		42,
387		42,
388		42,
389		42,
390		42,
391		42,
392		42,
393	}
394}
395
396// --------------------------------------- //
397//   Test PPC64 SUBFCconst folding rules   //
398//   triggered by slice operations.        //
399// --------------------------------------- //
400
401func SliceWithConstCompare(a []int, b int) []int {
402	var c []int = []int{1, 2, 3, 4, 5}
403	if b+len(a) < len(c) {
404		// ppc64x:-"NEG"
405		return c[b:]
406	}
407	return a
408}
409
410func SliceWithSubtractBound(a []int, b int) []int {
411	// ppc64x:"SUBC",-"NEG"
412	return a[(3 - b):]
413}
414
415// --------------------------------------- //
416//   Code generation for unsafe.Slice      //
417// --------------------------------------- //
418
419func Slice1(p *byte, i int) []byte {
420	// amd64:-"MULQ"
421	return unsafe.Slice(p, i)
422}
423func Slice0(p *struct{}, i int) []struct{} {
424	// amd64:-"MULQ"
425	return unsafe.Slice(p, i)
426}
427