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) {
moduleFragment.transform(ExpectDeclarationRemover(psi2IrContext.symbolTable, false), null)
moduleFragment.accept(ExpectDeclarationRemover(psi2IrContext.symbolTable, false), null)
}
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.declarations.IrDeclaration
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.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.util.copyTypeAndValueArgumentsFrom
import org.jetbrains.kotlin.ir.util.irCall
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
/**
* [ExpectSymbolTransformer] replaces `expect` symbols in expressions with `actual` symbols. An `actual` symbol must be provided by
* overriding [getActualClass], [getActualProperty], [getActualConstructor], and [getActualFunction].
*/
@OptIn(ObsoleteDescriptorBasedAPI::class)
abstract class ExpectSymbolTransformer : IrElementTransformerVoid() {
abstract class ExpectSymbolTransformer : IrElementVisitorVoid {
protected abstract fun getActualClass(descriptor: ClassDescriptor): IrClassSymbol?
@@ -49,112 +46,60 @@ abstract class ExpectSymbolTransformer : IrElementTransformerVoid() {
*/
protected open fun isTargetDeclaration(declaration: IrDeclaration): Boolean = declaration.isExpect
override fun visitElement(element: IrElement): IrElement {
element.transformChildrenVoid()
return element
override fun visitElement(element: IrElement) {
element.acceptChildren(this, null)
}
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
val nExpression = super.visitConstructorCall(expression) as IrConstructorCall
if (!isTargetDeclaration(nExpression.symbol.owner)) return nExpression
override fun visitConstructorCall(expression: IrConstructorCall) {
super.visitConstructorCall(expression)
if (!isTargetDeclaration(expression.symbol.owner)) return
val newCallee = getActualConstructor(nExpression.symbol.descriptor) ?: return nExpression
with(nExpression) {
return IrConstructorCallImpl(
startOffset, endOffset, type, newCallee, typeArgumentsCount, constructorTypeArgumentsCount, valueArgumentsCount, origin
).also {
it.attributeOwnerId = attributeOwnerId
it.copyTypeAndValueArgumentsFrom(nExpression)
}
}
expression.symbol = getActualConstructor(expression.symbol.descriptor) ?: return
}
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
val nExpression = super.visitDelegatingConstructorCall(expression) as IrDelegatingConstructorCall
if (!isTargetDeclaration(nExpression.symbol.owner)) return nExpression
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall) {
super.visitDelegatingConstructorCall(expression)
if (!isTargetDeclaration(expression.symbol.owner)) return
val newCallee = getActualConstructor(nExpression.symbol.descriptor) ?: return nExpression
with(nExpression) {
return IrDelegatingConstructorCallImpl(
startOffset, endOffset, type, newCallee, typeArgumentsCount, valueArgumentsCount
).also {
it.attributeOwnerId = attributeOwnerId
it.copyTypeAndValueArgumentsFrom(nExpression)
}
}
expression.symbol = getActualConstructor(expression.symbol.descriptor) ?: return
}
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression {
val nExpression = super.visitEnumConstructorCall(expression) as IrEnumConstructorCall
if (!isTargetDeclaration(nExpression.symbol.owner)) return nExpression
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall) {
super.visitEnumConstructorCall(expression)
if (!isTargetDeclaration(expression.symbol.owner)) return
val newCallee = getActualConstructor(nExpression.symbol.descriptor) ?: return nExpression
with(nExpression) {
return IrEnumConstructorCallImpl(
startOffset, endOffset, type, newCallee, typeArgumentsCount, valueArgumentsCount
).also {
it.attributeOwnerId = attributeOwnerId
it.copyTypeAndValueArgumentsFrom(nExpression)
}
}
expression.symbol = getActualConstructor(expression.symbol.descriptor) ?: return
}
override fun visitCall(expression: IrCall): IrExpression {
val nExpression = super.visitCall(expression) as IrCall
if (!isTargetDeclaration(nExpression.symbol.owner)) return nExpression
override fun visitCall(expression: IrCall) {
super.visitCall(expression)
if (!isTargetDeclaration(expression.symbol.owner)) return
val newCallee = getActualFunction(nExpression.symbol.descriptor) ?: return nExpression
return irCall(nExpression, newCallee).also {
it.attributeOwnerId = nExpression.attributeOwnerId
}
expression.symbol = getActualFunction(expression.symbol.descriptor) ?: return
}
override fun visitPropertyReference(expression: IrPropertyReference): IrExpression {
val nExpression = super.visitPropertyReference(expression) as IrPropertyReference
if (!isTargetDeclaration(nExpression.symbol.owner)) return nExpression
override fun visitPropertyReference(expression: IrPropertyReference) {
super.visitPropertyReference(expression)
if (!isTargetDeclaration(expression.symbol.owner)) return
val (newSymbol, newGetter, newSetter) = getActualProperty(nExpression.symbol.descriptor) ?: return nExpression
with(nExpression) {
return IrPropertyReferenceImpl(
startOffset, endOffset, type,
newSymbol, typeArgumentsCount,
field, newGetter, newSetter,
origin
).also {
it.attributeOwnerId = attributeOwnerId
copyTypeArgumentsFrom(nExpression)
it.dispatchReceiver = dispatchReceiver
it.extensionReceiver = extensionReceiver
}
}
val (newSymbol, newGetter, newSetter) = getActualProperty(expression.symbol.descriptor) ?: return
expression.symbol = newSymbol
expression.getter = newGetter
expression.setter = newSetter
}
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
val nExpression = super.visitFunctionReference(expression) as IrFunctionReference
if (!isTargetDeclaration(nExpression.symbol.owner)) return nExpression
override fun visitFunctionReference(expression: IrFunctionReference) {
super.visitFunctionReference(expression)
if (!isTargetDeclaration(expression.symbol.owner)) return
val newCallee = getActualFunction(nExpression.symbol.descriptor) ?: return nExpression
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
}
}
expression.symbol = getActualFunction(expression.symbol.descriptor) ?: return
}
override fun visitClassReference(expression: IrClassReference): IrExpression {
val nExpression = super.visitClassReference(expression) as IrClassReference
val oldSymbol = nExpression.symbol as? IrClassSymbol ?: return nExpression
if (!isTargetDeclaration(oldSymbol.owner)) return nExpression
override fun visitClassReference(expression: IrClassReference) {
super.visitClassReference(expression)
val oldSymbol = expression.symbol as? IrClassSymbol ?: return
if (!isTargetDeclaration(oldSymbol.owner)) return
val newSymbol = getActualClass(oldSymbol.descriptor) ?: return nExpression
with(nExpression) {
return IrClassReferenceImpl(startOffset, endOffset, type, newSymbol, classType)
}
expression.symbol = getActualClass(oldSymbol.descriptor) ?: return
}
}
@@ -9,13 +9,14 @@ import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.ir.ExpectSymbolTransformer
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
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.util.*
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
@@ -27,8 +28,8 @@ import kotlin.collections.set
// `doRemove` means should expect-declaration be removed from IR
@OptIn(ObsoleteDescriptorBasedAPI::class)
open class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, private val doRemove: Boolean)
: ExpectSymbolTransformer(), FileLoweringPass {
open class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, private val doRemove: Boolean) : ExpectSymbolTransformer(),
FileLoweringPass {
constructor(context: BackendContext) : this(context.ir.symbols.externalSymbolTable, true)
@@ -38,16 +39,16 @@ open class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, priva
visitFile(irFile)
}
override fun visitFile(declaration: IrFile): IrFile {
override fun visitFile(declaration: IrFile) {
if (doRemove) {
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)
return super.visitValueParameter(declaration)
super.visitValueParameter(declaration)
}
fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {