IR: do not copy calls/references in ExpectSymbolTransformer

This is just a refactoring/optimization that makes use of the fact that
IrCall.symbol and other similar fields are now mutable.
This commit is contained in:
Alexander Udalov
2023-06-16 23:28:44 +02:00
committed by Space Team
parent 978553c513
commit bb4d25dfc9
3 changed files with 46 additions and 101 deletions
@@ -115,9 +115,8 @@ fun generateIrForKlibSerialization(
} }
if (configuration.get(CommonConfigurationKeys.EXPECT_ACTUAL_LINKER) != true) { if (configuration.get(CommonConfigurationKeys.EXPECT_ACTUAL_LINKER) != true) {
moduleFragment.transform(ExpectDeclarationRemover(psi2IrContext.symbolTable, false), null) moduleFragment.accept(ExpectDeclarationRemover(psi2IrContext.symbolTable, false), null)
} }
return moduleFragment to pluginContext return moduleFragment to pluginContext
} }
@@ -13,21 +13,18 @@ import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.IrDeclaration import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.util.copyTypeAndValueArgumentsFrom import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.util.irCall
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
/** /**
* [ExpectSymbolTransformer] replaces `expect` symbols in expressions with `actual` symbols. An `actual` symbol must be provided by * [ExpectSymbolTransformer] replaces `expect` symbols in expressions with `actual` symbols. An `actual` symbol must be provided by
* overriding [getActualClass], [getActualProperty], [getActualConstructor], and [getActualFunction]. * overriding [getActualClass], [getActualProperty], [getActualConstructor], and [getActualFunction].
*/ */
@OptIn(ObsoleteDescriptorBasedAPI::class) @OptIn(ObsoleteDescriptorBasedAPI::class)
abstract class ExpectSymbolTransformer : IrElementTransformerVoid() { abstract class ExpectSymbolTransformer : IrElementVisitorVoid {
protected abstract fun getActualClass(descriptor: ClassDescriptor): IrClassSymbol? protected abstract fun getActualClass(descriptor: ClassDescriptor): IrClassSymbol?
@@ -49,112 +46,60 @@ abstract class ExpectSymbolTransformer : IrElementTransformerVoid() {
*/ */
protected open fun isTargetDeclaration(declaration: IrDeclaration): Boolean = declaration.isExpect protected open fun isTargetDeclaration(declaration: IrDeclaration): Boolean = declaration.isExpect
override fun visitElement(element: IrElement): IrElement { override fun visitElement(element: IrElement) {
element.transformChildrenVoid() element.acceptChildren(this, null)
return element
} }
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression { override fun visitConstructorCall(expression: IrConstructorCall) {
val nExpression = super.visitConstructorCall(expression) as IrConstructorCall super.visitConstructorCall(expression)
if (!isTargetDeclaration(nExpression.symbol.owner)) return nExpression if (!isTargetDeclaration(expression.symbol.owner)) return
val newCallee = getActualConstructor(nExpression.symbol.descriptor) ?: return nExpression expression.symbol = getActualConstructor(expression.symbol.descriptor) ?: return
with(nExpression) {
return IrConstructorCallImpl(
startOffset, endOffset, type, newCallee, typeArgumentsCount, constructorTypeArgumentsCount, valueArgumentsCount, origin
).also {
it.attributeOwnerId = attributeOwnerId
it.copyTypeAndValueArgumentsFrom(nExpression)
}
}
} }
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression { override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) {
val nExpression = super.visitDelegatingConstructorCall(expression) as IrDelegatingConstructorCall super.visitDelegatingConstructorCall(expression)
if (!isTargetDeclaration(nExpression.symbol.owner)) return nExpression if (!isTargetDeclaration(expression.symbol.owner)) return
val newCallee = getActualConstructor(nExpression.symbol.descriptor) ?: return nExpression expression.symbol = getActualConstructor(expression.symbol.descriptor) ?: return
with(nExpression) {
return IrDelegatingConstructorCallImpl(
startOffset, endOffset, type, newCallee, typeArgumentsCount, valueArgumentsCount
).also {
it.attributeOwnerId = attributeOwnerId
it.copyTypeAndValueArgumentsFrom(nExpression)
}
}
} }
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression { override fun visitEnumConstructorCall(expression: IrEnumConstructorCall) {
val nExpression = super.visitEnumConstructorCall(expression) as IrEnumConstructorCall super.visitEnumConstructorCall(expression)
if (!isTargetDeclaration(nExpression.symbol.owner)) return nExpression if (!isTargetDeclaration(expression.symbol.owner)) return
val newCallee = getActualConstructor(nExpression.symbol.descriptor) ?: return nExpression expression.symbol = getActualConstructor(expression.symbol.descriptor) ?: return
with(nExpression) {
return IrEnumConstructorCallImpl(
startOffset, endOffset, type, newCallee, typeArgumentsCount, valueArgumentsCount
).also {
it.attributeOwnerId = attributeOwnerId
it.copyTypeAndValueArgumentsFrom(nExpression)
}
}
} }
override fun visitCall(expression: IrCall): IrExpression { override fun visitCall(expression: IrCall) {
val nExpression = super.visitCall(expression) as IrCall super.visitCall(expression)
if (!isTargetDeclaration(nExpression.symbol.owner)) return nExpression if (!isTargetDeclaration(expression.symbol.owner)) return
val newCallee = getActualFunction(nExpression.symbol.descriptor) ?: return nExpression expression.symbol = getActualFunction(expression.symbol.descriptor) ?: return
return irCall(nExpression, newCallee).also {
it.attributeOwnerId = nExpression.attributeOwnerId
}
} }
override fun visitPropertyReference(expression: IrPropertyReference): IrExpression { override fun visitPropertyReference(expression: IrPropertyReference) {
val nExpression = super.visitPropertyReference(expression) as IrPropertyReference super.visitPropertyReference(expression)
if (!isTargetDeclaration(nExpression.symbol.owner)) return nExpression if (!isTargetDeclaration(expression.symbol.owner)) return
val (newSymbol, newGetter, newSetter) = getActualProperty(nExpression.symbol.descriptor) ?: return nExpression val (newSymbol, newGetter, newSetter) = getActualProperty(expression.symbol.descriptor) ?: return
with(nExpression) { expression.symbol = newSymbol
return IrPropertyReferenceImpl( expression.getter = newGetter
startOffset, endOffset, type, expression.setter = newSetter
newSymbol, typeArgumentsCount,
field, newGetter, newSetter,
origin
).also {
it.attributeOwnerId = attributeOwnerId
copyTypeArgumentsFrom(nExpression)
it.dispatchReceiver = dispatchReceiver
it.extensionReceiver = extensionReceiver
}
}
} }
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { override fun visitFunctionReference(expression: IrFunctionReference) {
val nExpression = super.visitFunctionReference(expression) as IrFunctionReference super.visitFunctionReference(expression)
if (!isTargetDeclaration(nExpression.symbol.owner)) return nExpression if (!isTargetDeclaration(expression.symbol.owner)) return
val newCallee = getActualFunction(nExpression.symbol.descriptor) ?: return nExpression expression.symbol = getActualFunction(expression.symbol.descriptor) ?: return
with(nExpression) {
return IrFunctionReferenceImpl(
startOffset, endOffset, type, newCallee, typeArgumentsCount, valueArgumentsCount, reflectionTarget, origin
).also {
it.attributeOwnerId = attributeOwnerId
it.copyTypeArgumentsFrom(nExpression)
it.dispatchReceiver = dispatchReceiver
it.extensionReceiver = extensionReceiver
}
}
} }
override fun visitClassReference(expression: IrClassReference): IrExpression { override fun visitClassReference(expression: IrClassReference) {
val nExpression = super.visitClassReference(expression) as IrClassReference super.visitClassReference(expression)
val oldSymbol = nExpression.symbol as? IrClassSymbol ?: return nExpression val oldSymbol = expression.symbol as? IrClassSymbol ?: return
if (!isTargetDeclaration(oldSymbol.owner)) return nExpression if (!isTargetDeclaration(oldSymbol.owner)) return
val newSymbol = getActualClass(oldSymbol.descriptor) ?: return nExpression expression.symbol = getActualClass(oldSymbol.descriptor) ?: return
with(nExpression) {
return IrClassReferenceImpl(startOffset, endOffset, type, newSymbol, classType)
}
} }
} }
@@ -9,13 +9,14 @@ import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.FileLoweringPass import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.ir.ExpectSymbolTransformer import org.jetbrains.kotlin.backend.common.ir.ExpectSymbolTransformer
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
import org.jetbrains.kotlin.ir.expressions.IrGetValue import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.extractTypeParameters import org.jetbrains.kotlin.ir.types.extractTypeParameters
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
@@ -27,8 +28,8 @@ import kotlin.collections.set
// `doRemove` means should expect-declaration be removed from IR // `doRemove` means should expect-declaration be removed from IR
@OptIn(ObsoleteDescriptorBasedAPI::class) @OptIn(ObsoleteDescriptorBasedAPI::class)
open class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, private val doRemove: Boolean) open class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, private val doRemove: Boolean) : ExpectSymbolTransformer(),
: ExpectSymbolTransformer(), FileLoweringPass { FileLoweringPass {
constructor(context: BackendContext) : this(context.ir.symbols.externalSymbolTable, true) constructor(context: BackendContext) : this(context.ir.symbols.externalSymbolTable, true)
@@ -38,16 +39,16 @@ open class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, priva
visitFile(irFile) visitFile(irFile)
} }
override fun visitFile(declaration: IrFile): IrFile { override fun visitFile(declaration: IrFile) {
if (doRemove) { if (doRemove) {
declaration.declarations.removeAll { shouldRemoveTopLevelDeclaration(it) } declaration.declarations.removeAll { shouldRemoveTopLevelDeclaration(it) }
} }
return super.visitFile(declaration) super.visitFile(declaration)
} }
override fun visitValueParameter(declaration: IrValueParameter): IrStatement { override fun visitValueParameter(declaration: IrValueParameter) {
tryCopyDefaultArguments(declaration) tryCopyDefaultArguments(declaration)
return super.visitValueParameter(declaration) super.visitValueParameter(declaration)
} }
fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? { fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {