mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-26 06:38:42 +00:00
335b085fd2
Add allocation diagnostics coverage for pointer-returning helpers, aggregate slice returns, and conditional pointer returns before changing the allocation optimizer. The golden files record the current heap-allocation behavior so later commits show exactly which diagnostics each optimizer improvement removes.
177 lines
3.0 KiB
Go
177 lines
3.0 KiB
Go
package main
|
|
|
|
import (
|
|
"runtime/volatile"
|
|
"unsafe"
|
|
)
|
|
|
|
func main() {
|
|
n1 := 5
|
|
derefInt(&n1)
|
|
|
|
n2 := 6
|
|
returnIntPtr(&n2)
|
|
|
|
s1 := make([]int, 3)
|
|
readIntSlice(s1)
|
|
|
|
s2 := [3]int{}
|
|
readIntSlice(s2[:])
|
|
|
|
s3 := make([]int, 3)
|
|
returnIntSlice(s3)
|
|
|
|
useSlice(make([]int, getUnknownNumber()))
|
|
|
|
s4 := make([]byte, 300)
|
|
readByteSlice(s4)
|
|
|
|
s5 := make([]int, 4)
|
|
_ = append(s5, 5)
|
|
|
|
s6 := make([]int, 3)
|
|
s7 := []int{1, 2, 3}
|
|
copySlice(s6, s7)
|
|
|
|
c1 := getComplex128()
|
|
useInterface(c1)
|
|
|
|
n3 := 5
|
|
func() int {
|
|
return n3
|
|
}()
|
|
|
|
callVariadic(3, 5, 8)
|
|
|
|
s8 := []int{3, 5, 8}
|
|
callVariadic(s8...)
|
|
|
|
n4 := 3
|
|
n5 := 7
|
|
func() {
|
|
n4 = n5
|
|
}()
|
|
println(n4, n5)
|
|
|
|
// This shouldn't escape.
|
|
var buf [32]byte
|
|
s := string(buf[:])
|
|
println(len(s))
|
|
|
|
var rbuf [5]rune
|
|
s = string(rbuf[:])
|
|
println(s)
|
|
|
|
// Unsafe usage of DMA buffers: the compiler thinks this buffer won't be
|
|
// used anymore after the volatile store.
|
|
var dmaBuf1 [4]byte
|
|
pseudoVolatile.Set(uint32(unsafeNoEscape(unsafe.Pointer(&dmaBuf1[0]))))
|
|
|
|
// Safe usage of DMA buffers: keep the buffer alive until it is no longer
|
|
// needed, but don't mark it as needing to be heap allocated. The compiler
|
|
// will keep the buffer stack allocated if possible.
|
|
var dmaBuf2 [4]byte
|
|
pseudoVolatile.Set(uint32(unsafeNoEscape(unsafe.Pointer(&dmaBuf2[0]))))
|
|
// ...use the buffer in the DMA peripheral
|
|
keepAliveNoEscape(unsafe.Pointer(&dmaBuf2[0]))
|
|
}
|
|
|
|
type vector3 [3]float32
|
|
|
|
func scaleVector3(vec *vector3, f float32) *vector3 {
|
|
vec[0] *= f
|
|
vec[1] *= f
|
|
vec[2] *= f
|
|
return vec
|
|
}
|
|
|
|
func crossVector3(a, b *vector3) vector3 {
|
|
return vector3{
|
|
a[1]*b[2] - a[2]*b[1],
|
|
a[2]*b[0] - a[0]*b[2],
|
|
a[0]*b[1] - a[1]*b[0],
|
|
}
|
|
}
|
|
|
|
func nonEscapingReturnedPointer() vector3 {
|
|
a := vector3{1, 2, 3}
|
|
b := vector3{4, 5, 6}
|
|
|
|
c := scaleVector3(&b, 0.5)
|
|
return crossVector3(&a, c)
|
|
}
|
|
|
|
var escapedSlice []int
|
|
|
|
func escapingReturnedSlice() {
|
|
s := make([]int, 3)
|
|
escapedSlice = returnIntSlice(s)
|
|
}
|
|
|
|
var escapedVector3 *vector3
|
|
|
|
func escapingReturnedPointer() {
|
|
b := vector3{4, 5, 6}
|
|
|
|
c := scaleVector3(&b, 0.5)
|
|
escapedVector3 = c
|
|
}
|
|
|
|
func recursiveScaleVector3(vec *vector3, n int) *vector3 {
|
|
if n == 0 {
|
|
return vec
|
|
}
|
|
return recursiveScaleVector3(vec, n-1)
|
|
}
|
|
|
|
func recursiveReturnedPointer() vector3 {
|
|
b := vector3{4, 5, 6}
|
|
|
|
c := recursiveScaleVector3(&b, 1)
|
|
return *c
|
|
}
|
|
|
|
func derefInt(x *int) int {
|
|
return *x
|
|
}
|
|
|
|
func returnIntPtr(x *int) *int {
|
|
return x
|
|
}
|
|
|
|
func readIntSlice(s []int) int {
|
|
return s[1]
|
|
}
|
|
|
|
func readByteSlice(s []byte) byte {
|
|
return s[1]
|
|
}
|
|
|
|
func returnIntSlice(s []int) []int {
|
|
return s
|
|
}
|
|
|
|
func getUnknownNumber() int
|
|
|
|
func copySlice(out, in []int) {
|
|
copy(out, in)
|
|
}
|
|
|
|
func getComplex128() complex128
|
|
|
|
func useInterface(interface{})
|
|
|
|
func callVariadic(...int)
|
|
|
|
func useSlice([]int)
|
|
|
|
// See the function with the same name in the machine package.
|
|
//
|
|
//go:linkname unsafeNoEscape machine.unsafeNoEscape
|
|
func unsafeNoEscape(ptr unsafe.Pointer) uintptr
|
|
|
|
//go:linkname keepAliveNoEscape machine.keepAliveNoEscape
|
|
func keepAliveNoEscape(ptr unsafe.Pointer)
|
|
|
|
var pseudoVolatile volatile.Register32
|