[JS IR] JsIrBuilder - add returnType and parent to buildFunction

This commit is contained in:
Svyatoslav Kuzmich
2018-11-08 17:17:07 +03:00
parent 0934db8fbd
commit fe6b36391d
9 changed files with 107 additions and 67 deletions
@@ -10,6 +10,7 @@ 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.declarations.IrFunction import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrProperty import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl
@@ -193,7 +194,8 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
// Arrays: // Arrays:
val array = context.symbolTable.referenceClass(irBuiltIns.builtIns.array) val array = context.symbolTable.referenceClass(irBuiltIns.builtIns.array)
val primitiveArrays = PrimitiveType.values().associate { context.symbolTable.referenceClass(irBuiltIns.builtIns.getPrimitiveArrayClassDescriptor(it)) to it } val primitiveArrays = PrimitiveType.values()
.associate { context.symbolTable.referenceClass(irBuiltIns.builtIns.getPrimitiveArrayClassDescriptor(it)) to it }
val jsArray = getInternalFunction("arrayWithFun") val jsArray = getInternalFunction("arrayWithFun")
val jsFillArray = getInternalFunction("fillArrayFun") val jsFillArray = getInternalFunction("fillArrayFun")
@@ -209,12 +211,15 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
val arrayLiteral = unOp("arrayLiteral").symbol val arrayLiteral = unOp("arrayLiteral").symbol
val primitiveToTypedArrayMap = EnumMap(mapOf( val primitiveToTypedArrayMap = EnumMap(
mapOf(
PrimitiveType.BYTE to "Int8", PrimitiveType.BYTE to "Int8",
PrimitiveType.SHORT to "Int16", PrimitiveType.SHORT to "Int16",
PrimitiveType.INT to "Int32", PrimitiveType.INT to "Int32",
PrimitiveType.FLOAT to "Float32", PrimitiveType.FLOAT to "Float32",
PrimitiveType.DOUBLE to "Float64")) PrimitiveType.DOUBLE to "Float64"
)
)
val primitiveToSizeConstructor = val primitiveToSizeConstructor =
PrimitiveType.values().associate { type -> PrimitiveType.values().associate { type ->
@@ -241,9 +246,12 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
// TODO move CharSequence-related stiff to IntrinsifyCallsLowering // TODO move CharSequence-related stiff to IntrinsifyCallsLowering
val charSequenceClassSymbol = context.symbolTable.referenceClass(context.getClass(FqName("kotlin.CharSequence"))) val charSequenceClassSymbol = context.symbolTable.referenceClass(context.getClass(FqName("kotlin.CharSequence")))
val charSequenceLengthPropertyGetterSymbol = charSequenceClassSymbol.owner.declarations.filterIsInstance<IrProperty>().first { it.name.asString() == "length" }.getter!!.symbol val charSequenceLengthPropertyGetterSymbol =
val charSequenceGetFunctionSymbol = charSequenceClassSymbol.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "get"}.symbol charSequenceClassSymbol.owner.declarations.filterIsInstance<IrProperty>().first { it.name.asString() == "length" }.getter!!.symbol
val charSequenceSubSequenceFunctionSymbol = charSequenceClassSymbol.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "subSequence"}.symbol val charSequenceGetFunctionSymbol =
charSequenceClassSymbol.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "get" }.symbol
val charSequenceSubSequenceFunctionSymbol =
charSequenceClassSymbol.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "subSequence" }.symbol
val jsCharSequenceGet = getInternalFunction("charSequenceGet") val jsCharSequenceGet = getInternalFunction("charSequenceGet")
@@ -265,42 +273,55 @@ class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendC
context.symbolTable.referenceClass(context.getClass(FqName(fqName))) context.symbolTable.referenceClass(context.getClass(FqName(fqName)))
// TODO: unify how we create intrinsic symbols // TODO: unify how we create intrinsic symbols
private fun defineObjectCreateIntrinsic() = private fun defineObjectCreateIntrinsic(): IrSimpleFunction {
JsIrBuilder.buildFunction("Object\$create", isInline = true, origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB).also { return JsIrBuilder.buildFunction(
"Object\$create",
returnType = irBuiltIns.anyType,
parent = externalPackageFragment,
isInline = true,
origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB
).also {
val typeParameter = JsIrBuilder.buildTypeParameter(Name.identifier("T"), 0, true) val typeParameter = JsIrBuilder.buildTypeParameter(Name.identifier("T"), 0, true)
val anyType = irBuiltIns.anyType
typeParameter.parent = it typeParameter.parent = it
typeParameter.superTypes += anyType typeParameter.superTypes += irBuiltIns.anyType
it.typeParameters += typeParameter it.typeParameters += typeParameter
it.returnType = anyType
it.parent = externalPackageFragment
externalPackageFragment.declarations += it externalPackageFragment.declarations += it
} }
}
private fun defineGetJSPropertyIntrinsic() = private fun defineGetJSPropertyIntrinsic() =
JsIrBuilder.buildFunction("\$getJSProperty\$", origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB).also { JsIrBuilder.buildFunction(
it.returnType = irBuiltIns.anyNType "\$getJSProperty\$",
returnType = irBuiltIns.anyNType,
parent = externalPackageFragment,
origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB
).also {
listOf("receiver", "fieldName").mapIndexedTo(it.valueParameters) { i, p -> listOf("receiver", "fieldName").mapIndexedTo(it.valueParameters) { i, p ->
JsIrBuilder.buildValueParameter(p, i, irBuiltIns.anyType).also { v -> v.parent = it } JsIrBuilder.buildValueParameter(p, i, irBuiltIns.anyType).also { v -> v.parent = it }
} }
it.parent = externalPackageFragment
externalPackageFragment.declarations += it externalPackageFragment.declarations += it
} }
private fun defineSetJSPropertyIntrinsic() = private fun defineSetJSPropertyIntrinsic() =
JsIrBuilder.buildFunction("\$setJSProperty\$", origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB).also { JsIrBuilder.buildFunction(
it.returnType = irBuiltIns.unitType "\$setJSProperty\$",
returnType = irBuiltIns.unitType,
parent = externalPackageFragment,
origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB
).also {
listOf("receiver", "fieldName", "fieldValue").mapIndexedTo(it.valueParameters) { i, p -> listOf("receiver", "fieldName", "fieldValue").mapIndexedTo(it.valueParameters) { i, p ->
JsIrBuilder.buildValueParameter(p, i, irBuiltIns.anyType).also { v -> v.parent = it } JsIrBuilder.buildValueParameter(p, i, irBuiltIns.anyType).also { v -> v.parent = it }
} }
it.parent = externalPackageFragment
externalPackageFragment.declarations += it externalPackageFragment.declarations += it
} }
private fun defineUnreachableIntrinsic() = private fun defineUnreachableIntrinsic() =
JsIrBuilder.buildFunction(Namer.UNREACHABLE_NAME, origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB).also { JsIrBuilder.buildFunction(
it.returnType = irBuiltIns.nothingType Namer.UNREACHABLE_NAME,
it.parent = externalPackageFragment returnType = irBuiltIns.nothingType,
parent = externalPackageFragment,
origin = JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB
).also {
externalPackageFragment.declarations += it externalPackageFragment.declarations += it
} }
@@ -97,6 +97,8 @@ object JsIrBuilder {
fun buildFunction( fun buildFunction(
name: String, name: String,
returnType: IrType,
parent: IrDeclarationParent,
visibility: Visibility = Visibilities.PUBLIC, visibility: Visibility = Visibilities.PUBLIC,
modality: Modality = Modality.FINAL, modality: Modality = Modality.FINAL,
isInline: Boolean = false, isInline: Boolean = false,
@@ -104,10 +106,23 @@ object JsIrBuilder {
isTailrec: Boolean = false, isTailrec: Boolean = false,
isSuspend: Boolean = false, isSuspend: Boolean = false,
origin: IrDeclarationOrigin = SYNTHESIZED_DECLARATION origin: IrDeclarationOrigin = SYNTHESIZED_DECLARATION
) = JsIrBuilder.buildFunction(Name.identifier(name), visibility, modality, isInline, isExternal, isTailrec, isSuspend, origin) ) = JsIrBuilder.buildFunction(
Name.identifier(name),
returnType,
parent,
visibility,
modality,
isInline,
isExternal,
isTailrec,
isSuspend,
origin
)
fun buildFunction( fun buildFunction(
name: Name, name: Name,
returnType: IrType,
parent: IrDeclarationParent,
visibility: Visibility = Visibilities.PUBLIC, visibility: Visibility = Visibilities.PUBLIC,
modality: Modality = Modality.FINAL, modality: Modality = Modality.FINAL,
isInline: Boolean = false, isInline: Boolean = false,
@@ -129,7 +144,11 @@ object JsIrBuilder {
isExternal, isExternal,
isTailrec, isTailrec,
isSuspend isSuspend
).also { descriptor.bind(it) } ).also {
descriptor.bind(it)
it.returnType = returnType
it.parent = parent
}
} }
fun buildGetObjectValue(type: IrType, classSymbol: IrClassSymbol) = fun buildGetObjectValue(type: IrType, classSymbol: IrClassSymbol) =
@@ -55,10 +55,12 @@ class BlockDecomposerLowering(context: JsIrBackendContext) : DeclarationContaine
fun lower(irField: IrField, container: IrDeclarationContainer): List<IrDeclaration> { fun lower(irField: IrField, container: IrDeclarationContainer): List<IrDeclaration> {
irField.initializer?.apply { irField.initializer?.apply {
val initFunction = JsIrBuilder.buildFunction(irField.name.asString() + "\$init\$", irField.visibility).also { val initFunction = JsIrBuilder.buildFunction(
it.parent = container irField.name.asString() + "\$init\$",
it.returnType = expression.type expression.type,
} container,
irField.visibility
)
val newBody = toBlockBody(initFunction) val newBody = toBlockBody(initFunction)
@@ -425,11 +427,14 @@ class BlockDecomposerTransformer(context: JsIrBackendContext) : IrElementTransfo
override fun visitSetField(expression: IrSetField) = expression.asExpression(unitValue) override fun visitSetField(expression: IrSetField) = expression.asExpression(unitValue)
override fun visitBreakContinue(jump: IrBreakContinue) = jump.asExpression(JsIrBuilder.buildCall(unreachableFunction.symbol, nothingType)) override fun visitBreakContinue(jump: IrBreakContinue) =
jump.asExpression(JsIrBuilder.buildCall(unreachableFunction.symbol, nothingType))
override fun visitThrow(expression: IrThrow) = expression.asExpression(JsIrBuilder.buildCall(unreachableFunction.symbol, nothingType)) override fun visitThrow(expression: IrThrow) =
expression.asExpression(JsIrBuilder.buildCall(unreachableFunction.symbol, nothingType))
override fun visitReturn(expression: IrReturn) = expression.asExpression(JsIrBuilder.buildCall(unreachableFunction.symbol, nothingType)) override fun visitReturn(expression: IrReturn) =
expression.asExpression(JsIrBuilder.buildCall(unreachableFunction.symbol, nothingType))
override fun visitVariable(declaration: IrVariable) = declaration.asExpression(unitValue) override fun visitVariable(declaration: IrVariable) = declaration.asExpression(unitValue)
@@ -104,6 +104,8 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
// TODO: Support offsets for debug info // TODO: Support offsets for debug info
val irFunction = JsIrBuilder.buildFunction( val irFunction = JsIrBuilder.buildFunction(
bridge.name, bridge.name,
bridge.returnType,
delegateTo.parent,
bridge.visibility, bridge.visibility,
bridge.modality, // TODO: should copy modality? bridge.modality, // TODO: should copy modality?
bridge.isInline, bridge.isInline,
@@ -121,8 +123,6 @@ class BridgesConstruction(val context: JsIrBackendContext) : ClassLoweringPass {
typeParameters += bridge.typeParameters typeParameters += bridge.typeParameters
valueParameters += bridge.valueParameters.map { p -> p.copyTo(this) } valueParameters += bridge.valueParameters.map { p -> p.copyTo(this) }
annotations += bridge.annotations annotations += bridge.annotations
returnType = bridge.returnType
parent = delegateTo.parent
overriddenSymbols.addAll(delegateTo.overriddenSymbols) overriddenSymbols.addAll(delegateTo.overriddenSymbols)
} }
@@ -394,7 +394,9 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
callable.dispatchReceiverParameter?.let { dispatch -> callable.dispatchReceiverParameter?.let { dispatch ->
if (reference.dispatchReceiver == null) { if (reference.dispatchReceiver == null) {
result.add(JsIrBuilder.buildValueParameter(dispatch.name, result.size, dispatch.type.boxIfInlined()).also { it.parent = closure }) result.add(JsIrBuilder.buildValueParameter(dispatch.name, result.size, dispatch.type.boxIfInlined()).also {
it.parent = closure
})
} else { } else {
// do not add dispatch receiver in result signature if it is bound // do not add dispatch receiver in result signature if it is bound
capturedParams-- capturedParams--
@@ -434,10 +436,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
val boundValueParameters = receivers + declaration.valueParameters.filter { it.origin == BOUND_VALUE_PARAMETER } val boundValueParameters = receivers + declaration.valueParameters.filter { it.origin == BOUND_VALUE_PARAMETER }
val factoryDeclaration = JsIrBuilder.buildFunction(getterName, declaration.visibility) val factoryDeclaration = JsIrBuilder.buildFunction(getterName, reference.type, implicitDeclarationFile, declaration.visibility)
factoryDeclaration.parent = implicitDeclarationFile
factoryDeclaration.returnType = reference.type
for ((i, p) in boundValueParameters.withIndex()) { for ((i, p) in boundValueParameters.withIndex()) {
val descriptor = WrappedValueParameterDescriptor() val descriptor = WrappedValueParameterDescriptor()
@@ -491,18 +490,22 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
arity: Int arity: Int
): IrFunction { ): IrFunction {
val closureName = createClosureInstanceName(declaration) val closureName = createClosureInstanceName(declaration)
val returnType = declaration.returnType.boxIfInlined()
val closureFunction = val closureFunction =
JsIrBuilder.buildFunction(closureName, Visibilities.LOCAL, origin = JsIrBackendContext.callableClosureOrigin) JsIrBuilder.buildFunction(
.also { it.parent = factoryFunction } closureName,
returnType,
factoryFunction,
Visibilities.LOCAL,
origin = JsIrBackendContext.callableClosureOrigin
)
// the params which are passed to closure // the params which are passed to closure
val boundParamSymbols = factoryFunction.valueParameters.map { it.symbol } val boundParamSymbols = factoryFunction.valueParameters.map { it.symbol }
val unboundParamDeclarations = generateSignatureForClosure(declaration, factoryFunction, closureFunction, reference, arity) val unboundParamDeclarations = generateSignatureForClosure(declaration, factoryFunction, closureFunction, reference, arity)
val unboundParamSymbols = unboundParamDeclarations.map { it.symbol } val unboundParamSymbols = unboundParamDeclarations.map { it.symbol }
val returnType = declaration.returnType.boxIfInlined()
closureFunction.valueParameters += unboundParamDeclarations closureFunction.valueParameters += unboundParamDeclarations
closureFunction.returnType = returnType
val callTarget = context.ir.defaultParameterDeclarationsCache[declaration] ?: declaration val callTarget = context.ir.defaultParameterDeclarationsCache[declaration] ?: declaration
@@ -72,10 +72,11 @@ class EnumUsageLowering(val context: JsIrBackendContext) : FileLoweringPass {
private fun lowerEnumEntry(enumEntry: IrEnumEntry, klass: IrClass) = private fun lowerEnumEntry(enumEntry: IrEnumEntry, klass: IrClass) =
context.enumEntryToGetInstanceFunction.getOrPut(enumEntry.symbol) { context.enumEntryToGetInstanceFunction.getOrPut(enumEntry.symbol) {
JsIrBuilder.buildFunction(createEntryAccessorName(klass.name.identifier, enumEntry)).also { JsIrBuilder.buildFunction(
it.returnType = enumEntry.getType(klass) createEntryAccessorName(klass.name.identifier, enumEntry),
it.parent = klass returnType = enumEntry.getType(klass),
} parent = klass
)
}.run { JsIrBuilder.buildCall(symbol) } }.run { JsIrBuilder.buildCall(symbol) }
} }
@@ -442,18 +443,13 @@ class EnumClassTransformer(val context: JsIrBackendContext, private val irClass:
private fun buildFunction( private fun buildFunction(
name: String, name: String,
returnType: IrType = context.irBuiltIns.unitType returnType: IrType = context.irBuiltIns.unitType
) = JsIrBuilder.buildFunction(name).also { ) = JsIrBuilder.buildFunction(name, returnType, irClass)
it.returnType = returnType
it.parent = irClass
}
private fun buildFunction( private fun buildFunction(
name: String, name: String,
returnType: IrType = context.irBuiltIns.unitType, returnType: IrType = context.irBuiltIns.unitType,
bodyBuilder: IrBlockBodyBuilder.() -> Unit bodyBuilder: IrBlockBodyBuilder.() -> Unit
) = JsIrBuilder.buildFunction(name).also { ) = JsIrBuilder.buildFunction(name, returnType, irClass).also {
it.returnType = returnType
it.parent = irClass
it.body = context.createIrBuilder(it.symbol).irBlockBody(it, bodyBuilder) it.body = context.createIrBuilder(it.symbol).irBlockBody(it, bodyBuilder)
} }
@@ -149,6 +149,8 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) {
return JsIrBuilder.buildFunction( return JsIrBuilder.buildFunction(
functionName, functionName,
type,
declaration.parent,
declaration.visibility, declaration.visibility,
Modality.FINAL, Modality.FINAL,
declaration.isInline, declaration.isInline,
@@ -163,9 +165,6 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) {
val newValueParameters = declaration.valueParameters.map { p -> p.copyTo(it) } val newValueParameters = declaration.valueParameters.map { p -> p.copyTo(it) }
it.valueParameters += (newValueParameters + thisParam) it.valueParameters += (newValueParameters + thisParam)
it.returnType = type
it.parent = declaration.parent
val oldValueParameters = declaration.valueParameters + oldThisReceiver val oldValueParameters = declaration.valueParameters + oldThisReceiver
// TODO: replace parameters as well // TODO: replace parameters as well
@@ -186,6 +185,8 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) {
return JsIrBuilder.buildFunction( return JsIrBuilder.buildFunction(
functionName, functionName,
type,
declaration.parent,
declaration.visibility, declaration.visibility,
Modality.FINAL, Modality.FINAL,
declaration.isInline, declaration.isInline,
@@ -193,9 +194,6 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) {
).also { ).also {
it.copyTypeParametersFrom(declaration) it.copyTypeParametersFrom(declaration)
it.valueParameters += declaration.valueParameters.map { p -> p.copyTo(it) } it.valueParameters += declaration.valueParameters.map { p -> p.copyTo(it) }
it.parent = declaration.parent
it.returnType = type
val createFunctionIntrinsic = context.intrinsics.jsObjectCreate val createFunctionIntrinsic = context.intrinsics.jsObjectCreate
val irCreateCall = JsIrBuilder.buildCall(createFunctionIntrinsic.symbol, type, listOf(type)) val irCreateCall = JsIrBuilder.buildCall(createFunctionIntrinsic.symbol, type, listOf(type))
@@ -180,10 +180,8 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
private fun createPropertyAccessor(fakeAccessor: IrSimpleFunction, field: IrField) { private fun createPropertyAccessor(fakeAccessor: IrSimpleFunction, field: IrField) {
val name = fakeAccessor.name val name = fakeAccessor.name
val function = JsIrBuilder.buildFunction(name).apply { val function = JsIrBuilder.buildFunction(name, fakeAccessor.returnType, fakeAccessor.parent).apply {
parent = fakeAccessor.parent
overriddenSymbols += fakeAccessor.overriddenSymbols overriddenSymbols += fakeAccessor.overriddenSymbols
returnType = fakeAccessor.returnType
correspondingProperty = fakeAccessor.correspondingProperty correspondingProperty = fakeAccessor.correspondingProperty
dispatchReceiverParameter = fakeAccessor.dispatchReceiverParameter dispatchReceiverParameter = fakeAccessor.dispatchReceiverParameter
} }
@@ -440,6 +440,8 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
fun createFakeOverride(irFunction: IrSimpleFunction) = JsIrBuilder.buildFunction( fun createFakeOverride(irFunction: IrSimpleFunction) = JsIrBuilder.buildFunction(
irFunction.name, irFunction.name,
irFunction.returnType,
this,
irFunction.visibility, irFunction.visibility,
Modality.FINAL, Modality.FINAL,
irFunction.isInline, irFunction.isInline,
@@ -448,8 +450,6 @@ internal class SuspendFunctionsLowering(val context: JsIrBackendContext): FileLo
irFunction.isSuspend, irFunction.isSuspend,
IrDeclarationOrigin.FAKE_OVERRIDE IrDeclarationOrigin.FAKE_OVERRIDE
).apply { ).apply {
parent = this@setSuperSymbolsAndAddFakeOverrides
returnType = irFunction.returnType
overriddenSymbols += irFunction.symbol overriddenSymbols += irFunction.symbol
copyParameterDeclarationsFrom(irFunction) copyParameterDeclarationsFrom(irFunction)
} }