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
@@ -203,9 +203,9 @@ fun <T : CVariable> CPointed.readValues(size: Int, align: Int): CValues<T> {
inline fun <reified T : CVariable> T.readValues(count: Int): CValues<T> =
this.readValues<T>(size = count * sizeOf<T>().toInt(), align = alignOf<T>())
fun <T : CVariable> CPointed.readValue(size: Int, align: Int): CValue<T> {
val bytes = ByteArray(size)
nativeMemUtils.getByteArray(this, bytes, size)
fun <T : CVariable> CPointed.readValue(size: Long, align: Int): CValue<T> {
val bytes = ByteArray(size.toInt())
nativeMemUtils.getByteArray(this, bytes, size.toInt())
return object : CValue<T>() {
override fun getPointer(placement: NativePlacement): CPointer<T> = placement.placeBytes(bytes, align)
override val size get() = bytes.size
@@ -214,7 +214,7 @@ fun <T : CVariable> CPointed.readValue(size: Int, align: Int): CValue<T> {
// Note: can't be declared as property due to possible clash with a struct field.
// TODO: find better name.
inline fun <reified T : CStructVar> T.readValue(): CValue<T> = this.readValue(sizeOf<T>().toInt(), alignOf<T>())
inline fun <reified T : CStructVar> T.readValue(): CValue<T> = this.readValue(sizeOf<T>(), alignOf<T>())
// TODO: optimize
fun <T : CVariable> CValues<T>.getBytes(): ByteArray = memScoped {
@@ -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)
}