JVM_IR. support big arity
This commit is contained in:
@@ -169,6 +169,8 @@ abstract class Symbols<out T : CommonBackendContext>(val context: T, private val
|
||||
|
||||
abstract val coroutineSuspendedGetter: IrSimpleFunctionSymbol
|
||||
|
||||
fun getFunction(parameterCount: Int) = symbolTable.referenceClass(context.builtIns.getFunction(parameterCount))
|
||||
|
||||
val functionReference = calc { symbolTable.referenceClass(context.getInternalClass("FunctionReference")) }
|
||||
|
||||
fun getFunction(name: Name, receiverType: KotlinType, vararg argTypes: KotlinType) =
|
||||
|
||||
@@ -57,6 +57,7 @@ class JvmLower(val context: JvmBackendContext) {
|
||||
true
|
||||
).runOnFilePostfix(irFile)
|
||||
CallableReferenceLowering(context).lower(irFile)
|
||||
FunctionNVarargInvokeLowering(context).runOnFilePostfix(irFile)
|
||||
|
||||
InnerClassesLowering(context).runOnFilePostfix(irFile)
|
||||
InnerClassConstructorCallsLowering(context).runOnFilePostfix(irFile)
|
||||
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2010-2016 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 org.jetbrains.kotlin.backend.jvm.intrinsics
|
||||
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.BlockInfo
|
||||
import org.jetbrains.kotlin.backend.jvm.codegen.ExpressionCodegen
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.JAVA_STRING_TYPE
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
class IrIllegalArgumentException : IntrinsicMethod() {
|
||||
val exceptionTypeDescriptor = Type.getInternalName(IllegalArgumentException::class.java)
|
||||
|
||||
override fun toCallable(
|
||||
expression: IrMemberAccessExpression,
|
||||
signature: JvmMethodSignature,
|
||||
context: JvmBackendContext
|
||||
): IrIntrinsicFunction {
|
||||
return object : IrIntrinsicFunction(expression, signature, context, listOf(JAVA_STRING_TYPE)) {
|
||||
override fun genInvokeInstruction(v: InstructionAdapter) {
|
||||
v.invokespecial(exceptionTypeDescriptor, "<init>", Type.getMethodDescriptor(Type.VOID_TYPE, JAVA_STRING_TYPE), false)
|
||||
v.athrow()
|
||||
}
|
||||
|
||||
override fun invoke(v: InstructionAdapter, codegen: ExpressionCodegen, data: BlockInfo): StackValue {
|
||||
v.anew(Type.getType(exceptionTypeDescriptor))
|
||||
v.dup()
|
||||
return super.invoke(v, codegen, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -52,6 +52,7 @@ class IrIntrinsicMethods(irBuiltIns: IrBuiltIns) {
|
||||
|
||||
irMapping[irBuiltIns.enumValueOf] = IrEnumValueOf()
|
||||
irMapping[irBuiltIns.noWhenBranchMatchedException] = IrNoWhenBranchMatchedException()
|
||||
irMapping[irBuiltIns.illegalArgumentException] = IrIllegalArgumentException()
|
||||
irMapping[irBuiltIns.throwNpe] = ThrowNPE()
|
||||
}
|
||||
|
||||
|
||||
+119
-29
@@ -37,20 +37,14 @@ import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrClassReferenceImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
|
||||
import org.jetbrains.kotlin.ir.types.toIrType
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||
@@ -99,8 +93,41 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
|
||||
}
|
||||
}
|
||||
|
||||
val argumentsCount = expression.valueArgumentsCount
|
||||
// Change calls to FunctionN with large N to varargs calls.
|
||||
val newCall = if (argumentsCount > MAX_ARGCOUNT_WITHOUT_VARARG &&
|
||||
descriptor.containingDeclaration in listOf(
|
||||
context.builtIns.getFunction(argumentsCount),
|
||||
context.reflectionTypes.getKFunction(argumentsCount)
|
||||
)
|
||||
) {
|
||||
val vararg = IrVarargImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
context.ir.symbols.array.typeWith(),
|
||||
context.ir.symbols.any.typeWith(),
|
||||
(0 until argumentsCount).map { i -> expression.getValueArgument(i)!! }
|
||||
)
|
||||
val invokeFunDescriptor = context.getClass(FqName("kotlin.jvm.functions.FunctionN"))
|
||||
.getFunction("invoke", listOf(expression.type.toKotlinType()))
|
||||
val invokeFunSymbol = context.ir.symbols.externalSymbolTable.referenceSimpleFunction(invokeFunDescriptor)
|
||||
|
||||
IrCallImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
expression.type,
|
||||
invokeFunSymbol, invokeFunDescriptor,
|
||||
1,
|
||||
expression.origin,
|
||||
expression.superQualifier?.let { context.ir.symbols.externalSymbolTable.referenceClass(it) }
|
||||
).apply {
|
||||
putTypeArgument(0, expression.type)
|
||||
dispatchReceiver = expression.dispatchReceiver
|
||||
extensionReceiver = expression.extensionReceiver
|
||||
putValueArgument(0, vararg)
|
||||
}
|
||||
} else expression
|
||||
|
||||
//TODO: clean
|
||||
return super.visitCall(expression)
|
||||
return super.visitCall(newCall)
|
||||
}
|
||||
|
||||
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
||||
@@ -155,6 +182,8 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
|
||||
|
||||
private val functionReferenceOrLambda = if (isLambda) context.ir.symbols.lambdaClass else context.ir.symbols.functionReference
|
||||
|
||||
var useVararg: Boolean = false
|
||||
|
||||
fun build(): BuiltFunctionReference {
|
||||
val startOffset = irFunctionReference.startOffset
|
||||
val endOffset = irFunctionReference.endOffset
|
||||
@@ -165,9 +194,17 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
|
||||
)
|
||||
|
||||
val numberOfParameters = unboundFunctionParameters.size
|
||||
val functionClassDescriptor = context.getClass(FqName("kotlin.jvm.functions.Function$numberOfParameters"))
|
||||
useVararg = (numberOfParameters > MAX_ARGCOUNT_WITHOUT_VARARG)
|
||||
|
||||
val functionClassDescriptor = if (useVararg)
|
||||
context.getClass(FqName("kotlin.jvm.functions.FunctionN"))
|
||||
else
|
||||
context.getClass(FqName("kotlin.jvm.functions.Function$numberOfParameters"))
|
||||
val functionParameterTypes = unboundFunctionParameters.map { it.type }
|
||||
val functionClassTypeParameters = functionParameterTypes + returnType
|
||||
val functionClassTypeParameters = if (useVararg)
|
||||
listOf(returnType)
|
||||
else
|
||||
functionParameterTypes + returnType
|
||||
superTypes += functionClassDescriptor.defaultType.replace(functionClassTypeParameters)
|
||||
|
||||
var suspendFunctionClassDescriptor: ClassDescriptor? = null
|
||||
@@ -197,7 +234,17 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
|
||||
endOffset = endOffset,
|
||||
origin = DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
descriptor = functionReferenceClassDescriptor
|
||||
)
|
||||
).apply {
|
||||
createParameterDeclarations()
|
||||
val typeTranslator = TypeTranslator(context.ir.symbols.externalSymbolTable, context.state.languageVersionSettings,
|
||||
enterTableScope=true)
|
||||
val constantValueGenerator = ConstantValueGenerator(context.state.module, context.ir.symbols.externalSymbolTable)
|
||||
typeTranslator.constantValueGenerator = constantValueGenerator
|
||||
constantValueGenerator.typeTranslator = typeTranslator
|
||||
functionReferenceClassDescriptor.typeConstructor.supertypes.mapTo(this.superTypes) {
|
||||
typeTranslator.translateType(it)
|
||||
}
|
||||
}
|
||||
|
||||
val contributedDescriptors = mutableListOf<DeclarationDescriptor>()
|
||||
val constructorBuilder = createConstructorBuilder()
|
||||
@@ -205,8 +252,6 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
|
||||
SimpleMemberScope(contributedDescriptors), setOf(constructorBuilder.symbol.descriptor), null
|
||||
)
|
||||
|
||||
functionReferenceClass.createParameterDeclarations()
|
||||
|
||||
functionReferenceThis = functionReferenceClass.thisReceiver!!.symbol
|
||||
|
||||
val invokeFunctionDescriptor = functionClassDescriptor.getFunction("invoke", functionClassTypeParameters)
|
||||
@@ -219,7 +264,6 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
|
||||
invokeMethodBuilder.initialize()
|
||||
functionReferenceClass.declarations.add(invokeMethodBuilder.ir)
|
||||
|
||||
|
||||
if (!isLambda) {
|
||||
val getSignatureBuilder =
|
||||
createGetSignatureMethodBuilder(functionReferenceOrLambda.owner.descriptor.getFunction("getSignature", emptyList()))
|
||||
@@ -245,7 +289,6 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
|
||||
).filterNotNull()
|
||||
)
|
||||
|
||||
|
||||
getSignatureBuilder.initialize()
|
||||
functionReferenceClass.declarations.add(getSignatureBuilder.ir)
|
||||
|
||||
@@ -391,31 +434,74 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
|
||||
createParameterDeclarations()
|
||||
|
||||
body = irBuilder.irBlockBody(startOffset, endOffset) {
|
||||
val arrayGetFun = context.irBuiltIns.arrayClass.owner
|
||||
.declarations.find {
|
||||
(it as? IrSimpleFunction)?.name?.toString() == "get"
|
||||
}!! as IrSimpleFunction
|
||||
|
||||
if (useVararg) {
|
||||
val varargParam = valueParameters.single()
|
||||
val arraySizeProperty = context.irBuiltIns.arrayClass.owner.declarations.find {
|
||||
(it as? IrProperty)?.name?.toString() == "size"
|
||||
} as IrProperty
|
||||
+irIfThen(
|
||||
irNotEquals(
|
||||
irCall(arraySizeProperty.getter!!).apply {
|
||||
dispatchReceiver = irGet(varargParam)
|
||||
},
|
||||
irInt(unboundFunctionParameters.size)
|
||||
),
|
||||
irCall(context.irBuiltIns.illegalArgumentExceptionFun).apply {
|
||||
putValueArgument(0, irString("Expected ${unboundFunctionParameters.size} arguments"))
|
||||
}
|
||||
)
|
||||
}
|
||||
+irReturn(
|
||||
irCall(irFunctionReference.symbol).apply {
|
||||
var unboundIndex = 0
|
||||
val unboundArgsSet = unboundFunctionParameters.toSet()
|
||||
functionParameters.forEach {
|
||||
val argument =
|
||||
if (!unboundArgsSet.contains(it))
|
||||
// Bound parameter - read from field.
|
||||
irGetField(irGet(functionReferenceThis.owner), argumentToPropertiesMap[it]!!.owner)
|
||||
else {
|
||||
if (ourSymbol.descriptor.isSuspend && unboundIndex == valueParameters.size)
|
||||
|
||||
functionParameters.forEach { parameter ->
|
||||
val argument = when {
|
||||
!unboundArgsSet.contains(parameter) ->
|
||||
// Bound parameter - read from field.
|
||||
irGetField(irGet(functionReferenceThis.owner), argumentToPropertiesMap[parameter]!!.owner)
|
||||
ourSymbol.descriptor.isSuspend && unboundIndex == valueParameters.size ->
|
||||
// For suspend functions the last argument is continuation and it is implicit.
|
||||
TODO()
|
||||
TODO()
|
||||
// irCall(getContinuationSymbol,
|
||||
// listOf(ourSymbol.descriptor.returnType!!))
|
||||
else
|
||||
irGet(valueParameters[unboundIndex++])
|
||||
useVararg -> {
|
||||
val type = parameter.type.toIrType()!!
|
||||
val varargParam = valueParameters.single()
|
||||
irBlock(resultType = type) {
|
||||
val argValue = irTemporary(
|
||||
irCall(arrayGetFun).apply {
|
||||
dispatchReceiver = irGet(varargParam)
|
||||
putValueArgument(0, irInt(unboundIndex++))
|
||||
}
|
||||
)
|
||||
+irIfThen(
|
||||
irNotIs(irGet(argValue), type),
|
||||
irCall(context.irBuiltIns.illegalArgumentExceptionFun).apply {
|
||||
putValueArgument(0, irString("Wrong type, expected $type"))
|
||||
}
|
||||
)
|
||||
+irGet(argValue)
|
||||
}
|
||||
}
|
||||
when (it) {
|
||||
else -> {
|
||||
irGet(valueParameters[unboundIndex++])
|
||||
}
|
||||
}
|
||||
when (parameter) {
|
||||
functionDescriptor.dispatchReceiverParameter -> dispatchReceiver = argument
|
||||
functionDescriptor.extensionReceiverParameter -> extensionReceiver = argument
|
||||
else -> putValueArgument((it as ValueParameterDescriptor).index, argument)
|
||||
else -> putValueArgument((parameter as ValueParameterDescriptor).index, argument)
|
||||
}
|
||||
}
|
||||
assert(unboundIndex == valueParameters.size) { "Not all arguments of <invoke> are used" }
|
||||
|
||||
if (!useVararg) assert(unboundIndex == valueParameters.size) { "Not all arguments of <invoke> are used" }
|
||||
}
|
||||
)
|
||||
}
|
||||
@@ -703,6 +789,10 @@ class CallableReferenceLowering(val context: JvmBackendContext) : FileLoweringPa
|
||||
Name.identifier("$${name.substring(1, name.length - 1)}")
|
||||
} else this
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val MAX_ARGCOUNT_WITHOUT_VARARG = 22
|
||||
}
|
||||
}
|
||||
|
||||
// Copied from K/Native IrUtils2.kt
|
||||
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.lower.irIfThen
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrTypeOperatorCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.types.typeWith
|
||||
import org.jetbrains.kotlin.ir.util.filterDeclarations
|
||||
import org.jetbrains.kotlin.ir.util.findDeclaration
|
||||
import org.jetbrains.kotlin.ir.util.isSubclassOf
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class FunctionNVarargInvokeLowering(var context: JvmBackendContext) : ClassLoweringPass {
|
||||
|
||||
override fun lower(irClass: IrClass) {
|
||||
val invokeFunctions = irClass.filterDeclarations<IrSimpleFunction> { it.name.toString() == "invoke" }
|
||||
if (invokeFunctions.isEmpty() ||
|
||||
invokeFunctions.any { it.valueParameters.size > 0 && it.valueParameters.last().varargElementType != null } ||
|
||||
invokeFunctions.all { it.valueParameters.size + (if (it.extensionReceiverParameter != null) 1 else 0) <= CallableReferenceLowering.MAX_ARGCOUNT_WITHOUT_VARARG }
|
||||
) {
|
||||
// No need to add a new vararg invoke method
|
||||
return
|
||||
}
|
||||
val functionInvokes = invokeFunctions.filter { irClass.isSubclassOf(context.ir.symbols.getFunction(it.valueParameters.size).owner) }
|
||||
if (functionInvokes.isEmpty()) return
|
||||
|
||||
irClass.declarations.add(generateVarargInvoke(irClass, functionInvokes))
|
||||
}
|
||||
|
||||
private fun generateVarargInvoke(irClass: IrClass, invokesToDelegateTo: List<IrSimpleFunction>): IrFunction {
|
||||
val backendContext = context
|
||||
val descriptor = WrappedSimpleFunctionDescriptor()
|
||||
return IrFunctionImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
origin = CallableReferenceLowering.DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
symbol = IrSimpleFunctionSymbolImpl(descriptor),
|
||||
name = Name.identifier("invoke"),
|
||||
visibility = Visibilities.PUBLIC,
|
||||
modality = Modality.OPEN,
|
||||
isInline = false,
|
||||
isExternal = false,
|
||||
isTailrec = false,
|
||||
isSuspend = false
|
||||
).apply {
|
||||
descriptor.bind(this)
|
||||
returnType = context.irBuiltIns.anyNType
|
||||
dispatchReceiverParameter = irClass.thisReceiver
|
||||
val varargParameterDescriptor = WrappedValueParameterDescriptor()
|
||||
val varargParam = IrValueParameterImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
origin = CallableReferenceLowering.DECLARATION_ORIGIN_FUNCTION_REFERENCE_IMPL,
|
||||
symbol = IrValueParameterSymbolImpl(varargParameterDescriptor),
|
||||
name = Name.identifier("args"),
|
||||
index = 0,
|
||||
type = context.irBuiltIns.arrayClass.typeWith(),
|
||||
varargElementType = context.irBuiltIns.anyClass.typeWith(),
|
||||
isCrossinline = false,
|
||||
isNoinline = false
|
||||
).apply {
|
||||
varargParameterDescriptor.bind(this)
|
||||
}
|
||||
valueParameters.add(varargParam)
|
||||
val irBuilder = context.createIrBuilder(symbol, UNDEFINED_OFFSET, UNDEFINED_OFFSET)
|
||||
body = irBuilder.irBlockBody(UNDEFINED_OFFSET, UNDEFINED_OFFSET) {
|
||||
val arrayGetFun =
|
||||
backendContext.irBuiltIns.arrayClass.owner.findDeclaration<IrSimpleFunction> { it.name.toString() == "get" }!!
|
||||
val arraySizeProperty = context.irBuiltIns.arrayClass.owner.findDeclaration<IrProperty> { it.name.toString() == "size" }!!
|
||||
val numberOfArguments = irTemporary(irCall(arraySizeProperty.getter!!).apply {
|
||||
dispatchReceiver = irGet(varargParam)
|
||||
})
|
||||
|
||||
for (target in invokesToDelegateTo) {
|
||||
+irIfThen(
|
||||
backendContext.irBuiltIns.unitType,
|
||||
irEquals(irGet(numberOfArguments), irInt(target.valueParameters.size)),
|
||||
irReturn(
|
||||
IrTypeOperatorCallImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
backendContext.irBuiltIns.anyNType,
|
||||
IrTypeOperator.CAST,
|
||||
target.returnType,
|
||||
target.returnType.classifierOrFail,
|
||||
irCall(target).apply {
|
||||
dispatchReceiver = irGet(irClass.thisReceiver!!)
|
||||
target.valueParameters.forEachIndexed { i, irValueParameter ->
|
||||
val type = irValueParameter.type
|
||||
putValueArgument(
|
||||
i,
|
||||
irBlock(resultType = type) {
|
||||
val argValue = irTemporary(
|
||||
irCallOp(
|
||||
arrayGetFun.symbol,
|
||||
context.irBuiltIns.anyNType,
|
||||
irGet(varargParam),
|
||||
irInt(i)
|
||||
)
|
||||
)
|
||||
+irIfThen(
|
||||
irNotIs(irGet(argValue), type),
|
||||
irCall(context.irBuiltIns.illegalArgumentExceptionFun).apply {
|
||||
putValueArgument(0, irString("Wrong type, expected $type"))
|
||||
}
|
||||
)
|
||||
+irGet(argValue)
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
val throwMessage = invokesToDelegateTo.map { it.valueParameters.size.toString() }.joinToString(
|
||||
prefix = "Expected ",
|
||||
separator = " or ",
|
||||
postfix = " arguments to invoke call"
|
||||
)
|
||||
+irCall(context.irBuiltIns.illegalArgumentExceptionFun.symbol).apply {
|
||||
putValueArgument(0, irString(throwMessage))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -124,6 +124,8 @@ class IrBuiltIns(
|
||||
val stringType = string.toIrType()
|
||||
val stringClass = builtIns.string.toIrSymbol()
|
||||
|
||||
val arrayClass = builtIns.array.toIrSymbol()
|
||||
|
||||
val throwableType = builtIns.throwable.defaultType.toIrType()
|
||||
val throwableClass = builtIns.throwable.toIrSymbol()
|
||||
|
||||
@@ -152,6 +154,7 @@ class IrBuiltIns(
|
||||
val throwIseFun = defineOperator("THROW_ISE", nothing, listOf())
|
||||
val booleanNotFun = defineOperator("NOT", bool, listOf(bool))
|
||||
val noWhenBranchMatchedExceptionFun = defineOperator("noWhenBranchMatchedException", nothing, listOf())
|
||||
val illegalArgumentExceptionFun = defineOperator("illegalArgumentException", nothing, listOf(string))
|
||||
|
||||
val eqeqeq = eqeqeqFun.descriptor
|
||||
val eqeq = eqeqFun.descriptor
|
||||
@@ -159,6 +162,7 @@ class IrBuiltIns(
|
||||
val throwCce = throwCceFun.descriptor
|
||||
val booleanNot = booleanNotFun.descriptor
|
||||
val noWhenBranchMatchedException = noWhenBranchMatchedExceptionFun.descriptor
|
||||
val illegalArgumentException = illegalArgumentExceptionFun.descriptor
|
||||
|
||||
val eqeqeqSymbol = eqeqeqFun.symbol
|
||||
val eqeqSymbol = eqeqFun.symbol
|
||||
@@ -167,6 +171,7 @@ class IrBuiltIns(
|
||||
val throwIseSymbol = throwIseFun.symbol
|
||||
val booleanNotSymbol = booleanNotFun.symbol
|
||||
val noWhenBranchMatchedExceptionSymbol = noWhenBranchMatchedExceptionFun.symbol
|
||||
val illegalArgumentExceptionSymbol = illegalArgumentExceptionFun.symbol
|
||||
|
||||
val enumValueOfFun = createEnumValueOfFun()
|
||||
val enumValueOf = enumValueOfFun.descriptor
|
||||
|
||||
@@ -266,6 +266,26 @@ val IrClass.defaultType: IrType
|
||||
|
||||
val IrSimpleFunction.isReal: Boolean get() = descriptor.kind.isReal
|
||||
|
||||
fun IrClass.isImmediateSubClassOf(ancestor: IrClass) = ancestor.symbol in superTypes.mapNotNull {
|
||||
(it as? IrSimpleType)?.classifier
|
||||
}
|
||||
|
||||
fun IrClass.isSubclassOf(ancestor: IrClass): Boolean {
|
||||
|
||||
val alreadyVisited = mutableSetOf<IrClass>()
|
||||
|
||||
fun IrClass.hasAncestorInSuperTypes(): Boolean = when {
|
||||
this === ancestor -> true
|
||||
this in alreadyVisited -> false
|
||||
else -> {
|
||||
alreadyVisited.add(this)
|
||||
superTypes.mapNotNull { ((it as? IrSimpleType)?.classifier as? IrClassSymbol)?.owner }.any { it.hasAncestorInSuperTypes() }
|
||||
}
|
||||
}
|
||||
|
||||
return this.hasAncestorInSuperTypes()
|
||||
}
|
||||
|
||||
// This implementation is from kotlin-native
|
||||
// TODO: use this implementation instead of any other
|
||||
fun IrSimpleFunction.resolveFakeOverride(): IrSimpleFunction? {
|
||||
@@ -339,6 +359,12 @@ fun IrDeclaration.isEffectivelyExternal(): Boolean {
|
||||
|
||||
fun IrDeclaration.isDynamic() = this is IrFunction && dispatchReceiverParameter?.type is IrDynamicType
|
||||
|
||||
inline fun <reified T : IrDeclaration> IrDeclarationContainer.findDeclaration(predicate: (T) -> Boolean): T? =
|
||||
declarations.find { it is T && predicate(it) } as? T
|
||||
|
||||
inline fun <reified T : IrDeclaration> IrDeclarationContainer.filterDeclarations(predicate: (T) -> Boolean): List<T> =
|
||||
declarations.filter { it is T && predicate(it) } as List<T>
|
||||
|
||||
fun IrValueParameter.copy(newDescriptor: ParameterDescriptor): IrValueParameter {
|
||||
assert(this.descriptor.type == newDescriptor.type)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user