[JS IR BE] Support calls, property accesses and most of operators on expressions with dynamic type

This commit is contained in:
Zalim Bashorov
2018-07-25 13:56:27 +03:00
parent 4a7ecaa908
commit 0da14e4189
9 changed files with 76 additions and 22 deletions
@@ -65,6 +65,12 @@ class JsIntrinsics(
val jsDiv = binOp("jsDiv")
val jsMod = binOp("jsMod")
val jsPlusAssign = binOp("jsPlusAssign")
val jsMinusAssign = binOp("jsMinusAssign")
val jsMultAssign = binOp("jsMultAssign")
val jsDivAssign = binOp("jsDivAssign")
val jsModAssign = binOp("jsModAssign")
val jsAnd = binOp("jsAnd")
val jsOr = binOp("jsOr")
@@ -41,11 +41,13 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL
private val memberToTransformer: MemberToTransformer
private val symbolToTransformer: SymbolToTransformer
private val nameToTransformer: Map<Name, (IrCall) -> IrExpression>
private val dynamicCallOriginToIrFunction: Map<IrStatementOrigin, IrSimpleFunction>
init {
symbolToTransformer = mutableMapOf()
memberToTransformer = mutableMapOf()
nameToTransformer = mutableMapOf()
dynamicCallOriginToIrFunction = mutableMapOf()
val primitiveNumbers = context.irBuiltIns.run { listOf(intType, shortType, byteType, floatType, doubleType) }
@@ -222,6 +224,43 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL
put(Name.identifier("equals"), ::transformEqualsMethodCall)
}
dynamicCallOriginToIrFunction.run {
put(IrStatementOrigin.EXCL, context.intrinsics.jsNot)
put(IrStatementOrigin.LT, context.intrinsics.jsLt)
put(IrStatementOrigin.GT, context.intrinsics.jsGt)
put(IrStatementOrigin.LTEQ, context.intrinsics.jsLtEq)
put(IrStatementOrigin.GTEQ, context.intrinsics.jsGtEq)
put(IrStatementOrigin.EQEQ, context.intrinsics.jsEqeq)
put(IrStatementOrigin.EQEQEQ, context.intrinsics.jsEqeqeq)
put(IrStatementOrigin.EXCLEQ, context.intrinsics.jsNotEq)
put(IrStatementOrigin.EXCLEQEQ, context.intrinsics.jsNotEqeq)
put(IrStatementOrigin.ANDAND, context.intrinsics.jsAnd)
put(IrStatementOrigin.OROR, context.intrinsics.jsOr)
put(IrStatementOrigin.UMINUS, context.intrinsics.jsUnaryMinus)
put(IrStatementOrigin.UPLUS, context.intrinsics.jsUnaryPlus)
put(IrStatementOrigin.PLUS, context.intrinsics.jsPlus)
put(IrStatementOrigin.MINUS, context.intrinsics.jsMinus)
put(IrStatementOrigin.MUL, context.intrinsics.jsMult)
put(IrStatementOrigin.DIV, context.intrinsics.jsDiv)
put(IrStatementOrigin.PERC, context.intrinsics.jsMod)
put(IrStatementOrigin.PLUSEQ, context.intrinsics.jsPlusAssign)
put(IrStatementOrigin.MINUSEQ, context.intrinsics.jsMinusAssign)
put(IrStatementOrigin.MULTEQ, context.intrinsics.jsMultAssign)
put(IrStatementOrigin.DIVEQ, context.intrinsics.jsDivAssign)
put(IrStatementOrigin.PERCEQ, context.intrinsics.jsModAssign)
put(IrStatementOrigin.PREFIX_INCR, context.intrinsics.jsPrefixInc)
put(IrStatementOrigin.PREFIX_DECR, context.intrinsics.jsPrefixDec)
put(IrStatementOrigin.POSTFIX_INCR, context.intrinsics.jsPostfixInc)
put(IrStatementOrigin.POSTFIX_DECR, context.intrinsics.jsPostfixDec)
}
}
override fun lower(irFile: IrFile) {
@@ -261,7 +300,7 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL
if (call is IrCall) {
val symbol = call.symbol
if (symbol.isEffectivelyExternal()) {
if (symbol.isDynamic() || symbol.isEffectivelyExternal()) {
when (call.origin) {
IrStatementOrigin.GET_PROPERTY -> {
val fieldSymbol = IrFieldSymbolImpl((symbol.descriptor as PropertyAccessorDescriptor).correspondingProperty)
@@ -277,6 +316,12 @@ class IntrinsicifyCallsLowering(private val context: JsIrBackendContext) : FileL
}
}
if (symbol.isDynamic()) {
dynamicCallOriginToIrFunction[call.origin]?.let {
return irCall(call, it.symbol, dispatchReceiverAsFirstArgument = true)
}
}
symbolToTransformer[symbol]?.let {
return it(call)
}
@@ -53,6 +53,12 @@ class JsIntrinsicTransformers(backendContext: JsIrBackendContext) {
binOp(intrinsics.jsDiv, JsBinaryOperator.DIV)
binOp(intrinsics.jsMod, JsBinaryOperator.MOD)
binOp(intrinsics.jsPlusAssign, JsBinaryOperator.ASG_ADD)
binOp(intrinsics.jsMinusAssign, JsBinaryOperator.ASG_SUB)
binOp(intrinsics.jsMultAssign, JsBinaryOperator.ASG_MUL)
binOp(intrinsics.jsDivAssign, JsBinaryOperator.ASG_DIV)
binOp(intrinsics.jsModAssign, JsBinaryOperator.ASG_MOD)
binOp(intrinsics.jsBitAnd, JsBinaryOperator.BIT_AND)
binOp(intrinsics.jsBitOr, JsBinaryOperator.BIT_OR)
binOp(intrinsics.jsBitXor, JsBinaryOperator.BIT_XOR)
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.js.backend.ast.JsName
import org.jetbrains.kotlin.js.naming.isES5IdentifierPart
import org.jetbrains.kotlin.js.naming.isES5IdentifierStart
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
@@ -31,6 +32,10 @@ class SimpleNameGenerator : NameGenerator {
nameCache.getOrPut(descriptor) {
var nameDeclarator: (String) -> JsName = context.currentScope::declareName
if (descriptor.isDynamic()) {
return@getOrPut nameDeclarator(descriptor.name.asString())
}
if (descriptor is MemberDescriptor && descriptor.isEffectivelyExternal()) {
val descriptorForName = when (descriptor) {
is ConstructorDescriptor -> descriptor.constructedClass
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrSymbol
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
import org.jetbrains.kotlin.types.KotlinType
@@ -53,3 +54,5 @@ fun CallableMemberDescriptor.isFakeOverriddenFromAny(): Boolean {
fun IrDeclaration.isEffectivelyExternal() = descriptor.isEffectivelyExternal()
fun IrSymbol.isEffectivelyExternal() = descriptor.isEffectivelyExternal()
fun IrSymbol.isDynamic() = descriptor.isDynamic()
@@ -20,8 +20,17 @@ import java.io.File
private val runtimeSources = listOfKtFilesFrom(
"libraries/stdlib/js/src/kotlin/core.kt",
"libraries/stdlib/js/src/kotlin/js.core.kt",
"libraries/stdlib/js/src/kotlin/jsTypeOf.kt",
"libraries/stdlib/js/src/kotlin/dynamic.kt",
"libraries/stdlib/js/src/kotlin/annotations.kt",
"libraries/stdlib/src/kotlin/internal/Annotations.kt",
"core/builtins/native/kotlin/Annotation.kt",
"core/builtins/native/kotlin/Number.kt",
"core/builtins/native/kotlin/Comparable.kt",
"core/builtins/src/kotlin/Annotations.kt",
"core/builtins/src/kotlin/internal/InternalAnnotations.kt",
"core/builtins/src/kotlin/internal/progressionUtil.kt",
"core/builtins/src/kotlin/Iterators.kt",
@@ -32,6 +41,7 @@ private val runtimeSources = listOfKtFilesFrom(
"core/builtins/src/kotlin/Unit.kt",
"core/builtins/native/kotlin/Collections.kt",
"core/builtins/native/kotlin/Iterator.kt",
"libraries/stdlib/js/irRuntime",
BasicBoxTest.COMMON_FILES_DIR_PATH
)
@@ -1,8 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package kotlin
interface Annotation
@@ -1,10 +0,0 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package kotlin.internal
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY)
@Retention(AnnotationRetention.BINARY)
internal annotation class DynamicExtension
@@ -5,9 +5,6 @@
package kotlin.js
@kotlin.internal.DynamicExtension
public inline fun <T> dynamic.unsafeCast(): T = this
private fun isInterfaceImpl(ctor: dynamic, iface: dynamic): Boolean {
if (ctor === iface) return true;