Fix for finally block for inline functions

For local return from inline function to outer scope just
call super version of genReturn.
This commit is contained in:
Igor Chevdar
2017-03-28 18:50:49 +03:00
parent 1bf73fd9d7
commit a3becd24ec
@@ -152,16 +152,6 @@ internal interface CodeContext {
*/ */
fun genGetValue(descriptor: ValueDescriptor): LLVMValueRef fun genGetValue(descriptor: ValueDescriptor): LLVMValueRef
/**
* Gets the exit block for the context owned by specified descriptor.
*/
fun getExit(descriptor: CallableDescriptor): LLVMBasicBlockRef
/**
* Gets the result value for the context owned by specified descriptor.
*/
fun getResult(descriptor: CallableDescriptor): LLVMValueRef
/** /**
* Returns owning function scope. * Returns owning function scope.
* *
@@ -208,10 +198,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
override fun genGetValue(descriptor: ValueDescriptor) = unsupported(descriptor) override fun genGetValue(descriptor: ValueDescriptor) = unsupported(descriptor)
override fun getExit(descriptor: CallableDescriptor): LLVMBasicBlockRef = unsupported(descriptor)
override fun getResult(descriptor: CallableDescriptor): LLVMValueRef = unsupported(descriptor)
override fun functionScope(): CodeContext = unsupported() override fun functionScope(): CodeContext = unsupported()
} }
@@ -1395,19 +1381,15 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
var bbExit : LLVMBasicBlockRef? = null var bbExit : LLVMBasicBlockRef? = null
var resultPhi : LLVMValueRef? = null var resultPhi : LLVMValueRef? = null
override fun getExit(descriptor: CallableDescriptor): LLVMBasicBlockRef { private fun getExit(): LLVMBasicBlockRef {
if (descriptor != inlineBody.descriptor)
return super.getExit(descriptor)
if (bbExit == null) bbExit = codegen.basicBlock("inline_body_exit") if (bbExit == null) bbExit = codegen.basicBlock("inline_body_exit")
return bbExit!! return bbExit!!
} }
override fun getResult(descriptor: CallableDescriptor): LLVMValueRef { private fun getResult(): LLVMValueRef {
if (descriptor != inlineBody.descriptor)
return super.getResult(descriptor)
if (resultPhi == null) { if (resultPhi == null) {
val bbCurrent = codegen.currentBlock val bbCurrent = codegen.currentBlock
codegen.positionAtEnd(getExit(descriptor)) codegen.positionAtEnd(getExit())
resultPhi = codegen.phi(codegen.getLLVMType(inlineBody.type)) resultPhi = codegen.phi(codegen.getLLVMType(inlineBody.type))
codegen.positionAtEnd(bbCurrent) codegen.positionAtEnd(bbCurrent)
} }
@@ -1415,15 +1397,15 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
} }
override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) { override fun genReturn(target: CallableDescriptor, value: LLVMValueRef?) {
if (target == codegen.functionDescriptor) { // It is "non local return". if (target != inlineBody.descriptor) { // It is not our "local return".
super.genReturn(target, value) // Generate real "return". super.genReturn(target, value)
return return
} }
// It is local return. // It is local return from current function.
codegen.br(getExit(target)!!) // Generate branch on exit block. codegen.br(getExit()) // Generate branch on exit block.
if (!KotlinBuiltIns.isUnit(inlineBody.type)) { // If function returns more then "unit" if (!KotlinBuiltIns.isUnit(inlineBody.type)) { // If function returns more then "unit"
codegen.assignPhis(getResult(target) to value!!) // Assign return value to result PHI node. codegen.assignPhis(getResult() to value!!) // Assign return value to result PHI node.
} }
} }
} }
@@ -1442,22 +1424,19 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
} }
} }
if (inlinedFunctionScope.bbExit != null) { val bbExit = inlinedFunctionScope.bbExit
if (bbExit != null) {
if (!codegen.isAfterTerminator()) { // TODO should we solve this problem once and for all if (!codegen.isAfterTerminator()) { // TODO should we solve this problem once and for all
if (inlinedFunctionScope.resultPhi != null) { if (inlinedFunctionScope.resultPhi != null) {
codegen.unreachable() codegen.unreachable()
} else { } else {
codegen.br(inlinedFunctionScope.bbExit!!) codegen.br(bbExit)
} }
} }
codegen.positionAtEnd(inlinedFunctionScope.bbExit!!) codegen.positionAtEnd(bbExit)
} }
if (inlinedFunctionScope.resultPhi != null) { return inlinedFunctionScope.resultPhi ?: codegen.theUnitInstanceRef.llvm
return inlinedFunctionScope.resultPhi!!
} else {
return codegen.theUnitInstanceRef.llvm
}
} }
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//