Rewrote callable reference lowering
For each callable reference a class inherited from KFunctionImpl is built.
This commit is contained in:
+6
-3
@@ -52,10 +52,13 @@ abstract internal class IrElementTransformerVoidWithContext : IrElementTransform
|
|||||||
}
|
}
|
||||||
|
|
||||||
override final fun visitField(declaration: IrField): IrStatement {
|
override final fun visitField(declaration: IrField): IrStatement {
|
||||||
val isDelegated = declaration.descriptor.isDelegated
|
val peek = scopeStack.peek()
|
||||||
if (isDelegated) scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration))
|
val fieldDiffersFromProperty = peek == null || peek.scope.scopeOwner != declaration.descriptor
|
||||||
|
if (fieldDiffersFromProperty)
|
||||||
|
scopeStack.push(ScopeWithIr(Scope(declaration.descriptor), declaration))
|
||||||
val result = visitFieldNew(declaration)
|
val result = visitFieldNew(declaration)
|
||||||
if (isDelegated) scopeStack.pop()
|
if (fieldDiffersFromProperty)
|
||||||
|
scopeStack.pop()
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
@@ -55,6 +55,7 @@ class LocalDeclarationsLowering(val context: BackendContext) : DeclarationContai
|
|||||||
when (memberDeclaration) {
|
when (memberDeclaration) {
|
||||||
is IrFunction -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
|
is IrFunction -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
|
||||||
is IrProperty -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
|
is IrProperty -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
|
||||||
|
is IrField -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
|
||||||
is IrAnonymousInitializer -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
|
is IrAnonymousInitializer -> LocalDeclarationsTransformer(memberDeclaration).lowerLocalDeclarations()
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-20
@@ -101,34 +101,35 @@ internal class SpecialDescriptorsFactory(val context: Context) {
|
|||||||
descriptor: FunctionDescriptor,
|
descriptor: FunctionDescriptor,
|
||||||
bridgeDirections: Array<BridgeDirection>) {
|
bridgeDirections: Array<BridgeDirection>) {
|
||||||
val returnType = when (bridgeDirections[0]) {
|
val returnType = when (bridgeDirections[0]) {
|
||||||
BridgeDirection.TO_VALUE_TYPE -> descriptor.returnType!!
|
BridgeDirection.TO_VALUE_TYPE -> descriptor.returnType!!
|
||||||
BridgeDirection.NOT_NEEDED -> descriptor.returnType
|
BridgeDirection.NOT_NEEDED -> descriptor.returnType
|
||||||
BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.anyType
|
BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.anyType
|
||||||
}
|
}
|
||||||
|
|
||||||
val extensionReceiverType = when (bridgeDirections[1]) {
|
val extensionReceiverType = when (bridgeDirections[1]) {
|
||||||
BridgeDirection.TO_VALUE_TYPE -> descriptor.extensionReceiverParameter!!.type
|
BridgeDirection.TO_VALUE_TYPE -> descriptor.extensionReceiverParameter!!.type
|
||||||
BridgeDirection.NOT_NEEDED -> descriptor.extensionReceiverParameter?.type
|
BridgeDirection.NOT_NEEDED -> descriptor.extensionReceiverParameter?.type
|
||||||
BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.anyType
|
BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.anyType
|
||||||
}
|
}
|
||||||
|
|
||||||
val valueParameters = descriptor.valueParameters.mapIndexed { index, valueParameterDescriptor ->
|
val valueParameters = descriptor.valueParameters.mapIndexed { index, valueParameterDescriptor ->
|
||||||
when (bridgeDirections[index + 2]) {
|
val outType = when (bridgeDirections[index + 2]) {
|
||||||
BridgeDirection.TO_VALUE_TYPE -> valueParameterDescriptor
|
BridgeDirection.TO_VALUE_TYPE -> valueParameterDescriptor.type
|
||||||
BridgeDirection.NOT_NEEDED -> valueParameterDescriptor
|
BridgeDirection.NOT_NEEDED -> valueParameterDescriptor.type
|
||||||
BridgeDirection.FROM_VALUE_TYPE -> ValueParameterDescriptorImpl(
|
BridgeDirection.FROM_VALUE_TYPE -> context.builtIns.anyType
|
||||||
containingDeclaration = valueParameterDescriptor.containingDeclaration,
|
}
|
||||||
original = null,
|
ValueParameterDescriptorImpl(
|
||||||
index = index,
|
containingDeclaration = valueParameterDescriptor.containingDeclaration,
|
||||||
annotations = Annotations.EMPTY,
|
original = null,
|
||||||
name = valueParameterDescriptor.name,
|
index = index,
|
||||||
outType = context.builtIns.anyType,
|
annotations = Annotations.EMPTY,
|
||||||
declaresDefaultValue = valueParameterDescriptor.declaresDefaultValue(),
|
name = valueParameterDescriptor.name,
|
||||||
isCrossinline = valueParameterDescriptor.isCrossinline,
|
outType = outType,
|
||||||
isNoinline = valueParameterDescriptor.isNoinline,
|
declaresDefaultValue = valueParameterDescriptor.declaresDefaultValue(),
|
||||||
varargElementType = valueParameterDescriptor.varargElementType,
|
isCrossinline = valueParameterDescriptor.isCrossinline,
|
||||||
source = SourceElement.NO_SOURCE)
|
isNoinline = valueParameterDescriptor.isNoinline,
|
||||||
}
|
varargElementType = valueParameterDescriptor.varargElementType,
|
||||||
|
source = SourceElement.NO_SOURCE)
|
||||||
}
|
}
|
||||||
bridgeDescriptor.initialize(
|
bridgeDescriptor.initialize(
|
||||||
/* receiverParameterType = */ extensionReceiverType,
|
/* receiverParameterType = */ extensionReceiverType,
|
||||||
|
|||||||
+4
-6
@@ -29,19 +29,17 @@ enum class KonanPhase(val description: String,
|
|||||||
/* ... */ LOWER("IR Lowering"),
|
/* ... */ LOWER("IR Lowering"),
|
||||||
/* ... ... */ LOWER_INLINE("Functions inlining"),
|
/* ... ... */ LOWER_INLINE("Functions inlining"),
|
||||||
/* ... ... ... */ DESERIALIZER("Deserialize inline bodies"),
|
/* ... ... ... */ DESERIALIZER("Deserialize inline bodies"),
|
||||||
/* ... ... */ LOWER_INTEROP("Interop lowering"),
|
|
||||||
/* ... ... */ LOWER_ENUMS("Enum classes lowering"),
|
/* ... ... */ LOWER_ENUMS("Enum classes lowering"),
|
||||||
/* ... ... */ LOWER_DELEGATION("Delegation lowering"),
|
/* ... ... */ LOWER_DELEGATION("Delegation lowering"),
|
||||||
/* ... ... */ LOWER_INITIALIZERS("Initializers lowering", LOWER_ENUMS),
|
/* ... ... */ LOWER_INITIALIZERS("Initializers lowering", LOWER_ENUMS),
|
||||||
/* ... ... */ LOWER_SHARED_VARIABLES("Shared Variable Lowering", LOWER_INITIALIZERS),
|
/* ... ... */ LOWER_SHARED_VARIABLES("Shared Variable Lowering", LOWER_INITIALIZERS),
|
||||||
/* ... ... */ LOWER_CALLABLES("Callable references Lowering",
|
|
||||||
LOWER_INTEROP, LOWER_INITIALIZERS, LOWER_DELEGATION),
|
|
||||||
/* ... ... */ LOWER_VARARG("Vararg lowering", LOWER_CALLABLES),
|
|
||||||
/* ... ... */ LOWER_LOCAL_FUNCTIONS("Local Function Lowering", LOWER_SHARED_VARIABLES),
|
/* ... ... */ LOWER_LOCAL_FUNCTIONS("Local Function Lowering", LOWER_SHARED_VARIABLES),
|
||||||
|
/* ... ... */ LOWER_INTEROP("Interop lowering", LOWER_LOCAL_FUNCTIONS),
|
||||||
|
/* ... ... */ LOWER_CALLABLES("Callable references Lowering", LOWER_INTEROP, LOWER_DELEGATION, LOWER_LOCAL_FUNCTIONS),
|
||||||
|
/* ... ... */ LOWER_VARARG("Vararg lowering", LOWER_CALLABLES),
|
||||||
/* ... ... */ LOWER_TAILREC("tailrec lowering", LOWER_LOCAL_FUNCTIONS),
|
/* ... ... */ LOWER_TAILREC("tailrec lowering", LOWER_LOCAL_FUNCTIONS),
|
||||||
/* ... ... */ LOWER_FINALLY("Finally blocks lowering", LOWER_INITIALIZERS, LOWER_LOCAL_FUNCTIONS, LOWER_TAILREC),
|
/* ... ... */ LOWER_FINALLY("Finally blocks lowering", LOWER_INITIALIZERS, LOWER_LOCAL_FUNCTIONS, LOWER_TAILREC),
|
||||||
/* ... ... */ LOWER_DEFAULT_PARAMETER_EXTENT("Default Parameter Extent Lowering",
|
/* ... ... */ LOWER_DEFAULT_PARAMETER_EXTENT("Default Parameter Extent Lowering", LOWER_TAILREC, LOWER_ENUMS),
|
||||||
LOWER_TAILREC, LOWER_ENUMS),
|
|
||||||
/* ... ... */ LOWER_INNER_CLASSES("Inner classes lowering", LOWER_DEFAULT_PARAMETER_EXTENT),
|
/* ... ... */ LOWER_INNER_CLASSES("Inner classes lowering", LOWER_DEFAULT_PARAMETER_EXTENT),
|
||||||
/* ... ... */ LOWER_LATEINIT("Lateinit properties lowering"),
|
/* ... ... */ LOWER_LATEINIT("Lateinit properties lowering"),
|
||||||
/* ... ... */ LOWER_BUILTIN_OPERATORS("BuiltIn Operators Lowering", LOWER_DEFAULT_PARAMETER_EXTENT, LOWER_LATEINIT),
|
/* ... ... */ LOWER_BUILTIN_OPERATORS("BuiltIn Operators Lowering", LOWER_DEFAULT_PARAMETER_EXTENT, LOWER_LATEINIT),
|
||||||
|
|||||||
-1
@@ -40,7 +40,6 @@ enum class ValueType(val classFqName: FqNameUnsafe, val isNullable: Boolean = fa
|
|||||||
FLOAT(KotlinBuiltIns.FQ_NAMES._float),
|
FLOAT(KotlinBuiltIns.FQ_NAMES._float),
|
||||||
DOUBLE(KotlinBuiltIns.FQ_NAMES._double),
|
DOUBLE(KotlinBuiltIns.FQ_NAMES._double),
|
||||||
|
|
||||||
UNBOUND_CALLABLE_REFERENCE(FqNameUnsafe("konan.internal.UnboundCallableReference")),
|
|
||||||
NATIVE_PTR(KonanBuiltIns.FqNames.nativePtr),
|
NATIVE_PTR(KonanBuiltIns.FqNames.nativePtr),
|
||||||
|
|
||||||
NATIVE_POINTED(InteropBuiltIns.FqNames.nativePointed, isNullable = true),
|
NATIVE_POINTED(InteropBuiltIns.FqNames.nativePointed, isNullable = true),
|
||||||
|
|||||||
-2
@@ -137,8 +137,6 @@ internal fun KonanBuiltIns.getKonanInternalFunctions(name: String): List<Functio
|
|||||||
return konanInternal.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).toList()
|
return konanInternal.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).toList()
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun KotlinType.isUnboundCallableReference() = this.isRepresentedAs(ValueType.UNBOUND_CALLABLE_REFERENCE)
|
|
||||||
|
|
||||||
internal val KotlinType.isFunctionOrKFunctionType: Boolean
|
internal val KotlinType.isFunctionOrKFunctionType: Boolean
|
||||||
get() {
|
get() {
|
||||||
val kind = constructor.declarationDescriptor?.getFunctionalClassKind()
|
val kind = constructor.declarationDescriptor?.getFunctionalClassKind()
|
||||||
|
|||||||
-1
@@ -33,7 +33,6 @@ private val valueTypes = ValueType.values().associate {
|
|||||||
ValueType.FLOAT -> LLVMFloatType()
|
ValueType.FLOAT -> LLVMFloatType()
|
||||||
ValueType.DOUBLE -> LLVMDoubleType()
|
ValueType.DOUBLE -> LLVMDoubleType()
|
||||||
|
|
||||||
ValueType.UNBOUND_CALLABLE_REFERENCE,
|
|
||||||
ValueType.NATIVE_PTR, ValueType.NATIVE_POINTED, ValueType.C_POINTER -> int8TypePtr
|
ValueType.NATIVE_PTR, ValueType.NATIVE_POINTED, ValueType.C_POINTER -> int8TypePtr
|
||||||
}!!
|
}!!
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-43
@@ -689,7 +689,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
is IrBreak -> return evaluateBreak (value)
|
is IrBreak -> return evaluateBreak (value)
|
||||||
is IrContinue -> return evaluateContinue (value)
|
is IrContinue -> return evaluateContinue (value)
|
||||||
is IrGetObjectValue -> return evaluateGetObjectValue (value)
|
is IrGetObjectValue -> return evaluateGetObjectValue (value)
|
||||||
is IrCallableReference -> return evaluateCallableReference (value)
|
is IrFunctionReference -> return evaluateFunctionReference (value)
|
||||||
is IrSuspendableExpression ->
|
is IrSuspendableExpression ->
|
||||||
return evaluateSuspendableExpression (value)
|
return evaluateSuspendableExpression (value)
|
||||||
is IrSuspensionPoint -> return evaluateSuspensionPoint (value)
|
is IrSuspensionPoint -> return evaluateSuspensionPoint (value)
|
||||||
@@ -1744,17 +1744,16 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
private fun evaluateCallableReference(expression: IrCallableReference): LLVMValueRef {
|
private fun evaluateFunctionReference(expression: IrFunctionReference): LLVMValueRef {
|
||||||
// TODO: consider creating separate IR element for pointer to function.
|
// TODO: consider creating separate IR element for pointer to function.
|
||||||
assert (expression.type.isUnboundCallableReference() ||
|
assert (TypeUtils.getClassDescriptor(expression.type) == context.interopBuiltIns.cPointer)
|
||||||
TypeUtils.getClassDescriptor(expression.type) == context.interopBuiltIns.cPointer)
|
|
||||||
|
|
||||||
assert (expression.getArguments().isEmpty())
|
assert (expression.getArguments().isEmpty())
|
||||||
|
|
||||||
val descriptor = expression.descriptor
|
val descriptor = expression.descriptor
|
||||||
assert (descriptor.dispatchReceiverParameter == null)
|
assert (descriptor.dispatchReceiverParameter == null)
|
||||||
|
|
||||||
val entry = codegen.functionEntryPointAddress(descriptor as FunctionDescriptor)
|
val entry = codegen.functionEntryPointAddress(descriptor)
|
||||||
return entry
|
return entry
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1822,10 +1821,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
val argsWithContinuationIfNeeded = if (descriptor.isSuspend)
|
val argsWithContinuationIfNeeded = if (descriptor.isSuspend)
|
||||||
args + getContinuation()
|
args + getContinuation()
|
||||||
else args
|
else args
|
||||||
if (descriptor.isFunctionInvoke) {
|
|
||||||
return evaluateFunctionInvoke(descriptor, argsWithContinuationIfNeeded, resultLifetime)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (descriptor.isIntrinsic) {
|
if (descriptor.isIntrinsic) {
|
||||||
return evaluateIntrinsicCall(callee, argsWithContinuationIfNeeded)
|
return evaluateIntrinsicCall(callee, argsWithContinuationIfNeeded)
|
||||||
}
|
}
|
||||||
@@ -1840,40 +1835,6 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
|
|||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
private val functionImplUnboundRefGetter by lazy {
|
|
||||||
context.builtIns.getKonanInternalClass("FunctionImpl")
|
|
||||||
.unsubstitutedMemberScope.getContributedDescriptors()
|
|
||||||
.filterIsInstance<PropertyDescriptor>()
|
|
||||||
.single { it.name.asString() == "unboundRef" }
|
|
||||||
.getter!!
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun evaluateFunctionInvoke(descriptor: FunctionDescriptor,
|
|
||||||
args: List<LLVMValueRef>, resultLifetime: Lifetime): LLVMValueRef {
|
|
||||||
|
|
||||||
// Note: the whole function code below is written in the assumption that
|
|
||||||
// `invoke` method receiver is passed as first argument.
|
|
||||||
|
|
||||||
val functionImpl = args[0] // Instance of `konan.internal.FunctionImpl`.
|
|
||||||
|
|
||||||
// `functionImpl.unboundRef` is the pointer to (static) function of type
|
|
||||||
// `(FunctionImpl, Arg_1, ..., Arg_n): Ret`. See [CallableReferenceLowering] for details.
|
|
||||||
// LLVM type for such function is equal to type for `FunctionImpl.invoke(Arg_1, ..., Arg_n): Ret`.
|
|
||||||
// So we can use the latter for simplicity:
|
|
||||||
val unboundRefType = codegen.getLlvmFunctionType(descriptor)
|
|
||||||
|
|
||||||
// Get `functionImpl.unboundRef`:
|
|
||||||
val unboundRef = evaluateSimpleFunctionCall(functionImplUnboundRefGetter,
|
|
||||||
listOf(functionImpl), Lifetime.IRRELEVANT /* unboundRef isn't managed reference */)
|
|
||||||
|
|
||||||
// Cast `functionImpl.unboundRef` to pointer to function:
|
|
||||||
val entryPtr = codegen.bitcast(pointerType(unboundRefType), unboundRef, "entry")
|
|
||||||
|
|
||||||
return call(descriptor, entryPtr, args, resultLifetime)
|
|
||||||
}
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------//
|
|
||||||
|
|
||||||
private fun evaluateSimpleFunctionCall(
|
private fun evaluateSimpleFunctionCall(
|
||||||
descriptor: FunctionDescriptor, args: List<LLVMValueRef>,
|
descriptor: FunctionDescriptor, args: List<LLVMValueRef>,
|
||||||
resultLifetime: Lifetime, superClass: ClassDescriptor? = null): LLVMValueRef {
|
resultLifetime: Lifetime, superClass: ClassDescriptor? = null): LLVMValueRef {
|
||||||
|
|||||||
+451
-205
@@ -18,256 +18,502 @@ package org.jetbrains.kotlin.backend.konan.lower
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
|
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters
|
import org.jetbrains.kotlin.backend.common.descriptors.explicitParameters
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.backend.common.lower.*
|
||||||
import org.jetbrains.kotlin.backend.konan.KonanBackendContext
|
import org.jetbrains.kotlin.backend.konan.Context
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalClass
|
import org.jetbrains.kotlin.backend.konan.descriptors.getKonanInternalClass
|
||||||
import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionOrKFunctionType
|
import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionOrKFunctionType
|
||||||
|
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.createFakeOverrideDescriptor
|
||||||
|
import org.jetbrains.kotlin.backend.konan.llvm.functionName
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
import org.jetbrains.kotlin.descriptors.impl.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrCallableReference
|
import org.jetbrains.kotlin.ir.expressions.IrConstKind
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
||||||
import org.jetbrains.kotlin.ir.util.addArguments
|
|
||||||
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
import org.jetbrains.kotlin.ir.util.createParameterDeclarations
|
||||||
import org.jetbrains.kotlin.ir.util.getArguments
|
import org.jetbrains.kotlin.ir.util.getArguments
|
||||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.TypeProjectionImpl
|
||||||
|
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||||
|
import org.jetbrains.kotlin.types.replace
|
||||||
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
|
|
||||||
/**
|
internal class CallableReferenceLowering(val context: Context): DeclarationContainerLoweringPass {
|
||||||
* This lowering pass lowers all [IrCallableReference]s to unbound ones.
|
|
||||||
*/
|
|
||||||
internal class CallableReferenceLowering(val context: KonanBackendContext) : DeclarationContainerLoweringPass {
|
|
||||||
|
|
||||||
var callableReferenceCount = 0
|
private var functionReferenceCount = 0
|
||||||
|
|
||||||
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
||||||
irDeclarationContainer.declarations.transformFlat { declaration ->
|
irDeclarationContainer.declarations.transformFlat { declaration ->
|
||||||
if (declaration !is IrDeclarationContainer)
|
if (declaration !is IrDeclarationContainer)
|
||||||
lowerCallableReferences(this, irDeclarationContainer, declaration)
|
lowerFunctionReferences(irDeclarationContainer, declaration)
|
||||||
else
|
else
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
private fun lowerFunctionReferences(irDeclarationContainer: IrDeclarationContainer,
|
||||||
* Replaces all callable references in the function body to unbound ones.
|
declaration: IrDeclaration): List<IrDeclaration> {
|
||||||
* Returns the list of this function and all created ones.
|
val containingDeclaration = when (irDeclarationContainer) {
|
||||||
*/
|
is IrClass -> irDeclarationContainer.descriptor
|
||||||
private fun lowerCallableReferences(lower: CallableReferenceLowering,
|
is IrFile -> irDeclarationContainer.packageFragmentDescriptor
|
||||||
irDeclarationContainer: IrDeclarationContainer,
|
else -> throw AssertionError("Unexpected declaration container: $irDeclarationContainer")
|
||||||
declaration: IrDeclaration): List<IrDeclaration> {
|
|
||||||
val containingDeclaration = when (irDeclarationContainer) {
|
|
||||||
is IrClass -> irDeclarationContainer.descriptor
|
|
||||||
is IrFile -> irDeclarationContainer.packageFragmentDescriptor
|
|
||||||
else -> throw AssertionError("Unexpected declaration container: $irDeclarationContainer")
|
|
||||||
}
|
|
||||||
val transformer = CallableReferencesUnbinder(lower, containingDeclaration)
|
|
||||||
declaration.transformChildrenVoid(transformer)
|
|
||||||
return listOf(declaration) + transformer.createdFunctions
|
|
||||||
}
|
|
||||||
|
|
||||||
private object DECLARATION_ORIGIN_FUNCTION_FOR_CALLABLE_REFERENCE :
|
|
||||||
IrDeclarationOriginImpl("FUNCTION_FOR_CALLABLE_REFERENCE")
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replaces all callable references in the function body to unbound ones.
|
|
||||||
* Adds all created functions to [createdFunctions].
|
|
||||||
*/
|
|
||||||
private class CallableReferencesUnbinder(val lower: CallableReferenceLowering,
|
|
||||||
val containingDeclaration: DeclarationDescriptor) : IrElementTransformerVoid() {
|
|
||||||
|
|
||||||
val createdFunctions = mutableListOf<IrFunction>()
|
|
||||||
|
|
||||||
private val builtIns = lower.context.builtIns
|
|
||||||
|
|
||||||
override fun visitElement(element: IrElement): IrElement {
|
|
||||||
return super.visitElement(element)
|
|
||||||
}
|
|
||||||
|
|
||||||
private val unboundCallableReferenceType by lazy {
|
|
||||||
builtIns.getKonanInternalClass("UnboundCallableReference").defaultType
|
|
||||||
}
|
|
||||||
|
|
||||||
private val simpleFunctionImplClass by lazy {
|
|
||||||
builtIns.getKonanInternalClass("SimpleFunctionImpl")
|
|
||||||
}
|
|
||||||
|
|
||||||
private val simpleFunctionImplBoundArgsGetter by lazy {
|
|
||||||
simpleFunctionImplClass.defaultType.memberScope.getContributedDescriptors()
|
|
||||||
.filterIsInstance<PropertyDescriptor>()
|
|
||||||
.single { it.name.asString() == "boundArgs" }
|
|
||||||
.getter!!
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitClass(declaration: IrClass): IrStatement {
|
|
||||||
// Class is a declaration container - it will be visited by the main visitor (CallableReferenceLowering).
|
|
||||||
return declaration
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
|
||||||
expression.transformChildrenVoid(this)
|
|
||||||
if (!expression.type.isFunctionOrKFunctionType) {
|
|
||||||
// Not a subject of this lowering.
|
|
||||||
return expression
|
|
||||||
}
|
}
|
||||||
|
val createdClasses = mutableListOf<IrDeclaration>()
|
||||||
|
declaration.transformChildrenVoid(object: IrElementTransformerVoid() {
|
||||||
|
|
||||||
val descriptor = expression.descriptor
|
override fun visitClass(declaration: IrClass): IrStatement {
|
||||||
val boundArgs = expression.getArguments()
|
// Class is a declaration container - it will be visited by the main visitor (CallableReferenceLowering).
|
||||||
val boundParams = boundArgs.map { it.first }
|
return declaration
|
||||||
|
|
||||||
val allParams = descriptor.explicitParameters
|
|
||||||
val unboundParams = allParams - boundParams
|
|
||||||
|
|
||||||
val startOffset = expression.startOffset
|
|
||||||
val endOffset = expression.endOffset
|
|
||||||
|
|
||||||
// The code below creates a call to `SimpleFunctionImpl` constructor which creates the object implementing
|
|
||||||
// the function type.
|
|
||||||
|
|
||||||
// Create the function to be used as `unboundRef` of `SimpleFunctionImpl`:
|
|
||||||
val newFunction = createSimpleFunctionImplTarget(descriptor, unboundParams, boundParams, startOffset, endOffset)
|
|
||||||
|
|
||||||
createdFunctions.add(newFunction)
|
|
||||||
|
|
||||||
// Create the call to constructor and its arguments:
|
|
||||||
|
|
||||||
val unboundRef = IrFunctionReferenceImpl(startOffset, endOffset,
|
|
||||||
unboundCallableReferenceType, newFunction.descriptor, null)
|
|
||||||
val simpleFunctionImplClassConstructor = simpleFunctionImplClass.unsubstitutedPrimaryConstructor!!
|
|
||||||
|
|
||||||
val boundArgsVarargParam = simpleFunctionImplClassConstructor.valueParameters[1]
|
|
||||||
val boundArgsVararg = IrVarargImpl(
|
|
||||||
startOffset, endOffset,
|
|
||||||
boundArgsVarargParam.type,
|
|
||||||
boundArgsVarargParam.varargElementType!!,
|
|
||||||
boundArgs.map { it.second }
|
|
||||||
)
|
|
||||||
|
|
||||||
return IrCallImpl(startOffset, endOffset, simpleFunctionImplClassConstructor).apply {
|
|
||||||
putValueArgument(0, unboundRef)
|
|
||||||
putValueArgument(1, boundArgsVararg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For given function [descriptor] creates the function which calls [descriptor] but
|
|
||||||
* takes all [boundParams] packed into `SimpleFunctionImpl` (and all [unboundParams] as is).
|
|
||||||
*/
|
|
||||||
private fun createSimpleFunctionImplTarget(descriptor: FunctionDescriptor,
|
|
||||||
unboundParams: List<ParameterDescriptor>,
|
|
||||||
boundParams: List<ParameterDescriptor>,
|
|
||||||
startOffset: Int, endOffset: Int): IrFunctionImpl {
|
|
||||||
|
|
||||||
// Create new function descriptor:
|
|
||||||
val newDescriptor = createSimpleFunctionImplTargetDescriptor(descriptor, unboundParams)
|
|
||||||
|
|
||||||
val builder = lower.context.createIrBuilder(newDescriptor)
|
|
||||||
val blockBody = builder.irBlockBody(startOffset, endOffset) {
|
|
||||||
val boundArgsGet = irCall(simpleFunctionImplBoundArgsGetter).apply {
|
|
||||||
dispatchReceiver = irGet(newDescriptor.valueParameters[0])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+irLet(boundArgsGet) { boundArgs ->
|
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
||||||
val arrayGet = boundArgs.type.memberScope.getContributedDescriptors()
|
expression.transformChildrenVoid(this)
|
||||||
.filterIsInstance<FunctionDescriptor>().single { it.name.asString() == "get" }
|
|
||||||
|
|
||||||
// TODO: some handling for type parameters is probably required here.
|
if (!expression.type.isFunctionOrKFunctionType) {
|
||||||
|
// Not a subject of this lowering.
|
||||||
// Call to old function from new function:
|
return expression
|
||||||
val call = irCall(descriptor).apply {
|
|
||||||
// unboundParams are received as all new function parameters except first:
|
|
||||||
val newUnboundParams = newDescriptor.valueParameters.drop(1)
|
|
||||||
assert (unboundParams.size == newUnboundParams.size)
|
|
||||||
addArguments(unboundParams.mapIndexed { index, param ->
|
|
||||||
param to irGet(newUnboundParams[index])
|
|
||||||
})
|
|
||||||
|
|
||||||
// boundParams are received in `SimpleFunctionImpl.boundArgs`:
|
|
||||||
addArguments(boundParams.mapIndexed { index, param ->
|
|
||||||
param to irCall(arrayGet).apply {
|
|
||||||
dispatchReceiver = irGet(boundArgs)
|
|
||||||
putValueArgument(0, irInt(index))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
irReturn(call)
|
val loweredFunctionReference = FunctionReferenceBuilder(containingDeclaration, expression).build()
|
||||||
|
createdClasses += loweredFunctionReference.functionReferenceClass
|
||||||
|
return IrCallImpl(
|
||||||
|
startOffset = expression.startOffset,
|
||||||
|
endOffset = expression.endOffset,
|
||||||
|
calleeDescriptor = loweredFunctionReference.functionReferenceConstructorDescriptor).apply {
|
||||||
|
expression.getArguments().forEachIndexed { index, argument ->
|
||||||
|
putValueArgument(index, argument.second)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return listOf(declaration) + createdClasses
|
||||||
|
}
|
||||||
|
|
||||||
|
private abstract class DescriptorWithIrBuilder<out D : DeclarationDescriptor, out B : IrDeclaration> {
|
||||||
|
|
||||||
|
protected abstract fun buildDescriptor(): D
|
||||||
|
|
||||||
|
protected open fun doInitialize() {}
|
||||||
|
|
||||||
|
protected abstract fun buildIr(): B
|
||||||
|
|
||||||
|
val descriptor by lazy { buildDescriptor() }
|
||||||
|
|
||||||
|
private val builtIr by lazy { buildIr() }
|
||||||
|
private var initialized: Boolean = false
|
||||||
|
|
||||||
|
fun initialize() {
|
||||||
|
doInitialize()
|
||||||
|
initialized = true
|
||||||
|
}
|
||||||
|
|
||||||
|
val ir: B
|
||||||
|
get() {
|
||||||
|
if (!initialized)
|
||||||
|
throw Error("Access to IR before initialization")
|
||||||
|
return builtIr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class BuiltFunctionReference(val functionReferenceClass: IrClass,
|
||||||
|
val functionReferenceConstructorDescriptor: ClassConstructorDescriptor)
|
||||||
|
|
||||||
|
private inner class FunctionReferenceBuilder(val containingDeclaration: DeclarationDescriptor,
|
||||||
|
val functionReference: IrFunctionReference) {
|
||||||
|
|
||||||
|
private val functionDescriptor = functionReference.descriptor
|
||||||
|
private val functionParameters = functionDescriptor.explicitParameters
|
||||||
|
private val boundFunctionParameters = functionReference.getArguments().map { it.first }
|
||||||
|
private val unboundFunctionParameters = functionParameters - boundFunctionParameters
|
||||||
|
|
||||||
|
private lateinit var functionReferenceClassDescriptor: ClassDescriptorImpl
|
||||||
|
private lateinit var argumentToPropertiesMap: Map<ParameterDescriptor, PropertyDescriptor>
|
||||||
|
private val functionReferenceMembers = mutableListOf<IrDeclaration>()
|
||||||
|
|
||||||
|
private fun KotlinType.replace(types: List<KotlinType>) = this.replace(types.map(::TypeProjectionImpl))
|
||||||
|
|
||||||
|
private val kFunctionImplClassDescriptor = context.builtIns.getKonanInternalClass("KFunctionImpl")
|
||||||
|
|
||||||
|
fun build(): BuiltFunctionReference {
|
||||||
|
val startOffset = functionReference.startOffset
|
||||||
|
val endOffset = functionReference.endOffset
|
||||||
|
|
||||||
|
val superTypes = mutableListOf<KotlinType>(
|
||||||
|
kFunctionImplClassDescriptor.defaultType.replace(listOf(functionDescriptor.returnType!!))
|
||||||
|
)
|
||||||
|
var suspendFunctionClassDescriptor: ClassDescriptor? = null
|
||||||
|
val functionClassDescriptor = context.reflectionTypes.getKFunction(unboundFunctionParameters.size)
|
||||||
|
val types = unboundFunctionParameters.map { it.type } + functionDescriptor.returnType!!
|
||||||
|
superTypes += functionClassDescriptor.defaultType.replace(types)
|
||||||
|
|
||||||
|
functionReferenceClassDescriptor = ClassDescriptorImpl(
|
||||||
|
/* containingDeclaration = */ containingDeclaration,
|
||||||
|
/* name = */ "${functionDescriptor.name}\$${functionReferenceCount++}".synthesizedName,
|
||||||
|
/* modality = */ Modality.FINAL,
|
||||||
|
/* kind = */ ClassKind.CLASS,
|
||||||
|
/* superTypes = */ superTypes,
|
||||||
|
/* source = */ SourceElement.NO_SOURCE,
|
||||||
|
/* isExternal = */ false
|
||||||
|
)
|
||||||
|
val constructorBuilder = createConstructorBuilder()
|
||||||
|
|
||||||
|
val typeSubstitutor = TypeSubstitutor.create(
|
||||||
|
functionClassDescriptor.declaredTypeParameters
|
||||||
|
.withIndex()
|
||||||
|
.associateBy({ it.value.typeConstructor }, { TypeProjectionImpl(types[it.index]) })
|
||||||
|
)
|
||||||
|
val invokeFunctionDescriptor = functionClassDescriptor.unsubstitutedMemberScope
|
||||||
|
.getContributedFunctions(Name.identifier("invoke"), NoLookupLocation.FROM_BACKEND).single().substitute(typeSubstitutor)!!
|
||||||
|
val invokeMethodBuilder = createInvokeMethodBuilder(invokeFunctionDescriptor)
|
||||||
|
|
||||||
|
val inheritedKFunctionImpl = kFunctionImplClassDescriptor.unsubstitutedMemberScope
|
||||||
|
.getContributedDescriptors()
|
||||||
|
.map { it.createFakeOverrideDescriptor(functionReferenceClassDescriptor) }
|
||||||
|
.filterNotNull()
|
||||||
|
val contributedDescriptors = (
|
||||||
|
inheritedKFunctionImpl + invokeMethodBuilder.descriptor
|
||||||
|
).toList()
|
||||||
|
functionReferenceClassDescriptor.initialize(SimpleMemberScope(contributedDescriptors), setOf(constructorBuilder.descriptor), null)
|
||||||
|
|
||||||
|
constructorBuilder.initialize()
|
||||||
|
functionReferenceMembers.add(constructorBuilder.ir)
|
||||||
|
|
||||||
|
invokeMethodBuilder.initialize()
|
||||||
|
functionReferenceMembers.add(invokeMethodBuilder.ir)
|
||||||
|
|
||||||
|
val functionReferenceClass = IrClassImpl(
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||||
|
descriptor = functionReferenceClassDescriptor,
|
||||||
|
members = functionReferenceMembers
|
||||||
|
)
|
||||||
|
|
||||||
|
functionReferenceClass.createParameterDeclarations()
|
||||||
|
|
||||||
|
return BuiltFunctionReference(functionReferenceClass, constructorBuilder.descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun ParameterDescriptor.copyAsValueParameter(newOwner: CallableDescriptor, index: Int)
|
||||||
|
= when (this) {
|
||||||
|
is ValueParameterDescriptor -> this.copy(newOwner, name, index)
|
||||||
|
is ReceiverParameterDescriptor -> ValueParameterDescriptorImpl(
|
||||||
|
containingDeclaration = newOwner,
|
||||||
|
original = null,
|
||||||
|
index = index,
|
||||||
|
annotations = annotations,
|
||||||
|
name = name,
|
||||||
|
outType = type,
|
||||||
|
declaresDefaultValue = false,
|
||||||
|
isCrossinline = false,
|
||||||
|
isNoinline = false,
|
||||||
|
varargElementType = null,
|
||||||
|
source = source
|
||||||
|
)
|
||||||
|
else -> throw Error("Unexpected parameter descriptor: $this")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createConstructorBuilder()
|
||||||
|
= object : DescriptorWithIrBuilder<ClassConstructorDescriptorImpl, IrConstructor>() {
|
||||||
|
|
||||||
|
private val kFunctionImplConstructorDescriptor = kFunctionImplClassDescriptor.constructors.single()
|
||||||
|
private lateinit var constructorParameters: List<ValueParameterDescriptor>
|
||||||
|
|
||||||
|
override fun buildDescriptor(): ClassConstructorDescriptorImpl {
|
||||||
|
return ClassConstructorDescriptorImpl.create(
|
||||||
|
/* containingDeclaration = */ functionReferenceClassDescriptor,
|
||||||
|
/* annotations = */ Annotations.EMPTY,
|
||||||
|
/* isPrimary = */ false,
|
||||||
|
/* source = */ SourceElement.NO_SOURCE
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun doInitialize() {
|
||||||
|
constructorParameters = boundFunctionParameters.mapIndexed { index, parameter ->
|
||||||
|
parameter.copyAsValueParameter(descriptor, index)
|
||||||
|
}
|
||||||
|
descriptor.initialize(constructorParameters, Visibilities.PUBLIC)
|
||||||
|
descriptor.returnType = functionReferenceClassDescriptor.defaultType
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun buildIr(): IrConstructor {
|
||||||
|
argumentToPropertiesMap = boundFunctionParameters.associate {
|
||||||
|
it to buildPropertyWithBackingField(it.name, it.type, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
val startOffset = functionReference.startOffset
|
||||||
|
val endOffset = functionReference.endOffset
|
||||||
|
val irBuilder = context.createIrBuilder(descriptor, startOffset, endOffset)
|
||||||
|
return IrConstructorImpl(
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||||
|
descriptor = descriptor).apply {
|
||||||
|
|
||||||
|
createParameterDeclarations()
|
||||||
|
|
||||||
|
body = irBuilder.irBlockBody {
|
||||||
|
+IrDelegatingConstructorCallImpl(startOffset, endOffset, kFunctionImplConstructorDescriptor).apply {
|
||||||
|
val name = IrConstImpl<String>(startOffset, endOffset, context.builtIns.stringType,
|
||||||
|
IrConstKind.String, functionDescriptor.name.asString())
|
||||||
|
putValueArgument(0, name)
|
||||||
|
val fqName = IrConstImpl<String>(startOffset, endOffset, context.builtIns.stringType, IrConstKind.String,
|
||||||
|
functionDescriptor.fullName)
|
||||||
|
putValueArgument(1, fqName)
|
||||||
|
val bound = IrConstImpl.boolean(startOffset, endOffset, context.builtIns.booleanType,
|
||||||
|
boundFunctionParameters.isNotEmpty())
|
||||||
|
putValueArgument(2, bound)
|
||||||
|
val needReceiver = boundFunctionParameters.singleOrNull() is ReceiverParameterDescriptor
|
||||||
|
val receiver = if (needReceiver) irGet(constructorParameters.single()) else irNull()
|
||||||
|
putValueArgument(3, receiver)
|
||||||
|
}
|
||||||
|
+IrInstanceInitializerCallImpl(startOffset, endOffset, functionReferenceClassDescriptor)
|
||||||
|
// Save all arguments to fields.
|
||||||
|
boundFunctionParameters.forEachIndexed { index, parameter ->
|
||||||
|
+irSetField(irThis(), argumentToPropertiesMap[parameter]!!, irGet(constructorParameters[index]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val newFunction = IrFunctionImpl(
|
// TODO: what about private package level functions?
|
||||||
startOffset, endOffset, DECLARATION_ORIGIN_FUNCTION_FOR_CALLABLE_REFERENCE,
|
private val DeclarationDescriptor.fullName: String
|
||||||
newDescriptor,
|
get() {
|
||||||
blockBody
|
return when (this) {
|
||||||
)
|
is PackageFragmentDescriptor -> fqNameSafe.asString()
|
||||||
|
is ClassDescriptor -> containingDeclaration.fullName + "." + fqNameSafe
|
||||||
|
is FunctionDescriptor -> containingDeclaration.fullName + "." + functionName
|
||||||
|
is PropertyDescriptor -> containingDeclaration.fullName + "." + fqNameSafe
|
||||||
|
else -> TODO("$this")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
newFunction.createParameterDeclarations()
|
private fun createInvokeMethodBuilder(functionInvokeFunctionDescriptor: FunctionDescriptor)
|
||||||
|
= object : DescriptorWithIrBuilder<SimpleFunctionDescriptorImpl, IrFunction>() {
|
||||||
|
|
||||||
return newFunction
|
override fun buildDescriptor() = SimpleFunctionDescriptorImpl.create(
|
||||||
}
|
/* containingDeclaration = */ functionReferenceClassDescriptor,
|
||||||
|
/* annotations = */ Annotations.EMPTY,
|
||||||
|
/* name = */ Name.identifier("invoke"),
|
||||||
|
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
||||||
|
/* source = */ SourceElement.NO_SOURCE)
|
||||||
|
|
||||||
/**
|
override fun doInitialize() {
|
||||||
* Creates descriptor for [createSimpleFunctionImplTarget].
|
val valueParameters = functionInvokeFunctionDescriptor.valueParameters
|
||||||
*/
|
.map { it.copyAsValueParameter(this.descriptor, it.index) }
|
||||||
private fun createSimpleFunctionImplTargetDescriptor(descriptor: CallableDescriptor,
|
|
||||||
unboundParams: List<ParameterDescriptor>): FunctionDescriptor {
|
|
||||||
|
|
||||||
val newName = Name.identifier("${descriptor.name}\$bound-${lower.callableReferenceCount++}")
|
this.descriptor.initialize(
|
||||||
|
/* receiverParameterType = */ null,
|
||||||
|
/* dispatchReceiverParameter = */ functionReferenceClassDescriptor.thisAsReceiverParameter,
|
||||||
|
/* typeParameters = */ emptyList(),
|
||||||
|
/* unsubstitutedValueParameters = */ valueParameters,
|
||||||
|
/* unsubstitutedReturnType = */ functionInvokeFunctionDescriptor.returnType,
|
||||||
|
/* modality = */ Modality.FINAL,
|
||||||
|
/* visibility = */ Visibilities.PRIVATE).apply {
|
||||||
|
overriddenDescriptors += functionInvokeFunctionDescriptor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val newDescriptor = SimpleFunctionDescriptorImpl.create(
|
override fun buildIr(): IrFunction {
|
||||||
containingDeclaration, Annotations.EMPTY,
|
val startOffset = functionReference.startOffset
|
||||||
newName, CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE)
|
val endOffset = functionReference.endOffset
|
||||||
|
val ourDescriptor = this.descriptor
|
||||||
|
val irBuilder = context.createIrBuilder(this.descriptor, startOffset, endOffset)
|
||||||
|
return IrFunctionImpl(
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||||
|
descriptor = this.descriptor).apply {
|
||||||
|
|
||||||
val simpleFunctionImplType = simpleFunctionImplClass.defaultType
|
createParameterDeclarations()
|
||||||
|
|
||||||
// Map each unbound param of original function to parameter of new function.
|
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||||
val newUnboundParams = unboundParams.mapIndexed { index, param ->
|
+irReturn(
|
||||||
ValueParameterDescriptorImpl(
|
irCall(functionReference.descriptor).apply {
|
||||||
containingDeclaration = newDescriptor,
|
var unboundIndex = 0
|
||||||
original = null,
|
val unboundArgsSet = unboundFunctionParameters.toSet()
|
||||||
index = index + 1,
|
functionParameters.forEach {
|
||||||
annotations = Annotations.EMPTY,
|
val argument = if (unboundArgsSet.contains(it))
|
||||||
name = param.name,
|
irGet(ourDescriptor.valueParameters[unboundIndex++])
|
||||||
outType = builtIns.nullableAnyType, // Use erased type.
|
else
|
||||||
declaresDefaultValue = false,
|
irGet(irThis(), argumentToPropertiesMap[it]!!)
|
||||||
isCrossinline = false, isNoinline = false,
|
when (it) {
|
||||||
varargElementType = null,
|
functionDescriptor.dispatchReceiverParameter -> dispatchReceiver = argument
|
||||||
source = SourceElement.NO_SOURCE)
|
functionDescriptor.extensionReceiverParameter -> extensionReceiver = argument
|
||||||
|
else -> putValueArgument((it as ValueParameterDescriptor).index, argument)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(unboundIndex == ourDescriptor.valueParameters.size,
|
||||||
|
{ "Not all arguments of <invoke> are used" })
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// `<func>: SimpleFunctionImpl`
|
private fun createPropertyGetterBuilder(propertyDescriptor: PropertyDescriptor, type: KotlinType)
|
||||||
val functionParameter = ValueParameterDescriptorImpl(
|
= object : DescriptorWithIrBuilder<PropertyGetterDescriptorImpl, IrFunction>() {
|
||||||
containingDeclaration = newDescriptor,
|
|
||||||
original = null,
|
|
||||||
index = 0,
|
|
||||||
annotations = Annotations.EMPTY,
|
|
||||||
name = Name.special("<func>"),
|
|
||||||
outType = simpleFunctionImplType,
|
|
||||||
declaresDefaultValue = false,
|
|
||||||
isCrossinline = false, isNoinline = false,
|
|
||||||
varargElementType = null,
|
|
||||||
source = SourceElement.NO_SOURCE)
|
|
||||||
|
|
||||||
val newValueParameters = listOf(functionParameter) + newUnboundParams
|
override fun buildDescriptor() = PropertyGetterDescriptorImpl(
|
||||||
|
/* correspondingProperty = */ propertyDescriptor,
|
||||||
|
/* annotations = */ Annotations.EMPTY,
|
||||||
|
/* modality = */ Modality.FINAL,
|
||||||
|
/* visibility = */ Visibilities.PRIVATE,
|
||||||
|
/* isDefault = */ false,
|
||||||
|
/* isExternal = */ false,
|
||||||
|
/* isInline = */ false,
|
||||||
|
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
||||||
|
/* original = */ null,
|
||||||
|
/* source = */ SourceElement.NO_SOURCE
|
||||||
|
)
|
||||||
|
|
||||||
val newReturnType = builtIns.nullableAnyType // Use erased type.
|
override fun doInitialize() {
|
||||||
|
descriptor.apply {
|
||||||
|
initialize(type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
newDescriptor.initialize(null, null, descriptor.typeParameters, newValueParameters,
|
override fun buildIr() = IrFunctionImpl(
|
||||||
newReturnType, Modality.FINAL, Visibilities.PRIVATE)
|
startOffset = functionReference.startOffset,
|
||||||
|
endOffset = functionReference.endOffset,
|
||||||
|
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||||
|
descriptor = descriptor).apply {
|
||||||
|
|
||||||
return newDescriptor
|
createParameterDeclarations()
|
||||||
|
|
||||||
|
body = context.createIrBuilder(descriptor, startOffset, endOffset).irBlockBody {
|
||||||
|
+irReturn(irGetField(irThis(), propertyDescriptor))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createPropertySetterBuilder(propertyDescriptor: PropertyDescriptor, type: KotlinType)
|
||||||
|
= object : DescriptorWithIrBuilder<PropertySetterDescriptorImpl, IrFunction>() {
|
||||||
|
|
||||||
|
override fun buildDescriptor() = PropertySetterDescriptorImpl(
|
||||||
|
/* correspondingProperty = */ propertyDescriptor,
|
||||||
|
/* annotations = */ Annotations.EMPTY,
|
||||||
|
/* modality = */ Modality.FINAL,
|
||||||
|
/* visibility = */ Visibilities.PRIVATE,
|
||||||
|
/* isDefault = */ false,
|
||||||
|
/* isExternal = */ false,
|
||||||
|
/* isInline = */ false,
|
||||||
|
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
||||||
|
/* original = */ null,
|
||||||
|
/* source = */ SourceElement.NO_SOURCE
|
||||||
|
)
|
||||||
|
|
||||||
|
lateinit var valueParameterDescriptor: ValueParameterDescriptor
|
||||||
|
|
||||||
|
override fun doInitialize() {
|
||||||
|
descriptor.apply {
|
||||||
|
valueParameterDescriptor = ValueParameterDescriptorImpl(
|
||||||
|
containingDeclaration = this,
|
||||||
|
original = null,
|
||||||
|
index = 0,
|
||||||
|
annotations = Annotations.EMPTY,
|
||||||
|
name = Name.identifier("value"),
|
||||||
|
outType = type,
|
||||||
|
declaresDefaultValue = false,
|
||||||
|
isCrossinline = false,
|
||||||
|
isNoinline = false,
|
||||||
|
varargElementType = null,
|
||||||
|
source = SourceElement.NO_SOURCE
|
||||||
|
)
|
||||||
|
|
||||||
|
initialize(valueParameterDescriptor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun buildIr() = IrFunctionImpl(
|
||||||
|
startOffset = functionReference.startOffset,
|
||||||
|
endOffset = functionReference.endOffset,
|
||||||
|
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||||
|
descriptor = descriptor).apply {
|
||||||
|
|
||||||
|
createParameterDeclarations()
|
||||||
|
|
||||||
|
body = context.createIrBuilder(descriptor, startOffset, endOffset).irBlockBody {
|
||||||
|
+irSetField(irThis(), propertyDescriptor, irGet(valueParameterDescriptor))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createPropertyWithBackingFieldBuilder(name: Name, type: KotlinType, isMutable: Boolean)
|
||||||
|
= object : DescriptorWithIrBuilder<PropertyDescriptorImpl, IrProperty>() {
|
||||||
|
|
||||||
|
private lateinit var getterBuilder: DescriptorWithIrBuilder<PropertyGetterDescriptorImpl, IrFunction>
|
||||||
|
private var setterBuilder: DescriptorWithIrBuilder<PropertySetterDescriptorImpl, IrFunction>? = null
|
||||||
|
|
||||||
|
override fun buildDescriptor() = PropertyDescriptorImpl.create(
|
||||||
|
/* containingDeclaration = */ functionReferenceClassDescriptor,
|
||||||
|
/* annotations = */ Annotations.EMPTY,
|
||||||
|
/* modality = */ Modality.FINAL,
|
||||||
|
/* visibility = */ Visibilities.PRIVATE,
|
||||||
|
/* isVar = */ isMutable,
|
||||||
|
/* name = */ name,
|
||||||
|
/* kind = */ CallableMemberDescriptor.Kind.DECLARATION,
|
||||||
|
/* source = */ SourceElement.NO_SOURCE,
|
||||||
|
/* lateInit = */ false,
|
||||||
|
/* isConst = */ false,
|
||||||
|
/* isHeader = */ false,
|
||||||
|
/* isImpl = */ false,
|
||||||
|
/* isExternal = */ false,
|
||||||
|
/* isDelegated = */ false)
|
||||||
|
|
||||||
|
override fun doInitialize() {
|
||||||
|
getterBuilder = createPropertyGetterBuilder(descriptor, type).apply { initialize() }
|
||||||
|
if (isMutable)
|
||||||
|
setterBuilder = createPropertySetterBuilder(descriptor, type).apply { initialize() }
|
||||||
|
descriptor.initialize(getterBuilder.descriptor, setterBuilder?.descriptor)
|
||||||
|
val receiverType: KotlinType? = null
|
||||||
|
descriptor.setType(type, emptyList(), functionReferenceClassDescriptor.thisAsReceiverParameter, receiverType)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun buildIr(): IrProperty {
|
||||||
|
val startOffset = functionReference.startOffset
|
||||||
|
val endOffset = functionReference.endOffset
|
||||||
|
val backingField = IrFieldImpl(
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||||
|
descriptor = descriptor)
|
||||||
|
return IrPropertyImpl(
|
||||||
|
startOffset = startOffset,
|
||||||
|
endOffset = endOffset,
|
||||||
|
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||||
|
isDelegated = false,
|
||||||
|
descriptor = descriptor,
|
||||||
|
backingField = backingField,
|
||||||
|
getter = getterBuilder.ir,
|
||||||
|
setter = setterBuilder?.ir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildPropertyWithBackingField(name: Name, type: KotlinType, isMutable: Boolean): PropertyDescriptor {
|
||||||
|
val propertyBuilder = createPropertyWithBackingFieldBuilder(name, type, isMutable).apply { initialize() }
|
||||||
|
|
||||||
|
functionReferenceMembers.add(propertyBuilder.ir)
|
||||||
|
return propertyBuilder.descriptor
|
||||||
|
}
|
||||||
|
|
||||||
|
private object DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL :
|
||||||
|
IrDeclarationOriginImpl("FUNCTION_REFERENCE_IMPL")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2010-2017 JetBrains s.r.o.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package konan.internal
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents the reference to callable without any bound arguments.
|
|
||||||
* It is supposed to be represented at runtime as native pointer to code.
|
|
||||||
*
|
|
||||||
* TODO: it seems to be very closely related to native interop types.
|
|
||||||
*/
|
|
||||||
abstract class UnboundCallableReference internal constructor()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Values of function types are represented at runtime as instances of this class (and its subclasses).
|
|
||||||
*
|
|
||||||
* [FunctionImpl] is a reference to callable with itself as single bound argument,
|
|
||||||
* i.e. when calling this function with arguments `args`, [unboundRef] is called with arguments `(this, *args)`.
|
|
||||||
* So the instance is supposed to contain all implicit (bound) arguments of target function, e.g. captured values.
|
|
||||||
*/
|
|
||||||
open class FunctionImpl(val unboundRef: UnboundCallableReference)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple [FunctionImpl] implementation: all bound arguments of target callable to be placed into [boundArgs].
|
|
||||||
*/
|
|
||||||
class SimpleFunctionImpl(unboundRef: UnboundCallableReference, vararg val boundArgs: Any?) : FunctionImpl(unboundRef)
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2017 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package konan.internal
|
||||||
|
|
||||||
|
import kotlin.reflect.KFunction
|
||||||
|
|
||||||
|
@FixmeReflection
|
||||||
|
open class KFunctionImpl<out R>(override val name: String, val fqName: String, val bound: Boolean, val receiver: Any?): KFunction<R> {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (other !is KFunctionImpl<*>) return false
|
||||||
|
return fqName == other.fqName && bound == other.bound && receiver == other.receiver
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
return (fqName.hashCode() * 31 + if (bound) 1 else 0) * 31 + receiver.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return fqName
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -65,11 +65,11 @@ public interface KProperty<out R> : KCallable<R> {
|
|||||||
|
|
||||||
//
|
//
|
||||||
@FixmeReflection
|
@FixmeReflection
|
||||||
public interface KProperty0<out R> : kotlin.reflect.KProperty<R>/* TODO , (T) -> R*/ {
|
public interface KProperty0<out R> : kotlin.reflect.KProperty<R>, () -> R {
|
||||||
// public abstract val getter: kotlin.reflect.KProperty1.Getter<T, R>
|
// public abstract val getter: kotlin.reflect.KProperty1.Getter<T, R>
|
||||||
|
|
||||||
public abstract fun get(): R
|
public abstract fun get(): R
|
||||||
public abstract operator fun invoke(): R
|
public override abstract operator fun invoke(): R
|
||||||
|
|
||||||
// @kotlin.SinceKotlin public abstract fun getDelegate(receiver: T): kotlin.Any?
|
// @kotlin.SinceKotlin public abstract fun getDelegate(receiver: T): kotlin.Any?
|
||||||
//
|
//
|
||||||
@@ -78,11 +78,11 @@ public interface KProperty0<out R> : kotlin.reflect.KProperty<R>/* TODO , (T) ->
|
|||||||
}
|
}
|
||||||
|
|
||||||
@FixmeReflection
|
@FixmeReflection
|
||||||
public interface KProperty1<T, out R> : kotlin.reflect.KProperty<R>/* TODO , (T) -> R*/ {
|
public interface KProperty1<T, out R> : kotlin.reflect.KProperty<R>, (T) -> R {
|
||||||
// public abstract val getter: kotlin.reflect.KProperty1.Getter<T, R>
|
// public abstract val getter: kotlin.reflect.KProperty1.Getter<T, R>
|
||||||
|
|
||||||
public abstract fun get(receiver: T): R
|
public abstract fun get(receiver: T): R
|
||||||
public abstract operator fun invoke(receiver: T): R
|
public override abstract operator fun invoke(receiver: T): R
|
||||||
|
|
||||||
// @kotlin.SinceKotlin public abstract fun getDelegate(receiver: T): kotlin.Any?
|
// @kotlin.SinceKotlin public abstract fun getDelegate(receiver: T): kotlin.Any?
|
||||||
//
|
//
|
||||||
@@ -91,11 +91,11 @@ public interface KProperty1<T, out R> : kotlin.reflect.KProperty<R>/* TODO , (T)
|
|||||||
}
|
}
|
||||||
|
|
||||||
@FixmeReflection
|
@FixmeReflection
|
||||||
public interface KProperty2<T1, T2, out R> : kotlin.reflect.KProperty<R>/* TODO , (T) -> R*/ {
|
public interface KProperty2<T1, T2, out R> : kotlin.reflect.KProperty<R>, (T1, T2) -> R {
|
||||||
// public abstract val getter: kotlin.reflect.KProperty1.Getter<T, R>
|
// public abstract val getter: kotlin.reflect.KProperty1.Getter<T, R>
|
||||||
|
|
||||||
public abstract fun get(receiver1: T1, receiver2: T2): R
|
public abstract fun get(receiver1: T1, receiver2: T2): R
|
||||||
public abstract operator fun invoke(receiver1: T1, receiver2: T2): R
|
public override abstract operator fun invoke(receiver1: T1, receiver2: T2): R
|
||||||
|
|
||||||
// @kotlin.SinceKotlin public abstract fun getDelegate(receiver: T): kotlin.Any?
|
// @kotlin.SinceKotlin public abstract fun getDelegate(receiver: T): kotlin.Any?
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user