Source file test/codegen/stack.go
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 7 package codegen 8 9 import "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 // ppc64:"TEXT\t.*, [$]0-" 22 // ppc64le:"TEXT\t.*, [$]0-" 23 // s390x:"TEXT\t.*, [$]0-" 24 func StackStore() int { 25 var x int 26 return *(&x) 27 } 28 29 type T struct { 30 A, B, C, D int // keep exported fields 31 x, y, z int // reset unexported fields 32 } 33 34 // Check that large structs are cleared directly (issue #24416). 35 36 // 386:"TEXT\t.*, [$]0-" 37 // amd64:"TEXT\t.*, [$]0-" 38 // arm:"TEXT\t.*, [$]0-" (spills return address) 39 // arm64:"TEXT\t.*, [$]0-" 40 // mips:"TEXT\t.*, [$]-4-" 41 // ppc64:"TEXT\t.*, [$]0-" 42 // ppc64le:"TEXT\t.*, [$]0-" 43 // s390x:"TEXT\t.*, [$]0-" 44 func ZeroLargeStruct(x *T) { 45 t := T{} 46 *x = t 47 } 48 49 // Check that structs are partially initialised directly (issue #24386). 50 51 // Notes: 52 // - 386 fails due to spilling a register 53 // amd64:"TEXT\t.*, [$]0-" 54 // arm:"TEXT\t.*, [$]0-" (spills return address) 55 // arm64:"TEXT\t.*, [$]0-" 56 // ppc64:"TEXT\t.*, [$]0-" 57 // ppc64le:"TEXT\t.*, [$]0-" 58 // s390x:"TEXT\t.*, [$]0-" 59 // Note: that 386 currently has to spill a register. 60 func KeepWanted(t *T) { 61 *t = T{A: t.A, B: t.B, C: t.C, D: t.D} 62 } 63 64 // Check that small array operations avoid using the stack (issue #15925). 65 66 // Notes: 67 // - 386 fails due to spilling a register 68 // - arm & mips fail due to softfloat calls 69 // amd64:"TEXT\t.*, [$]0-" 70 // arm64:"TEXT\t.*, [$]0-" 71 // ppc64:"TEXT\t.*, [$]0-" 72 // ppc64le:"TEXT\t.*, [$]0-" 73 // s390x:"TEXT\t.*, [$]0-" 74 func ArrayAdd64(a, b [4]float64) [4]float64 { 75 return [4]float64{a[0] + b[0], a[1] + b[1], a[2] + b[2], a[3] + b[3]} 76 } 77 78 // Check that small array initialization avoids using the stack. 79 80 // 386:"TEXT\t.*, [$]0-" 81 // amd64:"TEXT\t.*, [$]0-" 82 // arm:"TEXT\t.*, [$]0-" (spills return address) 83 // arm64:"TEXT\t.*, [$]0-" 84 // mips:"TEXT\t.*, [$]-4-" 85 // ppc64:"TEXT\t.*, [$]0-" 86 // ppc64le:"TEXT\t.*, [$]0-" 87 // s390x:"TEXT\t.*, [$]0-" 88 func ArrayInit(i, j int) [4]int { 89 return [4]int{i, 0, j, 0} 90 } 91 92 // Check that assembly output has matching offset and base register 93 // (issue #21064). 94 95 func check_asmout(b [2]int) int { 96 runtime.GC() // use some frame 97 // amd64:`.*b\+24\(SP\)` 98 // arm:`.*b\+4\(FP\)` 99 return b[1] 100 } 101 102 // Check that simple functions get promoted to nosplit, even when 103 // they might panic in various ways. See issue 31219. 104 // amd64:"TEXT\t.*NOSPLIT.*" 105 func MightPanic(a []int, i, j, k, s int) { 106 _ = a[i] // panicIndex 107 _ = a[i:j] // panicSlice 108 _ = a[i:j:k] // also panicSlice 109 _ = i << s // panicShift 110 _ = i / j // panicDivide 111 } 112 113 // Put a defer in a loop, so second defer is not open-coded 114 func Defer() { 115 for i := 0; i < 2; i++ { 116 defer func() {}() 117 } 118 // amd64:`CALL\truntime\.deferprocStack` 119 defer func() {}() 120 } 121