compiler: implement builtin copy(dst, src []T)
Not implemented: copying a string into a []byte slice.
Этот коммит содержится в:
родитель
fd9fa038a9
коммит
5aa8b71ae1
3 изменённых файлов: 55 добавлений и 1 удалений
22
compiler.go
22
compiler.go
|
@ -1523,6 +1523,28 @@ func (c *Compiler) parseBuiltin(frame *Frame, args []ssa.Value, callName string)
|
||||||
default:
|
default:
|
||||||
return llvm.Value{}, errors.New("todo: cap: unknown type")
|
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":
|
case "len":
|
||||||
value, err := c.parseExpr(frame, args[0])
|
value, err := c.parseExpr(frame, args[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -37,11 +37,13 @@ func main() {
|
||||||
// slice
|
// slice
|
||||||
l := 5
|
l := 5
|
||||||
foo := []int{1, 2, 4, 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 foo:", len(foo), cap(foo))
|
||||||
println("len/cap bar:", len(bar), cap(bar))
|
println("len/cap bar:", len(bar), cap(bar))
|
||||||
println("foo[3]:", foo[3])
|
println("foo[3]:", foo[3])
|
||||||
println("sum foo:", sum(foo))
|
println("sum foo:", sum(foo))
|
||||||
|
println("copy foo -> bar:", copy(bar, foo))
|
||||||
|
println("sum bar:", sum(bar))
|
||||||
|
|
||||||
// interfaces, pointers
|
// interfaces, pointers
|
||||||
thing := &Thing{"foo"}
|
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.
|
// Set the given number of bytes to zero.
|
||||||
func memzero(ptr unsafe.Pointer, size uintptr) {
|
func memzero(ptr unsafe.Pointer, size uintptr) {
|
||||||
for i := uintptr(0); i < size; i++ {
|
for i := uintptr(0); i < size; i++ {
|
||||||
|
@ -81,3 +100,14 @@ func memequal(x, y unsafe.Pointer, n uintptr) bool {
|
||||||
}
|
}
|
||||||
return true
|
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
|
||||||
|
}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче