mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-07-26 06:38:42 +00:00
df09dbdf0f
I think it's much nicer to have the test output inline in the source file, that way it's much easier to review any changes. For example, when escape analysis is improved this is visible with removed `// OUT` lines. This is similar to how LLVM writes its tests, and I like that style.
177 lines
3.3 KiB
Go
177 lines
3.3 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())) // OUT: size is not constant
|
|
|
|
s4 := make([]byte, 300) // OUT: object size 300 exceeds maximum stack allocation size 256
|
|
readByteSlice(s4)
|
|
|
|
s5 := make([]int, 4) // OUT: escapes at line 30
|
|
_ = append(s5, 5)
|
|
|
|
s6 := make([]int, 3)
|
|
s7 := []int{1, 2, 3}
|
|
copySlice(s6, s7)
|
|
|
|
c1 := getComplex128() // OUT: escapes at line 37
|
|
useInterface(c1)
|
|
|
|
n3 := 5
|
|
func() int {
|
|
return n3
|
|
}()
|
|
|
|
callVariadic(3, 5, 8) // OUT: escapes at line 44
|
|
|
|
s8 := []int{3, 5, 8} // OUT: escapes at line 47
|
|
callVariadic(s8...)
|
|
|
|
n4 := 3 // OUT: escapes at line 51
|
|
n5 := 7 // OUT: escapes at line 51
|
|
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) // OUT: escapes at line 108
|
|
escapedSlice = returnIntSlice(s)
|
|
}
|
|
|
|
var escapedVector3 *vector3
|
|
|
|
func escapingReturnedPointer() {
|
|
b := vector3{4, 5, 6} // OUT: escapes at line 117
|
|
|
|
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} // OUT: escapes at unknown line
|
|
|
|
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
|