[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(
PrimitiveType.BYTE to "Int8", mapOf(
PrimitiveType.SHORT to "Int16", PrimitiveType.BYTE to "Int8",
PrimitiveType.INT to "Int32", PrimitiveType.SHORT to "Int16",
PrimitiveType.FLOAT to "Float32", PrimitiveType.INT to "Int32",
PrimitiveType.DOUBLE to "Float64")) PrimitiveType.FLOAT to "Float32",
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)
} }