moved initilizers lowering from code generation to lowering phase (#219)
* moved initilizers lowering from code generation to lowering phase * bug fix * bug fix * permuted phases * supported KFunction
This commit is contained in:
+3
@@ -49,6 +49,9 @@ internal class KonanLower(val context: Context) {
|
||||
phaser.phase(KonanPhase.LOWER_INNER_CLASSES) {
|
||||
InnerClassLowering(context).runOnFilePostfix(irFile)
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_INITIALIZERS) {
|
||||
InitializersLowering(context).runOnFilePostfix(irFile)
|
||||
}
|
||||
phaser.phase(KonanPhase.LOWER_CALLABLES) {
|
||||
CallableReferenceLowering(context).runOnFilePostfix(irFile)
|
||||
}
|
||||
|
||||
+1
@@ -23,6 +23,7 @@ enum class KonanPhase(val description: String,
|
||||
/* ... ... */ LOWER_ENUMS("Enum classes lowering"),
|
||||
/* ... ... */ LOWER_INNER_CLASSES("Inner classes lowering"),
|
||||
/* ... ... */ LOWER_STRING_CONCAT("String concatenation lowering"),
|
||||
/* ... ... */ LOWER_INITIALIZERS("Initializers lowering"),
|
||||
/* ... */ BITCODE("LLVM BitCode Generation"),
|
||||
/* ... ... */ RTTI("RTTI Generation"),
|
||||
/* ... ... */ CODEGEN("Code Generation"),
|
||||
|
||||
+15
@@ -5,6 +5,8 @@ import org.jetbrains.kotlin.backend.konan.ValueType
|
||||
import org.jetbrains.kotlin.backend.konan.isRepresentedAs
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.functionName
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||
import org.jetbrains.kotlin.builtins.getFunctionalClassKind
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
@@ -140,9 +142,22 @@ internal val CallableDescriptor.allValueParameters: List<ParameterDescriptor>
|
||||
return receivers + this.valueParameters
|
||||
}
|
||||
|
||||
internal val KotlinType.isFunctionOrKFunctionType: Boolean
|
||||
get() {
|
||||
val kind = constructor.declarationDescriptor?.getFunctionalClassKind()
|
||||
return kind == FunctionClassDescriptor.Kind.Function || kind == FunctionClassDescriptor.Kind.KFunction
|
||||
}
|
||||
|
||||
internal val KotlinType.isKFunctionType: Boolean
|
||||
get() {
|
||||
val kind = constructor.declarationDescriptor?.getFunctionalClassKind()
|
||||
return kind == FunctionClassDescriptor.Kind.KFunction
|
||||
}
|
||||
|
||||
internal val FunctionDescriptor.isFunctionInvoke: Boolean
|
||||
get() {
|
||||
val dispatchReceiver = dispatchReceiverParameter ?: return false
|
||||
assert (!dispatchReceiver.type.isKFunctionType)
|
||||
|
||||
return dispatchReceiver.type.isFunctionType &&
|
||||
this.isOperator && this.name == OperatorNameConventions.INVOKE
|
||||
|
||||
+25
-105
@@ -352,78 +352,25 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
override fun visitConstructor(constructorDeclaration: IrConstructor) {
|
||||
context.log("visitConstructor : ${ir2string(constructorDeclaration)}")
|
||||
if (constructorDeclaration.descriptor.containingDeclaration.isIntrinsic) {
|
||||
// Do not generate any ctors for intrinsic classes.
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
codegen.prologue(constructorDeclaration.descriptor)
|
||||
|
||||
val constructorDescriptor = constructorDeclaration.descriptor
|
||||
val classDescriptor = constructorDescriptor.constructedClass
|
||||
if (constructorDescriptor.isPrimary) {
|
||||
if (DescriptorUtils.isObject(classDescriptor)) {
|
||||
if (!classDescriptor.isUnit()) {
|
||||
val objectPtr = objectPtrByName(classDescriptor)
|
||||
|
||||
using(FunctionScope(constructorDeclaration)) {
|
||||
|
||||
val thisPtr = currentCodeContext.genGetValue(classDescriptor.thisAsReceiverParameter)
|
||||
|
||||
/**
|
||||
* IR for kotlin.Any is:
|
||||
* BLOCK_BODY
|
||||
* DELEGATING_CONSTRUCTOR_CALL 'constructor Any()'
|
||||
* INSTANCE_INITIALIZER_CALL classDescriptor='Any'
|
||||
*
|
||||
* to avoid possible recursion we manually reject body generation for Any.
|
||||
*/
|
||||
|
||||
if (!skipConstructorBodyGeneration(constructorDeclaration)) {
|
||||
constructorDeclaration.body?.let {
|
||||
generateBody(it)
|
||||
LLVMSetInitializer(objectPtr, codegen.kNullObjHeaderPtr)
|
||||
}
|
||||
}
|
||||
|
||||
if (constructorDescriptor.isPrimary) {
|
||||
if (DescriptorUtils.isObject(classDescriptor)) {
|
||||
if (!classDescriptor.isUnit()) {
|
||||
val objectPtr = objectPtrByName(classDescriptor)
|
||||
|
||||
LLVMSetInitializer(objectPtr, codegen.kNullObjHeaderPtr)
|
||||
}
|
||||
}
|
||||
val irOfCurrentClass = context.ir.moduleIndexForCodegen.classes[classDescriptor]
|
||||
irOfCurrentClass!!.acceptChildrenVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitField(fieldDeclaration: IrField) {
|
||||
|
||||
val fieldDescriptor = fieldDeclaration.descriptor
|
||||
fieldDeclaration.initializer?.let {
|
||||
val value = evaluateExpression(it.expression)
|
||||
val fieldPtr = fieldPtrOfClass(thisPtr, fieldDescriptor)
|
||||
codegen.storeAnyGlobal(value, fieldPtr)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitAnonymousInitializer(declaration: IrAnonymousInitializer) {
|
||||
generateBlockBody(declaration.body)
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass) {
|
||||
return
|
||||
}
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor) {
|
||||
return
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
codegen.ret(null)
|
||||
codegen.epilogue()
|
||||
context.log("visitConstructor : ${ir2string(constructorDeclaration)}")
|
||||
visitFunction(constructorDeclaration)
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
@@ -434,25 +381,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun generateBlockBody(body: IrBlockBody) {
|
||||
using(VariableScope()) {
|
||||
body.statements.forEach {
|
||||
generateStatement(it)
|
||||
}
|
||||
// TODO: write it properly!
|
||||
if (codegen.constructedClass == null && !codegen.isAfterTerminator()) {
|
||||
if (codegen.returnType == voidType) {
|
||||
codegen.ret(null)
|
||||
} else {
|
||||
codegen.unreachable()
|
||||
}
|
||||
}
|
||||
}
|
||||
context.log("generateBlockBody : ${ir2string(body)}")
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
/**
|
||||
* The scope of variable visibility.
|
||||
*/
|
||||
@@ -559,14 +487,29 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
override fun visitFunction(declaration: IrFunction) {
|
||||
context.log("visitFunction : ${ir2string(declaration)}")
|
||||
val body = declaration.body
|
||||
if (declaration.descriptor.modality == Modality.ABSTRACT || body == null)
|
||||
return
|
||||
|
||||
if (declaration.descriptor.modality == Modality.ABSTRACT || declaration.descriptor.isExternal || body == null)
|
||||
return
|
||||
|
||||
codegen.prologue(declaration.descriptor)
|
||||
|
||||
using(FunctionScope(declaration)) {
|
||||
generateBody(body)
|
||||
using(VariableScope()) {
|
||||
context.log("generateBlockBody : ${ir2string(body)}")
|
||||
when (body) {
|
||||
is IrBlockBody -> body.statements.forEach { generateStatement(it) }
|
||||
is IrExpressionBody -> generateStatement(body.expression)
|
||||
is IrSyntheticBody -> throw AssertionError("Synthetic body ${body.kind} has not been lowered")
|
||||
else -> TODO(ir2string(body))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!codegen.isAfterTerminator()) {
|
||||
if (codegen.returnType == voidType)
|
||||
codegen.ret(null)
|
||||
else
|
||||
codegen.unreachable()
|
||||
}
|
||||
|
||||
codegen.epilogue()
|
||||
@@ -665,13 +608,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
private fun IrStatement.generate() = generateStatement(this)
|
||||
|
||||
private fun generateBody(body: IrBody) {
|
||||
when (body) {
|
||||
is IrBlockBody -> generateBlockBody(body)
|
||||
else -> TODO(ir2string(body))
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun evaluateGetObjectValue(value: IrGetObjectValue): LLVMValueRef {
|
||||
@@ -1895,22 +1831,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun skipConstructorBodyGeneration(declaration: IrConstructor): Boolean {
|
||||
var skipBody = false
|
||||
declaration.acceptChildrenVoid(object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) {
|
||||
skipBody = expression.descriptor == declaration.descriptor
|
||||
}
|
||||
})
|
||||
return skipBody
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
fun appendLlvmUsed(args: List<LLVMValueRef>) {
|
||||
if (args.isEmpty()) return
|
||||
|
||||
|
||||
+2
-1
@@ -5,6 +5,7 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.konan.*
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.*
|
||||
import org.jetbrains.kotlin.backend.konan.ir.*
|
||||
import org.jetbrains.kotlin.builtins.getFunctionalClassKind
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
@@ -86,7 +87,7 @@ private class CallableReferencesUnbinder(val lower: CallableReferenceLowering,
|
||||
}
|
||||
|
||||
override fun visitCallableReference(expression: IrCallableReference): IrExpression {
|
||||
assert (expression.type.isFunctionType)
|
||||
assert (expression.type.isFunctionOrKFunctionType)
|
||||
|
||||
val descriptor = expression.descriptor
|
||||
val boundArgs = expression.getArguments()
|
||||
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
package org.jetbrains.kotlin.backend.konan.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBlockBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrDelegatingConstructorCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrInstanceInitializerCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOriginImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
|
||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
internal class InitializersLowering(val context: Context) : ClassLoweringPass {
|
||||
override fun lower(irClass: IrClass) {
|
||||
InitializersTransformer(irClass).lowerInitializers()
|
||||
}
|
||||
|
||||
private inner class InitializersTransformer(val irClass: IrClass) {
|
||||
val fieldInitializers = mutableListOf<IrStatement>()
|
||||
val initializers = mutableListOf<IrStatement>()
|
||||
|
||||
fun lowerInitializers() {
|
||||
collectAndRemoveInitializers()
|
||||
lowerConstructors()
|
||||
}
|
||||
|
||||
object STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER :
|
||||
IrStatementOriginImpl("ANONYMOUS_INITIALIZER")
|
||||
|
||||
private fun collectAndRemoveInitializers() {
|
||||
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
override fun visitClass(declaration: IrClass): IrStatement {
|
||||
// Skip nested.
|
||||
return declaration
|
||||
}
|
||||
|
||||
override fun visitField(declaration: IrField): IrStatement {
|
||||
val initializer = declaration.initializer ?: return declaration
|
||||
val propertyDescriptor = declaration.descriptor
|
||||
val startOffset = initializer.startOffset
|
||||
val endOffset = initializer.endOffset
|
||||
fieldInitializers.add(IrBlockImpl(startOffset, endOffset, context.builtIns.unitType, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER,
|
||||
listOf(
|
||||
IrSetFieldImpl(startOffset, endOffset, propertyDescriptor,
|
||||
IrGetValueImpl(startOffset, endOffset, irClass.descriptor.thisAsReceiverParameter),
|
||||
initializer.expression, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER))))
|
||||
return IrFieldImpl(declaration.startOffset, declaration.endOffset, declaration.origin, propertyDescriptor)
|
||||
}
|
||||
})
|
||||
|
||||
irClass.declarations.transformFlat {
|
||||
if (it !is IrAnonymousInitializer)
|
||||
null
|
||||
else {
|
||||
initializers.add(IrBlockImpl(it.startOffset, it.endOffset,
|
||||
context.builtIns.unitType, STATEMENT_ORIGIN_ANONYMOUS_INITIALIZER, it.body.statements))
|
||||
listOf()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun lowerConstructors() {
|
||||
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
override fun visitClass(declaration: IrClass): IrStatement {
|
||||
// Skip nested.
|
||||
return declaration
|
||||
}
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor): IrStatement {
|
||||
val blockBody = declaration.body as? IrBlockBody ?: throw AssertionError("Unexpected constructor body: ${declaration.body}")
|
||||
|
||||
blockBody.statements.transformFlat {
|
||||
when {
|
||||
it is IrInstanceInitializerCall -> fieldInitializers + initializers
|
||||
/**
|
||||
* IR for kotlin.Any is:
|
||||
* BLOCK_BODY
|
||||
* DELEGATING_CONSTRUCTOR_CALL 'constructor Any()'
|
||||
* INSTANCE_INITIALIZER_CALL classDescriptor='Any'
|
||||
*
|
||||
* to avoid possible recursion we manually reject body generation for Any.
|
||||
*/
|
||||
it is IrDelegatingConstructorCall && irClass.descriptor == context.builtIns.any
|
||||
&& it.descriptor == declaration.descriptor -> listOf()
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
return declaration
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user