JS IR BE: migrate to IR types
(cherry picked from commit 064f47b)
This commit is contained in:
committed by
Dmitry Petrov
parent
952163b2fb
commit
bf2aa5263e
+4
-14
@@ -1,17 +1,6 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
|
||||
* that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.backend.js
|
||||
@@ -29,6 +18,7 @@ import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrConstructorSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -64,7 +54,7 @@ class JsDescriptorsFactory : DescriptorsFactory {
|
||||
false
|
||||
).apply {
|
||||
setType(
|
||||
outerClass.defaultType,
|
||||
outerClass.defaultType.toKotlinType(),
|
||||
emptyList(),
|
||||
innerClass.descriptor.thisAsReceiverParameter,
|
||||
null as? ReceiverParameterDescriptor
|
||||
|
||||
@@ -25,7 +25,7 @@ class JsIntrinsics(
|
||||
context: JsIrBackendContext
|
||||
) {
|
||||
|
||||
private val stubBuilder = DeclarationStubGenerator(context.module, context.symbolTable, JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB)
|
||||
private val stubBuilder = DeclarationStubGenerator(module, context.module, context.symbolTable, JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB)
|
||||
|
||||
// Equality operations:
|
||||
|
||||
|
||||
@@ -15,8 +15,8 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.inline.ModuleIndex
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
@@ -25,6 +25,8 @@ import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
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.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -59,7 +61,7 @@ class JsIrBackendContext(
|
||||
|
||||
val secondaryConstructorsMap = mutableMapOf<IrConstructorSymbol, SecondaryCtorPair>()
|
||||
|
||||
fun getOperatorByName(name: Name, type: KotlinType) = operatorMap[name]?.get(type)
|
||||
fun getOperatorByName(name: Name, type: IrType) = operatorMap[name]?.get(type.toKotlinType())
|
||||
|
||||
val originalModuleIndex = ModuleIndex(irModuleFragment)
|
||||
|
||||
@@ -109,6 +111,7 @@ class JsIrBackendContext(
|
||||
}
|
||||
|
||||
private fun referenceOperators() = OperatorNames.ALL.map { name ->
|
||||
// TODO to replace KotlinType with IrType we need right equals on IrType
|
||||
name to irBuiltIns.primitiveTypes.fold(mutableMapOf<KotlinType, IrFunctionSymbol>()) { m, t ->
|
||||
val function = t.memberScope.getContributedFunctions(name, NoLookupLocation.FROM_BACKEND).singleOrNull()
|
||||
function?.let { m.put(t, symbolTable.referenceSimpleFunction(it)) }
|
||||
|
||||
+15
-5
@@ -40,24 +40,28 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack
|
||||
false, false, variableDescriptor.isLateInit, variableDescriptor.source
|
||||
)
|
||||
|
||||
val valueType = originalDeclaration.descriptor.type
|
||||
val valueType = originalDeclaration.type
|
||||
val boxConstructor = closureBoxConstructorTypeDescriptor
|
||||
val boxConstructorSymbol = closureBoxConstructorTypeSymbol
|
||||
val constructorTypeParam = closureBoxConstructorTypeDescriptor.typeParameters[0]
|
||||
val boxConstructorTypeArgument = mapOf(constructorTypeParam to valueType)
|
||||
val initializer = originalDeclaration.initializer ?: IrConstImpl.constNull(
|
||||
originalDeclaration.startOffset,
|
||||
originalDeclaration.endOffset,
|
||||
valueType
|
||||
)
|
||||
// TODO use buildCall?
|
||||
val constructorCall = IrCallImpl(
|
||||
originalDeclaration.startOffset,
|
||||
originalDeclaration.endOffset,
|
||||
// TODO wrong type
|
||||
originalDeclaration.type,
|
||||
boxConstructorSymbol,
|
||||
boxConstructor,
|
||||
boxConstructorTypeArgument,
|
||||
1,
|
||||
JsLoweredDeclarationOrigin.JS_CLOSURE_BOX_CLASS
|
||||
).apply { putValueArgument(0, initializer) }
|
||||
).apply {
|
||||
putTypeArgument(0, valueType)
|
||||
putValueArgument(0, initializer)
|
||||
}
|
||||
|
||||
|
||||
return IrVariableImpl(
|
||||
@@ -65,6 +69,8 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack
|
||||
originalDeclaration.endOffset,
|
||||
originalDeclaration.origin,
|
||||
sharedVariableDescriptor,
|
||||
// TODO wrong type ?
|
||||
originalDeclaration.type,
|
||||
constructorCall
|
||||
)
|
||||
}
|
||||
@@ -75,9 +81,11 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack
|
||||
IrGetFieldImpl(
|
||||
originalGet.startOffset, originalGet.endOffset,
|
||||
closureBoxFieldSymbol,
|
||||
originalGet.type,
|
||||
IrGetValueImpl(
|
||||
originalGet.startOffset,
|
||||
originalGet.endOffset,
|
||||
originalGet.type,
|
||||
sharedVariableSymbol
|
||||
),
|
||||
originalGet.origin
|
||||
@@ -90,9 +98,11 @@ class JsSharedVariablesManager(val builtIns: KotlinBuiltIns, val jsInterinalPack
|
||||
IrGetValueImpl(
|
||||
originalSet.startOffset,
|
||||
originalSet.endOffset,
|
||||
originalSet.type,
|
||||
sharedVariableSymbol
|
||||
),
|
||||
originalSet.value,
|
||||
originalSet.type,
|
||||
originalSet.origin
|
||||
)
|
||||
|
||||
|
||||
@@ -45,7 +45,8 @@ fun compile(
|
||||
moduleFragment
|
||||
)
|
||||
|
||||
ExternalDependenciesGenerator(psi2IrContext.symbolTable, psi2IrContext.irBuiltIns).generateUnboundSymbolsAsDependencies(moduleFragment)
|
||||
ExternalDependenciesGenerator(psi2IrContext.moduleDescriptor, psi2IrContext.symbolTable, psi2IrContext.irBuiltIns)
|
||||
.generateUnboundSymbolsAsDependencies(moduleFragment)
|
||||
|
||||
context.performInlining(moduleFragment)
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class JsIrArithBuilder(val context: JsIrBackendContext) {
|
||||
fun inv(v: IrExpression): IrExpression = buildUnaryOperator(OperatorNames.INV, v)
|
||||
|
||||
fun andand(l: IrExpression, r: IrExpression) = // if (l) r else false
|
||||
JsIrBuilder.buildIfElse(context.builtIns.booleanType, l, r, JsIrBuilder.buildBoolean(context.builtIns.booleanType, false))
|
||||
JsIrBuilder.buildIfElse(context.irBuiltIns.booleanType, l, r, JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, false))
|
||||
fun oror(l: IrExpression, r: IrExpression) = // if (l) true else r
|
||||
JsIrBuilder.buildIfElse(context.builtIns.booleanType, l, JsIrBuilder.buildBoolean(context.builtIns.booleanType, true), r)
|
||||
JsIrBuilder.buildIfElse(context.irBuiltIns.booleanType, l, JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true), r)
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js.ir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationOriginImpl
|
||||
@@ -15,76 +15,103 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrVariableImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
|
||||
object JsIrBuilder {
|
||||
|
||||
object SYNTHESIZED_STATEMENT : IrStatementOriginImpl("SYNTHESIZED_STATEMENT")
|
||||
object SYNTHESIZED_DECLARATION : IrDeclarationOriginImpl("SYNTHESIZED_DECLARATION")
|
||||
|
||||
fun buildCall(target: IrFunctionSymbol, type: KotlinType? = null, typeArguments: Map<TypeParameterDescriptor, KotlinType>? = null) =
|
||||
fun buildCall(target: IrFunctionSymbol, type: IrType? = null, typeArguments: List<IrType>? = null): IrCall =
|
||||
IrCallImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
type ?: target.descriptor.returnType!!,
|
||||
type ?: target.owner.returnType,
|
||||
target,
|
||||
target.descriptor,
|
||||
typeArguments,
|
||||
target.owner.typeParameters.size,
|
||||
SYNTHESIZED_STATEMENT
|
||||
)
|
||||
).apply {
|
||||
typeArguments?.let {
|
||||
assert(typeArguments.size == typeArgumentsCount)
|
||||
it.withIndex().forEach { (i, t) -> putTypeArgument(i, t) }
|
||||
}
|
||||
}
|
||||
|
||||
fun buildReturn(targetSymbol: IrFunctionSymbol, value: IrExpression) =
|
||||
IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, targetSymbol, value)
|
||||
fun buildReturn(targetSymbol: IrFunctionSymbol, value: IrExpression, context: BackendContext) =
|
||||
IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.nothingType, targetSymbol, value)
|
||||
|
||||
fun buildThrow(type: KotlinType, value: IrExpression) = IrThrowImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, value)
|
||||
fun buildThrow(type: IrType, value: IrExpression) = IrThrowImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, value)
|
||||
|
||||
fun buildValueParameter(symbol: IrValueParameterSymbol) =
|
||||
IrValueParameterImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol)
|
||||
fun buildValueParameter(symbol: IrValueParameterSymbol, type: IrType? = null) =
|
||||
IrValueParameterImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol, type ?: symbol.owner.type, null)
|
||||
|
||||
fun buildFunction(symbol: IrSimpleFunctionSymbol) = IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol)
|
||||
fun buildFunction(symbol: IrSimpleFunctionSymbol, returnType: IrType) =
|
||||
IrFunctionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol).apply {
|
||||
this.returnType = returnType
|
||||
}
|
||||
|
||||
fun buildGetObjectValue(type: KotlinType, classSymbol: IrClassSymbol) =
|
||||
fun buildGetObjectValue(type: IrType, classSymbol: IrClassSymbol) =
|
||||
IrGetObjectValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, classSymbol)
|
||||
|
||||
fun buildGetClass(expression: IrExpression, type: KotlinType) = IrGetClassImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, expression)
|
||||
fun buildGetClass(expression: IrExpression, type: IrType) = IrGetClassImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, expression)
|
||||
|
||||
fun buildGetValue(symbol: IrValueSymbol) = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, SYNTHESIZED_STATEMENT)
|
||||
fun buildSetVariable(symbol: IrVariableSymbol, value: IrExpression) =
|
||||
IrSetVariableImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, value, SYNTHESIZED_STATEMENT)
|
||||
fun buildGetValue(symbol: IrValueSymbol) = IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol.owner.type, symbol, SYNTHESIZED_STATEMENT)
|
||||
fun buildSetVariable(symbol: IrVariableSymbol, value: IrExpression, type: IrType) =
|
||||
IrSetVariableImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, symbol, value, SYNTHESIZED_STATEMENT)
|
||||
|
||||
fun buildGetField(symbol: IrFieldSymbol, receiver: IrExpression?, superQualifierSymbol: IrClassSymbol? = null) =
|
||||
IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, receiver, SYNTHESIZED_STATEMENT, superQualifierSymbol)
|
||||
IrGetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, symbol.owner.type, receiver, SYNTHESIZED_STATEMENT, superQualifierSymbol)
|
||||
|
||||
fun buildSetField(symbol: IrFieldSymbol, receiver: IrExpression?, value: IrExpression, superQualifierSymbol: IrClassSymbol? = null) =
|
||||
IrSetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, receiver, value, SYNTHESIZED_STATEMENT, superQualifierSymbol)
|
||||
fun buildSetField(symbol: IrFieldSymbol, receiver: IrExpression?, value: IrExpression, type: IrType, superQualifierSymbol: IrClassSymbol? = null) =
|
||||
IrSetFieldImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, symbol, receiver, value, type, SYNTHESIZED_STATEMENT, superQualifierSymbol)
|
||||
|
||||
fun buildBlockBody(statements: List<IrStatement>) = IrBlockBodyImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, statements)
|
||||
|
||||
fun buildBlock(type: KotlinType) = IrBlockImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, SYNTHESIZED_STATEMENT)
|
||||
fun buildBlock(type: KotlinType, statements: List<IrStatement>) =
|
||||
fun buildBlock(type: IrType) = IrBlockImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, SYNTHESIZED_STATEMENT)
|
||||
fun buildBlock(type: IrType, statements: List<IrStatement>) =
|
||||
IrBlockImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, SYNTHESIZED_STATEMENT, statements)
|
||||
|
||||
fun buildFunctionReference(type: KotlinType, symbol: IrFunctionSymbol) =
|
||||
IrFunctionReferenceImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, symbol, symbol.descriptor)
|
||||
fun buildFunctionReference(type: IrType, symbol: IrFunctionSymbol) =
|
||||
IrFunctionReferenceImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, symbol, symbol.descriptor, 0, null)
|
||||
|
||||
fun buildVar(symbol: IrVariableSymbol, initializer: IrExpression? = null) =
|
||||
IrVariableImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol).apply { this.initializer = initializer }
|
||||
fun buildVar(symbol: IrVariableSymbol, initializer: IrExpression? = null, type: IrType?) =
|
||||
IrVariableImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, SYNTHESIZED_DECLARATION, symbol, type ?: symbol.owner.type).apply { this.initializer = initializer }
|
||||
|
||||
fun buildBreak(type: KotlinType, loop: IrLoop) = IrBreakImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, loop)
|
||||
fun buildContinue(type: KotlinType, loop: IrLoop) = IrContinueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, loop)
|
||||
fun buildBreak(type: IrType, loop: IrLoop) = IrBreakImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, loop)
|
||||
fun buildContinue(type: IrType, loop: IrLoop) = IrContinueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, loop)
|
||||
|
||||
fun buildIfElse(type: KotlinType, cond: IrExpression, thenBranch: IrExpression, elseBranch: IrExpression? = null) = IrIfThenElseImpl(
|
||||
fun buildIfElse(type: IrType, cond: IrExpression, thenBranch: IrExpression, elseBranch: IrExpression? = null): IrWhen = buildIfElse(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, cond, thenBranch, elseBranch, SYNTHESIZED_STATEMENT
|
||||
)
|
||||
|
||||
fun buildWhen(type: KotlinType, branches: List<IrBranch>) =
|
||||
fun buildIfElse(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
type: IrType,
|
||||
cond: IrExpression,
|
||||
thenBranch: IrExpression,
|
||||
elseBranch: IrExpression? = null,
|
||||
origin: IrStatementOrigin? = null
|
||||
): IrWhen {
|
||||
val element = IrIfThenElseImpl(startOffset, endOffset, type, origin)
|
||||
element.branches.add(IrBranchImpl(cond, thenBranch))
|
||||
if (elseBranch != null) {
|
||||
val irTrue = IrConstImpl.boolean(UNDEFINED_OFFSET, UNDEFINED_OFFSET, cond.type, true)
|
||||
element.branches.add(IrElseBranchImpl(irTrue, elseBranch))
|
||||
}
|
||||
|
||||
return element
|
||||
}
|
||||
|
||||
fun buildWhen(type: IrType, branches: List<IrBranch>) =
|
||||
IrWhenImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, SYNTHESIZED_STATEMENT, branches)
|
||||
|
||||
fun buildTypeOperator(type: KotlinType, operator: IrTypeOperator, argument: IrExpression, toType: KotlinType, symbol: IrClassifierSymbol) =
|
||||
IrTypeOperatorCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, operator, toType, argument, symbol)
|
||||
fun buildTypeOperator(type: IrType, operator: IrTypeOperator, argument: IrExpression, toType: IrType, symbol: IrClassifierSymbol) =
|
||||
IrTypeOperatorCallImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, operator, toType, symbol, argument)
|
||||
|
||||
fun buildNull(type: KotlinType) = IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type)
|
||||
fun buildBoolean(type: KotlinType, v: Boolean) = IrConstImpl.boolean(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, v)
|
||||
fun buildInt(type: KotlinType, v: Int) = IrConstImpl.int(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, v)
|
||||
fun buildString(type: KotlinType, s: String) = IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, s)
|
||||
}
|
||||
fun buildNull(type: IrType) = IrConstImpl.constNull(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type)
|
||||
fun buildBoolean(type: IrType, v: Boolean) = IrConstImpl.boolean(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, v)
|
||||
fun buildInt(type: IrType, v: Int) = IrConstImpl.int(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, v)
|
||||
fun buildString(type: IrType, s: String) = IrConstImpl.string(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, s)
|
||||
}
|
||||
|
||||
+39
-32
@@ -6,7 +6,6 @@
|
||||
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
@@ -17,9 +16,11 @@ import org.jetbrains.kotlin.ir.backend.js.utils.Namer
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
|
||||
private typealias VisitData = Nothing?
|
||||
|
||||
@@ -30,15 +31,20 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
|
||||
private val statementVisitor = StatementVisitor()
|
||||
private val expressionVisitor = ExpressionVisitor()
|
||||
|
||||
private val constTrue = JsIrBuilder.buildBoolean(context.builtIns.booleanType, true)
|
||||
private val constFalse = JsIrBuilder.buildBoolean(context.builtIns.booleanType, false)
|
||||
private val nothingType = context.builtIns.nullableNothingType
|
||||
private val constTrue = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true)
|
||||
private val constFalse = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, false)
|
||||
private val nothingType get() = context.irBuiltIns.nothingType
|
||||
private val unitType get() = context.irBuiltIns.unitType
|
||||
|
||||
private val unitType = context.builtIns.unitType
|
||||
private val unitValue = JsIrBuilder.buildGetObjectValue(unitType, context.symbolTable.referenceClass(context.builtIns.unit))
|
||||
|
||||
private val unreachableFunction =
|
||||
JsSymbolBuilder.buildSimpleFunction(context.module, Namer.UNREACHABLE_NAME).initialize(type = nothingType)
|
||||
private val unreachableFunction = JsIrBuilder.buildFunction(
|
||||
JsSymbolBuilder.buildSimpleFunction(
|
||||
context.module,
|
||||
Namer.UNREACHABLE_NAME
|
||||
).initialize(returnType = nothingType),
|
||||
nothingType
|
||||
)
|
||||
|
||||
override fun lower(irDeclarationContainer: IrDeclarationContainer) {
|
||||
irDeclarationContainer.declarations.transformFlat { declaration ->
|
||||
@@ -61,17 +67,18 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
|
||||
|
||||
fun lower(irField: IrField, container: IrDeclarationContainer): List<IrDeclaration> {
|
||||
irField.initializer?.apply {
|
||||
val returnType = expression.type
|
||||
val initFnSymbol = JsSymbolBuilder.buildSimpleFunction(
|
||||
(container as IrSymbolOwner).symbol.descriptor,
|
||||
irField.name.asString() + "\$init\$"
|
||||
).initialize(type = expression.type)
|
||||
).initialize(returnType = returnType)
|
||||
|
||||
|
||||
val newBody = IrBlockBodyImpl(expression.startOffset, expression.endOffset).apply {
|
||||
statements += JsIrBuilder.buildReturn(initFnSymbol, expression)
|
||||
statements += JsIrBuilder.buildReturn(initFnSymbol, expression, context)
|
||||
}
|
||||
|
||||
val initFn = JsIrBuilder.buildFunction(initFnSymbol).apply {
|
||||
val initFn = JsIrBuilder.buildFunction(initFnSymbol, returnType).apply {
|
||||
body = newBody
|
||||
}
|
||||
|
||||
@@ -314,15 +321,15 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
|
||||
expression.type,
|
||||
expression.operator,
|
||||
expression.typeOperand,
|
||||
resultValue,
|
||||
expression.typeOperandClassifier
|
||||
expression.typeOperandClassifier,
|
||||
resultValue
|
||||
)
|
||||
|
||||
val resValue: IrExpression
|
||||
|
||||
if (!KotlinBuiltIns.isUnit(expression.type)) {
|
||||
if (!expression.type.isUnit()) {
|
||||
val resVar = makeTempVar(expression.type)
|
||||
statements += JsIrBuilder.buildVar(resVar, newOperator)
|
||||
statements += JsIrBuilder.buildVar(resVar, newOperator, type = expression.type)
|
||||
resValue = JsIrBuilder.buildGetValue(resVar)
|
||||
} else {
|
||||
statements += newOperator
|
||||
@@ -364,7 +371,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
|
||||
}
|
||||
|
||||
if (needNew) {
|
||||
newStatements += JsIrBuilder.buildSetField(expression.symbol, newReceiver, newValue, expression.superQualifierSymbol)
|
||||
newStatements += JsIrBuilder.buildSetField(expression.symbol, newReceiver, newValue, unitType, expression.superQualifierSymbol)
|
||||
return DecomposedResult(newStatements, unitValue)
|
||||
}
|
||||
|
||||
@@ -375,7 +382,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
|
||||
val valueResult = expression.value.accept(expressionVisitor, data)
|
||||
|
||||
return valueResult.runIfChanged {
|
||||
statements += JsIrBuilder.buildSetVariable(expression.symbol, resultValue)
|
||||
statements += JsIrBuilder.buildSetVariable(expression.symbol, resultValue, unitType)
|
||||
DecomposedResult(statements, unitValue)
|
||||
}
|
||||
}
|
||||
@@ -400,7 +407,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
|
||||
// val x = x_tmp
|
||||
override fun visitContainerExpression(expression: IrContainerExpression, data: VisitData): VisitResult {
|
||||
val variable = makeTempVar(expression.type)
|
||||
val varDeclaration = JsIrBuilder.buildVar(variable)
|
||||
val varDeclaration = JsIrBuilder.buildVar(variable, type = expression.type)
|
||||
|
||||
val blockStatements = expression.statements
|
||||
val lastStatement: IrStatement? = blockStatements.lastOrNull()
|
||||
@@ -434,7 +441,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
|
||||
collectingList += statements
|
||||
resultValue
|
||||
}
|
||||
collectingList += JsIrBuilder.buildSetVariable(variable, result)
|
||||
collectingList += JsIrBuilder.buildSetVariable(variable, result, unitType)
|
||||
if (body is IrComposite) {
|
||||
DecomposedResult(mutableListOf(varDeclaration, *collectingList.toTypedArray()) , JsIrBuilder.buildGetValue(variable))
|
||||
} else {
|
||||
@@ -463,7 +470,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
|
||||
private fun prepareArgument(arg: IrExpression, needWrap: Boolean, statements: MutableList<IrStatement>): IrExpression {
|
||||
return if (needWrap) {
|
||||
val wrapVar = makeTempVar(arg.type)
|
||||
statements += JsIrBuilder.buildVar(wrapVar, arg)
|
||||
statements += JsIrBuilder.buildVar(wrapVar, arg, type = arg.type)
|
||||
JsIrBuilder.buildGetValue(wrapVar)
|
||||
} else arg
|
||||
}
|
||||
@@ -543,21 +550,21 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
|
||||
val resultVar = makeTempVar(expression.type)
|
||||
|
||||
// TODO: get rid of temporary variable
|
||||
newStatements += JsIrBuilder.buildVar(resultVar, expression)
|
||||
newStatements += JsIrBuilder.buildVar(resultVar, expression, type = expression.type)
|
||||
|
||||
return DecomposedResult(newStatements, JsIrBuilder.buildGetValue(resultVar))
|
||||
}
|
||||
|
||||
override fun visitWhen(expression: IrWhen, data: VisitData): VisitResult {
|
||||
val collectiveVar = makeTempVar(expression.type)
|
||||
val varDeclaration = JsIrBuilder.buildVar(collectiveVar)
|
||||
val varDeclaration = JsIrBuilder.buildVar(collectiveVar, type = expression.type)
|
||||
val newWhen = processWhen(expression, data, this, this) { visitResult, original ->
|
||||
val resultList = mutableListOf<IrStatement>()
|
||||
val newResult = visitResult.runIfChangedOrDefault(original as IrExpression) {
|
||||
resultList += statements
|
||||
resultValue
|
||||
}
|
||||
resultList.apply { add(JsIrBuilder.buildSetVariable(collectiveVar, newResult)) }
|
||||
resultList.apply { add(JsIrBuilder.buildSetVariable(collectiveVar, newResult, unitType)) }
|
||||
}
|
||||
|
||||
if (newWhen != expression) {
|
||||
@@ -587,7 +594,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
|
||||
resultValue
|
||||
}
|
||||
val wrapVar = makeTempVar(expression.varargElementType)
|
||||
newStatements += JsIrBuilder.buildVar(wrapVar).apply { initializer = newExpression }
|
||||
newStatements += JsIrBuilder.buildVar(wrapVar, type = expression.type).apply { initializer = newExpression }
|
||||
val newValue = JsIrBuilder.buildGetValue(wrapVar)
|
||||
if (original is IrSpreadElement) {
|
||||
IrSpreadElementImpl(original.startOffset, original.endOffset, newValue)
|
||||
@@ -641,7 +648,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
|
||||
|
||||
newStatements += instantiater(returnValue)
|
||||
|
||||
return TerminatedResult(newStatements, JsIrBuilder.buildCall(unreachableFunction))
|
||||
return TerminatedResult(newStatements, JsIrBuilder.buildCall(unreachableFunction.symbol))
|
||||
}
|
||||
|
||||
|
||||
@@ -658,7 +665,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
|
||||
)
|
||||
|
||||
override fun visitBreakContinue(jump: IrBreakContinue, data: VisitData): VisitResult {
|
||||
return DecomposedResult(jump, JsIrBuilder.buildCall(unreachableFunction))
|
||||
return DecomposedResult(jump, JsIrBuilder.buildCall(unreachableFunction.symbol))
|
||||
}
|
||||
|
||||
override fun visitTry(aTry: IrTry, data: VisitData): VisitResult {
|
||||
@@ -669,10 +676,10 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
|
||||
finallyResult?.run { assert(status == VisitStatus.KEPT) }
|
||||
|
||||
val resultSymbol = makeTempVar(aTry.type)
|
||||
val resultDeclaration = JsIrBuilder.buildVar(resultSymbol)
|
||||
val resultDeclaration = JsIrBuilder.buildVar(resultSymbol, type = aTry.type)
|
||||
|
||||
val newTryValue = tryResult.runIfChangedOrDefault(aTry.tryResult) { resultValue }
|
||||
val trySetResult = JsIrBuilder.buildSetVariable(resultSymbol, newTryValue) as IrStatement
|
||||
val trySetResult = JsIrBuilder.buildSetVariable(resultSymbol, newTryValue, unitType) as IrStatement
|
||||
|
||||
val tryBlock = IrBlockImpl(aTry.tryResult.startOffset, aTry.tryResult.endOffset, unitType).apply {
|
||||
statements += tryResult.runIfChangedOrDefault(listOf(trySetResult)) { statements + trySetResult }
|
||||
@@ -680,7 +687,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
|
||||
|
||||
val catchBlocks = catchResults.map { (original, result) ->
|
||||
val newCatchResult = result.runIfChangedOrDefault(original.result) { resultValue }
|
||||
val catchSetResult = JsIrBuilder.buildSetVariable(resultSymbol, newCatchResult) as IrStatement
|
||||
val catchSetResult = JsIrBuilder.buildSetVariable(resultSymbol, newCatchResult, unitType) as IrStatement
|
||||
val catchBlock = IrBlockImpl(original.result.startOffset, original.result.endOffset, unitType)
|
||||
catchBlock.statements += result.runIfChangedOrDefault(listOf(catchSetResult)) { statements + catchSetResult }
|
||||
IrCatchImpl(original.startOffset, original.endOffset, original.catchParameter, catchBlock)
|
||||
@@ -713,7 +720,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
|
||||
}
|
||||
}
|
||||
|
||||
fun makeTempVar(type: KotlinType) =
|
||||
fun makeTempVar(type: IrType) =
|
||||
JsSymbolBuilder.buildTempVar(function.symbol, type, "tmp\$dcms\$${tmpVarCounter++}", true)
|
||||
|
||||
fun makeLoopLabel() = "\$l\$${tmpVarCounter++}"
|
||||
@@ -782,7 +789,7 @@ class BlockDecomposerLowering(val context: JsIrBackendContext) : DeclarationCont
|
||||
JsIrBuilder.buildBlock(unitType).also {
|
||||
val elseBlock = if (originalBranch is IrElseBranch) null else it
|
||||
|
||||
val ifElseNode = IrIfThenElseImpl(
|
||||
val ifElseNode = JsIrBuilder.buildIfElse(
|
||||
originalBranch.startOffset,
|
||||
originalBranch.endOffset,
|
||||
unitType,
|
||||
|
||||
+49
-29
@@ -24,6 +24,8 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.toIrType
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
|
||||
@@ -39,9 +41,9 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
|
||||
private val callableToGetterFunction = mutableMapOf<CallableReferenceKey, IrFunction>()
|
||||
private val collectedReferenceMap = mutableMapOf<CallableReferenceKey, IrCallableReference>()
|
||||
|
||||
private val callableNameConst = JsIrBuilder.buildString(context.irBuiltIns.string, Namer.KCALLABLE_NAME)
|
||||
private val getterConst = JsIrBuilder.buildString(context.irBuiltIns.string, Namer.KPROPERTY_GET)
|
||||
private val setterConst = JsIrBuilder.buildString(context.irBuiltIns.string, Namer.KPROPERTY_SET)
|
||||
private val callableNameConst = JsIrBuilder.buildString(context.irBuiltIns.stringType, Namer.KCALLABLE_NAME)
|
||||
private val getterConst = JsIrBuilder.buildString(context.irBuiltIns.stringType, Namer.KPROPERTY_GET)
|
||||
private val setterConst = JsIrBuilder.buildString(context.irBuiltIns.stringType, Namer.KPROPERTY_SET)
|
||||
|
||||
private val newDeclarations = mutableListOf<IrDeclaration>()
|
||||
|
||||
@@ -97,7 +99,13 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
|
||||
}
|
||||
|
||||
private fun redirectToFunction(callable: IrCallableReference, newTarget: IrFunction) =
|
||||
IrCallImpl(callable.startOffset, callable.endOffset, newTarget.symbol, callable.origin).apply {
|
||||
IrCallImpl(
|
||||
callable.startOffset, callable.endOffset,
|
||||
newTarget.symbol.owner.returnType,
|
||||
newTarget.symbol,
|
||||
newTarget.symbol.descriptor,
|
||||
callable.origin
|
||||
).apply {
|
||||
copyTypeArgumentsFrom(callable)
|
||||
var index = 0
|
||||
callable.dispatchReceiver?.let { putValueArgument(index++, it) }
|
||||
@@ -156,13 +164,13 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
|
||||
val additionalDeclarations = generateGetterBodyWithGuard(refGetFunction) {
|
||||
val irClosureReference = JsIrBuilder.buildFunctionReference(functionReference.type, refClosureFunction.symbol)
|
||||
val irVarSymbol = JsSymbolBuilder.buildTempVar(refGetFunction.symbol, irClosureReference.type)
|
||||
val irVar = JsIrBuilder.buildVar(irVarSymbol, irClosureReference)
|
||||
val irVar = JsIrBuilder.buildVar(irVarSymbol, irClosureReference, type = irClosureReference.type)
|
||||
|
||||
// TODO: fill other fields of callable reference (returnType, parameters, isFinal, etc.)
|
||||
val irSetName = JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply {
|
||||
putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol))
|
||||
putValueArgument(1, callableNameConst)
|
||||
putValueArgument(2, JsIrBuilder.buildString(context.irBuiltIns.string, getReferenceName(declaration.descriptor)))
|
||||
putValueArgument(2, JsIrBuilder.buildString(context.irBuiltIns.stringType, getReferenceName(declaration.descriptor)))
|
||||
}
|
||||
Pair(listOf(irVar, irSetName), irVarSymbol)
|
||||
}
|
||||
@@ -203,10 +211,11 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
|
||||
val statements = mutableListOf<IrStatement>()
|
||||
|
||||
val getterFunctionType = context.builtIns.getFunction(getterFunction.valueParameters.size + 1)
|
||||
val irGetReference = JsIrBuilder.buildFunctionReference(getterFunctionType.defaultType, getterFunction.symbol)
|
||||
val irVarSymbol = JsSymbolBuilder.buildTempVar(refGetFunction.symbol, getterFunctionType.defaultType)
|
||||
val type = getterFunctionType.toIrType()
|
||||
val irGetReference = JsIrBuilder.buildFunctionReference(type, getterFunction.symbol)
|
||||
val irVarSymbol = JsSymbolBuilder.buildTempVar(refGetFunction.symbol, type)
|
||||
|
||||
statements += JsIrBuilder.buildVar(irVarSymbol, irGetReference)
|
||||
statements += JsIrBuilder.buildVar(irVarSymbol, irGetReference, type = type)
|
||||
|
||||
statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply {
|
||||
putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol))
|
||||
@@ -216,7 +225,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
|
||||
|
||||
if (setterFunction != null) {
|
||||
val setterFunctionType = context.builtIns.getFunction(setterFunction.valueParameters.size + 1)
|
||||
val irSetReference = JsIrBuilder.buildFunctionReference(setterFunctionType.defaultType, setterFunction.symbol)
|
||||
val irSetReference = JsIrBuilder.buildFunctionReference(setterFunctionType.toIrType(), setterFunction.symbol)
|
||||
statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply {
|
||||
putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol))
|
||||
putValueArgument(1, setterConst)
|
||||
@@ -228,7 +237,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
|
||||
statements += JsIrBuilder.buildCall(context.intrinsics.jsSetJSField.symbol).apply {
|
||||
putValueArgument(0, JsIrBuilder.buildGetValue(irVarSymbol))
|
||||
putValueArgument(1, callableNameConst)
|
||||
putValueArgument(2, JsIrBuilder.buildString(context.irBuiltIns.string, getReferenceName(propertyReference.descriptor)))
|
||||
putValueArgument(2, JsIrBuilder.buildString(context.irBuiltIns.stringType, getReferenceName(propertyReference.descriptor)))
|
||||
}
|
||||
|
||||
Pair(statements, irVarSymbol)
|
||||
@@ -255,22 +264,23 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
|
||||
// }
|
||||
//
|
||||
val cacheName = "${getterFunction.name}_${Namer.KCALLABLE_CACHE_SUFFIX}"
|
||||
val type = getterFunction.returnType
|
||||
val cacheVarSymbol =
|
||||
JsSymbolBuilder.buildVar(getterFunction.descriptor.containingDeclaration, getterFunction.returnType, cacheName, true)
|
||||
val irNull = JsIrBuilder.buildNull(cacheVarSymbol.descriptor.type)
|
||||
val irCacheDeclaration = JsIrBuilder.buildVar(cacheVarSymbol)
|
||||
JsSymbolBuilder.buildVar(getterFunction.descriptor.containingDeclaration, type, cacheName, true)
|
||||
val irNull = JsIrBuilder.buildNull(context.irBuiltIns.nothingNType)
|
||||
val irCacheDeclaration = JsIrBuilder.buildVar(cacheVarSymbol, irNull, type = type)
|
||||
val irCacheValue = JsIrBuilder.buildGetValue(cacheVarSymbol)
|
||||
val irIfCondition = JsIrBuilder.buildCall(context.irBuiltIns.eqeqSymbol).apply {
|
||||
putValueArgument(0, irCacheValue)
|
||||
putValueArgument(1, irNull)
|
||||
}
|
||||
val irSetCache = JsIrBuilder.buildSetVariable(cacheVarSymbol, JsIrBuilder.buildGetValue(varSymbol))
|
||||
val irSetCache = JsIrBuilder.buildSetVariable(cacheVarSymbol, JsIrBuilder.buildGetValue(varSymbol), context.irBuiltIns.unitType)
|
||||
val thenStatements = mutableListOf<IrStatement>().apply {
|
||||
addAll(bodyStatements)
|
||||
add(irSetCache)
|
||||
}
|
||||
val irThenBranch = JsIrBuilder.buildBlock(context.irBuiltIns.unit, thenStatements)
|
||||
val irIfNode = JsIrBuilder.buildIfElse(context.irBuiltIns.unit, irIfCondition, irThenBranch)
|
||||
val irThenBranch = JsIrBuilder.buildBlock(context.irBuiltIns.unitType, thenStatements)
|
||||
val irIfNode = JsIrBuilder.buildIfElse(context.irBuiltIns.unitType, irIfCondition, irThenBranch)
|
||||
statements += irIfNode
|
||||
returnValue = irCacheValue
|
||||
returnStatements = listOf(irCacheDeclaration)
|
||||
@@ -280,7 +290,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
|
||||
returnStatements = emptyList()
|
||||
}
|
||||
|
||||
statements += JsIrBuilder.buildReturn(getterFunction.symbol, returnValue)
|
||||
statements += JsIrBuilder.buildReturn(getterFunction.symbol, returnValue, context)
|
||||
|
||||
getterFunction.body = JsIrBuilder.buildBlockBody(statements)
|
||||
return returnStatements
|
||||
@@ -314,8 +324,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
|
||||
private fun buildGetFunction(declaration: IrFunction, reference: IrCallableReference, getterName: String): IrSimpleFunction {
|
||||
|
||||
val callableType = reference.type
|
||||
val closureParams = callableType.arguments.dropLast(1) // drop return type
|
||||
var kFunctionValueParamsCount = closureParams.size
|
||||
var kFunctionValueParamsCount = (callableType as? IrSimpleType)?.arguments?.size?.minus(1) ?: 0
|
||||
|
||||
if (declaration.dispatchReceiverParameter != null && reference.dispatchReceiver == null) {
|
||||
kFunctionValueParamsCount--
|
||||
@@ -342,14 +351,22 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
|
||||
val refGetSymbol = JsSymbolBuilder.buildSimpleFunction(declaration.descriptor.containingDeclaration, getterName).apply {
|
||||
initialize(
|
||||
valueParameters = getterValueParameters.mapIndexed { i, p -> p.descriptor.copyAsValueParameter(descriptor, i) },
|
||||
type = callableType
|
||||
returnType = callableType
|
||||
)
|
||||
}
|
||||
|
||||
return JsIrBuilder.buildFunction(refGetSymbol).apply {
|
||||
return JsIrBuilder.buildFunction(refGetSymbol, callableType).apply {
|
||||
for (i in 0 until getterValueParameters.size) {
|
||||
val p = getterValueParameters[i]
|
||||
valueParameters += IrValueParameterImpl(p.startOffset, p.endOffset, p.origin, refGetSymbol.descriptor.valueParameters[i])
|
||||
valueParameters +=
|
||||
IrValueParameterImpl(
|
||||
p.startOffset,
|
||||
p.endOffset,
|
||||
p.origin,
|
||||
refGetSymbol.descriptor.valueParameters[i],
|
||||
p.type,
|
||||
p.varargElementType
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -366,15 +383,18 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
|
||||
val closureParamSymbols = generateSignatureForClosure(declaration, refGetFunction, refClosureSymbol, reference)
|
||||
val closureParamDescriptors = closureParamSymbols.map { it.descriptor as ValueParameterDescriptor }
|
||||
|
||||
refClosureSymbol.initialize(valueParameters = closureParamDescriptors, type = declaration.returnType)
|
||||
val returnType = declaration.returnType
|
||||
refClosureSymbol.initialize(valueParameters = closureParamDescriptors, returnType = returnType)
|
||||
|
||||
val closureFunction = JsIrBuilder.buildFunction(refClosureSymbol)
|
||||
val closureFunction = JsIrBuilder.buildFunction(refClosureSymbol, returnType)
|
||||
|
||||
for (it in closureParamSymbols) {
|
||||
closureFunction.valueParameters += JsIrBuilder.buildValueParameter(it)
|
||||
for (param in closureParamSymbols) {
|
||||
// TODO always take type from param
|
||||
val type = if (param.isBound) param.owner.type else context.irBuiltIns.anyType
|
||||
closureFunction.valueParameters += JsIrBuilder.buildValueParameter(param, type)
|
||||
}
|
||||
|
||||
val irCall = JsIrBuilder.buildCall(declaration.symbol)
|
||||
val irCall = JsIrBuilder.buildCall(declaration.symbol, type = returnType)
|
||||
|
||||
var cp = 0
|
||||
var gp = 0
|
||||
@@ -401,7 +421,7 @@ class CallableReferenceLowering(val context: JsIrBackendContext) : FileLoweringP
|
||||
irCall.putValueArgument(j++, JsIrBuilder.buildGetValue(closureParamSymbols[i]))
|
||||
}
|
||||
|
||||
val irClosureReturn = JsIrBuilder.buildReturn(closureFunction.symbol, irCall)
|
||||
val irClosureReturn = JsIrBuilder.buildReturn(closureFunction.symbol, irCall, context)
|
||||
|
||||
closureFunction.body = JsIrBuilder.buildBlockBody(listOf(irClosureReturn))
|
||||
|
||||
|
||||
+34
-19
@@ -6,7 +6,7 @@
|
||||
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.backend.common.utils.isSubtypeOfClass
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
|
||||
@@ -19,10 +19,10 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.copyTypeArgumentsFrom
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.impl.originalKotlinType
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.SimpleType
|
||||
|
||||
class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileLoweringPass {
|
||||
@@ -33,16 +33,13 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL
|
||||
private val symbolToIrFunction: Map<IrFunctionSymbol, IrSimpleFunction>
|
||||
private val nameToIrTransformer: Map<Name, (IrCall) -> IrCall>
|
||||
|
||||
val kCallable = context.builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.kCallable.toSafe())
|
||||
val kProperty = context.builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.kProperty.asSingleFqName())
|
||||
|
||||
init {
|
||||
memberToIrFunction = mutableMapOf()
|
||||
symbolToIrFunction = mutableMapOf()
|
||||
memberToTransformer = mutableMapOf()
|
||||
nameToIrTransformer = mutableMapOf()
|
||||
|
||||
val primitiveNumbers = context.irBuiltIns.run { listOf(int, short, byte, float, double) }
|
||||
val primitiveNumbers = context.irBuiltIns.run { listOf(intType, shortType, byteType, floatType, doubleType) }
|
||||
|
||||
memberToIrFunction.run {
|
||||
for (type in primitiveNumbers) {
|
||||
@@ -57,11 +54,11 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL
|
||||
op(type, OperatorNames.REM, context.intrinsics.jsMod)
|
||||
}
|
||||
|
||||
context.irBuiltIns.string.let {
|
||||
context.irBuiltIns.stringType.let {
|
||||
op(it, OperatorNames.ADD, context.intrinsics.jsPlus)
|
||||
}
|
||||
|
||||
context.irBuiltIns.int.let {
|
||||
context.irBuiltIns.intType.let {
|
||||
op(it, OperatorNames.SHL, context.intrinsics.jsBitShiftL)
|
||||
op(it, OperatorNames.SHR, context.intrinsics.jsBitShiftR)
|
||||
op(it, OperatorNames.SHRU, context.intrinsics.jsBitShiftRU)
|
||||
@@ -71,7 +68,7 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL
|
||||
op(it, OperatorNames.INV, context.intrinsics.jsBitNot)
|
||||
}
|
||||
|
||||
context.irBuiltIns.bool.let {
|
||||
context.irBuiltIns.booleanType.let {
|
||||
op(it, OperatorNames.AND, context.intrinsics.jsBitAnd)
|
||||
op(it, OperatorNames.OR, context.intrinsics.jsBitOr)
|
||||
op(it, OperatorNames.NOT, context.intrinsics.jsNot)
|
||||
@@ -99,12 +96,12 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL
|
||||
// TODO: use increment and decrement when it's possible
|
||||
op(type, OperatorNames.INC) {
|
||||
irCall(it, context.intrinsics.jsPlus.symbol, dispatchReceiverAsFirstArgument = true).apply {
|
||||
putValueArgument(1, JsIrBuilder.buildInt(context.irBuiltIns.int, 1))
|
||||
putValueArgument(1, JsIrBuilder.buildInt(context.irBuiltIns.intType, 1))
|
||||
}
|
||||
}
|
||||
op(type, OperatorNames.DEC) {
|
||||
irCall(it, context.intrinsics.jsMinus.symbol, dispatchReceiverAsFirstArgument = true).apply {
|
||||
putValueArgument(1, JsIrBuilder.buildInt(context.irBuiltIns.int, 1))
|
||||
putValueArgument(1, JsIrBuilder.buildInt(context.irBuiltIns.intType, 1))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -113,18 +110,18 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL
|
||||
nameToIrTransformer.run {
|
||||
addWithPredicate(
|
||||
Name.special(Namer.KCALLABLE_GET_NAME),
|
||||
{ call -> call.symbol.owner.dispatchReceiverParameter?.run { DescriptorUtils.isSubtypeOfClass(type, kCallable) } ?: false },
|
||||
{ call -> call.symbol.owner.dispatchReceiverParameter?.run { type.isSubtypeOfClass(context.irBuiltIns.kCallableClass) } ?: false },
|
||||
{ call -> irCall(call, context.intrinsics.jsName.symbol, dispatchReceiverAsFirstArgument = true) })
|
||||
|
||||
addWithPredicate(
|
||||
Name.identifier(Namer.KPROPERTY_GET),
|
||||
{ call -> call.symbol.owner.dispatchReceiverParameter?.run { DescriptorUtils.isSubtypeOfClass(type, kProperty) } ?: false },
|
||||
{ call -> call.symbol.owner.dispatchReceiverParameter?.run { type.isSubtypeOfClass(context.irBuiltIns.kPropertyClass) } ?: false },
|
||||
{ call -> irCall(call, context.intrinsics.jsPropertyGet.symbol, dispatchReceiverAsFirstArgument = true)}
|
||||
)
|
||||
|
||||
addWithPredicate(
|
||||
Name.identifier(Namer.KPROPERTY_SET),
|
||||
{ call -> call.symbol.owner.dispatchReceiverParameter?.run { DescriptorUtils.isSubtypeOfClass(type, kProperty) } ?: false},
|
||||
{ call -> call.symbol.owner.dispatchReceiverParameter?.run { type.isSubtypeOfClass(context.irBuiltIns.kPropertyClass) } ?: false},
|
||||
{ call -> irCall(call, context.intrinsics.jsPropertySet.symbol, dispatchReceiverAsFirstArgument = true)}
|
||||
)
|
||||
}
|
||||
@@ -207,12 +204,11 @@ private fun IrCall.copyTypeAndValueArgumentsFrom(call: IrCall, dispatchReceiverA
|
||||
}
|
||||
}
|
||||
|
||||
private fun <V> MutableMap<SimpleMemberKey, V>.op(type: KotlinType, name: Name, v: V) {
|
||||
private fun <V> MutableMap<SimpleMemberKey, V>.op(type: IrType, name: Name, v: V) {
|
||||
put(SimpleMemberKey(type, name), v)
|
||||
}
|
||||
|
||||
// TODO issue: marked as unused, but used; rename works wrongly.
|
||||
private fun <V> MutableMap<SimpleMemberKey, V>.op(type: KotlinType, name: String, v: V) {
|
||||
private fun <V> MutableMap<SimpleMemberKey, V>.op(type: IrType, name: String, v: V) {
|
||||
put(SimpleMemberKey(type, Name.identifier(name)), v)
|
||||
}
|
||||
|
||||
@@ -232,4 +228,23 @@ private fun <K> MutableMap<K, (IrCall) -> IrCall>.addWithPredicate(from: K, pred
|
||||
|
||||
private inline fun <T> select(crossinline predicate: () -> Boolean, crossinline ifTrue: () -> T, crossinline ifFalse: () -> T): T = if (predicate()) ifTrue() else ifFalse()
|
||||
|
||||
private data class SimpleMemberKey(val klass: KotlinType, val name: Name)
|
||||
private class SimpleMemberKey(val klass: IrType, val name: Name) {
|
||||
// TODO drop custom equals and hashCode when IrTypes will have right equals
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (javaClass != other?.javaClass) return false
|
||||
|
||||
other as SimpleMemberKey
|
||||
|
||||
if (name != other.name) return false
|
||||
if (klass.originalKotlinType != other.klass.originalKotlinType) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = klass.originalKotlinType?.hashCode() ?: 0
|
||||
result = 31 * result + name.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
+23
-19
@@ -6,6 +6,8 @@
|
||||
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.utils.commonSupertype
|
||||
import org.jetbrains.kotlin.backend.common.utils.isSubtypeOf
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||
@@ -18,11 +20,10 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrCatchImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrElseBranchImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrTryImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrDynamicType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.types.CommonSupertypes
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.isDynamic
|
||||
import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
|
||||
/**
|
||||
* Since JS does not support multiple catch blocks by default we should replace them with similar `when` statement, so
|
||||
@@ -49,9 +50,9 @@ import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf
|
||||
*/
|
||||
|
||||
class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
||||
val litTrue = JsIrBuilder.buildBoolean(context.irBuiltIns.bool, true)
|
||||
val unitType = context.irBuiltIns.unit
|
||||
val nothingType = context.irBuiltIns.nothing
|
||||
val litTrue = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true)
|
||||
val unitType = context.irBuiltIns.unitType
|
||||
val nothingType = context.irBuiltIns.nothingType
|
||||
|
||||
override fun lower(irFile: IrFile) {
|
||||
irFile.transformChildren(object : IrElementTransformer<IrDeclaration?> {
|
||||
@@ -67,7 +68,7 @@ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPas
|
||||
val commonType = mergeTypes(aTry.catches.map { it.catchParameter.type })
|
||||
|
||||
val pendingExceptionSymbol = JsSymbolBuilder.buildVar(data!!.descriptor, commonType, "\$pending\$", false)
|
||||
val pendingExceptionDeclaration = JsIrBuilder.buildVar(pendingExceptionSymbol)
|
||||
val pendingExceptionDeclaration = JsIrBuilder.buildVar(pendingExceptionSymbol, type = commonType)
|
||||
val pendingException = JsIrBuilder.buildGetValue(pendingExceptionSymbol)
|
||||
|
||||
val branches = mutableListOf<IrBranch>()
|
||||
@@ -75,24 +76,27 @@ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPas
|
||||
for (catch in aTry.catches) {
|
||||
assert(!catch.catchParameter.isVar) { "caught exception parameter has to immutable" }
|
||||
val type = catch.catchParameter.type
|
||||
val typeSymbol = context.symbolTable.referenceClassifier(type.constructor.declarationDescriptor!!)
|
||||
val castedPendingException = buildImplicitCast(pendingException, type, typeSymbol)
|
||||
val typeSymbol = type.classifierOrNull
|
||||
val catchBody = catch.result.transform(object : IrElementTransformer<VariableDescriptor> {
|
||||
override fun visitGetValue(expression: IrGetValue, data: VariableDescriptor) =
|
||||
if (expression.descriptor == data) castedPendingException else expression
|
||||
if (typeSymbol != null && expression.descriptor == data)
|
||||
// TODO how is it good to generate implicit cast for each access?
|
||||
buildImplicitCast(pendingException, type, typeSymbol)
|
||||
else
|
||||
expression
|
||||
}, catch.parameter)
|
||||
|
||||
if (type.isDynamic()) {
|
||||
if (type is IrDynamicType) {
|
||||
branches += IrElseBranchImpl(catch.startOffset, catch.endOffset, litTrue, catchBody)
|
||||
break
|
||||
} else {
|
||||
val typeCheck = buildIsCheck(pendingException, type, typeSymbol)
|
||||
val typeCheck = buildIsCheck(pendingException, type, typeSymbol!!)
|
||||
branches += IrBranchImpl(catch.startOffset, catch.endOffset, typeCheck, catchBody)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!commonType.isDynamic()) {
|
||||
if (commonType !is IrDynamicType) {
|
||||
val throwStatement = JsIrBuilder.buildThrow(nothingType, pendingException)
|
||||
branches += IrElseBranchImpl(litTrue, JsIrBuilder.buildBlock(nothingType, listOf(throwStatement)))
|
||||
}
|
||||
@@ -106,14 +110,14 @@ class MultipleCatchesLowering(val context: JsIrBackendContext) : FileLoweringPas
|
||||
return aTry.run { IrTryImpl(startOffset, endOffset, type, tryResult, listOf(newCatch), finallyExpression) }
|
||||
}
|
||||
|
||||
private fun buildIsCheck(value: IrExpression, toType: KotlinType, toTypeSymbol: IrClassifierSymbol) =
|
||||
JsIrBuilder.buildTypeOperator(context.irBuiltIns.bool, IrTypeOperator.INSTANCEOF, value, toType, toTypeSymbol)
|
||||
private fun buildIsCheck(value: IrExpression, toType: IrType, toTypeSymbol: IrClassifierSymbol) =
|
||||
JsIrBuilder.buildTypeOperator(context.irBuiltIns.booleanType, IrTypeOperator.INSTANCEOF, value, toType, toTypeSymbol)
|
||||
|
||||
private fun buildImplicitCast(value: IrExpression, toType: KotlinType, toTypeSymbol: IrClassifierSymbol) =
|
||||
private fun buildImplicitCast(value: IrExpression, toType: IrType, toTypeSymbol: IrClassifierSymbol) =
|
||||
JsIrBuilder.buildTypeOperator(toType, IrTypeOperator.IMPLICIT_CAST, value, toType, toTypeSymbol)
|
||||
|
||||
private fun mergeTypes(types: List<KotlinType>) = CommonSupertypes.commonSupertype(types).also {
|
||||
assert(it.isSubtypeOf(context.builtIns.throwable.defaultType) || it.isDynamic())
|
||||
private fun mergeTypes(types: List<IrType>) = types.commonSupertype().also {
|
||||
assert(it.isSubtypeOf(context.irBuiltIns.throwableType) || it is IrDynamicType)
|
||||
}
|
||||
|
||||
}, null)
|
||||
|
||||
+26
-16
@@ -26,6 +26,8 @@ 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.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.transformFlat
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
@@ -72,8 +74,9 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
|
||||
// val t = Object.create(Foo.prototype);
|
||||
// return Foo_init_$Init$(..., t)
|
||||
// }
|
||||
val newInitConstructor = createInitConstructor(declaration, constructorName)
|
||||
val newCreateConstructor = createCreateConstructor(declaration, newInitConstructor, constructorName)
|
||||
|
||||
val newInitConstructor = createInitConstructor(declaration, constructorName, irClass.defaultType)
|
||||
val newCreateConstructor = createCreateConstructor(declaration, newInitConstructor, constructorName, irClass.defaultType)
|
||||
|
||||
oldCtorToNewMap[declaration.symbol] =
|
||||
JsIrBackendContext.SecondaryCtorPair(newInitConstructor.symbol, newCreateConstructor.symbol)
|
||||
@@ -95,14 +98,16 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
|
||||
override fun visitReturn(expression: IrReturn): IrExpression = IrReturnImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
expression.type,
|
||||
function,
|
||||
IrGetValueImpl(expression.startOffset, expression.endOffset, thisSymbol)
|
||||
IrGetValueImpl(expression.startOffset, expression.endOffset, thisSymbol.owner.type, thisSymbol)
|
||||
)
|
||||
|
||||
override fun visitGetValue(expression: IrGetValue): IrExpression =
|
||||
if (expression.descriptor.name.isSpecial && expression.descriptor.name.asString() == Namer.THIS_SPECIAL_NAME) IrGetValueImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
expression.type,
|
||||
thisSymbol,
|
||||
expression.origin
|
||||
) else {
|
||||
@@ -110,28 +115,32 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
|
||||
}
|
||||
}
|
||||
|
||||
private fun createInitConstructor(declaration: IrConstructor, name: String): IrSimpleFunction =
|
||||
private fun createInitConstructor(
|
||||
declaration: IrConstructor,
|
||||
name: String,
|
||||
type: IrType
|
||||
): IrSimpleFunction =
|
||||
JsSymbolBuilder.copyFunctionSymbol(declaration.symbol, "${name}_\$Init\$").let {
|
||||
|
||||
val thisSymbol =
|
||||
JsSymbolBuilder.buildValueParameter(it, declaration.valueParameters.size, declaration.returnType, "\$this")
|
||||
JsSymbolBuilder.buildValueParameter(it, declaration.valueParameters.size, type, "\$this")
|
||||
|
||||
it.initialize(
|
||||
dispatchParameterDescriptor = declaration.descriptor.dispatchReceiverParameter,
|
||||
typeParameters = declaration.descriptor.typeParameters,
|
||||
valueParameters = declaration.descriptor.valueParameters + thisSymbol.descriptor as ValueParameterDescriptor,
|
||||
type = declaration.descriptor.returnType,
|
||||
returnType = type,
|
||||
modality = declaration.descriptor.modality,
|
||||
visibility = declaration.descriptor.visibility
|
||||
)
|
||||
|
||||
val thisParam = JsIrBuilder.buildValueParameter(thisSymbol)
|
||||
val thisParam = JsIrBuilder.buildValueParameter(thisSymbol, type)
|
||||
|
||||
return IrFunctionImpl(
|
||||
declaration.startOffset, declaration.endOffset,
|
||||
declaration.origin, it
|
||||
).apply {
|
||||
val retStmt = JsIrBuilder.buildReturn(it, JsIrBuilder.buildGetValue(thisSymbol))
|
||||
val retStmt = JsIrBuilder.buildReturn(it, JsIrBuilder.buildGetValue(thisSymbol), context)
|
||||
val statements = (declaration.body as IrStatementContainer).statements
|
||||
|
||||
valueParameters += (declaration.valueParameters + thisParam)
|
||||
@@ -145,13 +154,13 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
|
||||
}
|
||||
|
||||
|
||||
private fun createCreateConstructor(ctorOrig: IrConstructor, ctorImpl: IrSimpleFunction, name: String): IrSimpleFunction =
|
||||
private fun createCreateConstructor(ctorOrig: IrConstructor, ctorImpl: IrSimpleFunction, name: String, type: IrType): 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,
|
||||
returnType = type,
|
||||
modality = ctorOrig.descriptor.modality,
|
||||
visibility = ctorOrig.visibility
|
||||
)
|
||||
@@ -165,14 +174,14 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
|
||||
typeParameters += ctorOrig.typeParameters
|
||||
// parent = ctorOrig.parent
|
||||
|
||||
val returnType = ctorOrig.returnType
|
||||
val returnType = type
|
||||
val createFunctionIntrinsic = context.intrinsics.jsObjectCreate
|
||||
val irCreateCall = JsIrBuilder.buildCall(
|
||||
createFunctionIntrinsic.symbol,
|
||||
returnType,
|
||||
mapOf(createFunctionIntrinsic.typeParameters[0].descriptor to returnType)
|
||||
listOf(returnType)
|
||||
)
|
||||
val irDelegateCall = JsIrBuilder.buildCall(ctorImpl.symbol).also {
|
||||
val irDelegateCall = JsIrBuilder.buildCall(ctorImpl.symbol, type).also {
|
||||
for (i in 0 until valueParameters.size) {
|
||||
it.putValueArgument(i, JsIrBuilder.buildGetValue(valueParameters[i].symbol))
|
||||
}
|
||||
@@ -181,7 +190,7 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
|
||||
|
||||
// typeParameters.mapIndexed { i, t -> ctorImpl.typeParameters[i].descriptor -> }
|
||||
}
|
||||
val irReturn = JsIrBuilder.buildReturn(it, irDelegateCall)
|
||||
val irReturn = JsIrBuilder.buildReturn(it, irDelegateCall, context)
|
||||
|
||||
|
||||
body = JsIrBuilder.buildBlockBody(listOf(irReturn))
|
||||
@@ -233,10 +242,11 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
|
||||
IrGetValueImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
expression.type,
|
||||
IrValueParameterSymbolImpl(LazyClassReceiverParameterDescriptor(target.descriptor.containingDeclaration))
|
||||
)
|
||||
} else {
|
||||
IrGetValueImpl(expression.startOffset, expression.endOffset, ownerFunc.valueParameters.last().symbol)
|
||||
IrGetValueImpl(expression.startOffset, expression.endOffset, expression.type, ownerFunc.valueParameters.last().symbol)
|
||||
}
|
||||
|
||||
newCall.putValueArgument(expression.valueArgumentsCount, readThis)
|
||||
@@ -247,7 +257,7 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
|
||||
private fun redirectCall(
|
||||
call: IrFunctionAccessExpression,
|
||||
newTarget: IrSimpleFunctionSymbol
|
||||
) = IrCallImpl(call.startOffset, call.endOffset, newTarget).apply {
|
||||
) = IrCallImpl(call.startOffset, call.endOffset, call.type, newTarget).apply {
|
||||
|
||||
copyTypeArgumentsFrom(call)
|
||||
|
||||
|
||||
+57
-51
@@ -6,35 +6,34 @@
|
||||
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.isFunctionOrKFunctionType
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.backend.common.utils.*
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrArithBuilder
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||
import org.jetbrains.kotlin.ir.backend.js.symbols.JsSymbolBuilder
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.isReified
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperator
|
||||
import org.jetbrains.kotlin.ir.expressions.IrTypeOperatorCall
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.isNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.*
|
||||
|
||||
class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
||||
private val unit = context.builtIns.unit
|
||||
private val unitValue = JsIrBuilder.buildGetObjectValue(unit.defaultType, context.symbolTable.referenceClass(unit))
|
||||
private val unit = context.irBuiltIns.unitType
|
||||
private val unitValue = JsIrBuilder.buildGetObjectValue(unit, unit.classifierOrFail as IrClassSymbol)
|
||||
|
||||
private val lit24 = JsIrBuilder.buildInt(context.builtIns.intType, 24)
|
||||
private val lit16 = JsIrBuilder.buildInt(context.builtIns.intType, 16)
|
||||
private val lit24 = JsIrBuilder.buildInt(context.irBuiltIns.intType, 24)
|
||||
private val lit16 = JsIrBuilder.buildInt(context.irBuiltIns.intType, 16)
|
||||
|
||||
private val byteMask = JsIrBuilder.buildInt(context.builtIns.intType, 0xFF)
|
||||
private val shortMask = JsIrBuilder.buildInt(context.builtIns.intType, 0xFFFF)
|
||||
private val byteMask = JsIrBuilder.buildInt(context.irBuiltIns.intType, 0xFF)
|
||||
private val shortMask = JsIrBuilder.buildInt(context.irBuiltIns.intType, 0xFFFF)
|
||||
|
||||
private val calculator = JsIrArithBuilder(context)
|
||||
|
||||
@@ -53,13 +52,13 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
||||
private val typeOfIntrinsicSymbol = context.intrinsics.jsTypeOf.symbol
|
||||
private val toJSTypeIntrinsicSymbol = context.intrinsics.jsToJsType.symbol
|
||||
|
||||
private val stringMarker = JsIrBuilder.buildString(context.irBuiltIns.string, "string")
|
||||
private val booleanMarker = JsIrBuilder.buildString(context.irBuiltIns.string, "boolean")
|
||||
private val functionMarker = JsIrBuilder.buildString(context.irBuiltIns.string, "function")
|
||||
private val numberMarker = JsIrBuilder.buildString(context.irBuiltIns.string, "number")
|
||||
private val stringMarker = JsIrBuilder.buildString(context.irBuiltIns.stringType, "string")
|
||||
private val booleanMarker = JsIrBuilder.buildString(context.irBuiltIns.stringType, "boolean")
|
||||
private val functionMarker = JsIrBuilder.buildString(context.irBuiltIns.stringType, "function")
|
||||
private val numberMarker = JsIrBuilder.buildString(context.irBuiltIns.stringType, "number")
|
||||
|
||||
private val litTrue: IrExpression = JsIrBuilder.buildBoolean(context.irBuiltIns.bool, true)
|
||||
private val litNull: IrExpression = JsIrBuilder.buildNull(context.builtIns.nullableNothingType)
|
||||
private val litTrue: IrExpression = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, true)
|
||||
private val litNull: IrExpression = JsIrBuilder.buildNull(context.irBuiltIns.nothingNType)
|
||||
|
||||
private fun getInternalFunction(name: String) = context.symbolTable.referenceSimpleFunction(context.getInternalFunctions(name).single())
|
||||
|
||||
@@ -126,16 +125,21 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
||||
}
|
||||
|
||||
// Note: native `instanceOf` is not used which is important because of null-behaviour
|
||||
private fun advancedCheckRequired(type: KotlinType) = type.isInterface() ||
|
||||
KotlinBuiltIns.isArray(type) ||
|
||||
KotlinBuiltIns.isPrimitiveArray(type) ||
|
||||
private fun advancedCheckRequired(type: IrType) = type.isInterface() ||
|
||||
type.isArray() ||
|
||||
type.isPrimitiveArray() ||
|
||||
isTypeOfCheckingType(type)
|
||||
|
||||
private fun isTypeOfCheckingType(type: KotlinType) =
|
||||
((type.isPrimitiveNumberType() || KotlinBuiltIns.isNumber(type)) && !type.isLong() && !type.isChar()) ||
|
||||
private fun isTypeOfCheckingType(type: IrType) =
|
||||
type.isByte() ||
|
||||
type.isShort() ||
|
||||
type.isInt() ||
|
||||
type.isFloat() ||
|
||||
type.isDouble() ||
|
||||
type.isNumber() ||
|
||||
type.isBoolean() ||
|
||||
type.isFunctionOrKFunctionType ||
|
||||
KotlinBuiltIns.isString(type)
|
||||
type.isFunctionOrKFunction() ||
|
||||
type.isString()
|
||||
|
||||
fun lowerInstanceOf(
|
||||
expression: IrTypeOperatorCall,
|
||||
@@ -146,7 +150,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
||||
assert((expression.operator == IrTypeOperator.NOT_INSTANCEOF) == inverted)
|
||||
|
||||
val toType = expression.typeOperand
|
||||
val isCopyRequired = expression.argument.type.isNullable() && advancedCheckRequired(toType.makeNotNullable())
|
||||
val isCopyRequired = expression.argument.type.isNullable() && advancedCheckRequired(toType.makeNotNull())
|
||||
val newStatements = mutableListOf<IrStatement>()
|
||||
|
||||
val argument =
|
||||
@@ -167,12 +171,12 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
||||
|
||||
private fun cacheValue(value: IrExpression, newStatements: MutableList<IrStatement>, cd: DeclarationDescriptor): IrExpression {
|
||||
val varSymbol = JsSymbolBuilder.buildTempVar(cd, value.type, mutable = false)
|
||||
newStatements += JsIrBuilder.buildVar(varSymbol, value)
|
||||
newStatements += JsIrBuilder.buildVar(varSymbol, value, value.type)
|
||||
return JsIrBuilder.buildGetValue(varSymbol)
|
||||
}
|
||||
|
||||
private fun generateTypeCheck(argument: IrExpression, toType: KotlinType): IrExpression {
|
||||
val toNotNullable = toType.makeNotNullable()
|
||||
private fun generateTypeCheck(argument: IrExpression, toType: IrType): IrExpression {
|
||||
val toNotNullable = toType.makeNotNull()
|
||||
val instanceCheck = generateTypeCheckNonNull(argument, toNotNullable)
|
||||
val isFromNullable = argument.type.isNullable()
|
||||
val isToNullable = toType.isNullable()
|
||||
@@ -190,14 +194,14 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateTypeCheckNonNull(argument: IrExpression, toType: KotlinType): IrExpression {
|
||||
assert(!toType.isMarkedNullable)
|
||||
private fun generateTypeCheckNonNull(argument: IrExpression, toType: IrType): IrExpression {
|
||||
assert(!toType.isMarkedNullable())
|
||||
return when {
|
||||
KotlinBuiltIns.isAny(toType) -> generateIsObjectCheck(argument)
|
||||
toType.isAny() -> generateIsObjectCheck(argument)
|
||||
isTypeOfCheckingType(toType) -> generateTypeOfCheck(argument, toType)
|
||||
toType.isChar() -> generateCheckForChar(argument)
|
||||
KotlinBuiltIns.isArray(toType) -> generateGenericArrayCheck(argument)
|
||||
KotlinBuiltIns.isPrimitiveArray(toType) -> generatePrimitiveArrayTypeCheck(argument, toType)
|
||||
toType.isArray() -> generateGenericArrayCheck(argument)
|
||||
toType.isPrimitiveArray() -> generatePrimitiveArrayTypeCheck(argument, toType)
|
||||
toType.isTypeParameter() -> generateTypeCheckWithTypeParameter(argument, toType)
|
||||
toType.isInterface() -> generateInterfaceCheck(argument, toType)
|
||||
else -> generateNativeInstanceOf(argument, toType)
|
||||
@@ -208,12 +212,14 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
||||
putValueArgument(0, argument)
|
||||
}
|
||||
|
||||
private fun generateTypeCheckWithTypeParameter(argument: IrExpression, toType: KotlinType): IrExpression {
|
||||
val typeParameterDescriptor = toType.constructor.declarationDescriptor as TypeParameterDescriptor
|
||||
assert(!typeParameterDescriptor.isReified) { "reified parameters have to be lowered before" }
|
||||
private fun generateTypeCheckWithTypeParameter(argument: IrExpression, toType: IrType): IrExpression {
|
||||
val typeParameter =
|
||||
(toType.classifierOrNull as? IrTypeParameterSymbol)?.owner ?: error("expected type parameter, but $toType")
|
||||
|
||||
return typeParameterDescriptor.upperBounds.fold(litTrue) { r, t ->
|
||||
val check = generateTypeCheckNonNull(argument, t.makeNotNullable())
|
||||
assert(!typeParameter.isReified) { "reified parameters have to be lowered before" }
|
||||
|
||||
return typeParameter.superTypes.fold(litTrue) { r, t ->
|
||||
val check = generateTypeCheckNonNull(argument, t.makeNotNull())
|
||||
calculator.and(r, check)
|
||||
}
|
||||
}
|
||||
@@ -221,11 +227,11 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
||||
private fun generateCheckForChar(argument: IrExpression) =
|
||||
JsIrBuilder.buildCall(isCharSymbol).apply { dispatchReceiver = argument }
|
||||
|
||||
private fun generateTypeOfCheck(argument: IrExpression, toType: KotlinType): IrExpression {
|
||||
private fun generateTypeOfCheck(argument: IrExpression, toType: IrType): IrExpression {
|
||||
val marker = when {
|
||||
toType.isFunctionOrKFunctionType -> functionMarker
|
||||
toType.isFunctionOrKFunction() -> functionMarker
|
||||
toType.isBoolean() -> booleanMarker
|
||||
KotlinBuiltIns.isString(toType) -> stringMarker
|
||||
toType.isString() -> stringMarker
|
||||
else -> numberMarker
|
||||
}
|
||||
|
||||
@@ -236,17 +242,17 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
||||
}
|
||||
}
|
||||
|
||||
private fun wrapTypeReference(toType: KotlinType) =
|
||||
private fun wrapTypeReference(toType: IrType) =
|
||||
JsIrBuilder.buildCall(toJSTypeIntrinsicSymbol).apply { putTypeArgument(0, toType) }
|
||||
|
||||
private fun generateGenericArrayCheck(argument: IrExpression) =
|
||||
JsIrBuilder.buildCall(isArraySymbol).apply { putValueArgument(0, argument) }
|
||||
|
||||
private fun generatePrimitiveArrayTypeCheck(argument: IrExpression, toType: KotlinType): IrExpression {
|
||||
private fun generatePrimitiveArrayTypeCheck(argument: IrExpression, toType: IrType): IrExpression {
|
||||
TODO("Implement Typed Array check")
|
||||
}
|
||||
|
||||
private fun generateInterfaceCheck(argument: IrExpression, toType: KotlinType): IrExpression {
|
||||
private fun generateInterfaceCheck(argument: IrExpression, toType: IrType): IrExpression {
|
||||
val irType = wrapTypeReference(toType)
|
||||
return JsIrBuilder.buildCall(isInterfaceSymbol).apply {
|
||||
putValueArgument(0, argument)
|
||||
@@ -254,7 +260,7 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateNativeInstanceOf(argument: IrExpression, toType: KotlinType): IrExpression {
|
||||
private fun generateNativeInstanceOf(argument: IrExpression, toType: IrType): IrExpression {
|
||||
val irType = wrapTypeReference(toType)
|
||||
return JsIrBuilder.buildCall(instanceOfIntrinsicSymbol).apply {
|
||||
putValueArgument(0, argument)
|
||||
@@ -264,12 +270,12 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
||||
|
||||
private fun lowerCoercionToUnit(expression: IrTypeOperatorCall): IrExpression {
|
||||
assert(expression.operator === IrTypeOperator.IMPLICIT_COERCION_TO_UNIT)
|
||||
return expression.run { IrCompositeImpl(startOffset, endOffset, unit.defaultType, null, listOf(argument, unitValue)) }
|
||||
return expression.run { IrCompositeImpl(startOffset, endOffset, unit, null, listOf(argument, unitValue)) }
|
||||
}
|
||||
|
||||
private fun lowerIntegerCoercion(expression: IrTypeOperatorCall, containingDeclaration: DeclarationDescriptor): IrExpression {
|
||||
assert(expression.operator === IrTypeOperator.IMPLICIT_INTEGER_COERCION)
|
||||
assert(KotlinBuiltIns.isInt(expression.argument.type))
|
||||
assert(expression.argument.type.isInt())
|
||||
|
||||
val isNullable = expression.argument.type.isNullable()
|
||||
val toType = expression.typeOperand
|
||||
@@ -284,9 +290,9 @@ class TypeOperatorLowering(val context: JsIrBackendContext) : FileLoweringPass {
|
||||
if (isNullable) cacheValue(expression.argument, newStatements, containingDeclaration) else expression.argument
|
||||
|
||||
val casted = when {
|
||||
KotlinBuiltIns.isByte(toType) -> maskOp(argument, byteMask, lit24)
|
||||
KotlinBuiltIns.isShort(toType) -> maskOp(argument, shortMask, lit16)
|
||||
KotlinBuiltIns.isLong(toType) -> TODO("Long coercion")
|
||||
toType.isByte() -> maskOp(argument, byteMask, lit24)
|
||||
toType.isShort() -> maskOp(argument, shortMask, lit16)
|
||||
toType.isLong() -> TODO("Long coercion")
|
||||
else -> error("Unreachable execution (coercion to non-Integer type")
|
||||
}
|
||||
|
||||
|
||||
+13
-9
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.createClassSymbolOrNull
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.createFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.createValueSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.DeepCopyIrTree
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
@@ -34,7 +35,6 @@ import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
|
||||
|
||||
// backend.native/compiler/ir/backend.native/src/org/jetbrains/kotlin/backend/konan/lower/DeepCopyIrTreeWithDescriptors.kt
|
||||
@@ -479,7 +479,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
||||
return IrCallImpl(
|
||||
startOffset = expression.startOffset,
|
||||
endOffset = expression.endOffset,
|
||||
type = newDescriptor.returnType!!,
|
||||
type = newDescriptor.returnType?.toIrType()!!,
|
||||
descriptor = newDescriptor,
|
||||
typeArgumentsCount = expression.typeArgumentsCount,
|
||||
origin = expression.origin,
|
||||
@@ -517,7 +517,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
||||
|
||||
//---------------------------------------------------------------------//
|
||||
|
||||
fun getTypeOperatorReturnType(operator: IrTypeOperator, type: KotlinType) : KotlinType {
|
||||
fun getTypeOperatorReturnType(operator: IrTypeOperator, type: IrType) : IrType {
|
||||
return when (operator) {
|
||||
IrTypeOperator.CAST,
|
||||
IrTypeOperator.IMPLICIT_CAST,
|
||||
@@ -526,7 +526,7 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
||||
IrTypeOperator.IMPLICIT_INTEGER_COERCION -> type
|
||||
IrTypeOperator.SAFE_CAST -> type.makeNullable()
|
||||
IrTypeOperator.INSTANCEOF,
|
||||
IrTypeOperator.NOT_INSTANCEOF -> context.builtIns.booleanType
|
||||
IrTypeOperator.NOT_INSTANCEOF -> context.irBuiltIns.booleanType
|
||||
}
|
||||
}
|
||||
|
||||
@@ -541,7 +541,8 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
||||
type = returnType,
|
||||
operator = expression.operator,
|
||||
typeOperand = typeOperand,
|
||||
argument = expression.argument.transform(this, null)
|
||||
argument = expression.argument.transform(this, null),
|
||||
typeOperandClassifier = typeOperand.classifierOrFail
|
||||
)
|
||||
}
|
||||
|
||||
@@ -610,6 +611,8 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
private fun substituteType(oldType: IrType?): IrType? = substituteType(oldType?.toKotlinType())?.toIrType()
|
||||
|
||||
private fun substituteType(oldType: KotlinType?): KotlinType? {
|
||||
if (typeSubstitutor == null) return oldType
|
||||
if (oldType == null) return oldType
|
||||
@@ -699,7 +702,8 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap<
|
||||
endOffset = declaration.endOffset,
|
||||
origin = declaration.origin,
|
||||
descriptor = newDescriptor,
|
||||
initializer = declaration.initializer
|
||||
initializer = declaration.initializer,
|
||||
type = declaration.type
|
||||
)
|
||||
}
|
||||
|
||||
@@ -715,7 +719,8 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap<
|
||||
startOffset = expression.startOffset,
|
||||
endOffset = expression.endOffset,
|
||||
origin = expression.origin,
|
||||
symbol = createValueSymbol(newDescriptor)
|
||||
symbol = createValueSymbol(newDescriptor),
|
||||
type = expression.type
|
||||
)
|
||||
}
|
||||
|
||||
@@ -732,7 +737,7 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap<
|
||||
return IrCallImpl(
|
||||
startOffset = oldExpression.startOffset,
|
||||
endOffset = oldExpression.endOffset,
|
||||
type = newDescriptor.returnType!!,
|
||||
type = oldExpression.type,
|
||||
symbol = createFunctionSymbol(newDescriptor),
|
||||
descriptor = newDescriptor,
|
||||
typeArgumentsCount = oldExpression.typeArgumentsCount,
|
||||
@@ -763,4 +768,3 @@ class DescriptorSubstitutorForExternalScope(val globalSubstituteMap: MutableMap<
|
||||
return oldExpression.shallowCopy(oldExpression.origin, createFunctionSymbol(newDescriptor), oldExpression.superQualifierSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+17
-13
@@ -23,14 +23,16 @@ import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.getDefault
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.createValueSymbol
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.calls.components.hasDefaultValue
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.TypeProjection
|
||||
@@ -149,8 +151,8 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
val irBuilder = context.createIrBuilder(irReturnableBlockSymbol, startOffset, endOffset)
|
||||
irBuilder.run {
|
||||
val constructorDescriptor = delegatingConstructorCall.descriptor.original
|
||||
val constructorCall = irCall(delegatingConstructorCall.symbol,
|
||||
constructorDescriptor.typeParameters.associate { it to delegatingConstructorCall.getTypeArgument(it)!! }).apply {
|
||||
val constructorCall = irCall(delegatingConstructorCall.symbol).apply {
|
||||
constructorDescriptor.typeParameters.forEach() { putTypeArgument(it.index, delegatingConstructorCall.getTypeArgument(it)!!) }
|
||||
constructorDescriptor.valueParameters.forEach { putValueArgument(it, delegatingConstructorCall.getValueArgument(it)) }
|
||||
}
|
||||
val oldThis = delegatingConstructorCall.descriptor.constructedClass.thisAsReceiverParameter
|
||||
@@ -159,12 +161,12 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
nameHint = delegatingConstructorCall.descriptor.fqNameSafe.toString() + ".this"
|
||||
)
|
||||
statements[0] = newThis
|
||||
substituteMap[oldThis] = irGet(newThis.symbol)
|
||||
statements.add(irReturn(irGet(newThis.symbol)))
|
||||
substituteMap[oldThis] = irGet(newThis)
|
||||
statements.add(irReturn(irGet(newThis)))
|
||||
}
|
||||
}
|
||||
|
||||
val returnType = copyFunctionDeclaration.descriptor.returnType!! // Substituted return type.
|
||||
val returnType = copyFunctionDeclaration.returnType // Substituted return type.
|
||||
val sourceFileName = context.originalModuleIndex.declarationToFile[caller.descriptor.original] ?: ""
|
||||
val inlineFunctionBody = IrReturnableBlockImpl( // Create new IR element to replace "call".
|
||||
startOffset = startOffset,
|
||||
@@ -248,7 +250,7 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
val substitutionContext = mutableMapOf<TypeConstructor, TypeProjection>()
|
||||
for (index in 0 until irCall.typeArgumentsCount) {
|
||||
val typeArgument = irCall.getTypeArgument(index) ?: continue
|
||||
substitutionContext[typeParameters[index].typeConstructor] = TypeProjectionImpl(typeArgument)
|
||||
substitutionContext[typeParameters[index].typeConstructor] = TypeProjectionImpl(typeArgument.toKotlinType())
|
||||
}
|
||||
return TypeSubstitutor.create(substitutionContext)
|
||||
}
|
||||
@@ -309,7 +311,8 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
}
|
||||
|
||||
val parametersWithDefaultToArgument = mutableListOf<ParameterToArgument>()
|
||||
functionDescriptor.valueParameters.forEach { parameterDescriptor -> // Iterate value parameter descriptors.
|
||||
irFunction.valueParameters.forEach { parameter -> // Iterate value parameter descriptors.
|
||||
val parameterDescriptor = parameter.descriptor as ValueParameterDescriptor
|
||||
val argument = valueArguments[parameterDescriptor.index] // Get appropriate argument from call site.
|
||||
when {
|
||||
argument != null -> { // Argument is good enough.
|
||||
@@ -331,8 +334,8 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
val emptyArray = IrVarargImpl(
|
||||
startOffset = irCall.startOffset,
|
||||
endOffset = irCall.endOffset,
|
||||
type = parameterDescriptor.type,
|
||||
varargElementType = parameterDescriptor.varargElementType!!
|
||||
type = parameter.type,
|
||||
varargElementType = parameter.varargElementType!!
|
||||
)
|
||||
parameterToArgument += ParameterToArgument(
|
||||
parameterDescriptor = parameterDescriptor,
|
||||
@@ -377,7 +380,8 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
val getVal = IrGetValueImpl( // Create new expression, representing access the new variable.
|
||||
startOffset = currentScope.irElement.startOffset,
|
||||
endOffset = currentScope.irElement.endOffset,
|
||||
symbol = createValueSymbol(newVariable.descriptor)
|
||||
type = newVariable.type,
|
||||
symbol = newVariable.symbol
|
||||
)
|
||||
substituteMap[parameterDescriptor] = getVal // Parameter will be replaced with the new variable.
|
||||
}
|
||||
|
||||
+60
-34
@@ -11,12 +11,13 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.inline.addChildren
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrReturnTargetSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.types.toIrType
|
||||
import org.jetbrains.kotlin.ir.util.ExternalDependenciesGenerator
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
@@ -51,7 +52,11 @@ internal fun IrModuleFragment.replaceUnboundSymbols(context: JsIrBackendContext)
|
||||
// Generate missing external stubs:
|
||||
// TODO: ModuleGenerator::generateUnboundSymbolsAsDependencies(IRModuleFragment) is private function :/
|
||||
@Suppress("DEPRECATION")
|
||||
ExternalDependenciesGenerator(symbolTable = context.symbolTable, irBuiltIns = context.irBuiltIns).generateUnboundSymbolsAsDependencies(this)
|
||||
ExternalDependenciesGenerator(
|
||||
descriptor,
|
||||
symbolTable = context.symbolTable,
|
||||
irBuiltIns = context.irBuiltIns
|
||||
).generateUnboundSymbolsAsDependencies(this)
|
||||
|
||||
// Merge duplicated module and package declarations:
|
||||
this.acceptVoid(object : IrElementVisitorVoid {
|
||||
@@ -161,7 +166,7 @@ private class IrUnboundSymbolReplacer(
|
||||
|
||||
expression.transformChildrenVoid(this)
|
||||
return with(expression) {
|
||||
IrGetValueImpl(startOffset, endOffset, symbol, origin)
|
||||
IrGetValueImpl(startOffset, endOffset, expression.type, symbol, origin)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,13 +175,13 @@ private class IrUnboundSymbolReplacer(
|
||||
|
||||
expression.transformChildrenVoid(this)
|
||||
return with(expression) {
|
||||
IrSetVariableImpl(startOffset, endOffset, symbol, value, origin)
|
||||
IrSetVariableImpl(startOffset, endOffset, expression.type, symbol, value, origin)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitGetObjectValue(expression: IrGetObjectValue): IrExpression {
|
||||
val symbol = expression.symbol.replace(SymbolTable::referenceClass) ?:
|
||||
return super.visitGetObjectValue(expression)
|
||||
return super.visitGetObjectValue(expression)
|
||||
|
||||
expression.transformChildrenVoid(this)
|
||||
return with(expression) {
|
||||
@@ -186,7 +191,7 @@ private class IrUnboundSymbolReplacer(
|
||||
|
||||
override fun visitGetEnumValue(expression: IrGetEnumValue): IrExpression {
|
||||
val symbol = expression.symbol.replace(SymbolTable::referenceEnumEntry) ?:
|
||||
return super.visitGetEnumValue(expression)
|
||||
return super.visitGetEnumValue(expression)
|
||||
|
||||
expression.transformChildrenVoid(this)
|
||||
return with(expression) {
|
||||
@@ -200,17 +205,11 @@ private class IrUnboundSymbolReplacer(
|
||||
|
||||
expression.transformChildrenVoid(this)
|
||||
return with(expression) {
|
||||
IrClassReferenceImpl(startOffset, endOffset, type, symbol, symbol.descriptor.defaultType)
|
||||
IrClassReferenceImpl(startOffset, endOffset, type, symbol, symbol.descriptor.toIrType())
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitClass(declaration: IrClass): IrStatement {
|
||||
declaration.superClasses.forEachIndexed { index, symbol ->
|
||||
val newSymbol = symbol.replace(SymbolTable::referenceClass)
|
||||
if (newSymbol != null) {
|
||||
declaration.superClasses[index] = newSymbol
|
||||
}
|
||||
}
|
||||
withLocal(declaration.thisReceiver?.symbol) {
|
||||
return super.visitClass(declaration)
|
||||
}
|
||||
@@ -227,7 +226,7 @@ private class IrUnboundSymbolReplacer(
|
||||
|
||||
expression.transformChildrenVoid(this)
|
||||
return with(expression) {
|
||||
IrGetFieldImpl(startOffset, endOffset, symbol, receiver, origin, superQualifierSymbol)
|
||||
IrGetFieldImpl(startOffset, endOffset, symbol, type, receiver, origin, superQualifierSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,11 +241,13 @@ private class IrUnboundSymbolReplacer(
|
||||
|
||||
expression.transformChildrenVoid(this)
|
||||
return with(expression) {
|
||||
IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value, origin, superQualifierSymbol)
|
||||
IrSetFieldImpl(startOffset, endOffset, symbol, receiver, value, type /*wrong*/, origin, superQualifierSymbol)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall): IrExpression {
|
||||
expression.replaceTypeArguments()
|
||||
|
||||
val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?: expression.symbol
|
||||
|
||||
val superQualifierSymbol = expression.superQualifierSymbol?.replaceOrSame(SymbolTable::referenceClass)
|
||||
@@ -257,17 +258,21 @@ private class IrUnboundSymbolReplacer(
|
||||
|
||||
expression.transformChildrenVoid()
|
||||
return with(expression) {
|
||||
IrCallImpl(startOffset, endOffset, symbol, descriptor,
|
||||
getTypeArgumentsMap(),
|
||||
origin, superQualifierSymbol).also {
|
||||
IrCallImpl(startOffset, endOffset, type, symbol, descriptor,
|
||||
typeArgumentsCount,
|
||||
origin, superQualifierSymbol).also {
|
||||
|
||||
it.copyArgumentsFrom(this)
|
||||
it.copyTypeArgumentsFrom(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrMemberAccessExpression.getTypeArgumentsMap() =
|
||||
descriptor.original.typeParameters.associate { it to getTypeArgumentOrDefault(it) }
|
||||
private fun IrMemberAccessExpression.replaceTypeArguments() {
|
||||
repeat(typeArgumentsCount) {
|
||||
putTypeArgument(it, getTypeArgument(it)/*?.toKotlinType()?.let { context.ir.translateErased(it) }*/)
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrMemberAccessExpressionBase.copyArgumentsFrom(original: IrMemberAccessExpression) {
|
||||
dispatchReceiver = original.dispatchReceiver
|
||||
@@ -279,40 +284,48 @@ private class IrUnboundSymbolReplacer(
|
||||
|
||||
override fun visitEnumConstructorCall(expression: IrEnumConstructorCall): IrExpression {
|
||||
val symbol = expression.symbol.replace(SymbolTable::referenceConstructor) ?:
|
||||
return super.visitEnumConstructorCall(expression)
|
||||
return super.visitEnumConstructorCall(expression)
|
||||
|
||||
return with(expression) {
|
||||
IrEnumConstructorCallImpl(startOffset, endOffset, symbol, null).also {
|
||||
IrEnumConstructorCallImpl(startOffset, endOffset, expression.type, symbol, 0).also {
|
||||
it.copyArgumentsFrom(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall): IrExpression {
|
||||
expression.replaceTypeArguments()
|
||||
|
||||
val symbol = expression.symbol.replace(SymbolTable::referenceConstructor) ?:
|
||||
return super.visitDelegatingConstructorCall(expression)
|
||||
return super.visitDelegatingConstructorCall(expression)
|
||||
|
||||
expression.transformChildrenVoid()
|
||||
return with(expression) {
|
||||
IrDelegatingConstructorCallImpl(startOffset, endOffset, symbol, descriptor, getTypeArgumentsMap()).also {
|
||||
IrDelegatingConstructorCallImpl(startOffset, endOffset, type, symbol, descriptor, typeArgumentsCount).also {
|
||||
it.copyArgumentsFrom(this)
|
||||
it.copyTypeArgumentsFrom(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
||||
expression.replaceTypeArguments()
|
||||
|
||||
val symbol = expression.symbol.replace(SymbolTable::referenceFunction) ?:
|
||||
return super.visitFunctionReference(expression)
|
||||
return super.visitFunctionReference(expression)
|
||||
|
||||
expression.transformChildrenVoid(this)
|
||||
return with(expression) {
|
||||
IrFunctionReferenceImpl(startOffset, endOffset, type, symbol, descriptor, getTypeArgumentsMap()).also {
|
||||
IrFunctionReferenceImpl(startOffset, endOffset, type, symbol, descriptor, 0).also {
|
||||
it.copyArgumentsFrom(this)
|
||||
it.copyTypeArgumentsFrom(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitPropertyReference(expression: IrPropertyReference): IrExpression {
|
||||
expression.replaceTypeArguments()
|
||||
|
||||
val field = expression.field?.replaceOrSame(SymbolTable::referenceField)
|
||||
val getter = expression.getter?.replace(SymbolTable::referenceFunction) ?: expression.getter
|
||||
val setter = expression.setter?.replace(SymbolTable::referenceFunction) ?: expression.setter
|
||||
@@ -323,13 +336,14 @@ private class IrUnboundSymbolReplacer(
|
||||
|
||||
expression.transformChildrenVoid(this)
|
||||
return with(expression) {
|
||||
IrPropertyReferenceImpl(startOffset, endOffset, type, descriptor,
|
||||
field,
|
||||
getter,
|
||||
setter,
|
||||
getTypeArgumentsMap(), origin).also {
|
||||
IrPropertyReferenceImpl(startOffset, endOffset, type, descriptor, 0,
|
||||
field,
|
||||
getter,
|
||||
setter,
|
||||
origin).also {
|
||||
|
||||
it.copyArgumentsFrom(this)
|
||||
it.copyTypeArgumentsFrom(this)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -346,7 +360,7 @@ private class IrUnboundSymbolReplacer(
|
||||
expression.transformChildrenVoid(this)
|
||||
return with(expression) {
|
||||
IrLocalDelegatedPropertyReferenceImpl(startOffset, endOffset, type, descriptor,
|
||||
delegate, getter, setter, origin).also {
|
||||
delegate, getter, setter, origin).also {
|
||||
|
||||
it.copyArgumentsFrom(this)
|
||||
}
|
||||
@@ -406,12 +420,24 @@ private class IrUnboundSymbolReplacer(
|
||||
|
||||
override fun visitInstanceInitializerCall(expression: IrInstanceInitializerCall): IrExpression {
|
||||
val classSymbol = expression.classSymbol.replace(SymbolTable::referenceClass) ?:
|
||||
return super.visitInstanceInitializerCall(expression)
|
||||
return super.visitInstanceInitializerCall(expression)
|
||||
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
return with(expression) {
|
||||
IrInstanceInitializerCallImpl(startOffset, endOffset, classSymbol)
|
||||
IrInstanceInitializerCallImpl(startOffset, endOffset, classSymbol, type)
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitTypeOperator(expression: IrTypeOperatorCall): IrExpression {
|
||||
expression.transformChildrenVoid(this)
|
||||
|
||||
return with(expression) {
|
||||
val newTypeOperand = typeOperand /*context.ir.translateErased(typeOperand.toKotlinType())*/
|
||||
IrTypeOperatorCallImpl(startOffset, endOffset, type, operator, newTypeOperand).also {
|
||||
it.argument = argument
|
||||
it.typeOperandClassifier = newTypeOperand.classifierOrFail
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-18
@@ -5,10 +5,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js.lower.inline
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrTypeParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationContainer
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
|
||||
@@ -19,21 +20,6 @@ fun IrSimpleFunction.setOverrides(symbolTable: SymbolTable) {
|
||||
this.descriptor.overriddenDescriptors.mapTo(this.overriddenSymbols) {
|
||||
symbolTable.referenceSimpleFunction(it.original)
|
||||
}
|
||||
|
||||
this.typeParameters.forEach { it.setSupers(symbolTable) }
|
||||
}
|
||||
|
||||
fun IrTypeParameter.setSupers(symbolTable: SymbolTable) {
|
||||
assert(this.superClassifiers.isEmpty())
|
||||
this.descriptor.upperBounds.mapNotNullTo(this.superClassifiers) {
|
||||
it.constructor.declarationDescriptor?.let {
|
||||
if (it is TypeParameterDescriptor) {
|
||||
IrTypeParameterSymbolImpl(it) // Workaround for deserialized inline functions
|
||||
} else {
|
||||
symbolTable.referenceClassifier(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun IrDeclarationContainer.addChildren(declarations: List<IrDeclaration>) {
|
||||
|
||||
+7
-1
@@ -13,6 +13,8 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.getTypeArgumentOrDefault
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
@@ -43,6 +45,10 @@ fun IrModuleFragment.referenceAllTypeExternalClassifiers(symbolTable: SymbolTabl
|
||||
}
|
||||
}
|
||||
|
||||
fun IrType.referenceAllClassifiers() {
|
||||
this.toKotlinType().referenceAllClassifiers()
|
||||
}
|
||||
|
||||
val visitor = object : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
@@ -125,4 +131,4 @@ fun IrModuleFragment.referenceAllTypeExternalClassifiers(symbolTable: SymbolTabl
|
||||
it.acceptVoid(visitor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+15
-11
@@ -10,14 +10,18 @@ import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||
import org.jetbrains.kotlin.ir.backend.js.symbols.JsSymbolBuilder
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
|
||||
import org.jetbrains.kotlin.ir.expressions.IrContainerExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrReturn
|
||||
import org.jetbrains.kotlin.ir.expressions.IrReturnableBlock
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrDoWhileLoopImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
|
||||
/**
|
||||
* Replaces returnable blocks and `return`'s with loops and `break`'s correspondingly.
|
||||
@@ -93,7 +97,7 @@ private class ReturnableBlockTransformer(
|
||||
return super.visitDeclaration(declaration, data)
|
||||
}
|
||||
|
||||
private val constFalse = JsIrBuilder.buildBoolean(context.builtIns.booleanType, false)
|
||||
private val constFalse = JsIrBuilder.buildBoolean(context.irBuiltIns.booleanType, false)
|
||||
|
||||
override fun visitContainerExpression(expression: IrContainerExpression, data: ReturnableBlockLoweringContext): IrExpression {
|
||||
if (expression !is IrReturnableBlock) return super.visitContainerExpression(expression, data)
|
||||
@@ -111,7 +115,7 @@ private class ReturnableBlockTransformer(
|
||||
IrDoWhileLoopImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
context.builtIns.unitType,
|
||||
context.irBuiltIns.unitType,
|
||||
expression.origin
|
||||
).apply {
|
||||
label = "l\$ret\$${data.labelCnt++}"
|
||||
@@ -127,10 +131,10 @@ private class ReturnableBlockTransformer(
|
||||
IrCompositeImpl(
|
||||
returnExpression.startOffset,
|
||||
returnExpression.endOffset,
|
||||
context.builtIns.unitType
|
||||
context.irBuiltIns.unitType
|
||||
).apply {
|
||||
statements += JsIrBuilder.buildSetVariable(variable, returnExpression.value)
|
||||
statements += JsIrBuilder.buildBreak(context.builtIns.unitType, loop)
|
||||
statements += JsIrBuilder.buildSetVariable(variable, returnExpression.value, context.irBuiltIns.unitType)
|
||||
statements += JsIrBuilder.buildBreak(context.irBuiltIns.unitType, loop)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,7 +142,7 @@ private class ReturnableBlockTransformer(
|
||||
if (i == expression.statements.lastIndex && s is IrReturn && s.returnTargetSymbol == expression.symbol) {
|
||||
s.transformChildren(this, data)
|
||||
if (!hasReturned) s.value else {
|
||||
JsIrBuilder.buildSetVariable(variable, s.value)
|
||||
JsIrBuilder.buildSetVariable(variable, s.value, context.irBuiltIns.unitType)
|
||||
}
|
||||
} else {
|
||||
s.transform(this, data)
|
||||
@@ -159,7 +163,7 @@ private class ReturnableBlockTransformer(
|
||||
loop.body = IrBlockImpl(
|
||||
expression.startOffset,
|
||||
expression.endOffset,
|
||||
context.builtIns.unitType,
|
||||
context.irBuiltIns.unitType,
|
||||
expression.origin,
|
||||
newStatements
|
||||
)
|
||||
@@ -170,7 +174,7 @@ private class ReturnableBlockTransformer(
|
||||
expression.type,
|
||||
expression.origin
|
||||
).apply {
|
||||
statements += JsIrBuilder.buildVar(variable)
|
||||
statements += JsIrBuilder.buildVar(variable, type = expression.type)
|
||||
statements += loop
|
||||
statements += JsIrBuilder.buildGetValue(variable)
|
||||
}
|
||||
|
||||
+13
-12
@@ -18,12 +18,13 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrSimpleFunctionSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
object JsSymbolBuilder {
|
||||
fun buildValueParameter(containingSymbol: IrSimpleFunctionSymbol, index: Int, type: KotlinType, name: String? = null) =
|
||||
IrValueParameterSymbolImpl(createValueParameter(containingSymbol.descriptor, index, name ?: "param$index", type))
|
||||
fun buildValueParameter(containingSymbol: IrSimpleFunctionSymbol, index: Int, type: IrType, name: String? = null) =
|
||||
IrValueParameterSymbolImpl(createValueParameter(containingSymbol.descriptor, index, name ?: "param$index", type.toKotlinType()))
|
||||
|
||||
fun buildSimpleFunction(
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
@@ -53,7 +54,7 @@ object JsSymbolBuilder {
|
||||
|
||||
fun buildVar(
|
||||
containingDeclaration: DeclarationDescriptor,
|
||||
type: KotlinType,
|
||||
type: IrType,
|
||||
name: String,
|
||||
mutable: Boolean = false
|
||||
) = IrVariableSymbolImpl(
|
||||
@@ -61,42 +62,42 @@ object JsSymbolBuilder {
|
||||
containingDeclaration,
|
||||
Annotations.EMPTY,
|
||||
Name.identifier(name),
|
||||
type,
|
||||
type.toKotlinType(),
|
||||
mutable,
|
||||
false,
|
||||
SourceElement.NO_SOURCE
|
||||
)
|
||||
)
|
||||
|
||||
fun buildTempVar(containingSymbol: IrSymbol, type: KotlinType, name: String? = null, mutable: Boolean = false) =
|
||||
fun buildTempVar(containingSymbol: IrSymbol, type: IrType, name: String? = null, mutable: Boolean = false) =
|
||||
buildTempVar(containingSymbol.descriptor, type, name, mutable)
|
||||
|
||||
fun buildTempVar(containingDeclaration: DeclarationDescriptor, type: KotlinType, name: String? = null, mutable: Boolean = false) =
|
||||
fun buildTempVar(containingDeclaration: DeclarationDescriptor, type: IrType, name: String? = null, mutable: Boolean = false) =
|
||||
IrVariableSymbolImpl(
|
||||
IrTemporaryVariableDescriptorImpl(
|
||||
containingDeclaration,
|
||||
Name.identifier(name ?: "tmp"),
|
||||
type, mutable
|
||||
type.toKotlinType(), mutable
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
fun IrSimpleFunctionSymbol.initialize(
|
||||
receiverParameterType: KotlinType? = null,
|
||||
receiverParameterType: IrType? = null,
|
||||
dispatchParameterDescriptor: ReceiverParameterDescriptor? = null,
|
||||
typeParameters: List<TypeParameterDescriptor> = emptyList(),
|
||||
valueParameters: List<ValueParameterDescriptor> = emptyList(),
|
||||
type: KotlinType? = null,
|
||||
returnType: IrType? = null,
|
||||
modality: Modality = Modality.FINAL,
|
||||
visibility: Visibility = Visibilities.LOCAL
|
||||
) = this.apply {
|
||||
(descriptor as FunctionDescriptorImpl).initialize(
|
||||
receiverParameterType,
|
||||
receiverParameterType?.toKotlinType(),
|
||||
dispatchParameterDescriptor,
|
||||
typeParameters,
|
||||
valueParameters,
|
||||
type,
|
||||
returnType?.toKotlinType(),
|
||||
modality,
|
||||
visibility
|
||||
)
|
||||
|
||||
+3
-3
@@ -5,15 +5,15 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||
|
||||
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
|
||||
import org.jetbrains.kotlin.backend.common.utils.isFunctionTypeOrSubtype
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsExpression, JsGenerationContext> {
|
||||
@@ -158,7 +158,7 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
|
||||
val arguments = translateCallArguments(expression, context)
|
||||
|
||||
if (dispatchReceiver != null &&
|
||||
dispatchReceiver.type.isFunctionTypeOrSubtype && symbol.owner.name == OperatorNameConventions.INVOKE
|
||||
dispatchReceiver.type.isFunctionTypeOrSubtype() && symbol.owner.name == OperatorNameConventions.INVOKE
|
||||
) {
|
||||
return JsInvocation(jsDispatchReceiver!!, arguments)
|
||||
}
|
||||
|
||||
+14
-6
@@ -11,12 +11,14 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.isAny
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.types.isAny
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.ir.util.isReal
|
||||
import org.jetbrains.kotlin.ir.util.resolveFakeOverride
|
||||
@@ -26,8 +28,8 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
||||
|
||||
private val className = context.getNameForSymbol(irClass.symbol)
|
||||
private val classNameRef = className.makeRef()
|
||||
private val baseClass = irClass.superClasses.firstOrNull { !it.owner.isInterface }
|
||||
private val baseClassName = baseClass?.let { context.getNameForSymbol(it) }
|
||||
private val baseClass = irClass.superTypes.firstOrNull { !it.classifierOrFail.isInterface }
|
||||
private val baseClassName = baseClass?.let { context.getNameForSymbol(it.classifierOrFail) }
|
||||
private val classPrototypeRef = prototypeOf(classNameRef)
|
||||
private val classBlock = JsGlobalBlock()
|
||||
private val classModel = JsClassModel(className, baseClassName)
|
||||
@@ -130,7 +132,7 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
||||
}
|
||||
|
||||
private fun generateInheritanceCode(): List<JsStatement> {
|
||||
if (baseClass == null || baseClass.isAny) {
|
||||
if (baseClass == null || baseClass.isAny()) {
|
||||
return emptyList()
|
||||
}
|
||||
|
||||
@@ -158,7 +160,13 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
||||
|
||||
private fun generateSuperClasses(): JsPropertyInitializer = JsPropertyInitializer(
|
||||
JsNameRef(Namer.METADATA_INTERFACES),
|
||||
JsArrayLiteral(irClass.superClasses.filter { it.owner.isInterface }.map { JsNameRef(context.getNameForSymbol(it.owner.symbol)) })
|
||||
JsArrayLiteral(
|
||||
irClass.superTypes.mapNotNull {
|
||||
val symbol = it.classifierOrFail
|
||||
if (symbol.isInterface) JsNameRef(context.getNameForSymbol(symbol)) else null
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
private val IrClassifierSymbol.isInterface get() = (owner as? IrClass)?.isInterface == true
|
||||
+3
-5
@@ -5,14 +5,13 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrClassSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.js.backend.ast.*
|
||||
|
||||
typealias IrCallTransformer = (IrCall, context: JsGenerationContext) -> JsExpression
|
||||
@@ -69,7 +68,7 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
|
||||
|
||||
add(intrinsics.jsObjectCreate) { call, context ->
|
||||
val classToCreate = call.getTypeArgument(0)!!
|
||||
val className = context.getNameForSymbol(IrClassSymbolImpl(classToCreate.constructor.declarationDescriptor as ClassDescriptor))
|
||||
val className = context.getNameForSymbol(classToCreate.classifierOrFail)
|
||||
val prototype = prototypeOf(className.makeRef())
|
||||
JsInvocation(Namer.JS_OBJECT_CREATE_FUNCTION, prototype)
|
||||
}
|
||||
@@ -86,8 +85,7 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
|
||||
}
|
||||
|
||||
add(intrinsics.jsToJsType) { call, context ->
|
||||
val typeParameter = call.getTypeArgument(0)!!
|
||||
val typeName = context.getNameForSymbol(IrClassSymbolImpl(typeParameter.constructor.declarationDescriptor as ClassDescriptor))
|
||||
val typeName = context.getNameForSymbol(call.getTypeArgument(0)!!.classifierOrFail)
|
||||
typeName.makeRef()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user