@@ -31,7 +31,7 @@ func (b *builder) createLookupBoundsCheck(arrayLen, index llvm.Value) {
31
31
32
32
// Now do the bounds check: index >= arrayLen
33
33
outOfBounds := b .CreateICmp (llvm .IntUGE , index , arrayLen , "" )
34
- b .createRuntimeAssert (outOfBounds , "lookup" , "lookupPanic" )
34
+ b .createRuntimeAssert (outOfBounds , "lookup" , "lookupPanic" , false )
35
35
}
36
36
37
37
// createSliceBoundsCheck emits a bounds check before a slicing operation to make
@@ -74,7 +74,7 @@ func (b *builder) createSliceBoundsCheck(capacity, low, high, max llvm.Value, lo
74
74
outOfBounds3 := b .CreateICmp (llvm .IntUGT , max , capacity , "slice.maxcap" )
75
75
outOfBounds := b .CreateOr (outOfBounds1 , outOfBounds2 , "slice.lowmax" )
76
76
outOfBounds = b .CreateOr (outOfBounds , outOfBounds3 , "slice.lowcap" )
77
- b .createRuntimeAssert (outOfBounds , "slice" , "slicePanic" )
77
+ b .createRuntimeAssert (outOfBounds , "slice" , "slicePanic" , false )
78
78
}
79
79
80
80
// createSliceToArrayPointerCheck adds a check for slice-to-array pointer
@@ -86,7 +86,7 @@ func (b *builder) createSliceToArrayPointerCheck(sliceLen llvm.Value, arrayLen i
86
86
// > run-time panic occurs.
87
87
arrayLenValue := llvm .ConstInt (b .uintptrType , uint64 (arrayLen ), false )
88
88
isLess := b .CreateICmp (llvm .IntULT , sliceLen , arrayLenValue , "" )
89
- b .createRuntimeAssert (isLess , "slicetoarray" , "sliceToArrayPointerPanic" )
89
+ b .createRuntimeAssert (isLess , "slicetoarray" , "sliceToArrayPointerPanic" , false )
90
90
}
91
91
92
92
// createUnsafeSliceStringCheck inserts a runtime check used for unsafe.Slice
@@ -118,7 +118,7 @@ func (b *builder) createUnsafeSliceStringCheck(name string, ptr, len llvm.Value,
118
118
lenIsNotZero := b .CreateICmp (llvm .IntNE , len , zero , "" )
119
119
assert := b .CreateAnd (ptrIsNil , lenIsNotZero , "" )
120
120
assert = b .CreateOr (assert , lenOutOfBounds , "" )
121
- b .createRuntimeAssert (assert , name , "unsafeSlicePanic" )
121
+ b .createRuntimeAssert (assert , name , "unsafeSlicePanic" , false )
122
122
}
123
123
124
124
// createChanBoundsCheck creates a bounds check before creating a new channel to
@@ -155,7 +155,7 @@ func (b *builder) createChanBoundsCheck(elementSize uint64, bufSize llvm.Value,
155
155
156
156
// Do the check for a too large (or negative) buffer size.
157
157
bufSizeTooBig := b .CreateICmp (llvm .IntUGE , bufSize , maxBufSize , "" )
158
- b .createRuntimeAssert (bufSizeTooBig , "chan" , "chanMakePanic" )
158
+ b .createRuntimeAssert (bufSizeTooBig , "chan" , "chanMakePanic" , false )
159
159
}
160
160
161
161
// createNilCheck checks whether the given pointer is nil, and panics if it is.
@@ -199,7 +199,7 @@ func (b *builder) createNilCheck(inst ssa.Value, ptr llvm.Value, blockPrefix str
199
199
isnil := b .CreateICmp (llvm .IntEQ , ptr , nilptr , "" )
200
200
201
201
// Emit the nil check in IR.
202
- b .createRuntimeAssert (isnil , blockPrefix , "nilPanic" )
202
+ b .createRuntimeAssert (isnil , blockPrefix , "nilPanic" , false )
203
203
}
204
204
205
205
// createNegativeShiftCheck creates an assertion that panics if the given shift value is negative.
@@ -212,7 +212,7 @@ func (b *builder) createNegativeShiftCheck(shift llvm.Value) {
212
212
213
213
// isNegative = shift < 0
214
214
isNegative := b .CreateICmp (llvm .IntSLT , shift , llvm .ConstInt (shift .Type (), 0 , false ), "" )
215
- b .createRuntimeAssert (isNegative , "shift" , "negativeShiftPanic" )
215
+ b .createRuntimeAssert (isNegative , "shift" , "negativeShiftPanic" , false )
216
216
}
217
217
218
218
// createDivideByZeroCheck asserts that y is not zero. If it is, a runtime panic
@@ -225,12 +225,12 @@ func (b *builder) createDivideByZeroCheck(y llvm.Value) {
225
225
226
226
// isZero = y == 0
227
227
isZero := b .CreateICmp (llvm .IntEQ , y , llvm .ConstInt (y .Type (), 0 , false ), "" )
228
- b .createRuntimeAssert (isZero , "divbyzero" , "divideByZeroPanic" )
228
+ b .createRuntimeAssert (isZero , "divbyzero" , "divideByZeroPanic" , true )
229
229
}
230
230
231
231
// createRuntimeAssert is a common function to create a new branch on an assert
232
232
// bool, calling an assert func if the assert value is true (1).
233
- func (b * builder ) createRuntimeAssert (assert llvm.Value , blockPrefix , assertFunc string ) {
233
+ func (b * builder ) createRuntimeAssert (assert llvm.Value , blockPrefix , assertFunc string , invoke bool ) {
234
234
// Check whether we can resolve this check at compile time.
235
235
if ! assert .IsAConstantInt ().IsNil () {
236
236
val := assert .ZExtValue ()
@@ -252,7 +252,13 @@ func (b *builder) createRuntimeAssert(assert llvm.Value, blockPrefix, assertFunc
252
252
253
253
// Fail: the assert triggered so panic.
254
254
b .SetInsertPointAtEnd (faultBlock )
255
- b .createRuntimeCall (assertFunc , nil , "" )
255
+ if invoke {
256
+ // This runtime panic is recoverable.
257
+ b .createRuntimeInvoke (assertFunc , nil , "" )
258
+ } else {
259
+ // This runtime panic is not recoverable.
260
+ b .createRuntimeCall (assertFunc , nil , "" )
261
+ }
256
262
b .CreateUnreachable ()
257
263
258
264
// Ok: assert didn't trigger so continue normally.
0 commit comments