Skip to content

Commit 571a412

Browse files
aykevldeadprogram
authored andcommitted
compiler: merge some redundant assertion code
1 parent 79dae62 commit 571a412

File tree

1 file changed

+31
-60
lines changed

1 file changed

+31
-60
lines changed

compiler/asserts.go

Lines changed: 31 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,9 @@ func (c *Compiler) emitLookupBoundsCheck(frame *Frame, arrayLen, index llvm.Valu
3434
arrayLen = c.builder.CreateZExt(arrayLen, index.Type(), "")
3535
}
3636

37-
faultBlock := c.ctx.AddBasicBlock(frame.fn.LLVMFn, "lookup.outofbounds")
38-
nextBlock := c.ctx.AddBasicBlock(frame.fn.LLVMFn, "lookup.next")
39-
frame.blockExits[frame.currentBlock] = nextBlock // adjust outgoing block for phi nodes
40-
4137
// Now do the bounds check: index >= arrayLen
4238
outOfBounds := c.builder.CreateICmp(llvm.IntUGE, index, arrayLen, "")
43-
c.builder.CreateCondBr(outOfBounds, faultBlock, nextBlock)
44-
45-
// Fail: this is a nil pointer, exit with a panic.
46-
c.builder.SetInsertPointAtEnd(faultBlock)
47-
c.createRuntimeCall("lookupPanic", nil, "")
48-
c.builder.CreateUnreachable()
49-
50-
// Ok: this is a valid pointer.
51-
c.builder.SetInsertPointAtEnd(nextBlock)
39+
c.createRuntimeAssert(frame, outOfBounds, "lookup", "lookupPanic")
5240
}
5341

5442
// emitSliceBoundsCheck emits a bounds check before a slicing operation to make
@@ -103,25 +91,13 @@ func (c *Compiler) emitSliceBoundsCheck(frame *Frame, capacity, low, high, max l
10391
}
10492
}
10593

106-
faultBlock := c.ctx.AddBasicBlock(frame.fn.LLVMFn, "slice.outofbounds")
107-
nextBlock := c.ctx.AddBasicBlock(frame.fn.LLVMFn, "slice.next")
108-
frame.blockExits[frame.currentBlock] = nextBlock // adjust outgoing block for phi nodes
109-
11094
// Now do the bounds check: low > high || high > capacity
11195
outOfBounds1 := c.builder.CreateICmp(llvm.IntUGT, low, high, "slice.lowhigh")
11296
outOfBounds2 := c.builder.CreateICmp(llvm.IntUGT, high, max, "slice.highmax")
11397
outOfBounds3 := c.builder.CreateICmp(llvm.IntUGT, max, capacity, "slice.maxcap")
11498
outOfBounds := c.builder.CreateOr(outOfBounds1, outOfBounds2, "slice.lowmax")
11599
outOfBounds = c.builder.CreateOr(outOfBounds, outOfBounds3, "slice.lowcap")
116-
c.builder.CreateCondBr(outOfBounds, faultBlock, nextBlock)
117-
118-
// Fail: this is a nil pointer, exit with a panic.
119-
c.builder.SetInsertPointAtEnd(faultBlock)
120-
c.createRuntimeCall("slicePanic", nil, "")
121-
c.builder.CreateUnreachable()
122-
123-
// Ok: this is a valid pointer.
124-
c.builder.SetInsertPointAtEnd(nextBlock)
100+
c.createRuntimeAssert(frame, outOfBounds, "slice", "slicePanic")
125101
}
126102

127103
// emitChanBoundsCheck emits a bounds check before creating a new channel to
@@ -167,32 +143,9 @@ func (c *Compiler) emitChanBoundsCheck(frame *Frame, elementSize uint64, bufSize
167143
maxBufSize = llvm.ConstZExt(maxBufSize, bufSize.Type())
168144
}
169145

146+
// Do the check for a too large (or negative) buffer size.
170147
bufSizeTooBig := c.builder.CreateICmp(llvm.IntUGE, bufSize, maxBufSize, "")
171-
// Check whether we can resolve this check at compile time.
172-
if !bufSizeTooBig.IsAConstantInt().IsNil() {
173-
val := bufSizeTooBig.ZExtValue()
174-
if val == 0 {
175-
// Everything is constant so the check does not have to be emitted
176-
// in IR. This avoids emitting some redundant IR in the vast
177-
// majority of cases.
178-
return
179-
}
180-
}
181-
182-
faultBlock := c.ctx.AddBasicBlock(frame.fn.LLVMFn, "chan.outofbounds")
183-
nextBlock := c.ctx.AddBasicBlock(frame.fn.LLVMFn, "chan.next")
184-
frame.blockExits[frame.currentBlock] = nextBlock // adjust outgoing block for phi nodes
185-
186-
// Now branch to the out-of-bounds or the regular block.
187-
c.builder.CreateCondBr(bufSizeTooBig, faultBlock, nextBlock)
188-
189-
// Fail: this channel is created with an invalid size parameter.
190-
c.builder.SetInsertPointAtEnd(faultBlock)
191-
c.createRuntimeCall("chanMakePanic", nil, "")
192-
c.builder.CreateUnreachable()
193-
194-
// Ok: this channel value is not too big.
195-
c.builder.SetInsertPointAtEnd(nextBlock)
148+
c.createRuntimeAssert(frame, bufSizeTooBig, "chan", "chanMakePanic")
196149
}
197150

198151
// emitNilCheck checks whether the given pointer is nil, and panics if it is. It
@@ -204,11 +157,6 @@ func (c *Compiler) emitNilCheck(frame *Frame, ptr llvm.Value, blockPrefix string
204157
return
205158
}
206159

207-
// Check whether this is a nil pointer.
208-
faultBlock := c.ctx.AddBasicBlock(frame.fn.LLVMFn, blockPrefix+".nil")
209-
nextBlock := c.ctx.AddBasicBlock(frame.fn.LLVMFn, blockPrefix+".next")
210-
frame.blockExits[frame.currentBlock] = nextBlock // adjust outgoing block for phi nodes
211-
212160
// Compare against nil.
213161
var isnil llvm.Value
214162
if ptr.Type().PointerAddressSpace() == 0 {
@@ -227,13 +175,36 @@ func (c *Compiler) emitNilCheck(frame *Frame, ptr llvm.Value, blockPrefix string
227175
nilptr := llvm.ConstPointerNull(ptr.Type())
228176
isnil = c.builder.CreateICmp(llvm.IntEQ, ptr, nilptr, "")
229177
}
230-
c.builder.CreateCondBr(isnil, faultBlock, nextBlock)
231178

232-
// Fail: this is a nil pointer, exit with a panic.
179+
// Emit the nil check in IR.
180+
c.createRuntimeAssert(frame, isnil, blockPrefix, "nilPanic")
181+
}
182+
183+
// createRuntimeAssert is a common function to create a new branch on an assert
184+
// bool, calling an assert func if the assert value is true (1).
185+
func (c *Compiler) createRuntimeAssert(frame *Frame, assert llvm.Value, blockPrefix, assertFunc string) {
186+
// Check whether we can resolve this check at compile time.
187+
if !assert.IsAConstantInt().IsNil() {
188+
val := assert.ZExtValue()
189+
if val == 0 {
190+
// Everything is constant so the check does not have to be emitted
191+
// in IR. This avoids emitting some redundant IR.
192+
return
193+
}
194+
}
195+
196+
faultBlock := c.ctx.AddBasicBlock(frame.fn.LLVMFn, blockPrefix+".throw")
197+
nextBlock := c.ctx.AddBasicBlock(frame.fn.LLVMFn, blockPrefix+".next")
198+
frame.blockExits[frame.currentBlock] = nextBlock // adjust outgoing block for phi nodes
199+
200+
// Now branch to the out-of-bounds or the regular block.
201+
c.builder.CreateCondBr(assert, faultBlock, nextBlock)
202+
203+
// Fail: the assert triggered so panic.
233204
c.builder.SetInsertPointAtEnd(faultBlock)
234-
c.createRuntimeCall("nilPanic", nil, "")
205+
c.createRuntimeCall(assertFunc, nil, "")
235206
c.builder.CreateUnreachable()
236207

237-
// Ok: this is a valid pointer.
208+
// Ok: assert didn't trigger so continue normally.
238209
c.builder.SetInsertPointAtEnd(nextBlock)
239210
}

0 commit comments

Comments
 (0)