Refactor secondary constructor lowering using new builders

This commit is contained in:
Roman Artemev
2018-04-18 22:31:42 +03:00
parent 752cbf2714
commit 17ee38a0b7
@@ -6,25 +6,19 @@
package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.descriptors.SourceElement
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
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.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
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.isPrimary
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
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.impl.IrBlockBodyImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
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.IrSimpleFunctionSymbol
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.util.deepCopyWithSymbols
import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
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 {
// TODO delegate name generation
val actualName = "${name}_\$Init\$"
private fun createInitConstructor(declaration: IrConstructor, name: String): IrSimpleFunction =
JsSymbolBuilder.copyFunctionSymbol(declaration.symbol, "${name}_\$Init\$").let {
//region TODO: get rid of descriptors and replace them with direct symbol creation
val thisParamDesc = ValueParameterDescriptorImpl(
declaration.descriptor,
null,
declaration.descriptor.valueParameters.size,
Annotations.EMPTY,
Name.identifier("\$this"),
declaration.descriptor.returnType,
false,
false,
false,
null,
SourceElement.NO_SOURCE
)
val thisSymbol =
JsSymbolBuilder.buildValueParameter(it, declaration.valueParameters.size, declaration.returnType, "\$this")
val functionDescriptor = SimpleFunctionDescriptorImpl.create(
declaration.descriptor.containingDeclaration,
declaration.descriptor.annotations,
Name.identifier(actualName),
declaration.descriptor.kind,
declaration.descriptor.source
).initialize(
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)
)
it.initialize(
dispatchParameterDescriptor = declaration.descriptor.dispatchReceiverParameter,
typeParameters = declaration.descriptor.typeParameters,
valueParameters = declaration.descriptor.valueParameters + thisSymbol.descriptor as ValueParameterDescriptor,
type = declaration.descriptor.returnType,
modality = declaration.descriptor.modality,
visibility = declaration.descriptor.visibility
)
+irReturn(
irCall(ctorImpl.symbol).apply {
ctorOrig.valueParameters.forEachIndexed { index, irValueParameter ->
putValueArgument(index, irGet(irValueParameter.symbol))
}
putValueArgument(ctorOrig.valueParameters.size, irGet(thisVar.symbol))
val thisParam = JsIrBuilder.buildValueParameter(thisSymbol)
return IrFunctionImpl(
declaration.startOffset, declaration.endOffset,
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?> {
@@ -314,16 +246,14 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
private fun redirectCall(
call: IrFunctionAccessExpression,
newTarget: IrSimpleFunctionSymbol
): IrCallImpl {
val newCall = IrCallImpl(call.startOffset, call.endOffset, newTarget)
) = IrCallImpl(call.startOffset, call.endOffset, newTarget).apply {
newCall.copyTypeArgumentsFrom(call)
copyTypeArgumentsFrom(call)
for (i in 0 until call.valueArgumentsCount) {
newCall.putValueArgument(i, call.getValueArgument(i))
putValueArgument(i, call.getValueArgument(i))
}
return newCall
}
}
}