[JS IR BE] lateinit support

* Functions with IrExpressionBody are lowered to IrBlockBody
* Implemented throwUninitializedPropertyAccessException function
This commit is contained in:
Anton Bannykh
2018-09-20 18:09:26 +03:00
parent beaf6df8c5
commit 8e347f9f39
21 changed files with 25 additions and 34 deletions
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrBlock
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
@@ -50,19 +51,19 @@ class LateinitLowering(
val endOffset = getter.endOffset
val irBuilder = context.createIrBuilder(getter.symbol, startOffset, endOffset)
irBuilder.run {
val block = irBlock(type)
val body = IrBlockBodyImpl(startOffset, endOffset)
val resultVar = scope.createTemporaryVariable(
irGetField(getter.dispatchReceiverParameter?.let { irGet(it) }, backingField)
)
block.statements.add(resultVar)
body.statements.add(resultVar)
val throwIfNull = irIfThenElse(
context.irBuiltIns.nothingType,
irNotEquals(irGet(resultVar), irNull()),
irReturn(irGet(resultVar)),
throwUninitializedPropertyAccessException(backingField)
)
block.statements.add(throwIfNull)
getter.body = IrExpressionBodyImpl(startOffset, endOffset, block)
body.statements.add(throwIfNull)
getter.body = body
}
}
})
@@ -193,13 +193,8 @@ class JsIrBackendContext(
override val ThrowTypeCastException
get () = irBuiltIns.throwCceSymbol
override val ThrowUninitializedPropertyAccessException = symbolTable.referenceSimpleFunction(
irBuiltIns.defineOperator(
"throwUninitializedPropertyAccessException",
builtIns.nothingType,
listOf(builtIns.stringType)
).descriptor
)
override val ThrowUninitializedPropertyAccessException=
symbolTable.referenceSimpleFunction(getFunctions(FqName("kotlin.throwUninitializedPropertyAccessException")).single())
override val stringBuilder
get() = TODO("not implemented")
@@ -38,9 +38,19 @@ class BlockDecomposerLowering(context: JsIrBackendContext) : DeclarationContaine
}
fun lower(irFunction: IrFunction) {
(irFunction.body as? IrExpressionBody)?.apply {
irFunction.body = toBlockBody(irFunction)
}
irFunction.accept(decomposerTransformer, null)
}
private fun IrExpressionBody.toBlockBody(containingFunction: IrFunction): IrBlockBody {
val returnStatement = JsIrBuilder.buildReturn(containingFunction.symbol, expression, nothingType)
return IrBlockBodyImpl(expression.startOffset, expression.endOffset).apply {
statements += returnStatement
}
}
fun lower(irField: IrField, container: IrDeclarationContainer): List<IrDeclaration> {
irField.initializer?.apply {
val initFunction = JsIrBuilder.buildFunction(irField.name.asString() + "\$init\$", irField.visibility).also {
@@ -48,17 +58,14 @@ class BlockDecomposerLowering(context: JsIrBackendContext) : DeclarationContaine
it.returnType = expression.type
}
val returnStatement = JsIrBuilder.buildReturn(initFunction.symbol, expression, nothingType)
val newBody = IrBlockBodyImpl(expression.startOffset, expression.endOffset).apply {
statements += returnStatement
}
val newBody = toBlockBody(initFunction)
initFunction.body = newBody
lower(initFunction)
val lastStatement = newBody.statements.last()
if (lastStatement != returnStatement || (lastStatement as IrReturn).value != expression) {
if (newBody.statements.size > 1 || lastStatement !is IrReturn || lastStatement.value != expression) {
expression = JsIrBuilder.buildCall(initFunction.symbol, expression.type)
return listOf(initFunction, irField)
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
public class A {
fun setMyStr() {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
public class A {
fun getMyStr(): String {
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
class A {
private lateinit var str: String
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
class A {
public lateinit var str: String
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
interface Intf {
val str: String
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
interface Intf {
val str: String
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
class My {
lateinit var x: String
private set
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
class My {
lateinit var x: String
private set
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
open class A {
lateinit var x: String
private set
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
class A {
public lateinit var str: String
}
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// LANGUAGE_VERSION: 1.2
// WITH_RUNTIME
// FILE: lateinit.kt
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// LANGUAGE_VERSION: 1.2
// FILE: lateinit.kt
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// LANGUAGE_VERSION: 1.2
lateinit var ok: String
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// LANGUAGE_VERSION: 1.2
// WITH_RUNTIME
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// LANGUAGE_VERSION: 1.2
// WITH_RUNTIME
-1
View File
@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1233
class Greeting {
val noon = xrun {
@@ -1,4 +1,4 @@
// IGNORE_BACKEND: JS_IR
// EXPECTED_REACHABLE_NODES: 1336
// MODULE: lib
// FILE: lib.kt
+5 -1
View File
@@ -98,4 +98,8 @@ fun THROW_NPE() {
throw NullPointerException()
}
fun error(s: String): Nothing = throw IllegalStateException(s, null)
fun error(s: String): Nothing = throw IllegalStateException(s, null)
@PublishedApi
internal fun throwUninitializedPropertyAccessException(name: String): Nothing =
throw UninitializedPropertyAccessException("lateinit property $name has not been initialized")