compiler: implement make([]T, ...)

Этот коммит содержится в:
Ayke van Laethem 2018-09-06 09:46:58 +02:00
родитель ef2c406127
коммит 094c5561b6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E97FF5335DFDFDED
3 изменённых файлов: 54 добавлений и 1 удалений

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

@ -2087,6 +2087,48 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
llvmValueSize := llvm.ConstInt(llvm.Int8Type(), valueSize, false)
hashmap := c.builder.CreateCall(hashmapMake, []llvm.Value{llvmKeySize, llvmValueSize}, "")
return hashmap, nil
case *ssa.MakeSlice:
sliceLen, err := c.parseExpr(frame, expr.Len)
if err != nil {
return llvm.Value{}, nil
}
sliceCap, err := c.parseExpr(frame, expr.Cap)
if err != nil {
return llvm.Value{}, nil
}
sliceType := expr.Type().Underlying().(*types.Slice)
llvmElemType, err := c.getLLVMType(sliceType.Elem())
if err != nil {
return llvm.Value{}, nil
}
elemSize := c.targetData.TypeAllocSize(llvmElemType)
// Bounds checking.
if !frame.fn.nobounds {
sliceBoundsCheck := c.mod.NamedFunction("runtime.sliceBoundsCheckMake")
c.builder.CreateCall(sliceBoundsCheck, []llvm.Value{sliceLen, sliceCap}, "")
}
// Allocate the backing array.
// TODO: escape analysis
elemSizeValue := llvm.ConstInt(c.uintptrType, elemSize, false)
sliceCapCast, err := c.parseConvert(expr.Cap.Type(), types.Typ[types.Uintptr], sliceCap)
if err != nil {
return llvm.Value{}, err
}
sliceSize := c.builder.CreateBinOp(llvm.Mul, elemSizeValue, sliceCapCast, "makeslice.cap")
slicePtr := c.builder.CreateCall(c.allocFunc, []llvm.Value{sliceSize}, "makeslice.buf")
// Create the slice.
slice := llvm.ConstStruct([]llvm.Value{
llvm.Undef(slicePtr.Type()),
llvm.Undef(c.lenType),
llvm.Undef(c.lenType),
}, false)
slice = c.builder.CreateInsertValue(slice, slicePtr, 0, "")
slice = c.builder.CreateInsertValue(slice, sliceLen, 1, "")
slice = c.builder.CreateInsertValue(slice, sliceCap, 2, "")
return slice, nil
case *ssa.Phi:
t, err := c.getLLVMType(expr.Type())
if err != nil {

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

@ -35,8 +35,11 @@ func main() {
readMap(testmap, "data")
// slice
l := 5
foo := []int{1, 2, 4, 5}
bar := make([]byte, 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))

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

@ -99,10 +99,18 @@ func lookupBoundsCheck(length, index int) {
}
}
// Check for bounds in *ssa.Slice
// Check for bounds in *ssa.Slice.
func sliceBoundsCheck(length, low, high uint) {
if !(0 <= low && low <= high && high <= length) {
printstring("panic: runtime error: slice out of range\n")
abort()
}
}
// Check for bounds in *ssa.MakeSlice.
func sliceBoundsCheckMake(length, capacity uint) {
if !(0 <= length && length <= capacity) {
printstring("panic: runtime error: slice size out of range\n")
abort()
}
}