backend: lower safe casts

This commit is contained in:
Svyatoslav Scherbina
2016-12-23 10:41:53 +07:00
committed by SvyatoslavScherbina
parent 008b8ec031
commit 7b29f4854c
4 changed files with 61 additions and 28 deletions
@@ -20,6 +20,9 @@ internal class KonanLower(val context: Context) {
phaser.phase(KonanPhase.LOWER_BUILTIN_OPERATORS) {
BuiltinOperatorLowering(context).runOnFilePostfix(irFile)
}
phaser.phase(KonanPhase.LOWER_TYPE_OPERATORS) {
TypeOperatorLowering(context).runOnFilePostfix(irFile)
}
phaser.phase(KonanPhase.LOWER_SHARED_VARIABLES) {
SharedVariablesLowering(context).runOnFilePostfix(irFile)
}
@@ -9,6 +9,7 @@ enum class KonanPhase(val description: String,
/* */ BACKEND("All backend"),
/* ... */ LOWER("IR Lowering"),
/* ... ... */ LOWER_BUILTIN_OPERATORS("BuiltIn Operators Lowering"),
/* ... ... */ LOWER_TYPE_OPERATORS("Type operators lowering"),
/* ... ... */ LOWER_SHARED_VARIABLES("Shared Variable Lowering"),
/* ... ... */ LOWER_LOCAL_FUNCTIONS("Local Function Lowering"),
/* ... ... */ LOWER_CALLABLES("Callable references Lowering"),
@@ -1323,40 +1323,13 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
IrTypeOperator.IMPLICIT_CAST -> return evaluateExpression(value.argument)
IrTypeOperator.IMPLICIT_NOTNULL -> TODO("${ir2string(value)}")
IrTypeOperator.IMPLICIT_COERCION_TO_UNIT -> return evaluateExpression(value.argument)
IrTypeOperator.SAFE_CAST -> return evaluateSafeCast(value)
IrTypeOperator.SAFE_CAST -> throw IllegalStateException("safe cast wasn't lowered")
IrTypeOperator.INSTANCEOF -> return evaluateInstanceOf(value)
IrTypeOperator.NOT_INSTANCEOF -> return evaluateNotInstanceOf(value)
}
}
//-------------------------------------------------------------------------//
private fun evaluateSafeCast(value: IrTypeOperatorCall): LLVMValueRef? {
val bbTrue = codegen.basicBlock()
val bbFalse = codegen.basicBlock()
val bbExit = codegen.basicBlock()
val resultLlvmType = codegen.getLLVMType(value.type)
val result = codegen.vars.createAnonymousMutable(resultLlvmType)
val condition = evaluateInstanceOf(value)
codegen.condBr(condition, bbTrue, bbFalse)
codegen.positionAtEnd(bbTrue)
val castResult = evaluateExpression(value.argument)
codegen.vars.store(castResult!!, result)
codegen.br(bbExit)
codegen.positionAtEnd(bbFalse)
val nullResult = LLVMConstNull(resultLlvmType)!!
codegen.vars.store(nullResult, result)
codegen.br(bbExit)
codegen.positionAtEnd(bbExit)
return codegen.vars.load(result)
}
//-------------------------------------------------------------------------//
// table of conversion with llvm for primitive types
// to be used in replacement fo primitive.toX() calls with
@@ -0,0 +1,56 @@
package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.FunctionLoweringPass
import org.jetbrains.kotlin.backend.common.lower.createFunctionIrGenerator
import org.jetbrains.kotlin.backend.common.lower.irBlock
import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
/**
* This lowering pass lowers some [IrTypeOperatorCall]s.
*/
internal class TypeOperatorLowering(val context: Context) : FunctionLoweringPass {
override fun lower(irFunction: IrFunction) {
val transformer = TypeOperatorTransformer(context, irFunction.descriptor)
irFunction.transformChildrenVoid(transformer)
}
}
private class TypeOperatorTransformer(val context: Context, val function: FunctionDescriptor) : IrElementTransformerVoid() {
private val generator = context.createFunctionIrGenerator(function)
override fun visitFunction(declaration: IrFunction): IrStatement {
// ignore inner functions during this pass
return declaration
}
private fun lowerSafeCast(expression: IrTypeOperatorCall): IrExpression {
return generator.irBlock(expression) {
+irLet(expression.argument) { variable ->
irIfThenElse(expression.type,
condition = irIs(irGet(variable), expression.typeOperand),
thenPart = irImplicitCast(irGet(variable), expression.typeOperand),
elsePart = irNull())
}
}
}
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression {
expression.transformChildrenVoid(this)
return when (expression.operator) {
IrTypeOperator.SAFE_CAST -> lowerSafeCast(expression)
else -> expression
}
}
}