Supported nested non-local returns
This commit is contained in:
+4
-3
@@ -1,5 +1,6 @@
|
|||||||
package org.jetbrains.kotlin.backend.konan.ir
|
package org.jetbrains.kotlin.backend.konan.ir
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrBlock
|
import org.jetbrains.kotlin.ir.expressions.IrBlock
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||||
@@ -10,10 +11,10 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------//
|
//-----------------------------------------------------------------------------//
|
||||||
|
|
||||||
class IrInlineFunctionBody(startOffset: Int, endOffset: Int, type: KotlinType, origin: IrStatementOrigin? = null):
|
class IrInlineFunctionBody(startOffset: Int, endOffset: Int, type: KotlinType, val descriptor: FunctionDescriptor, origin: IrStatementOrigin? = null):
|
||||||
IrContainerExpressionBase(startOffset, endOffset, type, origin), IrBlock {
|
IrContainerExpressionBase(startOffset, endOffset, type, origin), IrBlock {
|
||||||
constructor(startOffset: Int, endOffset: Int, type: KotlinType, origin: IrStatementOrigin?, statements: List<IrStatement>) :
|
constructor(startOffset: Int, endOffset: Int, type: KotlinType, descriptor: FunctionDescriptor, origin: IrStatementOrigin?, statements: List<IrStatement>) :
|
||||||
this(startOffset, endOffset, type, origin) {
|
this(startOffset, endOffset, type, descriptor, origin) {
|
||||||
this.statements.addAll(statements)
|
this.statements.addAll(statements)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+24
-6
@@ -152,6 +152,16 @@ 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.
|
||||||
*
|
*
|
||||||
@@ -198,6 +208,10 @@ 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()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1381,15 +1395,19 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
var bbExit : LLVMBasicBlockRef? = null
|
var bbExit : LLVMBasicBlockRef? = null
|
||||||
var resultPhi : LLVMValueRef? = null
|
var resultPhi : LLVMValueRef? = null
|
||||||
|
|
||||||
fun getExit(): LLVMBasicBlockRef {
|
override fun getExit(descriptor: CallableDescriptor): 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!!
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getResult(): LLVMValueRef {
|
override fun getResult(descriptor: CallableDescriptor): 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())
|
codegen.positionAtEnd(getExit(descriptor))
|
||||||
resultPhi = codegen.phi(codegen.getLLVMType(inlineBody.type))
|
resultPhi = codegen.phi(codegen.getLLVMType(inlineBody.type))
|
||||||
codegen.positionAtEnd(bbCurrent)
|
codegen.positionAtEnd(bbCurrent)
|
||||||
}
|
}
|
||||||
@@ -1402,10 +1420,10 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// It is local return.
|
// It is local return.
|
||||||
codegen.br(getExit()!!) // Generate branch on exit block.
|
codegen.br(getExit(target)!!) // Generate branch on exit block.
|
||||||
|
|
||||||
if (KotlinBuiltIns.isUnit(inlineBody.type) == false) { // If function returns more then "unit"
|
if (!KotlinBuiltIns.isUnit(inlineBody.type)) { // If function returns more then "unit"
|
||||||
codegen.assignPhis(getResult() to value!!) // Assign return value to result PHI node.
|
codegen.assignPhis(getResult(target) to value!!) // Assign return value to result PHI node.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -170,7 +170,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
|
|||||||
if (copyFuncDeclaration.body == null) return irCall // TODO workaround
|
if (copyFuncDeclaration.body == null) return irCall // TODO workaround
|
||||||
val blockBody = copyFuncDeclaration.body!! as IrBlockBody
|
val blockBody = copyFuncDeclaration.body!! as IrBlockBody
|
||||||
val statements = blockBody.statements
|
val statements = blockBody.statements
|
||||||
val inlineBody = IrInlineFunctionBody(startOffset, endOffset, returnType, null, statements)
|
val inlineBody = IrInlineFunctionBody(startOffset, endOffset, returnType, originalDescriptor, null, statements)
|
||||||
|
|
||||||
val parametersOld = getArguments(irCall, copyFuncDeclaration) // Create map call_site_argument -> inline_function_parameter.
|
val parametersOld = getArguments(irCall, copyFuncDeclaration) // Create map call_site_argument -> inline_function_parameter.
|
||||||
val evaluatedParameters = evaluateParameters(parametersOld)
|
val evaluatedParameters = evaluateParameters(parametersOld)
|
||||||
@@ -412,7 +412,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerVoid(
|
|||||||
null) as IrFunction
|
null) as IrFunction
|
||||||
val lambdaStatements = (copyLambdaFunction.body as IrBlockBody).statements
|
val lambdaStatements = (copyLambdaFunction.body as IrBlockBody).statements
|
||||||
val lambdaReturnType = copyLambdaFunction.descriptor.returnType!!
|
val lambdaReturnType = copyLambdaFunction.descriptor.returnType!!
|
||||||
val inlineBody = IrInlineFunctionBody(0, 0, lambdaReturnType, null, lambdaStatements)
|
val inlineBody = IrInlineFunctionBody(0, 0, lambdaReturnType, lambdaFunction.descriptor, null, lambdaStatements)
|
||||||
|
|
||||||
val transformer = ParametersTransformer(parameterToArgument, null, lambdaStatements)
|
val transformer = ParametersTransformer(parameterToArgument, null, lambdaStatements)
|
||||||
inlineBody.accept(transformer, null) // Replace parameters with expression.
|
inlineBody.accept(transformer, null) // Replace parameters with expression.
|
||||||
@@ -442,6 +442,7 @@ class InlineCopyIr() : DeepCopyIrTree() {
|
|||||||
IrInlineFunctionBody(
|
IrInlineFunctionBody(
|
||||||
expression.startOffset, expression.endOffset,
|
expression.startOffset, expression.endOffset,
|
||||||
expression.type,
|
expression.type,
|
||||||
|
expression.descriptor,
|
||||||
mapStatementOrigin(expression.origin),
|
mapStatementOrigin(expression.origin),
|
||||||
expression.statements.map { it.transform(this, null) }
|
expression.statements.map { it.transform(this, null) }
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user