[JS_IR] Use IrSetValue for default argument handling for JS backend.

Fix a couple of parameter remappings that now have to take IrSetValue
into account as well as IrGetValue.
This commit is contained in:
Mads Ager
2020-09-10 09:18:22 +02:00
committed by Alexander Udalov
parent 9a93bb3f09
commit 87f17dec4a
6 changed files with 56 additions and 31 deletions
@@ -177,8 +177,24 @@ open class DefaultArgumentStubGenerator(
parameter: IrValueParameter,
default: IrExpression
): IrValueDeclaration {
val value = irIfThenElse(parameter.type, irNotEquals(defaultFlag, irInt(0)), default, irGet(parameter))
return createTmpVariable(value, nameHint = parameter.name.asString())
// For the JVM backend, we have to generate precisely this code because that results in the
// bytecode the inliner expects see `expandMaskConditionsAndUpdateVariableNodes`. In short,
// the bytecode sequence should be
//
// -- no loads of the parameter here, as after inlining its value will be uninitialized
// ILOAD <mask>
// ICONST <bit>
// IAND
// IFEQ Lx
// -- any code inserted here is removed if the call site specifies the parameter
// STORE <n>
// -- no jumps here
// Lx
//
// This control flow limits us to an if-then (without an else), and this together with the
// restriction on loading the parameter in the default case means we cannot create any temporaries.
+irIfThen(defaultFlag, irSet(parameter.symbol, default))
return parameter
}
protected open fun getOriginForCallToImplementation(): IrStatementOrigin? = null
@@ -106,6 +106,12 @@ class InlineClassLowering(val context: CommonBackendContext) {
return expression
}
override fun visitSetValue(expression: IrSetValue): IrExpression {
expression.transformChildrenVoid()
parameterMapping[expression.symbol]?.let { return irSet(it.symbol, expression.value) }
return expression
}
override fun visitDeclaration(declaration: IrDeclarationBase): IrStatement {
declaration.transformChildrenVoid(this)
if (declaration.parent == irConstructor)
@@ -171,6 +177,21 @@ class InlineClassLowering(val context: CommonBackendContext) {
}
)
}
override fun visitSetValue(expression: IrSetValue): IrExpression {
val valueDeclaration = expression.symbol.owner as? IrValueParameter ?: return super.visitSetValue(expression)
expression.transformChildrenVoid()
return context.createIrBuilder(staticMethod.symbol).irSet(
when (valueDeclaration) {
in function.valueParameters -> {
val offset = if (function.extensionReceiverParameter != null) 2 else 1
staticMethod.valueParameters[valueDeclaration.index + offset].symbol
}
else -> return expression
},
expression.value
)
}
})
}
}
@@ -171,6 +171,14 @@ private fun JsCommonBackendContext.fixReferencesToConstructorParameters(irClass:
return super.visitGetValue(expression)
}
override fun visitSetValue(expression: IrSetValue): IrExpression {
expression.transformChildrenVoid()
mapping.enumConstructorOldToNewValueParameters[expression.symbol.owner]?.let {
return builder.irSet(it.symbol, expression.value)
}
return super.visitSetValue(expression)
}
})
}
@@ -20,10 +20,7 @@ import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrRawFunctionReferenceImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
@@ -159,6 +156,13 @@ class SecondaryConstructorLowering(val context: JsIrBackendContext) : Declaratio
override fun visitGetValue(expression: IrGetValue) = symbolMapping[expression.symbol.owner]?.let {
expression.run { IrGetValueImpl(startOffset, endOffset, type, it.symbol, origin) }
} ?: expression
override fun visitSetValue(expression: IrSetValue): IrExpression {
expression.transformChildrenVoid()
return symbolMapping[expression.symbol.owner]?.let {
expression.run { IrSetValueImpl(startOffset, endOffset, type, it.symbol, expression.value, origin) }
} ?: expression
}
}
}
@@ -19,30 +19,6 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.util.isTopLevelDeclaration
class JvmDefaultArgumentStubGenerator(override val context: JvmBackendContext) : DefaultArgumentStubGenerator(context, false, false) {
override fun IrBlockBodyBuilder.selectArgumentOrDefault(
defaultFlag: IrExpression,
parameter: IrValueParameter,
default: IrExpression
): IrValueDeclaration {
// We have to generate precisely this code because that results in the bytecode the inliner expects;
// see `expandMaskConditionsAndUpdateVariableNodes`. In short, the bytecode sequence should be
//
// -- no loads of the parameter here, as after inlining its value will be uninitialized
// ILOAD <mask>
// ICONST <bit>
// IAND
// IFEQ Lx
// -- any code inserted here is removed if the call site specifies the parameter
// STORE <n>
// -- no jumps here
// Lx
//
// This control flow limits us to an if-then (without an else), and this together with the
// restriction on loading the parameter in the default case means we cannot create any temporaries.
+irIfThen(defaultFlag, irSet(parameter.symbol, default))
return parameter
}
override fun defaultArgumentStubVisibility(function: IrFunction) = function.getJvmVisibilityOfDefaultArgumentStub()
override fun useConstructorMarker(function: IrFunction): Boolean =
@@ -169,7 +169,7 @@ abstract class DataClassMembersGenerator(
for (property in properties.drop(1)) {
val shiftedResult = irCallOp(intTimesSymbol, irIntType, irGet(irResultVar), irInt(31))
val irRhs = irCallOp(intPlusSymbol, irIntType, shiftedResult, getHashCodeOfProperty(property))
+irSetVar(irResultVar.symbol, irRhs)
+irSet(irResultVar.symbol, irRhs)
}
+irReturn(irGet(irResultVar))