Workaround incomplete inline for interop's readValue

This commit is contained in:
Svyatoslav Scherbina
2017-04-10 12:12:18 +03:00
committed by SvyatoslavScherbina
parent c4cc91d880
commit 716efe7310
4 changed files with 53 additions and 4 deletions
@@ -103,6 +103,14 @@ internal class InteropBuiltIns(builtIns: KonanBuiltIns) {
it.valueParameters.size == 0
}
val readValue = packageScope.getContributedFunctions("readValue").single {
it.valueParameters.size == 0
}
val readValueBySizeAndAlign = packageScope.getContributedFunctions("readValue").single {
it.valueParameters.size == 2
}
val typeOf = packageScope.getContributedFunctions("typeOf").single()
val variableTypeClass =
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.builders.irGet
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrCallableReferenceImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetObjectValueImpl
@@ -179,6 +180,21 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
return alloc(placement, size, align)
}
private fun IrBuilderWithScope.readValue(receiver: IrExpression, typeArgument: KotlinType): IrCallImpl? {
val size = sizeOf(typeArgument) ?: return null
val align = alignOf(typeArgument) ?: return null
val callee = interop.readValueBySizeAndAlign
val typeParameter = callee.typeParameters.single()
val typeArguments = mapOf(typeParameter to typeArgument)
return irCall(callee, typeArguments).apply {
extensionReceiver = receiver
putValueArgument(0, size)
putValueArgument(1, align)
}
}
override fun visitCall(expression: IrCall): IrExpression {
expression.transformChildrenVoid(this)
@@ -252,6 +268,13 @@ private class InteropTransformer(val context: Context, val irFile: IrFile) : IrB
}
}
interop.readValue -> {
val typeArgument = expression.getSingleTypeArgument()
val receiver = expression.extensionReceiver!!
builder.readValue(receiver, typeArgument) ?: expression
}
interop.staticCFunction -> {
val argument = expression.getValueArgument(0)!!
if (argument !is IrCallableReference || argument.getArguments().isNotEmpty()) {
@@ -16,6 +16,8 @@
package org.jetbrains.kotlin.ir.builders
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.ValueDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.ir.expressions.IrExpression
@@ -23,6 +25,8 @@ import org.jetbrains.kotlin.ir.expressions.IrLoop
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeProjectionImpl
import org.jetbrains.kotlin.types.TypeSubstitutor
inline fun IrBuilderWithScope.irLetSequence(
value: IrExpression,
@@ -50,3 +54,17 @@ fun IrBuilderWithScope.irTrue() = IrConstImpl.boolean(startOffset, endOffset, co
fun IrBuilderWithScope.irGet(value: ValueDescriptor) =
IrGetValueImpl(startOffset, endOffset, value)
fun IrBuilderWithScope.irCall(
callee: CallableDescriptor,
typeArguments: Map<TypeParameterDescriptor, KotlinType>
): IrCallImpl {
val substitutionContext = typeArguments.map { (typeParameter, typeArgument) ->
typeParameter.typeConstructor to TypeProjectionImpl(typeArgument)
}.toMap()
val substitutor = TypeSubstitutor.create(substitutionContext)
val substitutedCallee = callee.substitute(substitutor)!!
return IrCallImpl(this.startOffset, this.endOffset, substitutedCallee, typeArguments)
}