diff --git a/compiler/compiler.go b/compiler/compiler.go index d0c518e5b..34300af0c 100644 --- a/compiler/compiler.go +++ b/compiler/compiler.go @@ -1599,7 +1599,8 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c elemsLen := b.CreateExtractValue(elems, 1, "append.elemsLen") elemType := b.getLLVMType(argTypes[0].Underlying().(*types.Slice).Elem()) elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false) - result := b.createRuntimeCall("sliceAppend", []llvm.Value{srcBuf, elemsBuf, srcLen, srcCap, elemsLen, elemSize}, "append.new") + elemLayout := b.createObjectLayout(elemType, pos) + result := b.createRuntimeCall("sliceAppend", []llvm.Value{srcBuf, elemsBuf, srcLen, srcCap, elemsLen, elemSize, elemLayout}, "append.new") newPtr := b.CreateExtractValue(result, 0, "append.newPtr") newLen := b.CreateExtractValue(result, 1, "append.newLen") newCap := b.CreateExtractValue(result, 2, "append.newCap") diff --git a/compiler/testdata/slice.ll b/compiler/testdata/slice.ll index 029fd0b44..1ebb80c61 100644 --- a/compiler/testdata/slice.ll +++ b/compiler/testdata/slice.ll @@ -55,7 +55,7 @@ entry: store i32 2, ptr %0, align 4 %1 = getelementptr inbounds nuw i8, ptr %varargs, i32 8 store i32 3, ptr %1, align 4 - %append.new = call { ptr, i32, i32 } @runtime.sliceAppend(ptr %ints.data, ptr nonnull %varargs, i32 %ints.len, i32 %ints.cap, i32 3, i32 4, ptr undef) #3 + %append.new = call { ptr, i32, i32 } @runtime.sliceAppend(ptr %ints.data, ptr nonnull %varargs, i32 %ints.len, i32 %ints.cap, i32 3, i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 %append.newPtr = extractvalue { ptr, i32, i32 } %append.new, 0 %append.newLen = extractvalue { ptr, i32, i32 } %append.new, 1 %append.newCap = extractvalue { ptr, i32, i32 } %append.new, 2 @@ -66,13 +66,13 @@ entry: ret { ptr, i32, i32 } %4 } -declare { ptr, i32, i32 } @runtime.sliceAppend(ptr, ptr nocapture readonly, i32, i32, i32, i32, ptr) #1 +declare { ptr, i32, i32 } @runtime.sliceAppend(ptr, ptr nocapture readonly, i32, i32, i32, i32, ptr, ptr) #1 ; Function Attrs: nounwind define hidden { ptr, i32, i32 } @main.sliceAppendSlice(ptr %ints.data, i32 %ints.len, i32 %ints.cap, ptr %added.data, i32 %added.len, i32 %added.cap, ptr %context) unnamed_addr #2 { entry: %stackalloc = alloca i8, align 1 - %append.new = call { ptr, i32, i32 } @runtime.sliceAppend(ptr %ints.data, ptr %added.data, i32 %ints.len, i32 %ints.cap, i32 %added.len, i32 4, ptr undef) #3 + %append.new = call { ptr, i32, i32 } @runtime.sliceAppend(ptr %ints.data, ptr %added.data, i32 %ints.len, i32 %ints.cap, i32 %added.len, i32 4, ptr nonnull inttoptr (i32 3 to ptr), ptr undef) #3 %append.newPtr = extractvalue { ptr, i32, i32 } %append.new, 0 %append.newLen = extractvalue { ptr, i32, i32 } %append.new, 1 %append.newCap = extractvalue { ptr, i32, i32 } %append.new, 2 diff --git a/src/internal/reflectlite/value.go b/src/internal/reflectlite/value.go index 22a662856..47f0462a7 100644 --- a/src/internal/reflectlite/value.go +++ b/src/internal/reflectlite/value.go @@ -1745,7 +1745,7 @@ func memzero(ptr unsafe.Pointer, size uintptr) func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer //go:linkname sliceAppend runtime.sliceAppend -func sliceAppend(srcBuf, elemsBuf unsafe.Pointer, srcLen, srcCap, elemsLen uintptr, elemSize uintptr) (unsafe.Pointer, uintptr, uintptr) +func sliceAppend(srcBuf, elemsBuf unsafe.Pointer, srcLen, srcCap, elemsLen uintptr, elemSize uintptr, layout unsafe.Pointer) (unsafe.Pointer, uintptr, uintptr) //go:linkname sliceCopy runtime.sliceCopy func sliceCopy(dst, src unsafe.Pointer, dstLen, srcLen uintptr, elemSize uintptr) int @@ -1810,7 +1810,7 @@ func buflen(v Value) (unsafe.Pointer, uintptr) { } //go:linkname sliceGrow runtime.sliceGrow -func sliceGrow(buf unsafe.Pointer, oldLen, oldCap, newCap, elemSize uintptr) (unsafe.Pointer, uintptr, uintptr) +func sliceGrow(buf unsafe.Pointer, oldLen, oldCap, newCap, elemSize uintptr, layout unsafe.Pointer) (unsafe.Pointer, uintptr, uintptr) // extend slice to hold n new elements func extendSlice(v Value, n int) sliceHeader { @@ -1823,7 +1823,10 @@ func extendSlice(v Value, n int) sliceHeader { old = *(*sliceHeader)(v.value) } - nbuf, nlen, ncap := sliceGrow(old.data, old.len, old.cap, old.len+uintptr(n), v.typecode.elem().Size()) + elem := v.typecode.elem() + elemSize := elem.Size() + elemLayout := elem.gcLayout() + nbuf, nlen, ncap := sliceGrow(old.data, old.len, old.cap, old.len+uintptr(n), elemSize, elemLayout) return sliceHeader{ data: nbuf, @@ -1862,8 +1865,10 @@ func AppendSlice(s, t Value) Value { } sSlice := (*sliceHeader)(s.value) tSlice := (*sliceHeader)(t.value) - elemSize := s.typecode.elem().Size() - ptr, len, cap := sliceAppend(sSlice.data, tSlice.data, sSlice.len, sSlice.cap, tSlice.len, elemSize) + elem := s.typecode.elem() + elemSize := elem.Size() + elemLayout := elem.gcLayout() + ptr, len, cap := sliceAppend(sSlice.data, tSlice.data, sSlice.len, sSlice.cap, tSlice.len, elemSize, elemLayout) result := &sliceHeader{ data: ptr, len: len, diff --git a/src/runtime/slice.go b/src/runtime/slice.go index 45d3b7417..ea0821551 100644 --- a/src/runtime/slice.go +++ b/src/runtime/slice.go @@ -3,19 +3,18 @@ package runtime // This file implements compiler builtins for slices: append() and copy(). import ( - "internal/gclayout" "math/bits" "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, elemSize uintptr) (unsafe.Pointer, uintptr, uintptr) { +func sliceAppend(srcBuf, elemsBuf unsafe.Pointer, srcLen, srcCap, elemsLen, elemSize uintptr, layout unsafe.Pointer) (unsafe.Pointer, uintptr, uintptr) { newLen := srcLen + elemsLen if elemsLen > 0 { // Allocate a new slice with capacity for elemsLen more elements, if necessary; // otherwise, reuse the passed slice. - srcBuf, _, srcCap = sliceGrow(srcBuf, srcLen, srcCap, newLen, elemSize) + srcBuf, _, srcCap = sliceGrow(srcBuf, srcLen, srcCap, newLen, elemSize, layout) // Append the new elements in-place. memmove(unsafe.Add(srcBuf, srcLen*elemSize), elemsBuf, elemsLen*elemSize) @@ -36,7 +35,7 @@ func sliceCopy(dst, src unsafe.Pointer, dstLen, srcLen uintptr, elemSize uintptr } // sliceGrow returns a new slice with space for at least newCap elements -func sliceGrow(oldBuf unsafe.Pointer, oldLen, oldCap, newCap, elemSize uintptr) (unsafe.Pointer, uintptr, uintptr) { +func sliceGrow(oldBuf unsafe.Pointer, oldLen, oldCap, newCap, elemSize uintptr, layout unsafe.Pointer) (unsafe.Pointer, uintptr, uintptr) { if oldCap >= newCap { // No need to grow, return the input slice. return oldBuf, oldLen, oldCap @@ -48,12 +47,6 @@ func sliceGrow(oldBuf unsafe.Pointer, oldLen, oldCap, newCap, elemSize uintptr) // memory allocators, this causes some difficult to debug issues. newCap = 1 << bits.Len(uint(newCap)) - var layout unsafe.Pointer - // less type info here; can only go off element size - if elemSize < unsafe.Sizeof(uintptr(0)) { - layout = gclayout.NoPtrs.AsPtr() - } - buf := alloc(newCap*elemSize, layout) if oldLen > 0 { // copy any data to new slice