createSliceBoundsCheck emits a bounds check before a slicing operation to make sure it is within bounds. This function is both used for slicing a slice (low and high have their normal meaning) and for creating a new slice, where 'capacity' means the biggest possible slice capacity, 'low' means len
(capacity, low, high, max llvm.Value, lowType, highType, maxType *types.Basic)
| 42 | // biggest possible slice capacity, 'low' means len and 'high' means cap. The |
| 43 | // logic is the same in both cases. |
| 44 | func (b *builder) createSliceBoundsCheck(capacity, low, high, max llvm.Value, lowType, highType, maxType *types.Basic) { |
| 45 | if b.info.nobounds { |
| 46 | // The //go:nobounds pragma was added to the function to avoid bounds |
| 47 | // checking. |
| 48 | return |
| 49 | } |
| 50 | |
| 51 | // Extend the capacity integer to be at least as wide as low and high. |
| 52 | capacityType := capacity.Type() |
| 53 | if low.Type().IntTypeWidth() > capacityType.IntTypeWidth() { |
| 54 | capacityType = low.Type() |
| 55 | } |
| 56 | if high.Type().IntTypeWidth() > capacityType.IntTypeWidth() { |
| 57 | capacityType = high.Type() |
| 58 | } |
| 59 | if max.Type().IntTypeWidth() > capacityType.IntTypeWidth() { |
| 60 | capacityType = max.Type() |
| 61 | } |
| 62 | if capacityType != capacity.Type() { |
| 63 | capacity = b.CreateZExt(capacity, capacityType, "") |
| 64 | } |
| 65 | |
| 66 | // Extend low and high to be the same size as capacity. |
| 67 | low = b.extendInteger(low, lowType, capacityType) |
| 68 | high = b.extendInteger(high, highType, capacityType) |
| 69 | max = b.extendInteger(max, maxType, capacityType) |
| 70 | |
| 71 | // Now do the bounds check: low > high || high > capacity |
| 72 | outOfBounds1 := b.CreateICmp(llvm.IntUGT, low, high, "slice.lowhigh") |
| 73 | outOfBounds2 := b.CreateICmp(llvm.IntUGT, high, max, "slice.highmax") |
| 74 | outOfBounds3 := b.CreateICmp(llvm.IntUGT, max, capacity, "slice.maxcap") |
| 75 | outOfBounds := b.CreateOr(outOfBounds1, outOfBounds2, "slice.lowmax") |
| 76 | outOfBounds = b.CreateOr(outOfBounds, outOfBounds3, "slice.lowcap") |
| 77 | b.createRuntimeAssert(outOfBounds, "slice", "slicePanic") |
| 78 | } |
| 79 | |
| 80 | // createSliceToArrayPointerCheck adds a check for slice-to-array pointer |
| 81 | // conversions. This conversion was added in Go 1.17. For details, see: |
no test coverage detected