Refactor secondary constructor lowering using new builders
This commit is contained in:
+78
-148
@@ -6,25 +6,19 @@
|
|||||||
package org.jetbrains.kotlin.ir.backend.js.lower
|
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
|
||||||
import org.jetbrains.kotlin.descriptors.impl.LazyClassReceiverParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.LazyClassReceiverParameterDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
|
||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.ir.backend.js.descriptors.JsSymbolBuilder
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.descriptors.initialize
|
||||||
|
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
|
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.isPrimary
|
import org.jetbrains.kotlin.ir.backend.js.utils.isPrimary
|
||||||
import org.jetbrains.kotlin.ir.builders.*
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
||||||
@@ -32,14 +26,11 @@ import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
|||||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||||
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
|
||||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import org.jetbrains.kotlin.name.Name
|
|
||||||
|
|
||||||
class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransformerVoid(), FileLoweringPass {
|
class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransformerVoid(), FileLoweringPass {
|
||||||
|
|
||||||
@@ -125,142 +116,83 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createInitConstructor(declaration: IrConstructor, name: String): IrSimpleFunction {
|
private fun createInitConstructor(declaration: IrConstructor, name: String): IrSimpleFunction =
|
||||||
// TODO delegate name generation
|
JsSymbolBuilder.copyFunctionSymbol(declaration.symbol, "${name}_\$Init\$").let {
|
||||||
val actualName = "${name}_\$Init\$"
|
|
||||||
|
|
||||||
//region TODO: get rid of descriptors and replace them with direct symbol creation
|
val thisSymbol =
|
||||||
val thisParamDesc = ValueParameterDescriptorImpl(
|
JsSymbolBuilder.buildValueParameter(it, declaration.valueParameters.size, declaration.returnType, "\$this")
|
||||||
declaration.descriptor,
|
|
||||||
null,
|
|
||||||
declaration.descriptor.valueParameters.size,
|
|
||||||
Annotations.EMPTY,
|
|
||||||
Name.identifier("\$this"),
|
|
||||||
declaration.descriptor.returnType,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
false,
|
|
||||||
null,
|
|
||||||
SourceElement.NO_SOURCE
|
|
||||||
)
|
|
||||||
|
|
||||||
val functionDescriptor = SimpleFunctionDescriptorImpl.create(
|
it.initialize(
|
||||||
declaration.descriptor.containingDeclaration,
|
dispatchParameterDescriptor = declaration.descriptor.dispatchReceiverParameter,
|
||||||
declaration.descriptor.annotations,
|
typeParameters = declaration.descriptor.typeParameters,
|
||||||
Name.identifier(actualName),
|
valueParameters = declaration.descriptor.valueParameters + thisSymbol.descriptor as ValueParameterDescriptor,
|
||||||
declaration.descriptor.kind,
|
type = declaration.descriptor.returnType,
|
||||||
declaration.descriptor.source
|
modality = declaration.descriptor.modality,
|
||||||
).initialize(
|
visibility = declaration.descriptor.visibility
|
||||||
null,
|
|
||||||
declaration.descriptor.dispatchReceiverParameter,
|
|
||||||
declaration.descriptor.typeParameters,
|
|
||||||
declaration.descriptor.valueParameters + thisParamDesc,
|
|
||||||
declaration.returnType,
|
|
||||||
declaration.descriptor.modality,
|
|
||||||
declaration.visibility
|
|
||||||
)
|
|
||||||
//endregion
|
|
||||||
|
|
||||||
|
|
||||||
val thisSymbol = IrValueParameterSymbolImpl(thisParamDesc)
|
|
||||||
val functionSymbol = IrSimpleFunctionSymbolImpl(functionDescriptor)
|
|
||||||
|
|
||||||
val thisParam = IrValueParameterImpl(
|
|
||||||
UNDEFINED_OFFSET,
|
|
||||||
UNDEFINED_OFFSET,
|
|
||||||
JsLoweredDeclarationOrigin.SECONDARY_CTOR_RECEIVER,
|
|
||||||
thisSymbol
|
|
||||||
)
|
|
||||||
|
|
||||||
val constructor = IrFunctionImpl(
|
|
||||||
declaration.startOffset, declaration.endOffset,
|
|
||||||
declaration.origin, functionSymbol
|
|
||||||
)
|
|
||||||
|
|
||||||
var statements = (declaration.body as IrStatementContainer).statements.map { it.deepCopyWithSymbols() }
|
|
||||||
val fixer = ThisUsageReplaceTransformer(functionSymbol, thisSymbol)
|
|
||||||
for (stmt in statements) {
|
|
||||||
stmt.transformChildrenVoid(fixer)
|
|
||||||
}
|
|
||||||
|
|
||||||
val retStmt = IrReturnImpl(
|
|
||||||
UNDEFINED_OFFSET,
|
|
||||||
UNDEFINED_OFFSET,
|
|
||||||
functionSymbol,
|
|
||||||
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, thisSymbol)
|
|
||||||
)
|
|
||||||
|
|
||||||
statements += retStmt
|
|
||||||
val newBody = IrBlockBodyImpl(declaration.body!!.startOffset, declaration.body!!.endOffset, statements)
|
|
||||||
|
|
||||||
constructor.valueParameters += declaration.valueParameters
|
|
||||||
constructor.typeParameters += declaration.typeParameters
|
|
||||||
constructor.parent = declaration.parent
|
|
||||||
constructor.valueParameters += thisParam
|
|
||||||
constructor.body = newBody
|
|
||||||
|
|
||||||
return constructor
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun createCreateConstructor(ctorOrig: IrConstructor, ctorImpl: IrSimpleFunction, name: String): IrSimpleFunction {
|
|
||||||
// TODO delegate name generation
|
|
||||||
val actualName = "${name}_\$Create\$"
|
|
||||||
|
|
||||||
//region TODO: descriptor -> symbol
|
|
||||||
val functionDescriptor = SimpleFunctionDescriptorImpl.create(
|
|
||||||
ctorOrig.descriptor,
|
|
||||||
ctorOrig.descriptor.annotations,
|
|
||||||
Name.identifier(actualName),
|
|
||||||
ctorOrig.descriptor.kind,
|
|
||||||
ctorOrig.descriptor.source
|
|
||||||
).initialize(
|
|
||||||
null,
|
|
||||||
ctorOrig.descriptor.dispatchReceiverParameter,
|
|
||||||
ctorOrig.descriptor.typeParameters,
|
|
||||||
ctorOrig.descriptor.valueParameters,
|
|
||||||
ctorOrig.returnType,
|
|
||||||
ctorOrig.descriptor.modality,
|
|
||||||
ctorOrig.visibility
|
|
||||||
)
|
|
||||||
//endregion
|
|
||||||
|
|
||||||
val functionSymbol = IrSimpleFunctionSymbolImpl(functionDescriptor)
|
|
||||||
|
|
||||||
val constructor = IrFunctionImpl(
|
|
||||||
ctorOrig.startOffset, ctorOrig.endOffset,
|
|
||||||
ctorOrig.origin, functionSymbol
|
|
||||||
)
|
|
||||||
|
|
||||||
val createFunctionIntrinsic = context.intrinsics.jsObjectCreate
|
|
||||||
val irBuilder = context.createIrBuilder(functionSymbol, ctorOrig.startOffset, ctorOrig.endOffset).irBlockBody {
|
|
||||||
val thisVar = irTemporaryVar(
|
|
||||||
IrCallImpl(
|
|
||||||
startOffset,
|
|
||||||
endOffset,
|
|
||||||
ctorOrig.returnType,
|
|
||||||
createFunctionIntrinsic.symbol,
|
|
||||||
createFunctionIntrinsic.descriptor,
|
|
||||||
mapOf(createFunctionIntrinsic.typeParameters[0].descriptor to ctorOrig.returnType)
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
+irReturn(
|
|
||||||
irCall(ctorImpl.symbol).apply {
|
val thisParam = JsIrBuilder.buildValueParameter(thisSymbol)
|
||||||
ctorOrig.valueParameters.forEachIndexed { index, irValueParameter ->
|
|
||||||
putValueArgument(index, irGet(irValueParameter.symbol))
|
return IrFunctionImpl(
|
||||||
}
|
declaration.startOffset, declaration.endOffset,
|
||||||
putValueArgument(ctorOrig.valueParameters.size, irGet(thisVar.symbol))
|
declaration.origin, it
|
||||||
|
).apply {
|
||||||
|
val retStmt = JsIrBuilder.buildReturn(it, JsIrBuilder.buildGetValue(thisSymbol))
|
||||||
|
val statements = (declaration.body as IrStatementContainer).statements
|
||||||
|
|
||||||
|
valueParameters += (declaration.valueParameters + thisParam)
|
||||||
|
typeParameters += declaration.typeParameters
|
||||||
|
parent = declaration.parent
|
||||||
|
body = JsIrBuilder.buildBlockBody(statements + retStmt).apply {
|
||||||
|
transformChildrenVoid(ThisUsageReplaceTransformer(it, thisSymbol))
|
||||||
}
|
}
|
||||||
)
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor.valueParameters += ctorOrig.valueParameters
|
|
||||||
constructor.typeParameters += ctorOrig.typeParameters
|
|
||||||
constructor.parent = ctorOrig.parent
|
|
||||||
constructor.body = IrBlockBodyImpl(ctorOrig.body?.startOffset!!, ctorOrig.body?.endOffset!!, irBuilder.statements)
|
|
||||||
|
|
||||||
return constructor
|
private fun createCreateConstructor(ctorOrig: IrConstructor, ctorImpl: IrSimpleFunction, name: String): IrSimpleFunction =
|
||||||
}
|
JsSymbolBuilder.copyFunctionSymbol(ctorOrig.symbol, "${name}_\$Create\$").let {
|
||||||
|
it.initialize(
|
||||||
|
dispatchParameterDescriptor = ctorOrig.descriptor.dispatchReceiverParameter,
|
||||||
|
typeParameters = ctorOrig.descriptor.typeParameters,
|
||||||
|
valueParameters = ctorOrig.descriptor.valueParameters,
|
||||||
|
type = ctorOrig.returnType,
|
||||||
|
modality = ctorOrig.descriptor.modality,
|
||||||
|
visibility = ctorOrig.visibility
|
||||||
|
)
|
||||||
|
|
||||||
|
return IrFunctionImpl(
|
||||||
|
ctorOrig.startOffset, ctorOrig.endOffset,
|
||||||
|
ctorOrig.origin, it
|
||||||
|
).apply {
|
||||||
|
|
||||||
|
valueParameters += ctorOrig.valueParameters
|
||||||
|
typeParameters += ctorOrig.typeParameters
|
||||||
|
parent = ctorOrig.parent
|
||||||
|
|
||||||
|
val returnType = ctorOrig.returnType
|
||||||
|
val createFunctionIntrinsic = context.intrinsics.jsObjectCreate
|
||||||
|
val irCreateCall = JsIrBuilder.buildCall(
|
||||||
|
createFunctionIntrinsic.symbol,
|
||||||
|
returnType,
|
||||||
|
mapOf(createFunctionIntrinsic.typeParameters[0].descriptor to returnType)
|
||||||
|
)
|
||||||
|
val irDelegateCall = JsIrBuilder.buildCall(ctorImpl.symbol).also {
|
||||||
|
for (i in 0 until valueParameters.size) {
|
||||||
|
it.putValueArgument(i, JsIrBuilder.buildGetValue(valueParameters[i].symbol))
|
||||||
|
}
|
||||||
|
// valueParameters.forEachIndexed { i, p -> it.putValueArgument(i, JsIrBuilder.buildGetValue(p.symbol)) }
|
||||||
|
it.putValueArgument(ctorOrig.valueParameters.size, irCreateCall)
|
||||||
|
|
||||||
|
// typeParameters.mapIndexed { i, t -> ctorImpl.typeParameters[i].descriptor -> }
|
||||||
|
}
|
||||||
|
val irReturn = JsIrBuilder.buildReturn(it, irDelegateCall)
|
||||||
|
|
||||||
|
|
||||||
|
body = JsIrBuilder.buildBlockBody(listOf(irReturn))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class CallsiteRedirectionTransformer(val context: JsIrBackendContext) : IrElementTransformer<IrFunction?> {
|
class CallsiteRedirectionTransformer(val context: JsIrBackendContext) : IrElementTransformer<IrFunction?> {
|
||||||
@@ -314,16 +246,14 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
|
|||||||
private fun redirectCall(
|
private fun redirectCall(
|
||||||
call: IrFunctionAccessExpression,
|
call: IrFunctionAccessExpression,
|
||||||
newTarget: IrSimpleFunctionSymbol
|
newTarget: IrSimpleFunctionSymbol
|
||||||
): IrCallImpl {
|
) = IrCallImpl(call.startOffset, call.endOffset, newTarget).apply {
|
||||||
val newCall = IrCallImpl(call.startOffset, call.endOffset, newTarget)
|
|
||||||
|
|
||||||
newCall.copyTypeArgumentsFrom(call)
|
copyTypeArgumentsFrom(call)
|
||||||
|
|
||||||
for (i in 0 until call.valueArgumentsCount) {
|
for (i in 0 until call.valueArgumentsCount) {
|
||||||
newCall.putValueArgument(i, call.getValueArgument(i))
|
putValueArgument(i, call.getValueArgument(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
return newCall
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user