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:
|
||||
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
|
||||
}
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче