compiler: share recoverable fault blocks

This commit is contained in:
Jake Bailey
2026-05-31 16:31:35 -07:00
committed by Ron Evans
parent dded832238
commit 278aa09819
5 changed files with 70 additions and 78 deletions
+18 -9
View File
@@ -828,18 +828,10 @@ func (b *builder) createTypeAssert(expr *ssa.TypeAssert) llvm.Value {
return tuple
} else {
// Type assert without comma-ok. If it fails, panic.
faultBlock := b.ctx.AddBasicBlock(b.llvmFn, "typeassert.throw")
faultBlock := b.getInterfaceAssertBlock()
b.currentBlockInfo.exit = okBlock
b.CreateCondBr(commaOk, okBlock, faultBlock)
// Fault: emit a checkpoint (for recover) and panic.
b.SetInsertPointAtEnd(faultBlock)
if b.hasDeferFrame() {
b.createFaultCheckpoint()
}
b.createRuntimeCall("interfaceTypeAssert", []llvm.Value{llvm.ConstInt(b.ctx.Int1Type(), 0, false)}, "")
b.CreateUnreachable()
// OK: extract the value from the interface.
b.SetInsertPointAtEnd(okBlock)
if _, ok := expr.AssertedType.Underlying().(*types.Interface); ok {
@@ -849,6 +841,23 @@ func (b *builder) createTypeAssert(expr *ssa.TypeAssert) llvm.Value {
}
}
func (b *builder) getInterfaceAssertBlock() llvm.BasicBlock {
if !b.interfaceAssertBlock.IsNil() {
return b.interfaceAssertBlock
}
savedBlock := b.GetInsertBlock()
block := b.ctx.AddBasicBlock(b.llvmFn, "typeassert.throw")
b.interfaceAssertBlock = block
b.SetInsertPointAtEnd(block)
if b.hasDeferFrame() {
b.createFaultCheckpoint()
}
b.createRuntimeCall("interfaceTypeAssert", []llvm.Value{llvm.ConstInt(b.ctx.Int1Type(), 0, false)}, "")
b.CreateUnreachable()
b.SetInsertPointAtEnd(savedBlock)
return block
}
// getMethodsString returns a string to be used in the "tinygo-methods" string
// attribute for interface functions.
func (c *compilerContext) getMethodsString(itf *types.Interface) string {