compiler: check slice cap instead of len during slicing

When doing a slice operation on a slice, use the capacity value instead
of the length. Of course, for strings and arrays, the slice operation
checks the length because there is no capacity. But according to the
spec, this check should be based on cap for slice instead of len:

> For slices, the upper index bound is the slice capacity cap(a) rather
> than the length.

https://golang.org/ref/spec#Slice_expressions

Fixes: https://github.com/aykevl/tinygo/issues/65
This commit is contained in:
Ayke van Laethem
2018-10-30 15:50:22 +01:00
parent 317b12b8c0
commit 0314a487ff
2 changed files with 8 additions and 8 deletions
+4 -4
View File
@@ -2237,7 +2237,7 @@ func (c *Compiler) emitBoundsCheck(frame *Frame, arrayLen, index llvm.Value, ind
}
}
func (c *Compiler) emitSliceBoundsCheck(frame *Frame, length, low, high llvm.Value) {
func (c *Compiler) emitSliceBoundsCheck(frame *Frame, capacity, low, high llvm.Value) {
if frame.fn.IsNoBounds() {
// The //go:nobounds pragma was added to the function to avoid bounds
// checking.
@@ -2251,9 +2251,9 @@ func (c *Compiler) emitSliceBoundsCheck(frame *Frame, length, low, high llvm.Val
if high.Type().IntTypeWidth() < 64 {
high = c.builder.CreateSExt(high, c.ctx.Int64Type(), "")
}
c.createRuntimeCall("sliceBoundsCheckLong", []llvm.Value{length, low, high}, "")
c.createRuntimeCall("sliceBoundsCheckLong", []llvm.Value{capacity, low, high}, "")
} else {
c.createRuntimeCall("sliceBoundsCheck", []llvm.Value{length, low, high}, "")
c.createRuntimeCall("sliceBoundsCheck", []llvm.Value{capacity, low, high}, "")
}
}
@@ -2684,7 +2684,7 @@ func (c *Compiler) parseExpr(frame *Frame, expr ssa.Value) (llvm.Value, error) {
high = oldLen
}
c.emitSliceBoundsCheck(frame, oldLen, low, high)
c.emitSliceBoundsCheck(frame, oldCap, low, high)
if c.targetData.TypeAllocSize(low.Type()) > c.targetData.TypeAllocSize(c.lenType) {
low = c.builder.CreateTrunc(low, c.lenType, "")