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
@@ -10,18 +10,16 @@ import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter
import org.jetbrains.kotlin.ir.builders.declarations.buildVariable
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrAnonymousInitializerImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.descriptors.WrappedClassDescriptor
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.*
import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.name.Name
@@ -103,28 +101,21 @@ object JsIrBuilder {
isOperator: Boolean = false,
isFakeOverride: Boolean = false,
origin: IrDeclarationOrigin = SYNTHESIZED_DECLARATION
): IrSimpleFunction {
val descriptor = WrappedSimpleFunctionDescriptor()
return IrFunctionImpl(
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
origin,
IrSimpleFunctionSymbolImpl(descriptor),
name,
visibility,
modality,
returnType,
isInline = isInline,
isExternal = isExternal,
isTailrec = isTailrec,
isSuspend = isSuspend,
isExpect = isExpect,
isFakeOverride = isFakeOverride,
isOperator = isOperator
).also {
descriptor.bind(it)
it.parent = parent
}
): IrSimpleFunction = buildFun {
this.origin = origin
this.name = name
this.visibility = visibility
this.modality = modality
this.returnType = returnType
this.isInline = isInline
this.isExternal = isExternal
this.isTailrec = isTailrec
this.isSuspend = isSuspend
this.isOperator = isOperator
this.isExpect = isExpect
this.isFakeOverride = isFakeOverride
}.also {
it.parent = parent
}
fun buildAnonymousInitializer() =
@@ -7,13 +7,11 @@ package org.jetbrains.kotlin.ir.backend.js.lower
import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
import org.jetbrains.kotlin.ir.descriptors.WrappedSimpleFunctionDescriptor
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrSetField
@@ -21,7 +19,6 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.util.transformFlat
import org.jetbrains.kotlin.name.Name
@@ -88,22 +85,18 @@ class CreateScriptFunctionsPhase(val context: CommonBackendContext) : FileLoweri
return (irScript.statements.lastOrNull() as? IrExpression)?.type ?: context.irBuiltIns.unitType
}
private fun createFunction(irScript: IrScript, name: String, returnType: IrType): IrSimpleFunction {
val (startOffset, endOffset) = getFunctionBodyOffsets(irScript)
val descriptor = WrappedSimpleFunctionDescriptor()
return IrFunctionImpl(
startOffset, endOffset, SCRIPT_FUNCTION,
IrSimpleFunctionSymbolImpl(descriptor),
Name.identifier(name),
Visibilities.PRIVATE, Modality.FINAL, returnType,
isInline = false, isExternal = false, isTailrec = false, isSuspend = false, isExpect = false, isFakeOverride = false,
isOperator = false
).also {
descriptor.bind(it)
private fun createFunction(irScript: IrScript, name: String, returnType: IrType): IrSimpleFunction =
buildFun {
val (startOffset, endOffset) = getFunctionBodyOffsets(irScript)
this.startOffset = startOffset
this.endOffset = endOffset
this.origin = SCRIPT_FUNCTION
this.name = Name.identifier(name)
this.visibility = Visibilities.PRIVATE
this.returnType = returnType
}.also {
it.parent = irScript
}
}
private fun List<IrStatement>.prepareForEvaluateScriptFunction(evaluateScriptFunction: IrFunction): List<IrStatement> {
return if (isNotEmpty()) {
@@ -10,13 +10,11 @@ import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
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.IrFunctionImpl
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.impl.IrSimpleFunctionSymbolImpl
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.name.Name
@@ -48,21 +46,13 @@ class PrivateMembersLowering(val context: JsIrBackendContext) : DeclarationTrans
if (function.visibility != Visibilities.PRIVATE || function.dispatchReceiverParameter == null) return null
val descriptor = WrappedSimpleFunctionDescriptor()
val symbol = IrSimpleFunctionSymbolImpl(descriptor)
val staticFunction = function.run {
IrFunctionImpl(
startOffset, endOffset, origin,
symbol, name, visibility, modality,
returnType,
isInline = isInline, isExternal = isExternal, isTailrec = isTailrec, isSuspend = isSuspend, isExpect = isExpect,
isFakeOverride = isFakeOverride,
isOperator = isOperator
).also {
descriptor.bind(it)
it.parent = parent
it.correspondingPropertySymbol = correspondingPropertySymbol
}
val staticFunction = buildFun {
updateFrom(function)
name = function.name
returnType = function.returnType
}.also {
it.parent = function.parent
it.correspondingPropertySymbol = function.correspondingPropertySymbol
}
staticFunction.typeParameters += function.typeParameters.map { it.deepCopyWithSymbols(staticFunction) }
@@ -14,15 +14,14 @@ import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.lower.CallableReferenceLowering
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
@@ -30,14 +29,15 @@ 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
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
import org.jetbrains.kotlin.name.Name
abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val context: C) : BodyLoweringPass {
@@ -302,128 +302,111 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
}
private fun buildInvokeSuspendMethod(stateMachineFunction: IrSimpleFunction): IrSimpleFunction {
val smFunction = 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.addChild(this)
val smFunction = buildFun {
startOffset = function.startOffset
endOffset = function.endOffset
origin = DECLARATION_ORIGIN_COROUTINE_IMPL
name = stateMachineFunction.name
visibility = stateMachineFunction.visibility
modality = Modality.FINAL
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.addChild(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 = listOf(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 = listOf(stateMachineFunction.symbol)
}
buildStateMachine(smFunction, function, argumentToPropertiesMap)
return smFunction
}
private fun buildCreateMethod(superCreateFunction: IrSimpleFunction?, constructor: IrConstructor): IrSimpleFunction {
// val i = $lambdaN(this.f1, this.f2, ..., this.fn, continuation) // bound
// i.s1 = p1 // unbound
// ...
// i.sn = pn
// return i
val createFunction = 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.addChild(this)
// val i = $lambdaN(this.f1, this.f2, ..., this.fn, continuation) // bound
// i.s1 = p1 // unbound
// ...
// i.sn = pn
// return i
private fun buildCreateMethod(superCreateFunction: IrSimpleFunction?, constructor: IrConstructor): IrSimpleFunction =
buildFun {
startOffset = function.startOffset
endOffset = function.endOffset
origin = DECLARATION_ORIGIN_COROUTINE_IMPL
name = Name.identifier("create")
visibility = Visibilities.PROTECTED
returnType = coroutineClass.defaultType
}.apply {
parent = coroutineClass
coroutineClass.addChild(this)
typeParameters = function.typeParameters.map { parameter ->
parameter.copyToWithoutSuperTypes(this, origin = DECLARATION_ORIGIN_COROUTINE_IMPL)
.apply { superTypes += parameter.superTypes }
}
typeParameters = function.typeParameters.map { parameter ->
parameter.copyToWithoutSuperTypes(this, origin = DECLARATION_ORIGIN_COROUTINE_IMPL)
.apply { superTypes += parameter.superTypes }
}
val unboundArgs = function.valueParameters
val unboundArgs = function.valueParameters
val createValueParameters = (unboundArgs + create1CompletionParameter).mapIndexed { index, parameter ->
parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index)
}
val createValueParameters = (unboundArgs + create1CompletionParameter).mapIndexed { index, parameter ->
parameter.copyTo(this, DECLARATION_ORIGIN_COROUTINE_IMPL, index)
}
valueParameters = createValueParameters
valueParameters = createValueParameters
this.createDispatchReceiverParameter()
this.createDispatchReceiverParameter()
superCreateFunction?.let {
overriddenSymbols = ArrayList<IrSimpleFunctionSymbol>(it.overriddenSymbols.size + 1).apply {
addAll(it.overriddenSymbols)
add(it.symbol)
}
}
val thisReceiver = this.dispatchReceiverParameter!!
val boundFields =
context.mapping.capturedFields[coroutineClass] ?: error("No captured values for class ${coroutineClass.render()}")
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
body = irBuilder.irBlockBody(startOffset, endOffset) {
val instanceCreate = irCall(constructor).apply {
var unboundIndex = 0
for (f in boundFields) {
putValueArgument(unboundIndex++, irGetField(irGet(thisReceiver), f))
}
putValueArgument(unboundIndex++, irGet(createValueParameters.last()))
assert(unboundIndex == constructor.valueParameters.size) {
"Not all arguments of <create> are used"
}
}
val instanceVal = scope.createTmpVariable(instanceCreate, "i")
+instanceVal
assert(createValueParameters.size - 1 == argumentToPropertiesMap.size)
for ((p, f) in createValueParameters.zip(argumentToPropertiesMap.values)) {
+irSetField(irGet(instanceVal), f, irGet(p))
}
+irReturn(irGet(instanceVal))
superCreateFunction?.let {
overriddenSymbols = ArrayList<IrSimpleFunctionSymbol>(it.overriddenSymbols.size + 1).apply {
addAll(it.overriddenSymbols)
add(it.symbol)
}
}
}
return createFunction
}
val thisReceiver = this.dispatchReceiverParameter!!
val boundFields =
context.mapping.capturedFields[coroutineClass] ?: error("No captured values for class ${coroutineClass.render()}")
val irBuilder = context.createIrBuilder(symbol, startOffset, endOffset)
body = irBuilder.irBlockBody(startOffset, endOffset) {
val instanceCreate = irCall(constructor).apply {
var unboundIndex = 0
for (f in boundFields) {
putValueArgument(unboundIndex++, irGetField(irGet(thisReceiver), f))
}
putValueArgument(unboundIndex++, irGet(createValueParameters.last()))
assert(unboundIndex == constructor.valueParameters.size) {
"Not all arguments of <create> are used"
}
}
val instanceVal = scope.createTmpVariable(instanceCreate, "i")
+instanceVal
assert(createValueParameters.size - 1 == argumentToPropertiesMap.size)
for ((p, f) in createValueParameters.zip(argumentToPropertiesMap.values)) {
+irSetField(irGet(instanceVal), f, irGet(p))
}
+irReturn(irGet(instanceVal))
}
}
private fun transformInvokeMethod(createFunction: IrSimpleFunction, stateMachineFunction: IrSimpleFunction) {
val irBuilder = context.createIrBuilder(function.symbol, startOffset, endOffset)