compiler: implement make([]T, ...)
Этот коммит содержится в:
родитель
ef2c406127
коммит
094c5561b6
3 изменённых файлов: 54 добавлений и 1 удалений
42
compiler.go
42
compiler.go
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче