[Wasm] Handle IrClass::thisReceiver receiver outside of constructors

This commit is contained in:
Svyatoslav Kuzmich
2021-10-11 15:53:29 +03:00
parent bcab78599f
commit e3f826d1b9
2 changed files with 14 additions and 3 deletions
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.backend.wasm.utils.*
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.backend.js.utils.findUnitGetInstanceFunction
import org.jetbrains.kotlin.ir.backend.js.utils.isDispatchReceiver
import org.jetbrains.kotlin.ir.backend.js.utils.realOverrideTarget
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
@@ -175,9 +176,16 @@ class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorV
override fun visitGetValue(expression: IrGetValue) {
val valueSymbol = expression.symbol
body.buildGetLocal(context.referenceLocal(valueSymbol))
val valueDeclaration = valueSymbol.owner
body.buildGetLocal(
// Handle cases when IrClass::thisReceiver is referenced instead
// of the value parameter of current function
if (valueDeclaration.isDispatchReceiver)
context.referenceLocal(0)
else
context.referenceLocal(valueSymbol)
)
if (valueSymbol.owner is IrValueParameter) {
val parent = valueDeclaration.parent
if (parent is IrFunction && parent.isExported(backendContext)) {
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.types.isAny
import org.jetbrains.kotlin.ir.util.isInterface
import org.jetbrains.kotlin.ir.util.parentAsClass
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
@@ -76,10 +77,12 @@ class EraseVirtualDispatchReceiverParametersTypes(val context: CommonBackendCont
val newReceiver = oldReceiver.copyTo(irFunction, type = context.irBuiltIns.anyType)
irFunction.dispatchReceiverParameter = newReceiver
val classThisReceiverSymbol = irFunction.parentAsClass.thisReceiver?.symbol
// Cast receiver usages back to original type
irFunction.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitGetValue(expression: IrGetValue): IrExpression {
if (expression.symbol == oldReceiver.symbol) {
if (expression.symbol == oldReceiver.symbol || expression.symbol == classThisReceiverSymbol) {
return with(builder) {
irImplicitCast(irGet(newReceiver), originalReceiverType)
}