Browse Source

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

pull/6/head
Ayke van Laethem 6 years ago
parent
commit
094c5561b6
No known key found for this signature in database GPG Key ID: E97FF5335DFDFDED
  1. 42
      compiler.go
  2. 3
      src/examples/test/test.go
  3. 10
      src/runtime/runtime.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 {

3
src/examples/test/test.go

@ -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))

10
src/runtime/runtime.go

@ -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()
}
}

Loading…
Cancel
Save