[JS IR BE] Make backend be able work with unbound symbols

* Fix array type deserialization
 * Prepare to compilation against klibs
This commit is contained in:
Roman Artemev
2019-02-14 20:01:48 +03:00
committed by romanart
parent 2334ea2742
commit 6863f9e4f3
6 changed files with 47 additions and 42 deletions
@@ -263,11 +263,11 @@ class JsIrBackendContext(
val throwableClass by lazy {
symbolTable.referenceClass(
getClass(JsIrBackendContext.KOTLIN_PACKAGE_FQN.child(Name.identifier("Throwable")))
).owner
)
}
val throwableConstructors by lazy { throwableClass.declarations.filterIsInstance<IrConstructor>() }
val throwableConstructors by lazy { throwableClass.owner.declarations.filterIsInstance<IrConstructor>().map { it.symbol } }
val defaultThrowableCtor by lazy { throwableConstructors.single { it.valueParameters.size == 0 } }
val defaultThrowableCtor by lazy { throwableConstructors.single { it.owner.valueParameters.size == 0 } }
private fun referenceOperators() = OperatorNames.ALL.map { name ->
// TODO to replace KotlinType with IrType we need right equals on IrType
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrFieldSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.makeNotNull
@@ -29,40 +30,44 @@ import org.jetbrains.kotlin.ir.util.isThrowableTypeOrSubtype
import org.jetbrains.kotlin.ir.visitors.*
import org.jetbrains.kotlin.name.Name
class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPass {
private val unitType = context.irBuiltIns.unitType
private val nothingNType = context.irBuiltIns.nothingNType
private val nothingType = context.irBuiltIns.nothingType
private val stringType = context.irBuiltIns.stringType
private val booleanType = context.irBuiltIns.booleanType
class ThrowableSuccessorsLowering(val context: JsIrBackendContext) : FileLoweringPass {
private val unitType get() = context.irBuiltIns.unitType
private val nothingNType get() = context.irBuiltIns.nothingNType
private val nothingType get() = context.irBuiltIns.nothingType
private val stringType get() = context.irBuiltIns.stringType
private val booleanType get() = context.irBuiltIns.booleanType
private val throwableType get() = context.irBuiltIns.throwableType
private val propertyGetter = context.intrinsics.jsGetJSField.symbol
private val propertySetter = context.intrinsics.jsSetJSField.symbol
private val eqeqeqSymbol = context.irBuiltIns.eqeqSymbol
private val propertyGetter get() = context.intrinsics.jsGetJSField.symbol
private val propertySetter get() = context.intrinsics.jsSetJSField.symbol
private val eqeqeqSymbol get() = context.irBuiltIns.eqeqSymbol
private val messageName get() = JsIrBuilder.buildString(stringType, "message")
private val causeName get() = JsIrBuilder.buildString(stringType, "cause")
private val nameName get() = JsIrBuilder.buildString(stringType, "name")
private val throwableClass = context.throwableClass
private val throwableConstructors = context.throwableConstructors
private val throwableClass by lazy { context.throwableClass }
private val throwableConstructors by lazy { context.throwableConstructors }
private val defaultCtor = context.defaultThrowableCtor
private val toString =
throwableClass.declarations.filterIsInstance<IrSimpleFunction>().single { it.name == Name.identifier("toString") }
private val defaultCtor by lazy { context.defaultThrowableCtor }
private val toString by lazy {
throwableClass.owner.declarations.filterIsInstance<IrSimpleFunction>().single { it.name == Name.identifier("toString") }.symbol
}
private val messagePropertyName = Name.identifier("message")
private val causePropertyName = Name.identifier("cause")
private val messageGetter =
throwableClass.declarations.filterIsInstance<IrFunction>().atMostOne { it.name == Name.special("<get-message>") }
?: throwableClass.declarations.filterIsInstance<IrProperty>().atMostOne { it.name == messagePropertyName }?.getter!!
private val causeGetter =
throwableClass.declarations.filterIsInstance<IrFunction>().atMostOne { it.name == Name.special("<get-cause>") }
?: throwableClass.declarations.filterIsInstance<IrProperty>().atMostOne { it.name == causePropertyName }?.getter!!
private val messageGetter by lazy {
throwableClass.owner.declarations.filterIsInstance<IrFunction>().atMostOne { it.name == Name.special("<get-message>") }?.symbol
?: throwableClass.owner.declarations.filterIsInstance<IrProperty>().atMostOne { it.name == messagePropertyName }?.getter?.symbol!!
}
private val causeGetter by lazy {
throwableClass.owner.declarations.filterIsInstance<IrFunction>().atMostOne { it.name == Name.special("<get-cause>") }?.symbol
?: throwableClass.owner.declarations.filterIsInstance<IrProperty>().atMostOne { it.name == causePropertyName }?.getter?.symbol!!
}
private val captureStackFunction = context.symbolTable.referenceSimpleFunction(context.getInternalFunctions("captureStack").single())
private val newThrowableFunction = context.symbolTable.referenceSimpleFunction(context.getInternalFunctions("newThrowable").single())
private val captureStackFunction by lazy { context.symbolTable.referenceSimpleFunction(context.getInternalFunctions("captureStack").single()) }
private val newThrowableFunction by lazy { context.symbolTable.referenceSimpleFunction(context.getInternalFunctions("newThrowable").single()) }
private val pendingSuperUsages = mutableListOf<DirectThrowableSuccessors>()
private data class DirectThrowableSuccessors(val klass: IrClass, val message: IrField, val cause: IrField)
@@ -104,7 +109,7 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
inner class ThrowableInstanceCreationLowering : IrElementTransformerVoid() {
override fun visitCall(expression: IrCall): IrExpression {
if (expression.symbol.owner !in throwableConstructors) return super.visitCall(expression)
if (expression.symbol !in throwableConstructors) return super.visitCall(expression)
expression.transformChildrenVoid(this)
@@ -141,8 +146,8 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
override fun visitClass(declaration: IrClass) {
if (isDirectChildOfThrowable(declaration)) {
val messageField = createBackingField(declaration, messagePropertyName, messageGetter.returnType)
val causeField = createBackingField(declaration, causePropertyName, causeGetter.returnType)
val messageField = createBackingField(declaration, messagePropertyName, stringType)
val causeField = createBackingField(declaration, causePropertyName, throwableType)
val existedMessageAccessor = ownPropertyAccessor(declaration, messageGetter)
if (existedMessageAccessor.origin == IrDeclarationOrigin.FAKE_OVERRIDE)
createPropertyAccessor(existedMessageAccessor, messageField)
@@ -202,13 +207,13 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
override fun visitFunction(declaration: IrFunction, data: IrDeclarationParent) = super.visitFunction(declaration, declaration)
override fun visitCall(expression: IrCall, data: IrDeclarationParent): IrElement {
if (expression.superQualifierSymbol?.owner != throwableClass) return super.visitCall(expression, data)
if (expression.superQualifierSymbol != throwableClass) return super.visitCall(expression, data)
expression.transformChildren(this, data)
val superField = when {
expression.symbol.owner == messageGetter -> successor.message
expression.symbol.owner == causeGetter -> successor.cause
expression.symbol == messageGetter -> successor.message
expression.symbol == causeGetter -> successor.cause
else -> error("Unknown accessor")
}
@@ -216,14 +221,14 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
}
override fun visitDelegatingConstructorCall(expression: IrDelegatingConstructorCall, data: IrDeclarationParent): IrElement {
if (expression.symbol.owner !in throwableConstructors) return super.visitDelegatingConstructorCall(expression, data)
if (expression.symbol !in throwableConstructors) return super.visitDelegatingConstructorCall(expression, data)
expression.transformChildren(this, data)
val (messageArg, causeArg, paramStatements) = extractConstructorParameters(expression, data)
val newDelegation = expression.run {
IrDelegatingConstructorCallImpl(startOffset, endOffset, type, defaultCtor.symbol, defaultCtor.descriptor)
IrDelegatingConstructorCallImpl(startOffset, endOffset, type, defaultCtor, defaultCtor.descriptor)
}
val klass = successor.klass
@@ -304,14 +309,14 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
putValueArgument(1, JsIrBuilder.buildNull(value.type))
}
val value2 = JsIrBuilder.buildGetValue(receiver.symbol)
val call = JsIrBuilder.buildCall(toString.symbol, stringType).apply { dispatchReceiver = value2 }
val call = JsIrBuilder.buildCall(toString, stringType).apply { dispatchReceiver = value2 }
return JsIrBuilder.buildIfElse(stringType.makeNullable(), check, JsIrBuilder.buildNull(stringType), call)
}
private fun isDirectChildOfThrowable(irClass: IrClass) = irClass.superTypes.any { it.isThrowable() }
private fun ownPropertyAccessor(irClass: IrClass, irBase: IrFunction) =
private fun ownPropertyAccessor(irClass: IrClass, irBase: IrFunctionSymbol) =
irClass.declarations.filterIsInstance<IrProperty>().mapNotNull { it.getter }
.single { it.overriddenSymbols.any { s -> s.owner == irBase } }
.single { it.overriddenSymbols.any { s -> s == irBase } }
inner class ThrowablePropertiesUsageTransformer : IrElementTransformerVoid() {
override fun visitCall(expression: IrCall): IrExpression {
@@ -321,7 +326,7 @@ class ThrowableSuccessorsLowering(context: JsIrBackendContext) : FileLoweringPas
expression.transformChildrenVoid(this)
val owner = expression.symbol.owner
val owner = expression.symbol
return when (owner) {
messageGetter -> {
IrCallImpl(expression.startOffset, expression.endOffset, expression.type, propertyGetter).apply {
@@ -28,7 +28,7 @@ class CoroutineIntrinsicLowering(val context: JsIrBackendContext): FileLoweringP
irCall(expression, context.coroutineSuspendOrReturn)
expression.descriptor.isBuiltInIntercepted(languageVersion) ->
error("Intercepted should not be used with release coroutines")
expression.symbol.owner == context.intrinsics.jsCoroutineContext.owner ->
expression.symbol == context.intrinsics.jsCoroutineContext ->
irCall(expression, context.coroutineGetContextJs)
else -> call
}
@@ -96,8 +96,8 @@ class IrBuiltIns(
builtIns.nothing to IrTypeMapper({ nothingType }, { nothingNType }),
builtIns.unit to IrTypeMapper({ unitType }, { buildNullableType(unitType) }),
builtIns.string to IrTypeMapper({ stringType }, { buildNullableType(stringType) }),
builtIns.throwable to IrTypeMapper({ throwableType }, { buildNullableType(throwableType) }),
builtIns.array to IrTypeMapper({ arrayType }, { buildNullableType(arrayType) })
builtIns.throwable to IrTypeMapper({ throwableType }, { buildNullableType(throwableType) })//,
// builtIns.array to IrTypeMapper({ arrayType }, { buildNullableType(arrayType) })
)
fun getPrimitiveTypeOrNullByDescriptor(descriptor: ClassifierDescriptor, isNullable: Boolean) =
@@ -61,7 +61,7 @@ class ExternalDependenciesGenerator(
deserializer?.declareForwardDeclarations()
assert(symbolTable.unboundClasses.isEmpty())
// assert(symbolTable.unboundClasses.isEmpty())
assert(symbolTable.unboundConstructors.isEmpty())
assert(symbolTable.unboundEnumEntries.isEmpty())
assert(symbolTable.unboundFields.isEmpty())
@@ -118,7 +118,7 @@ abstract class BasicIrBoxTest(
filesToCompile,
config.configuration,
listOf(FqName((testPackage?.let { "$it." } ?: "") + testFunction)),
CompilationMode.TEST_AGAINST_CACHE,
CompilationMode.TEST_AGAINST_CACHE,//CompilationMode.TEST_AGAINST_KLIB,
dependencies,
runtimeResult,
moduleType = if (isMainModule) ModuleType.MAIN else ModuleType.SECONDARY