[Interop] Generate IR for CEnum inheritors
Since there is non-trivial logic inside code that we generate for interop enums, we generate it inside special IrProvider.
This commit is contained in:
committed by
Sergey Bogolepov
parent
8de328e269
commit
44552393ad
+8
-3
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.isForwardDeclarationModule
|
|||||||
import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary
|
import org.jetbrains.kotlin.backend.konan.descriptors.konanLibrary
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForInteropStubs
|
import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForInteropStubs
|
||||||
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
|
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.interop.IrProviderForCEnumStubs
|
||||||
import org.jetbrains.kotlin.backend.konan.llvm.*
|
import org.jetbrains.kotlin.backend.konan.llvm.*
|
||||||
import org.jetbrains.kotlin.backend.konan.lower.ExpectToActualDefaultValueCopier
|
import org.jetbrains.kotlin.backend.konan.lower.ExpectToActualDefaultValueCopier
|
||||||
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
import org.jetbrains.kotlin.backend.konan.objcexport.ObjCExport
|
||||||
@@ -201,14 +202,16 @@ internal val psiToIrPhase = konanUnitPhase(
|
|||||||
|
|
||||||
val functionIrClassFactory = BuiltInFictitiousFunctionIrClassFactory(
|
val functionIrClassFactory = BuiltInFictitiousFunctionIrClassFactory(
|
||||||
symbolTable, generatorContext.irBuiltIns, reflectionTypes)
|
symbolTable, generatorContext.irBuiltIns, reflectionTypes)
|
||||||
// TODO: Add special handling for enums and structs.
|
|
||||||
val irProviderForInteropStubs = IrProviderForInteropStubs { false }
|
|
||||||
val symbols = KonanSymbols(this, symbolTable, symbolTable.lazyWrapper, functionIrClassFactory)
|
val symbols = KonanSymbols(this, symbolTable, symbolTable.lazyWrapper, functionIrClassFactory)
|
||||||
val stubGenerator = DeclarationStubGenerator(
|
val stubGenerator = DeclarationStubGenerator(
|
||||||
moduleDescriptor, symbolTable,
|
moduleDescriptor, symbolTable,
|
||||||
config.configuration.languageVersionSettings
|
config.configuration.languageVersionSettings
|
||||||
)
|
)
|
||||||
val irProviders = listOf(irProviderForInteropStubs, functionIrClassFactory, deserializer, stubGenerator)
|
val irProviderForCEnums = IrProviderForCEnumStubs(generatorContext, interopBuiltIns, stubGenerator, symbols)
|
||||||
|
val irProviderForInteropStubs = IrProviderForInteropStubs { symbol ->
|
||||||
|
irProviderForCEnums.canHandleSymbol(symbol)
|
||||||
|
}
|
||||||
|
val irProviders = listOf(irProviderForCEnums, irProviderForInteropStubs, functionIrClassFactory, deserializer, stubGenerator)
|
||||||
stubGenerator.setIrProviders(irProviders)
|
stubGenerator.setIrProviders(irProviders)
|
||||||
|
|
||||||
expectDescriptorToSymbol = mutableMapOf<DeclarationDescriptor, IrSymbol>()
|
expectDescriptorToSymbol = mutableMapOf<DeclarationDescriptor, IrSymbol>()
|
||||||
@@ -236,6 +239,8 @@ internal val psiToIrPhase = konanUnitPhase(
|
|||||||
functionIrClassFactory.module =
|
functionIrClassFactory.module =
|
||||||
(listOf(irModule!!) + deserializer.modules.values)
|
(listOf(irModule!!) + deserializer.modules.values)
|
||||||
.single { it.descriptor.isKonanStdlib() }
|
.single { it.descriptor.isKonanStdlib() }
|
||||||
|
|
||||||
|
irProviderForCEnums.module = module
|
||||||
},
|
},
|
||||||
name = "Psi2Ir",
|
name = "Psi2Ir",
|
||||||
description = "Psi to IR conversion",
|
description = "Psi to IR conversion",
|
||||||
|
|||||||
+113
@@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package org.jetbrains.kotlin.backend.konan.ir.interop
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations
|
||||||
|
import org.jetbrains.kotlin.backend.konan.InteropBuiltIns
|
||||||
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
|
import org.jetbrains.kotlin.ir.builders.IrBuilder
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.parentsWithSelf
|
||||||
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
|
||||||
|
internal inline fun <reified T: DeclarationDescriptor> ClassDescriptor.findDeclarationByName(name: String): T? =
|
||||||
|
unsubstitutedMemberScope
|
||||||
|
.getContributedDescriptors()
|
||||||
|
.filterIsInstance<T>()
|
||||||
|
.firstOrNull { it.name.identifier == name }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides a set of functions and properties that helps
|
||||||
|
* to translate descriptor declarations to corresponding IR.
|
||||||
|
*/
|
||||||
|
internal interface DescriptorToIrTranslationMixin {
|
||||||
|
|
||||||
|
val symbolTable: SymbolTable
|
||||||
|
|
||||||
|
val irBuiltIns: IrBuiltIns
|
||||||
|
|
||||||
|
val typeTranslator: TypeTranslator
|
||||||
|
|
||||||
|
val stubGenerator: DeclarationStubGenerator
|
||||||
|
|
||||||
|
fun KotlinType.toIrType() = typeTranslator.translateType(this)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declares [IrClass] instance from [descriptor] and populates it with
|
||||||
|
* supertypes, <this> parameter declaration and fake overrides.
|
||||||
|
* Additional elements are passed via [builder] callback.
|
||||||
|
*/
|
||||||
|
fun createClass(descriptor: ClassDescriptor, builder: (IrClass) -> Unit): IrClass =
|
||||||
|
symbolTable.declareClass(
|
||||||
|
startOffset = SYNTHETIC_OFFSET,
|
||||||
|
endOffset = SYNTHETIC_OFFSET,
|
||||||
|
origin = IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB,
|
||||||
|
descriptor = descriptor
|
||||||
|
).also { irClass ->
|
||||||
|
symbolTable.withScope(descriptor) {
|
||||||
|
descriptor.typeConstructor.supertypes.mapTo(irClass.superTypes) {
|
||||||
|
it.toIrType()
|
||||||
|
}
|
||||||
|
irClass.createParameterDeclarations()
|
||||||
|
builder(irClass)
|
||||||
|
createFakeOverrides(descriptor).forEach(irClass::addMember)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createFakeOverrides(classDescriptor: ClassDescriptor): List<IrDeclaration> {
|
||||||
|
val fakeOverrides = classDescriptor.unsubstitutedMemberScope
|
||||||
|
.getContributedDescriptors()
|
||||||
|
.filterIsInstance<CallableMemberDescriptor>()
|
||||||
|
.filter { it.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE }
|
||||||
|
return fakeOverrides.map {
|
||||||
|
when (it) {
|
||||||
|
is PropertyDescriptor -> createProperty(it)
|
||||||
|
is FunctionDescriptor -> createFunction(it, IrDeclarationOrigin.FAKE_OVERRIDE)
|
||||||
|
else -> error("Unexpected fake override descriptor: $it")
|
||||||
|
} as IrDeclaration // Assistance for type inference.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createConstructor(constructorDescriptor: ClassConstructorDescriptor): IrConstructor =
|
||||||
|
stubGenerator.generateMemberStub(constructorDescriptor) as IrConstructor
|
||||||
|
|
||||||
|
fun createProperty(propertyDescriptor: PropertyDescriptor): IrProperty =
|
||||||
|
stubGenerator.generateMemberStub(propertyDescriptor) as IrProperty
|
||||||
|
|
||||||
|
fun createFunction(
|
||||||
|
functionDescriptor: FunctionDescriptor,
|
||||||
|
origin: IrDeclarationOrigin? = IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB
|
||||||
|
): IrSimpleFunction =
|
||||||
|
stubGenerator.generateFunctionStub(functionDescriptor, createPropertyIfNeeded = false).also {
|
||||||
|
if (origin != null) it.origin = origin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun IrBuilder.irInstanceInitializer(classSymbol: IrClassSymbol): IrExpression =
|
||||||
|
IrInstanceInitializerCallImpl(
|
||||||
|
startOffset, endOffset,
|
||||||
|
classSymbol,
|
||||||
|
context.irBuiltIns.unitType
|
||||||
|
)
|
||||||
|
|
||||||
|
internal fun ClassDescriptor.implementsCEnum(interopBuiltIns: InteropBuiltIns): Boolean =
|
||||||
|
interopBuiltIns.cEnum in this.getSuperInterfaces()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* All enums that come from interop library implement CEnum interface.
|
||||||
|
* This function checks that given symbol located in subtree of
|
||||||
|
* CEnum inheritor.
|
||||||
|
*/
|
||||||
|
internal fun IrSymbol.findCEnumDescriptor(interopBuiltIns: InteropBuiltIns): ClassDescriptor? =
|
||||||
|
descriptor.parentsWithSelf
|
||||||
|
.filterIsInstance<ClassDescriptor>()
|
||||||
|
.firstOrNull { it.implementsCEnum(interopBuiltIns) }
|
||||||
+97
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package org.jetbrains.kotlin.backend.konan.ir.interop
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.konan.InteropBuiltIns
|
||||||
|
import org.jetbrains.kotlin.backend.konan.descriptors.findPackage
|
||||||
|
import org.jetbrains.kotlin.backend.konan.descriptors.isFromInteropLibrary
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.interop.cenum.CEnumByValueFunctionGenerator
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.interop.cenum.CEnumClassGenerator
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.interop.cenum.CEnumCompanionGenerator
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.interop.cenum.CEnumVarClassGenerator
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.*
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For the most of descriptors that come from metadata-based interop libraries
|
||||||
|
* we generate a lazy IR.
|
||||||
|
* We use a different approach for CEnums and generate IR eagerly. Motivation:
|
||||||
|
* 1. CEnums are "real" Kotlin enums. Thus, we need apply the same compilation approach
|
||||||
|
* as we use for usual Kotlin enums.
|
||||||
|
* Eager generation allows to reuse [EnumClassLowering], [EnumConstructorsLowering] and other
|
||||||
|
* compiler phases.
|
||||||
|
* 2. It is an easier and more obvious approach. Since implementation of metadata-based
|
||||||
|
* libraries generation already took too much time we take an easier approach here.
|
||||||
|
*/
|
||||||
|
internal class IrProviderForCEnumStubs(
|
||||||
|
context: GeneratorContext,
|
||||||
|
private val interopBuiltIns: InteropBuiltIns,
|
||||||
|
stubGenerator: DeclarationStubGenerator,
|
||||||
|
symbols: KonanSymbols
|
||||||
|
) : IrProvider {
|
||||||
|
|
||||||
|
private val symbolTable: SymbolTable = context.symbolTable
|
||||||
|
|
||||||
|
private val filesMap = mutableMapOf<PackageFragmentDescriptor, IrFile>()
|
||||||
|
|
||||||
|
private val cEnumByValueFunctionGenerator =
|
||||||
|
CEnumByValueFunctionGenerator(context, stubGenerator, symbols)
|
||||||
|
private val cEnumCompanionGenerator =
|
||||||
|
CEnumCompanionGenerator(context, stubGenerator, cEnumByValueFunctionGenerator)
|
||||||
|
private val cEnumVarClassGenerator =
|
||||||
|
CEnumVarClassGenerator(context, stubGenerator, interopBuiltIns)
|
||||||
|
private val cEnumClassGenerator =
|
||||||
|
CEnumClassGenerator(context, stubGenerator, cEnumCompanionGenerator, cEnumVarClassGenerator)
|
||||||
|
|
||||||
|
var module: IrModuleFragment? = null
|
||||||
|
set(value) {
|
||||||
|
if (value == null)
|
||||||
|
error("Provide a valid non-null module")
|
||||||
|
if (field != null)
|
||||||
|
error("Module has already been set")
|
||||||
|
field = value
|
||||||
|
value.files += filesMap.values
|
||||||
|
}
|
||||||
|
|
||||||
|
fun canHandleSymbol(symbol: IrSymbol): Boolean {
|
||||||
|
if (!symbol.descriptor.module.isFromInteropLibrary()) return false
|
||||||
|
return symbol.findCEnumDescriptor(interopBuiltIns) != null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getDeclaration(symbol: IrSymbol): IrDeclaration? {
|
||||||
|
if (symbol.isBound) return symbol.owner as IrDeclaration
|
||||||
|
if (!canHandleSymbol(symbol)) return null
|
||||||
|
|
||||||
|
val enumClassDescriptor = symbol.findCEnumDescriptor(interopBuiltIns)!!
|
||||||
|
// TODO: This call generates a whole subtree. This a simple but clearly suboptimal solution.
|
||||||
|
cEnumClassGenerator.findOrGenerateCEnum(enumClassDescriptor, irParentFor(enumClassDescriptor))
|
||||||
|
return when (symbol) {
|
||||||
|
is IrClassSymbol -> symbolTable.referenceClass(symbol.descriptor).owner
|
||||||
|
is IrEnumEntrySymbol -> symbolTable.referenceEnumEntry(symbol.descriptor).owner
|
||||||
|
is IrFunctionSymbol -> symbolTable.referenceFunction(symbol.descriptor).owner
|
||||||
|
is IrPropertySymbol -> symbolTable.referenceProperty(symbol.descriptor).owner
|
||||||
|
else -> error(symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun irParentFor(descriptor: ClassDescriptor): IrDeclarationContainer {
|
||||||
|
val packageFragmentDescriptor = descriptor.findPackage()
|
||||||
|
return filesMap.getOrPut(packageFragmentDescriptor) {
|
||||||
|
IrFileImpl(NaiveSourceBasedFileEntryImpl("CEnums"), packageFragmentDescriptor).also {
|
||||||
|
this@IrProviderForCEnumStubs.module?.files?.add(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+96
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package org.jetbrains.kotlin.backend.konan.ir.interop.cenum
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.KonanSymbols
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.interop.DescriptorToIrTranslationMixin
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.interop.findDeclarationByName
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||||
|
import org.jetbrains.kotlin.ir.types.getClass
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.ir.util.irCall
|
||||||
|
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate IR for function that returns appropriate enum entry for the provided integral value.
|
||||||
|
*/
|
||||||
|
internal class CEnumByValueFunctionGenerator(
|
||||||
|
context: GeneratorContext,
|
||||||
|
override val stubGenerator: DeclarationStubGenerator,
|
||||||
|
private val symbols: KonanSymbols
|
||||||
|
) : DescriptorToIrTranslationMixin {
|
||||||
|
|
||||||
|
override val irBuiltIns: IrBuiltIns = context.irBuiltIns
|
||||||
|
override val symbolTable: SymbolTable = context.symbolTable
|
||||||
|
override val typeTranslator: TypeTranslator = context.typeTranslator
|
||||||
|
|
||||||
|
fun generateByValueFunction(
|
||||||
|
companionIrClass: IrClass,
|
||||||
|
valuesIrFunctionSymbol: IrSimpleFunctionSymbol
|
||||||
|
): IrFunction {
|
||||||
|
val byValueFunctionDescriptor = companionIrClass.descriptor.findDeclarationByName<FunctionDescriptor>("byValue")!!
|
||||||
|
val byValueIrFunction = createFunction(byValueFunctionDescriptor)
|
||||||
|
val irValueParameter = byValueIrFunction.valueParameters.first()
|
||||||
|
// val values: Array<E> = values()
|
||||||
|
// var i: Int = 0
|
||||||
|
// val size: Int = values.size
|
||||||
|
// while (i < size) {
|
||||||
|
// val entry: E = values[i]
|
||||||
|
// if (entry.value == arg) {
|
||||||
|
// return entry
|
||||||
|
// }
|
||||||
|
// i++
|
||||||
|
// }
|
||||||
|
// throw NPE
|
||||||
|
byValueIrFunction.body = irBuilder(irBuiltIns, byValueIrFunction.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody {
|
||||||
|
+irReturn(irBlock {
|
||||||
|
val values = irTemporaryVar(irCall(valuesIrFunctionSymbol))
|
||||||
|
val inductionVariable = irTemporaryVar(irInt(0))
|
||||||
|
val arrayClass = values.type.classOrNull!!
|
||||||
|
val valuesSize = irCall(symbols.arraySize.getValue(arrayClass)).also { irCall ->
|
||||||
|
irCall.dispatchReceiver = irGet(values)
|
||||||
|
}
|
||||||
|
val getElementFn = symbols.arrayGet.getValue(arrayClass)
|
||||||
|
val plusFun = symbols.intPlusInt
|
||||||
|
val lessFunctionSymbol = irBuiltIns.lessFunByOperandType.getValue(irBuiltIns.intClass)
|
||||||
|
+irWhile().also { loop ->
|
||||||
|
loop.condition = irCall(lessFunctionSymbol).also { irCall ->
|
||||||
|
irCall.putValueArgument(0, irGet(inductionVariable))
|
||||||
|
irCall.putValueArgument(1, valuesSize)
|
||||||
|
}
|
||||||
|
loop.body = irBlock {
|
||||||
|
val untypedEntry = irCall(getElementFn).also { irCall ->
|
||||||
|
irCall.dispatchReceiver = irGet(values)
|
||||||
|
irCall.putValueArgument(0, irGet(inductionVariable))
|
||||||
|
}
|
||||||
|
val entry = irTemporaryVar(irImplicitCast(untypedEntry, byValueIrFunction.returnType))
|
||||||
|
val valueGetter = entry.type.getClass()!!.getPropertyGetter("value")!!
|
||||||
|
val entryValue = irGet(irValueParameter.type, irGet(entry), valueGetter)
|
||||||
|
+irIfThenElse(
|
||||||
|
type = irBuiltIns.unitType,
|
||||||
|
condition = irEquals(entryValue, irGet(irValueParameter)),
|
||||||
|
thenPart = irReturn(irGet(entry)),
|
||||||
|
elsePart = irSetVar(
|
||||||
|
inductionVariable,
|
||||||
|
irCallOp(plusFun, irBuiltIns.intType,
|
||||||
|
irGet(inductionVariable),
|
||||||
|
irInt(1)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+irCall(symbols.ThrowNullPointerException)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return byValueIrFunction
|
||||||
|
}
|
||||||
|
}
|
||||||
+166
@@ -0,0 +1,166 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package org.jetbrains.kotlin.backend.konan.ir.interop.cenum
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.konan.descriptors.enumEntries
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.interop.DescriptorToIrTranslationMixin
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.interop.findDeclarationByName
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.interop.irInstanceInitializer
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||||
|
import org.jetbrains.kotlin.ir.builders.*
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrEnumConstructorCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi2ir.generators.DeclarationGenerator
|
||||||
|
import org.jetbrains.kotlin.psi2ir.generators.EnumClassMembersGenerator
|
||||||
|
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
|
||||||
|
import org.jetbrains.kotlin.resolve.constants.ConstantValue
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.firstNotNullResult
|
||||||
|
|
||||||
|
private fun extractConstantValue(descriptor: DeclarationDescriptor, type: String): ConstantValue<*>? =
|
||||||
|
descriptor.annotations
|
||||||
|
.findAnnotation(cEnumEntryValueAnnotationName.child(Name.identifier(type)))
|
||||||
|
?.allValueArguments
|
||||||
|
?.getValue(Name.identifier("value"))
|
||||||
|
|
||||||
|
private val cEnumEntryValueAnnotationName = FqName("kotlinx.cinterop.internal.ConstantValue")
|
||||||
|
|
||||||
|
private val cEnumEntryValueTypes = setOf(
|
||||||
|
"Byte", "Short", "Int", "Long",
|
||||||
|
"UByte", "UShort", "UInt", "ULong"
|
||||||
|
)
|
||||||
|
|
||||||
|
internal class CEnumClassGenerator(
|
||||||
|
val context: GeneratorContext,
|
||||||
|
override val stubGenerator: DeclarationStubGenerator,
|
||||||
|
private val cEnumCompanionGenerator: CEnumCompanionGenerator,
|
||||||
|
private val cEnumVarClassGenerator: CEnumVarClassGenerator
|
||||||
|
) : DescriptorToIrTranslationMixin {
|
||||||
|
|
||||||
|
override val irBuiltIns: IrBuiltIns = context.irBuiltIns
|
||||||
|
override val symbolTable: SymbolTable = context.symbolTable
|
||||||
|
override val typeTranslator: TypeTranslator = context.typeTranslator
|
||||||
|
|
||||||
|
private val enumClassMembersGenerator = EnumClassMembersGenerator(DeclarationGenerator(context))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for an IR class for [classDescriptor] in symbol table.
|
||||||
|
* Generates one if absent.
|
||||||
|
*/
|
||||||
|
fun findOrGenerateCEnum(classDescriptor: ClassDescriptor, parent: IrDeclarationContainer): IrClass {
|
||||||
|
val irClassSymbol = symbolTable.referenceClass(classDescriptor)
|
||||||
|
return if (!irClassSymbol.isBound) {
|
||||||
|
provideIrClassForCEnum(classDescriptor).also {
|
||||||
|
it.patchDeclarationParents(parent)
|
||||||
|
parent.declarations += it
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
irClassSymbol.owner
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The main function that for given [descriptor] of the enum generates the whole
|
||||||
|
* IR tree including entries, CEnumVar class, and companion objects.
|
||||||
|
*/
|
||||||
|
private fun provideIrClassForCEnum(descriptor: ClassDescriptor): IrClass =
|
||||||
|
createClass(descriptor) { enumIrClass ->
|
||||||
|
enumIrClass.addMember(createEnumPrimaryConstructor(descriptor))
|
||||||
|
enumIrClass.addMember(createValueProperty(enumIrClass))
|
||||||
|
descriptor.enumEntries.mapTo(enumIrClass.declarations) { entryDescriptor ->
|
||||||
|
createEnumEntry(descriptor, entryDescriptor)
|
||||||
|
}
|
||||||
|
enumClassMembersGenerator.generateSpecialMembers(enumIrClass)
|
||||||
|
enumIrClass.addChild(cEnumCompanionGenerator.generate(enumIrClass))
|
||||||
|
enumIrClass.addChild(cEnumVarClassGenerator.generate(enumIrClass))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates `value` property that stores integral value of the enum.
|
||||||
|
*/
|
||||||
|
private fun createValueProperty(irClass: IrClass): IrProperty {
|
||||||
|
val propertyDescriptor = irClass.descriptor
|
||||||
|
.findDeclarationByName<PropertyDescriptor>("value")
|
||||||
|
?: error("No `value` property in ${irClass.name}")
|
||||||
|
val irProperty = createProperty(propertyDescriptor)
|
||||||
|
symbolTable.withScope(propertyDescriptor) {
|
||||||
|
irProperty.backingField = symbolTable.declareField(
|
||||||
|
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
|
||||||
|
propertyDescriptor, propertyDescriptor.type.toIrType(), Visibilities.PRIVATE
|
||||||
|
).also {
|
||||||
|
it.initializer = irBuilder(irBuiltIns, it.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).run {
|
||||||
|
irExprBody(irGet(irClass.primaryConstructor!!.valueParameters[0]))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
irProperty.getter = createFunction(
|
||||||
|
propertyDescriptor.getter!!,
|
||||||
|
IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR
|
||||||
|
).also { getter ->
|
||||||
|
getter.correspondingPropertySymbol = irProperty.symbol
|
||||||
|
getter.body = irBuilder(irBuiltIns, getter.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody {
|
||||||
|
+irReturn(
|
||||||
|
irGetField(
|
||||||
|
irGet(getter.dispatchReceiverParameter!!),
|
||||||
|
irProperty.backingField!!
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return irProperty
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createEnumEntry(enumDescriptor: ClassDescriptor, entryDescriptor: ClassDescriptor): IrEnumEntry {
|
||||||
|
return symbolTable.declareEnumEntry(
|
||||||
|
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
|
||||||
|
IrDeclarationOrigin.IR_EXTERNAL_DECLARATION_STUB, entryDescriptor
|
||||||
|
).also { enumEntry ->
|
||||||
|
enumEntry.initializerExpression = IrEnumConstructorCallImpl(
|
||||||
|
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET,
|
||||||
|
type = irBuiltIns.unitType,
|
||||||
|
symbol = symbolTable.referenceConstructor(enumDescriptor.unsubstitutedPrimaryConstructor!!),
|
||||||
|
typeArgumentsCount = 0 // enums can't be generic
|
||||||
|
).also {
|
||||||
|
it.putValueArgument(0, extractEnumEntryValue(entryDescriptor))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Every enum entry that came from metadata-based interop library is annotated with
|
||||||
|
* [kotlinx.cinterop.internal.ConstantValue] annotation that holds internal constant value of the
|
||||||
|
* corresponding entry.
|
||||||
|
*
|
||||||
|
* This function extracts value from the annotation.
|
||||||
|
*/
|
||||||
|
private fun extractEnumEntryValue(entryDescriptor: ClassDescriptor): IrExpression =
|
||||||
|
cEnumEntryValueTypes.firstNotNullResult { extractConstantValue(entryDescriptor, it) } ?.let {
|
||||||
|
context.constantValueGenerator.generateConstantValueAsExpression(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, it)
|
||||||
|
} ?: error("Enum entry $entryDescriptor has no appropriate @$cEnumEntryValueAnnotationName annotation!")
|
||||||
|
|
||||||
|
private fun createEnumPrimaryConstructor(descriptor: ClassDescriptor): IrConstructor {
|
||||||
|
val irConstructor = createConstructor(descriptor.unsubstitutedPrimaryConstructor!!)
|
||||||
|
val enumConstructor = context.builtIns.enum.constructors.single()
|
||||||
|
irConstructor.body = irBuilder(irBuiltIns, irConstructor.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody {
|
||||||
|
+IrEnumConstructorCallImpl(
|
||||||
|
startOffset, endOffset,
|
||||||
|
context.irBuiltIns.unitType,
|
||||||
|
symbolTable.referenceConstructor(enumConstructor),
|
||||||
|
typeArgumentsCount = 1 // kotlin.Enum<T> has a single type parameter.
|
||||||
|
).apply {
|
||||||
|
putTypeArgument(0, descriptor.defaultType.toIrType())
|
||||||
|
}
|
||||||
|
+irInstanceInitializer(symbolTable.referenceClass(descriptor))
|
||||||
|
}
|
||||||
|
return irConstructor
|
||||||
|
}
|
||||||
|
}
|
||||||
+95
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package org.jetbrains.kotlin.backend.konan.ir.interop.cenum
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.konan.descriptors.getArgumentValueOrNull
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.interop.DescriptorToIrTranslationMixin
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.interop.irInstanceInitializer
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
|
||||||
|
import org.jetbrains.kotlin.ir.builders.irBlockBody
|
||||||
|
import org.jetbrains.kotlin.ir.builders.irReturn
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetEnumValueImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||||
|
|
||||||
|
private val cEnumEntryAliasAnnonation = FqName("kotlinx.cinterop.internal.CEnumEntryAlias")
|
||||||
|
|
||||||
|
internal class CEnumCompanionGenerator(
|
||||||
|
context: GeneratorContext,
|
||||||
|
override val stubGenerator: DeclarationStubGenerator,
|
||||||
|
private val cEnumByValueFunctionGenerator: CEnumByValueFunctionGenerator
|
||||||
|
) : DescriptorToIrTranslationMixin {
|
||||||
|
|
||||||
|
override val irBuiltIns: IrBuiltIns = context.irBuiltIns
|
||||||
|
override val symbolTable: SymbolTable = context.symbolTable
|
||||||
|
override val typeTranslator: TypeTranslator = context.typeTranslator
|
||||||
|
|
||||||
|
// Depends on already generated `.values()` irFunction.
|
||||||
|
fun generate(enumClass: IrClass): IrClass =
|
||||||
|
createClass(enumClass.descriptor.companionObjectDescriptor!!) { companionIrClass ->
|
||||||
|
companionIrClass.superTypes += irBuiltIns.anyType
|
||||||
|
companionIrClass.addMember(createCompanionConstructor(companionIrClass.descriptor))
|
||||||
|
val valuesFunction = enumClass.functions.single { it.name.identifier == "values" }.symbol
|
||||||
|
val byValueIrFunction = cEnumByValueFunctionGenerator
|
||||||
|
.generateByValueFunction(companionIrClass, valuesFunction)
|
||||||
|
companionIrClass.addMember(byValueIrFunction)
|
||||||
|
findEntryAliases(companionIrClass.descriptor)
|
||||||
|
.map { declareEntryAliasProperty(it, enumClass) }
|
||||||
|
.forEach(companionIrClass::addMember)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createCompanionConstructor(companionObjectDescriptor: ClassDescriptor): IrConstructor {
|
||||||
|
val anyPrimaryConstructor = companionObjectDescriptor.builtIns.any.unsubstitutedPrimaryConstructor!!
|
||||||
|
val superConstructorSymbol = symbolTable.referenceConstructor(anyPrimaryConstructor)
|
||||||
|
return createConstructor(companionObjectDescriptor.unsubstitutedPrimaryConstructor!!).also {
|
||||||
|
it.body = irBuilder(irBuiltIns, it.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody {
|
||||||
|
+IrDelegatingConstructorCallImpl(
|
||||||
|
startOffset, endOffset, context.irBuiltIns.unitType,
|
||||||
|
superConstructorSymbol
|
||||||
|
)
|
||||||
|
+irInstanceInitializer(symbolTable.referenceClass(companionObjectDescriptor))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all properties in companion object that represent aliases to
|
||||||
|
* enum entries.
|
||||||
|
*/
|
||||||
|
private fun findEntryAliases(companionDescriptor: ClassDescriptor) =
|
||||||
|
companionDescriptor.defaultType.memberScope.getContributedDescriptors()
|
||||||
|
.filterIsInstance<PropertyDescriptor>()
|
||||||
|
.filter { it.annotations.hasAnnotation(cEnumEntryAliasAnnonation) }
|
||||||
|
|
||||||
|
private fun fundCorrespondingEnumEntrySymbol(aliasDescriptor: PropertyDescriptor, irClass: IrClass): IrEnumEntrySymbol {
|
||||||
|
val enumEntryName = aliasDescriptor.annotations
|
||||||
|
.findAnnotation(cEnumEntryAliasAnnonation)!!
|
||||||
|
.getArgumentValueOrNull<String>("entryName")
|
||||||
|
return irClass.declarations.filterIsInstance<IrEnumEntry>()
|
||||||
|
.single { it.name.identifier == enumEntryName }.symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun generateAliasGetterBody(getter: IrSimpleFunction, entrySymbol: IrEnumEntrySymbol): IrBody =
|
||||||
|
irBuilder(irBuiltIns, getter.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody {
|
||||||
|
+irReturn(
|
||||||
|
IrGetEnumValueImpl(startOffset, endOffset, entrySymbol.owner.parentAsClass.defaultType, entrySymbol)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun declareEntryAliasProperty(propertyDescriptor: PropertyDescriptor, enumClass: IrClass): IrProperty {
|
||||||
|
val entrySymbol = fundCorrespondingEnumEntrySymbol(propertyDescriptor, enumClass)
|
||||||
|
return createProperty(propertyDescriptor).also {
|
||||||
|
it.getter!!.body = generateAliasGetterBody(it.getter!!, entrySymbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+93
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||||
|
* that can be found in the LICENSE file.
|
||||||
|
*/
|
||||||
|
package org.jetbrains.kotlin.backend.konan.ir.interop.cenum
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.backend.konan.InteropBuiltIns
|
||||||
|
import org.jetbrains.kotlin.backend.konan.descriptors.getArgumentValueOrNull
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.interop.DescriptorToIrTranslationMixin
|
||||||
|
import org.jetbrains.kotlin.backend.konan.ir.interop.irInstanceInitializer
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
|
import org.jetbrains.kotlin.ir.builders.irBlockBody
|
||||||
|
import org.jetbrains.kotlin.ir.builders.irGet
|
||||||
|
import org.jetbrains.kotlin.ir.builders.irInt
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrProperty
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.addMember
|
||||||
|
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
|
||||||
|
|
||||||
|
private val typeSizeAnnotation = FqName("kotlinx.cinterop.internal.CEnumVarTypeSize")
|
||||||
|
|
||||||
|
internal class CEnumVarClassGenerator(
|
||||||
|
context: GeneratorContext,
|
||||||
|
override val stubGenerator: DeclarationStubGenerator,
|
||||||
|
private val interopBuiltIns: InteropBuiltIns
|
||||||
|
) : DescriptorToIrTranslationMixin {
|
||||||
|
|
||||||
|
override val irBuiltIns: IrBuiltIns = context.irBuiltIns
|
||||||
|
override val symbolTable: SymbolTable = context.symbolTable
|
||||||
|
override val typeTranslator: TypeTranslator = context.typeTranslator
|
||||||
|
|
||||||
|
fun generate(enumIrClass: IrClass): IrClass {
|
||||||
|
val enumVarClassDescriptor = enumIrClass.descriptor.unsubstitutedMemberScope
|
||||||
|
.getContributedClassifier(Name.identifier("Var"), NoLookupLocation.FROM_BACKEND)!! as ClassDescriptor
|
||||||
|
return createClass(enumVarClassDescriptor) { enumVarClass ->
|
||||||
|
enumVarClass.addMember(createPrimaryConstructor(enumVarClass))
|
||||||
|
enumVarClass.addMember(createCompanionObject(enumVarClass))
|
||||||
|
enumVarClass.addMember(createValueProperty(enumVarClass))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createValueProperty(enumVarClass: IrClass): IrProperty {
|
||||||
|
val valuePropertyDescriptor = enumVarClass.descriptor.unsubstitutedMemberScope
|
||||||
|
.getContributedVariables(Name.identifier("value"), NoLookupLocation.FROM_BACKEND).single()
|
||||||
|
return createProperty(valuePropertyDescriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createPrimaryConstructor(enumVarClass: IrClass): IrConstructor {
|
||||||
|
val irConstructor = createConstructor(enumVarClass.descriptor.unsubstitutedPrimaryConstructor!!)
|
||||||
|
val enumVarConstructorSymbol = symbolTable.referenceConstructor(
|
||||||
|
interopBuiltIns.cEnumVar.unsubstitutedPrimaryConstructor!!
|
||||||
|
)
|
||||||
|
irConstructor.body = irBuilder(irBuiltIns, irConstructor.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody {
|
||||||
|
+IrDelegatingConstructorCallImpl(
|
||||||
|
startOffset, endOffset, context.irBuiltIns.unitType, enumVarConstructorSymbol
|
||||||
|
).also {
|
||||||
|
it.putValueArgument(0, irGet(irConstructor.valueParameters[0]))
|
||||||
|
}
|
||||||
|
+irInstanceInitializer(symbolTable.referenceClass(enumVarClass.descriptor))
|
||||||
|
}
|
||||||
|
return irConstructor
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createCompanionObject(enumVarClass: IrClass): IrClass =
|
||||||
|
createClass(enumVarClass.descriptor.companionObjectDescriptor!!) { companionIrClass ->
|
||||||
|
val typeSize = companionIrClass.descriptor.annotations
|
||||||
|
.findAnnotation(typeSizeAnnotation)!!
|
||||||
|
.getArgumentValueOrNull<Int>("size")!!
|
||||||
|
companionIrClass.addMember(createCompanionConstructor(companionIrClass.descriptor, typeSize))
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createCompanionConstructor(companionObjectDescriptor: ClassDescriptor, typeSize: Int): IrConstructor {
|
||||||
|
val superConstructorSymbol = symbolTable.referenceConstructor(interopBuiltIns.cPrimitiveVarType.unsubstitutedPrimaryConstructor!!)
|
||||||
|
return createConstructor(companionObjectDescriptor.unsubstitutedPrimaryConstructor!!).also {
|
||||||
|
it.body = irBuilder(irBuiltIns, it.symbol, SYNTHETIC_OFFSET, SYNTHETIC_OFFSET).irBlockBody {
|
||||||
|
+IrDelegatingConstructorCallImpl(
|
||||||
|
startOffset, endOffset, context.irBuiltIns.unitType,
|
||||||
|
superConstructorSymbol
|
||||||
|
).also {
|
||||||
|
it.putValueArgument(0, irInt(typeSize))
|
||||||
|
}
|
||||||
|
+irInstanceInitializer(symbolTable.referenceClass(companionObjectDescriptor))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+8
-3
@@ -49,12 +49,17 @@ import org.jetbrains.kotlin.types.KotlinType
|
|||||||
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
|
||||||
import java.lang.reflect.Proxy
|
import java.lang.reflect.Proxy
|
||||||
|
|
||||||
internal fun irBuilder(irBuiltIns: IrBuiltIns, scopeOwnerSymbol: IrSymbol): IrBuilderWithScope =
|
internal fun irBuilder(
|
||||||
|
irBuiltIns: IrBuiltIns,
|
||||||
|
scopeOwnerSymbol: IrSymbol,
|
||||||
|
startOffset: Int = UNDEFINED_OFFSET,
|
||||||
|
endOffset: Int = UNDEFINED_OFFSET
|
||||||
|
): IrBuilderWithScope =
|
||||||
object : IrBuilderWithScope(
|
object : IrBuilderWithScope(
|
||||||
IrGeneratorContextBase(irBuiltIns),
|
IrGeneratorContextBase(irBuiltIns),
|
||||||
Scope(scopeOwnerSymbol),
|
Scope(scopeOwnerSymbol),
|
||||||
UNDEFINED_OFFSET,
|
startOffset,
|
||||||
UNDEFINED_OFFSET
|
endOffset
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
//TODO: delete file on next kotlin dependency update
|
//TODO: delete file on next kotlin dependency update
|
||||||
|
|||||||
Reference in New Issue
Block a user