IR: use buildFun where possible

This commit is contained in:
Alexander Udalov
2020-07-08 15:03:16 +02:00
parent 39e38c7049
commit 6aa09f61d4
14 changed files with 308 additions and 437 deletions
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.Scope
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.builders.declarations.buildReceiverParameter
import org.jetbrains.kotlin.ir.builders.declarations.buildTypeParameter
import org.jetbrains.kotlin.ir.declarations.*
@@ -486,25 +487,20 @@ fun IrClass.addFakeOverridesViaIncorrectHeuristic(implementedMembers: List<IrSim
fun createFakeOverride(overriddenFunctions: List<IrSimpleFunction>) =
overriddenFunctions.first().let { irFunction ->
val descriptor = WrappedSimpleFunctionDescriptor()
IrFunctionImpl(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
IrDeclarationOrigin.FAKE_OVERRIDE,
IrSimpleFunctionSymbolImpl(descriptor),
irFunction.name,
Visibilities.PUBLIC,
irFunction.modality,
irFunction.returnType,
isInline = irFunction.isInline,
isExternal = irFunction.isExternal,
isTailrec = irFunction.isTailrec,
isSuspend = irFunction.isSuspend,
isExpect = irFunction.isExpect,
isFakeOverride = true,
buildFun {
origin = IrDeclarationOrigin.FAKE_OVERRIDE
name = irFunction.name
visibility = Visibilities.PUBLIC
modality = irFunction.modality
returnType = irFunction.returnType
isInline = irFunction.isInline
isExternal = irFunction.isExternal
isTailrec = irFunction.isTailrec
isSuspend = irFunction.isSuspend
isOperator = irFunction.isOperator
).apply {
descriptor.bind(this)
isExpect = irFunction.isExpect
isFakeOverride = true
}.apply {
parent = this@addFakeOverridesViaIncorrectHeuristic
overriddenSymbols = overriddenFunctions.map { it.symbol }
copyParameterDeclarationsFrom(irFunction)
@@ -10,18 +10,17 @@ import org.jetbrains.kotlin.backend.common.ir.*
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrClassImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.descriptors.WrappedClassConstructorDescriptor
import org.jetbrains.kotlin.ir.descriptors.WrappedClassDescriptor
import org.jetbrains.kotlin.ir.descriptors.WrappedFieldDescriptor
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrInstanceInitializerCallImpl
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
@@ -29,7 +28,6 @@ import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
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.IrType
import org.jetbrains.kotlin.ir.types.classifierOrFail
import org.jetbrains.kotlin.ir.types.defaultType
@@ -472,65 +470,54 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
unboundArgs: List<IrValueParameter>,
superFunctionSymbol: IrSimpleFunctionSymbol?,
coroutineConstructor: IrConstructor
) = WrappedSimpleFunctionDescriptor().let { d ->
IrFunctionImpl(
startOffset, endOffset,
DECLARATION_ORIGIN_COROUTINE_IMPL,
IrSimpleFunctionSymbolImpl(d),
Name.identifier("create"),
Visibilities.PROTECTED,
Modality.FINAL,
coroutineClass.defaultType,
isInline = false,
isExternal = false,
isTailrec = false,
isSuspend = false,
isExpect = false,
isFakeOverride = false,
isOperator = false
).apply {
d.bind(this)
parent = coroutineClass
coroutineClass.declarations += this
): IrSimpleFunction = buildFun {
startOffset = irFunction.startOffset
endOffset = irFunction.endOffset
origin = DECLARATION_ORIGIN_COROUTINE_IMPL
name = Name.identifier("create")
visibility = Visibilities.PROTECTED
returnType = coroutineClass.defaultType
}.apply {
parent = coroutineClass
coroutineClass.declarations += this
typeParameters = irFunction.typeParameters.map { parameter ->
parameter.copyToWithoutSuperTypes(this, origin = DECLARATION_ORIGIN_COROUTINE_IMPL)
.apply { superTypes += parameter.superTypes }
}
typeParameters = irFunction.typeParameters.map { parameter ->
parameter.copyToWithoutSuperTypes(this, origin = DECLARATION_ORIGIN_COROUTINE_IMPL)
.apply { superTypes += parameter.superTypes }
}
valueParameters = (unboundArgs + create1CompletionParameter).mapIndexed { index, parameter ->
parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index)
}
valueParameters = (unboundArgs + create1CompletionParameter).mapIndexed { index, parameter ->
parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index)
}
this.createDispatchReceiverParameter()
this.createDispatchReceiverParameter()
superFunctionSymbol?.let {
overriddenSymbols += it.owner.overriddenSymbols
overriddenSymbols += it
}
superFunctionSymbol?.let {
overriddenSymbols += it.owner.overriddenSymbols
overriddenSymbols += it
}
val thisReceiver = this.dispatchReceiverParameter!!
val thisReceiver = this.dispatchReceiverParameter!!
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
body = irBuilder.irBlockBody(startOffset, endOffset) {
+irReturn(
irCall(coroutineConstructor).apply {
var unboundIndex = 0
val unboundArgsSet = unboundArgs.toSet()
functionParameters.map {
if (unboundArgsSet.contains(it))
irGet(valueParameters[unboundIndex++])
else
irGetField(irGet(thisReceiver), argumentToPropertiesMap.getValue(it))
}.forEachIndexed { index, argument ->
putValueArgument(index, argument)
}
putValueArgument(functionParameters.size, irGet(valueParameters[unboundIndex]))
assert(unboundIndex == valueParameters.size - 1) {
"Not all arguments of <create> are used"
}
})
}
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
body = irBuilder.irBlockBody(startOffset, endOffset) {
+irReturn(
irCall(coroutineConstructor).apply {
var unboundIndex = 0
val unboundArgsSet = unboundArgs.toSet()
functionParameters.map {
if (unboundArgsSet.contains(it))
irGet(valueParameters[unboundIndex++])
else
irGetField(irGet(thisReceiver), argumentToPropertiesMap.getValue(it))
}.forEachIndexed { index, argument ->
putValueArgument(index, argument)
}
putValueArgument(functionParameters.size, irGet(valueParameters[unboundIndex]))
assert(unboundIndex == valueParameters.size - 1) {
"Not all arguments of <create> are used"
}
})
}
}
@@ -539,59 +526,49 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
functionInvokeFunctionSymbol: IrSimpleFunctionSymbol,
createFunction: IrFunction,
stateMachineFunction: IrFunction
) = WrappedSimpleFunctionDescriptor().let { d ->
IrFunctionImpl(
startOffset, endOffset,
DECLARATION_ORIGIN_COROUTINE_IMPL,
IrSimpleFunctionSymbolImpl(d),
Name.identifier("invoke"),
Visibilities.PROTECTED,
Modality.FINAL,
context.irBuiltIns.anyNType,
isInline = false,
isExternal = false,
isTailrec = false,
isSuspend = true,
isExpect = false,
isFakeOverride = false,
isOperator = false
).apply {
d.bind(this)
parent = coroutineClass
coroutineClass.declarations += this
): IrSimpleFunction = buildFun {
startOffset = irFunction.startOffset
endOffset = irFunction.endOffset
origin = DECLARATION_ORIGIN_COROUTINE_IMPL
name = Name.identifier("invoke")
visibility = Visibilities.PROTECTED
returnType = context.irBuiltIns.anyNType
isSuspend = true
}.apply {
parent = coroutineClass
coroutineClass.declarations += this
typeParameters = irFunction.typeParameters.map { parameter ->
parameter.copyToWithoutSuperTypes(this, origin = DECLARATION_ORIGIN_COROUTINE_IMPL)
.apply { superTypes += parameter.superTypes }
typeParameters = irFunction.typeParameters.map { parameter ->
parameter.copyToWithoutSuperTypes(this, origin = DECLARATION_ORIGIN_COROUTINE_IMPL)
.apply { superTypes += parameter.superTypes }
}
valueParameters = createFunction.valueParameters
// Skip completion - invoke() already has it implicitly as a suspend function.
.take(createFunction.valueParameters.size - 1)
.mapIndexed { index, parameter ->
parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index)
}
valueParameters = createFunction.valueParameters
// Skip completion - invoke() already has it implicitly as a suspend function.
.take(createFunction.valueParameters.size - 1)
.mapIndexed { index, parameter ->
parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index)
this.createDispatchReceiverParameter()
overriddenSymbols += functionInvokeFunctionSymbol
overriddenSymbols += suspendFunctionInvokeFunctionSymbol
val thisReceiver = dispatchReceiverParameter!!
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
body = irBuilder.irBlockBody(startOffset, endOffset) {
generateCoroutineStart(stateMachineFunction, irCall(createFunction).apply {
dispatchReceiver = irGet(thisReceiver)
valueParameters.forEachIndexed { index, parameter ->
putValueArgument(index, irGet(parameter))
}
this.createDispatchReceiverParameter()
overriddenSymbols += functionInvokeFunctionSymbol
overriddenSymbols += suspendFunctionInvokeFunctionSymbol
val thisReceiver = dispatchReceiverParameter!!
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
body = irBuilder.irBlockBody(startOffset, endOffset) {
generateCoroutineStart(stateMachineFunction, irCall(createFunction).apply {
dispatchReceiver = irGet(thisReceiver)
valueParameters.forEachIndexed { index, parameter ->
putValueArgument(index, irGet(parameter))
}
putValueArgument(
valueParameters.size,
irCall(getContinuationSymbol, getContinuationSymbol.owner.returnType, listOf(returnType))
)
})
}
putValueArgument(
valueParameters.size,
irCall(getContinuationSymbol, getContinuationSymbol.owner.returnType, listOf(returnType))
)
})
}
}
@@ -599,40 +576,36 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
stateMachineFunction: IrSimpleFunction,
coroutineClass: IrClass
): IrSimpleFunction {
val function = WrappedSimpleFunctionDescriptor().let { d ->
IrFunctionImpl(
startOffset, endOffset,
DECLARATION_ORIGIN_COROUTINE_IMPL,
IrSimpleFunctionSymbolImpl(d),
stateMachineFunction.name,
stateMachineFunction.visibility,
Modality.FINAL,
context.irBuiltIns.anyNType,
isInline = stateMachineFunction.isInline,
isExternal = stateMachineFunction.isExternal,
isTailrec = stateMachineFunction.isTailrec,
isSuspend = stateMachineFunction.isSuspend,
isExpect = stateMachineFunction.isExpect,
isFakeOverride = false,
isOperator = false
).apply {
d.bind(this)
parent = coroutineClass
coroutineClass.declarations += this
val function = buildFun {
startOffset = irFunction.startOffset
endOffset = irFunction.endOffset
origin = DECLARATION_ORIGIN_COROUTINE_IMPL
name = stateMachineFunction.name
visibility = stateMachineFunction.visibility
returnType = context.irBuiltIns.anyNType
isInline = stateMachineFunction.isInline
isExternal = stateMachineFunction.isExternal
isTailrec = stateMachineFunction.isTailrec
isSuspend = stateMachineFunction.isSuspend
isOperator = false
isExpect = stateMachineFunction.isExpect
isFakeOverride = false
}.apply {
parent = coroutineClass
coroutineClass.declarations += this
typeParameters = stateMachineFunction.typeParameters.map { parameter ->
parameter.copyToWithoutSuperTypes(this, origin = DECLARATION_ORIGIN_COROUTINE_IMPL)
.apply { superTypes += parameter.superTypes }
}
valueParameters = stateMachineFunction.valueParameters.mapIndexed { index, parameter ->
parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index)
}
this.createDispatchReceiverParameter()
overriddenSymbols += stateMachineFunction.symbol
typeParameters = stateMachineFunction.typeParameters.map { parameter ->
parameter.copyToWithoutSuperTypes(this, origin = DECLARATION_ORIGIN_COROUTINE_IMPL)
.apply { superTypes += parameter.superTypes }
}
valueParameters = stateMachineFunction.valueParameters.mapIndexed { index, parameter ->
parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index)
}
this.createDispatchReceiverParameter()
overriddenSymbols += stateMachineFunction.symbol
}
buildStateMachine(function, irFunction, argumentToPropertiesMap)
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
import org.jetbrains.kotlin.ir.builders.declarations.buildFunWithDescriptorForInlining
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
@@ -514,7 +514,7 @@ private fun IrFunction.generateDefaultsFunctionImpl(
visibility = newVisibility
}
is IrSimpleFunction ->
buildFunWithDescriptorForInlining(descriptor) {
buildFun(descriptor) {
updateFrom(this@generateDefaultsFunctionImpl)
name = Name.identifier("${this@generateDefaultsFunctionImpl.name}\$default")
origin = newOrigin
@@ -17,14 +17,13 @@ import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.Scope
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrConstructorImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.descriptors.WrappedClassConstructorDescriptor
import org.jetbrains.kotlin.ir.descriptors.WrappedFieldDescriptor
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
@@ -32,11 +31,9 @@ import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
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.*
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.impl.IrTypeAbbreviationImpl
import org.jetbrains.kotlin.ir.types.impl.IrUninitializedType
import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection
import org.jetbrains.kotlin.ir.util.constructedClass
import org.jetbrains.kotlin.ir.util.file
@@ -587,38 +584,22 @@ class LocalDeclarationsLowering(
private fun createLiftedDeclaration(localFunctionContext: LocalFunctionContext) {
val oldDeclaration = localFunctionContext.declaration
assert(oldDeclaration.dispatchReceiverParameter == null)
val memberOwner = localFunctionContext.ownerForLoweredDeclaration
val newDescriptor = WrappedSimpleFunctionDescriptor(oldDeclaration.descriptor)
val newSymbol = IrSimpleFunctionSymbolImpl(newDescriptor)
val newName = generateNameForLiftedDeclaration(oldDeclaration, memberOwner)
if (oldDeclaration.dispatchReceiverParameter != null) {
throw AssertionError("local functions must not have dispatch receiver")
}
val memberOwner = localFunctionContext.ownerForLoweredDeclaration
val newName = generateNameForLiftedDeclaration(oldDeclaration, memberOwner)
// TODO: consider using fields to access the closure of enclosing class.
val (capturedValues, capturedTypeParameters) = localFunctionContext.closure
val newDeclaration = IrFunctionImpl(
oldDeclaration.startOffset,
oldDeclaration.endOffset,
oldDeclaration.origin,
newSymbol,
newName,
Visibilities.PRIVATE,
Modality.FINAL,
returnType = IrUninitializedType,
isInline = oldDeclaration.isInline,
isExternal = oldDeclaration.isExternal,
isTailrec = oldDeclaration.isTailrec,
isSuspend = oldDeclaration.isSuspend,
isExpect = oldDeclaration.isExpect,
isFakeOverride = oldDeclaration.isFakeOverride,
isOperator = oldDeclaration.isOperator
)
newDescriptor.bind(newDeclaration)
val newDeclaration = buildFun(oldDeclaration.descriptor) {
updateFrom(oldDeclaration)
name = newName
visibility = Visibilities.PRIVATE
modality = Modality.FINAL
}
localFunctionContext.transformedDeclaration = newDeclaration
@@ -105,7 +105,7 @@ inline fun IrProperty.addGetter(builder: IrFunctionBuilder.() -> Unit = {}): IrS
IrFunctionBuilder().run {
name = Name.special("<get-${this@addGetter.name}>")
builder()
buildFun().also { getter ->
buildFunction().also { getter ->
this@addGetter.getter = getter
getter.correspondingPropertySymbol = this@addGetter.symbol
getter.parent = this@addGetter.parent
@@ -116,13 +116,16 @@ inline fun IrProperty.addSetter(builder: IrFunctionBuilder.() -> Unit = {}): IrS
IrFunctionBuilder().run {
name = Name.special("<set-${this@addSetter.name}>")
builder()
buildFun().also { setter ->
buildFunction().also { setter ->
this@addSetter.setter = setter
setter.parent = this@addSetter.parent
}
}
fun IrFunctionBuilder.buildFun(originalDescriptor: FunctionDescriptor? = null): IrSimpleFunction {
@PublishedApi
internal fun IrFunctionBuilder.buildFunction(originalDescriptor: FunctionDescriptor? = null): IrSimpleFunction {
// Inlining relies on descriptors for external declarations. When replacing a potentially external function (e.g. in an IrCall),
// we have to ensure that we keep information from the original descriptor so as not to break inlining.
val wrappedDescriptor = when (originalDescriptor) {
is DescriptorWithContainerSource -> WrappedFunctionDescriptorWithContainerSource(originalDescriptor.containerSource)
is PropertyGetterDescriptor -> WrappedPropertyGetterDescriptor(originalDescriptor.annotations, originalDescriptor.source)
@@ -134,8 +137,7 @@ fun IrFunctionBuilder.buildFun(originalDescriptor: FunctionDescriptor? = null):
startOffset, endOffset, origin,
IrSimpleFunctionSymbolImpl(wrappedDescriptor),
name, visibility, modality, returnType,
isInline = isInline, isExternal = isExternal, isTailrec = isTailrec, isSuspend = isSuspend, isExpect = isExpect,
isFakeOverride = isFakeOverride, isOperator = isOperator
isInline, isExternal, isTailrec, isSuspend, isOperator, isExpect, isFakeOverride
).also {
wrappedDescriptor.bind(it)
}
@@ -154,27 +156,14 @@ fun IrFunctionBuilder.buildConstructor(): IrConstructor {
}
}
/**
* Inlining relies on descriptors for external declarations. When replacing a
* potentially external function (e.g. in an IrCall) we have to ensure that we keep
* information from the original descriptor so as not to break inlining.
*/
inline fun buildFunWithDescriptorForInlining(
originalDescriptor: FunctionDescriptor, builder: IrFunctionBuilder.() -> Unit
): IrSimpleFunction =
inline fun buildFun(originalDescriptor: FunctionDescriptor? = null, builder: IrFunctionBuilder.() -> Unit): IrSimpleFunction =
IrFunctionBuilder().run {
builder()
buildFun(originalDescriptor)
}
inline fun buildFun(builder: IrFunctionBuilder.() -> Unit): IrSimpleFunction =
IrFunctionBuilder().run {
builder()
buildFun()
buildFunction(originalDescriptor)
}
inline fun IrDeclarationContainer.addFunction(builder: IrFunctionBuilder.() -> Unit): IrSimpleFunction =
buildFun(builder).also { function ->
buildFun(null, builder).also { function ->
declarations.add(function)
function.parent = this@addFunction
}