[JS IR BE] Fix boolean and/or generation

This commit is contained in:
Svyatoslav Kuzmich
2019-04-27 22:05:07 +03:00
parent b8bbcb3f93
commit 3153a7dd7e
4 changed files with 52 additions and 6 deletions
@@ -7,15 +7,13 @@ package org.jetbrains.kotlin.ir.backend.js.lower.calls
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
import org.jetbrains.kotlin.ir.util.irCall
import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.irCall
import org.jetbrains.kotlin.name.Name
class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransformer {
@@ -47,10 +45,12 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
}
irBuiltIns.booleanType.let {
add(it, OperatorNames.AND, intrinsics.jsBitAnd)
add(it, OperatorNames.OR, intrinsics.jsBitOr)
// These operators are not short-circuit -- using bitwise operators '&', '|', '^' followed by coercion to boolean
add(it, OperatorNames.AND) { call -> toBoolean(irCall(call, intrinsics.jsBitAnd, dispatchReceiverAsFirstArgument = true)) }
add(it, OperatorNames.OR) { call -> toBoolean(irCall(call, intrinsics.jsBitOr, dispatchReceiverAsFirstArgument = true)) }
add(it, OperatorNames.XOR) { call -> toBoolean(irCall(call, intrinsics.jsBitXor, dispatchReceiverAsFirstArgument = true)) }
add(it, OperatorNames.NOT, intrinsics.jsNot)
add(it, OperatorNames.XOR, intrinsics.jsBitXor)
}
for (type in primitiveNumbers) {
@@ -231,6 +231,14 @@ class NumberOperatorCallsTransformer(context: JsIrBackendContext) : CallsTransfo
}
}
private fun booleanNegate(e: IrExpression) =
JsIrBuilder.buildCall(intrinsics.jsNot, irBuiltIns.booleanType).apply {
putValueArgument(0, e)
}
private fun toBoolean(e: IrExpression) =
booleanNegate(booleanNegate(e))
private fun toInt32(e: IrExpression) =
JsIrBuilder.buildCall(intrinsics.jsBitOr, irBuiltIns.intType).apply {
putValueArgument(0, e)
@@ -6791,6 +6791,11 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/box/regression/typeChecks"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS_IR, true);
}
@TestMetadata("booleanOperatorsTypes.kt")
public void testBooleanOperatorsTypes() throws Exception {
runTest("js/js.translator/testData/box/regression/typeChecks/booleanOperatorsTypes.kt");
}
@TestMetadata("emptyVarargInConstructorCall.kt")
public void testEmptyVarargInConstructorCall() throws Exception {
runTest("js/js.translator/testData/box/regression/typeChecks/emptyVarargInConstructorCall.kt");
@@ -6826,6 +6826,11 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("js/js.translator/testData/box/regression/typeChecks"), Pattern.compile("^([^_](.+))\\.kt$"), TargetBackend.JS, true);
}
@TestMetadata("booleanOperatorsTypes.kt")
public void testBooleanOperatorsTypes() throws Exception {
runTest("js/js.translator/testData/box/regression/typeChecks/booleanOperatorsTypes.kt");
}
@TestMetadata("emptyVarargInConstructorCall.kt")
public void testEmptyVarargInConstructorCall() throws Exception {
runTest("js/js.translator/testData/box/regression/typeChecks/emptyVarargInConstructorCall.kt");
@@ -0,0 +1,28 @@
// IGNORE_BACKEND: JS
// EXPECTED_REACHABLE_NODES: 1281
package foo
fun check(x: Any?) {
x as Boolean
}
fun tests(x: Boolean, y: Boolean) {
check(x)
check(!x)
check(x or y)
check(x and y)
check(x xor y)
check(x.not())
check(x || y)
check(x && y)
}
fun box(): String {
tests(false, false)
tests(false, true)
tests(true, false)
tests(true, true)
return "OK"
}