mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-20 20:39:06 +00:00
compiler/runtime: add element layout to sliceAppend
Attach the memory layout of the element type to newly created slices via append when using the precise collector.
This commit is contained in:
@@ -1599,7 +1599,8 @@ func (b *builder) createBuiltin(argTypes []types.Type, argValues []llvm.Value, c
|
|||||||
elemsLen := b.CreateExtractValue(elems, 1, "append.elemsLen")
|
elemsLen := b.CreateExtractValue(elems, 1, "append.elemsLen")
|
||||||
elemType := b.getLLVMType(argTypes[0].Underlying().(*types.Slice).Elem())
|
elemType := b.getLLVMType(argTypes[0].Underlying().(*types.Slice).Elem())
|
||||||
elemSize := llvm.ConstInt(b.uintptrType, b.targetData.TypeAllocSize(elemType), false)
|
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")
|
newPtr := b.CreateExtractValue(result, 0, "append.newPtr")
|
||||||
newLen := b.CreateExtractValue(result, 1, "append.newLen")
|
newLen := b.CreateExtractValue(result, 1, "append.newLen")
|
||||||
newCap := b.CreateExtractValue(result, 2, "append.newCap")
|
newCap := b.CreateExtractValue(result, 2, "append.newCap")
|
||||||
|
|||||||
Vendored
+3
-3
@@ -55,7 +55,7 @@ entry:
|
|||||||
store i32 2, ptr %0, align 4
|
store i32 2, ptr %0, align 4
|
||||||
%1 = getelementptr inbounds nuw i8, ptr %varargs, i32 8
|
%1 = getelementptr inbounds nuw i8, ptr %varargs, i32 8
|
||||||
store i32 3, ptr %1, align 4
|
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.newPtr = extractvalue { ptr, i32, i32 } %append.new, 0
|
||||||
%append.newLen = extractvalue { ptr, i32, i32 } %append.new, 1
|
%append.newLen = extractvalue { ptr, i32, i32 } %append.new, 1
|
||||||
%append.newCap = extractvalue { ptr, i32, i32 } %append.new, 2
|
%append.newCap = extractvalue { ptr, i32, i32 } %append.new, 2
|
||||||
@@ -66,13 +66,13 @@ entry:
|
|||||||
ret { ptr, i32, i32 } %4
|
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
|
; 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 {
|
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:
|
entry:
|
||||||
%stackalloc = alloca i8, align 1
|
%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.newPtr = extractvalue { ptr, i32, i32 } %append.new, 0
|
||||||
%append.newLen = extractvalue { ptr, i32, i32 } %append.new, 1
|
%append.newLen = extractvalue { ptr, i32, i32 } %append.new, 1
|
||||||
%append.newCap = extractvalue { ptr, i32, i32 } %append.new, 2
|
%append.newCap = extractvalue { ptr, i32, i32 } %append.new, 2
|
||||||
|
|||||||
@@ -1745,7 +1745,7 @@ func memzero(ptr unsafe.Pointer, size uintptr)
|
|||||||
func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer
|
func alloc(size uintptr, layout unsafe.Pointer) unsafe.Pointer
|
||||||
|
|
||||||
//go:linkname sliceAppend runtime.sliceAppend
|
//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
|
//go:linkname sliceCopy runtime.sliceCopy
|
||||||
func sliceCopy(dst, src unsafe.Pointer, dstLen, srcLen uintptr, elemSize uintptr) int
|
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
|
//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
|
// extend slice to hold n new elements
|
||||||
func extendSlice(v Value, n int) sliceHeader {
|
func extendSlice(v Value, n int) sliceHeader {
|
||||||
@@ -1823,7 +1823,10 @@ func extendSlice(v Value, n int) sliceHeader {
|
|||||||
old = *(*sliceHeader)(v.value)
|
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{
|
return sliceHeader{
|
||||||
data: nbuf,
|
data: nbuf,
|
||||||
@@ -1862,8 +1865,10 @@ func AppendSlice(s, t Value) Value {
|
|||||||
}
|
}
|
||||||
sSlice := (*sliceHeader)(s.value)
|
sSlice := (*sliceHeader)(s.value)
|
||||||
tSlice := (*sliceHeader)(t.value)
|
tSlice := (*sliceHeader)(t.value)
|
||||||
elemSize := s.typecode.elem().Size()
|
elem := s.typecode.elem()
|
||||||
ptr, len, cap := sliceAppend(sSlice.data, tSlice.data, sSlice.len, sSlice.cap, tSlice.len, elemSize)
|
elemSize := elem.Size()
|
||||||
|
elemLayout := elem.gcLayout()
|
||||||
|
ptr, len, cap := sliceAppend(sSlice.data, tSlice.data, sSlice.len, sSlice.cap, tSlice.len, elemSize, elemLayout)
|
||||||
result := &sliceHeader{
|
result := &sliceHeader{
|
||||||
data: ptr,
|
data: ptr,
|
||||||
len: len,
|
len: len,
|
||||||
|
|||||||
+3
-10
@@ -3,19 +3,18 @@ package runtime
|
|||||||
// This file implements compiler builtins for slices: append() and copy().
|
// This file implements compiler builtins for slices: append() and copy().
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"internal/gclayout"
|
|
||||||
"math/bits"
|
"math/bits"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Builtin append(src, elements...) function: append elements to src and return
|
// Builtin append(src, elements...) function: append elements to src and return
|
||||||
// the modified (possibly expanded) slice.
|
// 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
|
newLen := srcLen + elemsLen
|
||||||
if elemsLen > 0 {
|
if elemsLen > 0 {
|
||||||
// Allocate a new slice with capacity for elemsLen more elements, if necessary;
|
// Allocate a new slice with capacity for elemsLen more elements, if necessary;
|
||||||
// otherwise, reuse the passed slice.
|
// 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.
|
// Append the new elements in-place.
|
||||||
memmove(unsafe.Add(srcBuf, srcLen*elemSize), elemsBuf, elemsLen*elemSize)
|
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
|
// 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 {
|
if oldCap >= newCap {
|
||||||
// No need to grow, return the input slice.
|
// No need to grow, return the input slice.
|
||||||
return oldBuf, oldLen, oldCap
|
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.
|
// memory allocators, this causes some difficult to debug issues.
|
||||||
newCap = 1 << bits.Len(uint(newCap))
|
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)
|
buf := alloc(newCap*elemSize, layout)
|
||||||
if oldLen > 0 {
|
if oldLen > 0 {
|
||||||
// copy any data to new slice
|
// copy any data to new slice
|
||||||
|
|||||||
Reference in New Issue
Block a user