tinygo/src/runtime/slice.go
Ayke van Laethem 1a7369af6e runtime: return the correct type from the copy builtin
The copy builtin is defined as follows by the Go language spec:

    copy(dst, src []T) int
    copy(dst []byte, src string) int

In other words, it returns an int. The runtime.sliceCopy compiler
intrinsic returned a uintptr instead, which led to a problem while
compiling the strings package for AVR.

No other architecture should be affected by this change as the
conversion from an uintptr to an int is a no-op on most architectures.
2020-03-11 15:44:31 -07:00

53 строки
1,5 КиБ
Go

package runtime
// This file implements compiler builtins for slices: append() and copy().
import (
"unsafe"
)
// Builtin append(src, elements...) function: append elements to src and return
// the modified (possibly expanded) slice.
func sliceAppend(srcBuf, elemsBuf unsafe.Pointer, srcLen, srcCap, elemsLen uintptr, elemSize uintptr) (unsafe.Pointer, uintptr, uintptr) {
if elemsLen == 0 {
// Nothing to append, return the input slice.
return srcBuf, srcLen, srcCap
}
if srcLen+elemsLen > srcCap {
// Slice does not fit, allocate a new buffer that's large enough.
srcCap = srcCap * 2
if srcCap == 0 { // e.g. zero slice
srcCap = 1
}
for srcLen+elemsLen > srcCap {
// This algorithm may be made more memory-efficient: don't multiply
// by two but by 1.5 or something. As far as I can see, that's
// allowed by the Go language specification (but may be observed by
// programs).
srcCap *= 2
}
buf := alloc(srcCap * elemSize)
// Copy the old slice to the new slice.
if srcLen != 0 {
memmove(buf, srcBuf, srcLen*elemSize)
}
srcBuf = buf
}
// The slice fits (after possibly allocating a new one), append it in-place.
memmove(unsafe.Pointer(uintptr(srcBuf)+srcLen*elemSize), elemsBuf, elemsLen*elemSize)
return srcBuf, srcLen + elemsLen, srcCap
}
// Builtin copy(dst, src) function: copy bytes from dst to src.
func sliceCopy(dst, src unsafe.Pointer, dstLen, srcLen uintptr, elemSize uintptr) int {
// n = min(srcLen, dstLen)
n := srcLen
if n > dstLen {
n = dstLen
}
memmove(dst, src, n*elemSize)
return int(n)
}