compiler: implement builtin copy(dst, src []T)

Not implemented: copying a string into a []byte slice.
Этот коммит содержится в:
Ayke van Laethem 2018-09-06 10:37:44 +02:00
родитель fd9fa038a9
коммит 5aa8b71ae1
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E97FF5335DFDFDED
3 изменённых файлов: 55 добавлений и 1 удалений

Просмотреть файл

@ -1523,6 +1523,28 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string)
default:
return llvm.Value{}, errors.New("todo: cap: unknown type")
}
case "copy":
dst, err := c.parseExpr(frame, args[0])
if err != nil {
return llvm.Value{}, err
}
src, err := c.parseExpr(frame, args[1])
if err != nil {
return llvm.Value{}, err
}
if _, ok := args[1].Type().(*types.Basic); ok {
return llvm.Value{}, errors.New("todo: copy: string to []byte")
}
dstLen := c.builder.CreateExtractValue(dst, 1, "copy.dstLen")
srcLen := c.builder.CreateExtractValue(src, 1, "copy.srcLen")
dstBuf := c.builder.CreateExtractValue(dst, 0, "copy.dstArray")
srcBuf := c.builder.CreateExtractValue(src, 0, "copy.srcArray")
elemType := dstBuf.Type().ElementType()
dstBuf = c.builder.CreateBitCast(dstBuf, c.i8ptrType, "copy.dstPtr")
srcBuf = c.builder.CreateBitCast(srcBuf, c.i8ptrType, "copy.srcPtr")
elemSize := llvm.ConstInt(c.uintptrType, c.targetData.TypeAllocSize(elemType), false)
sliceCopy := c.mod.NamedFunction("runtime.sliceCopy")
return c.builder.CreateCall(sliceCopy, []llvm.Value{dstBuf, srcBuf, dstLen, srcLen, elemSize}, "copy.n"), nil
case "len":
value, err := c.parseExpr(frame, args[0])
if err != nil {

Просмотреть файл

@ -37,11 +37,13 @@ func main() {
// slice
l := 5
foo := []int{1, 2, 4, 5}
bar := make([]byte, l-2, l)
bar := make([]int, l-2, l)
println("len/cap foo:", len(foo), cap(foo))
println("len/cap bar:", len(bar), cap(bar))
println("foo[3]:", foo[3])
println("sum foo:", sum(foo))
println("copy foo -> bar:", copy(bar, foo))
println("sum bar:", sum(bar))
// interfaces, pointers
thing := &Thing{"foo"}

Просмотреть файл

@ -63,6 +63,25 @@ func memcpy(dst, src unsafe.Pointer, size uintptr) {
}
}
// Copy size bytes from src to dst. The memory areas may overlap and will do the
// correct thing.
func memmove(dst, src unsafe.Pointer, size uintptr) {
if uintptr(dst) < uintptr(src) {
// Copy forwards.
memcpy(dst, src, size)
return
}
// Copy backwards.
i := size
for {
i--
*(*uint8)(unsafe.Pointer(uintptr(dst) + i)) = *(*uint8)(unsafe.Pointer(uintptr(src) + i))
if i == 0 {
break
}
}
}
// Set the given number of bytes to zero.
func memzero(ptr unsafe.Pointer, size uintptr) {
for i := uintptr(0); i < size; i++ {
@ -81,3 +100,14 @@ func memequal(x, y unsafe.Pointer, n uintptr) bool {
}
return true
}
// Builtin copy(dst, src) function: copy bytes from dst to src.
func sliceCopy(dst, src unsafe.Pointer, dstLen, srcLen lenType, elemSize uintptr) lenType {
// n = min(srcLen, dstLen)
n := srcLen
if n > dstLen {
n = dstLen
}
memmove(dst, src, uintptr(n)*elemSize)
return n
}