@ -304,7 +304,7 @@ func (p *lowerInterfacesPass) run() {
// interface value should already have returned false.
// interface value should already have returned false.
// Replace the function pointer with undef (which will then be
// Replace the function pointer with undef (which will then be
// called), indicating to the optimizer this code is unreachable.
// called), indicating to the optimizer this code is unreachable.
use . ReplaceAllUsesWith ( llvm . Undef ( p . i8 ptrType) )
use . ReplaceAllUsesWith ( llvm . Undef ( p . uint ptrType) )
use . EraseFromParentAsInstruction ( )
use . EraseFromParentAsInstruction ( )
} else if len ( itf . types ) == 1 {
} else if len ( itf . types ) == 1 {
// There is only one implementation of the given type.
// There is only one implementation of the given type.
@ -314,12 +314,12 @@ func (p *lowerInterfacesPass) run() {
// There are multiple types implementing this interface, thus there
// There are multiple types implementing this interface, thus there
// are multiple possible functions to call. Delegate calling the
// are multiple possible functions to call. Delegate calling the
// right function to a special wrapper function.
// right function to a special wrapper function.
bitcast s := getUses ( use )
inttoptr s := getUses ( use )
if len ( bitcast s) != 1 || bitcast s[ 0 ] . IsABitCast Inst ( ) . IsNil ( ) {
if len ( inttoptr s) != 1 || inttoptr s[ 0 ] . IsAIntToPtr Inst ( ) . IsNil ( ) {
panic ( "expected exactly one bitcast use of runtime.interfaceMethod" )
panic ( "expected exactly one inttoptr use of runtime.interfaceMethod" )
}
}
bitcast := bitcast s[ 0 ]
inttoptr := inttoptr s[ 0 ]
calls := getUses ( bitcast )
calls := getUses ( inttoptr )
if len ( calls ) != 1 || calls [ 0 ] . IsACallInst ( ) . IsNil ( ) {
if len ( calls ) != 1 || calls [ 0 ] . IsACallInst ( ) . IsNil ( ) {
panic ( "expected exactly one call use of runtime.interfaceMethod" )
panic ( "expected exactly one call use of runtime.interfaceMethod" )
}
}
@ -340,14 +340,14 @@ func (p *lowerInterfacesPass) run() {
// call, after selecting the right concrete type.
// call, after selecting the right concrete type.
redirector := p . getInterfaceMethodFunc ( itf , signature , call . Type ( ) , paramTypes )
redirector := p . getInterfaceMethodFunc ( itf , signature , call . Type ( ) , paramTypes )
// Replace the old lookup/bitcast /call with the new call.
// Replace the old lookup/inttoptr /call with the new call.
p . builder . SetInsertPointBefore ( call )
p . builder . SetInsertPointBefore ( call )
retval := p . builder . CreateCall ( redirector , params , "" )
retval := p . builder . CreateCall ( redirector , params , "" )
if retval . Type ( ) . TypeKind ( ) != llvm . VoidTypeKind {
if retval . Type ( ) . TypeKind ( ) != llvm . VoidTypeKind {
call . ReplaceAllUsesWith ( retval )
call . ReplaceAllUsesWith ( retval )
}
}
call . EraseFromParentAsInstruction ( )
call . EraseFromParentAsInstruction ( )
bitcast . EraseFromParentAsInstruction ( )
inttoptr . EraseFromParentAsInstruction ( )
use . EraseFromParentAsInstruction ( )
use . EraseFromParentAsInstruction ( )
}
}
}
}
@ -542,22 +542,22 @@ func (p *lowerInterfacesPass) getSignature(name string) *signatureInfo {
return p . signatures [ name ]
return p . signatures [ name ]
}
}
// replaceInvokeWithCall replaces a runtime.interfaceMethod + bitcast with a
// replaceInvokeWithCall replaces a runtime.interfaceMethod + inttoptr with a
// concrete method. This can be done when only one type implements the
// concrete method. This can be done when only one type implements the
// interface.
// interface.
func ( p * lowerInterfacesPass ) replaceInvokeWithCall ( use llvm . Value , typ * typeInfo , signature * signatureInfo ) {
func ( p * lowerInterfacesPass ) replaceInvokeWithCall ( use llvm . Value , typ * typeInfo , signature * signatureInfo ) {
bitcast s := getUses ( use )
inttoptr s := getUses ( use )
if len ( bitcast s) != 1 || bitcast s[ 0 ] . IsABitCast Inst ( ) . IsNil ( ) {
if len ( inttoptr s) != 1 || inttoptr s[ 0 ] . IsAIntToPtr Inst ( ) . IsNil ( ) {
panic ( "expected exactly one bitcast use of runtime.interfaceMethod" )
panic ( "expected exactly one inttoptr use of runtime.interfaceMethod" )
}
}
bitcast := bitcast s[ 0 ]
inttoptr := inttoptr s[ 0 ]
function := typ . getMethod ( signature ) . function
function := typ . getMethod ( signature ) . function
if bitcast . Type ( ) != function . Type ( ) {
if inttoptr . Type ( ) != function . Type ( ) {
p . builder . SetInsertPointBefore ( use )
p . builder . SetInsertPointBefore ( use )
function = p . builder . CreateBitCast ( function , bitcast . Type ( ) , "" )
function = p . builder . CreateBitCast ( function , inttoptr . Type ( ) , "" )
}
}
bitcast . ReplaceAllUsesWith ( function )
inttoptr . ReplaceAllUsesWith ( function )
bitcast . EraseFromParentAsInstruction ( )
inttoptr . EraseFromParentAsInstruction ( )
use . EraseFromParentAsInstruction ( )
use . EraseFromParentAsInstruction ( )
}
}