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 "runtime" 10 11// This file contains code generation tests related to the use of the 12// stack. 13 14// Check that stack stores are optimized away. 15 16// 386:"TEXT\t.*, [$]0-" 17// amd64:"TEXT\t.*, [$]0-" 18// arm:"TEXT\t.*, [$]-4-" 19// arm64:"TEXT\t.*, [$]0-" 20// mips:"TEXT\t.*, [$]-4-" 21// ppc64x:"TEXT\t.*, [$]0-" 22// s390x:"TEXT\t.*, [$]0-" 23func StackStore() int { 24 var x int 25 return *(&x) 26} 27 28type T struct { 29 A, B, C, D int // keep exported fields 30 x, y, z int // reset unexported fields 31} 32 33// Check that large structs are cleared directly (issue #24416). 34 35// 386:"TEXT\t.*, [$]0-" 36// amd64:"TEXT\t.*, [$]0-" 37// arm:"TEXT\t.*, [$]0-" (spills return address) 38// arm64:"TEXT\t.*, [$]0-" 39// mips:"TEXT\t.*, [$]-4-" 40// ppc64x:"TEXT\t.*, [$]0-" 41// s390x:"TEXT\t.*, [$]0-" 42func ZeroLargeStruct(x *T) { 43 t := T{} 44 *x = t 45} 46 47// Check that structs are partially initialised directly (issue #24386). 48 49// Notes: 50// - 386 fails due to spilling a register 51// amd64:"TEXT\t.*, [$]0-" 52// arm:"TEXT\t.*, [$]0-" (spills return address) 53// arm64:"TEXT\t.*, [$]0-" 54// ppc64x:"TEXT\t.*, [$]0-" 55// s390x:"TEXT\t.*, [$]0-" 56// Note: that 386 currently has to spill a register. 57func KeepWanted(t *T) { 58 *t = T{A: t.A, B: t.B, C: t.C, D: t.D} 59} 60 61// Check that small array operations avoid using the stack (issue #15925). 62 63// Notes: 64// - 386 fails due to spilling a register 65// - arm & mips fail due to softfloat calls 66// amd64:"TEXT\t.*, [$]0-" 67// arm64:"TEXT\t.*, [$]0-" 68// ppc64x:"TEXT\t.*, [$]0-" 69// s390x:"TEXT\t.*, [$]0-" 70func ArrayAdd64(a, b [4]float64) [4]float64 { 71 return [4]float64{a[0] + b[0], a[1] + b[1], a[2] + b[2], a[3] + b[3]} 72} 73 74// Check that small array initialization avoids using the stack. 75 76// 386:"TEXT\t.*, [$]0-" 77// amd64:"TEXT\t.*, [$]0-" 78// arm:"TEXT\t.*, [$]0-" (spills return address) 79// arm64:"TEXT\t.*, [$]0-" 80// mips:"TEXT\t.*, [$]-4-" 81// ppc64x:"TEXT\t.*, [$]0-" 82// s390x:"TEXT\t.*, [$]0-" 83func ArrayInit(i, j int) [4]int { 84 return [4]int{i, 0, j, 0} 85} 86 87// Check that assembly output has matching offset and base register 88// (issue #21064). 89 90func check_asmout(b [2]int) int { 91 runtime.GC() // use some frame 92 // amd64:`.*b\+24\(SP\)` 93 // arm:`.*b\+4\(FP\)` 94 return b[1] 95} 96 97// Check that simple functions get promoted to nosplit, even when 98// they might panic in various ways. See issue 31219. 99// amd64:"TEXT\t.*NOSPLIT.*" 100func MightPanic(a []int, i, j, k, s int) { 101 _ = a[i] // panicIndex 102 _ = a[i:j] // panicSlice 103 _ = a[i:j:k] // also panicSlice 104 _ = i << s // panicShift 105 _ = i / j // panicDivide 106} 107 108// Put a defer in a loop, so second defer is not open-coded 109func Defer() { 110 for i := 0; i < 2; i++ { 111 defer func() {}() 112 } 113 // amd64:`CALL\truntime\.deferprocStack` 114 defer func() {}() 115} 116 117// Check that stack slots are shared among values of the same 118// type, but not pointer-identical types. See issue 65783. 119 120func spillSlotReuse() { 121 // The return values of getp1 and getp2 need to be 122 // spilled around the calls to nopInt. Make sure that 123 // spill slot gets reused. 124 125 //arm64:`.*autotmp_2-8\(SP\)` 126 getp1()[nopInt()] = 0 127 //arm64:`.*autotmp_2-8\(SP\)` 128 getp2()[nopInt()] = 0 129} 130 131//go:noinline 132func nopInt() int { 133 return 0 134} 135 136//go:noinline 137func getp1() *[4]int { 138 return nil 139} 140 141//go:noinline 142func getp2() *[4]int { 143 return nil 144} 145