[JS IR BE] move intrinsic for Object.create calls to JsIntrinsics

This commit is contained in:
Zalim Bashorov
2018-04-12 02:25:37 +03:00
parent 89aefb2e3f
commit 2ed82f136c
5 changed files with 79 additions and 65 deletions
@@ -5,27 +5,73 @@
package org.jetbrains.kotlin.ir.backend.js
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.js.resolve.JsPlatform.builtIns
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinTypeFactory
import org.jetbrains.kotlin.types.Variance
class JsIntrinsics(private val module: ModuleDescriptor, private val irBuiltIns: IrBuiltIns, symbolTable: SymbolTable) {
private val stubBuilder = DeclarationStubGenerator(symbolTable, JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB)
class JsIntrinsics(irBuiltIns: IrBuiltIns) {
// Equality
val jsEqeq = irBuiltIns.binOpBool("jsEqeq")
val jsNotEq = irBuiltIns.binOpBool("jsNotEq")
val jsEqeqeq = irBuiltIns.binOpBool("jsEqeqeq")
val jsNotEqeq = irBuiltIns.binOpBool("jsNotEqeq")
val jsEqeq = binOpBool("jsEqeq")
val jsNotEq = binOpBool("jsNotEq")
val jsEqeqeq = binOpBool("jsEqeqeq")
val jsNotEqeq = binOpBool("jsNotEqeq")
// Unary operations
val jsNot = irBuiltIns.unOpBool("jsNot")
val jsNot = unOpBool("jsNot")
// Binary operations
val jsPlus = irBuiltIns.binOp("jsPlus")
val jsMinus = irBuiltIns.binOp("jsMinus")
val jsMult = irBuiltIns.binOp("jsMult")
val jsDiv = irBuiltIns.binOp("jsDiv")
val jsMod = irBuiltIns.binOp("jsMod")
}
val jsPlus = binOp("jsPlus")
val jsMinus = binOp("jsMinus")
val jsMult = binOp("jsMult")
val jsDiv = binOp("jsDiv")
val jsMod = binOp("jsMod")
private fun IrBuiltIns.unOpBool(name: String) = defineOperator(name, bool, listOf(anyN, anyN))
private fun IrBuiltIns.binOpBool(name: String) = defineOperator(name, bool, listOf(anyN, anyN))
private fun IrBuiltIns.unOp(name: String) = defineOperator(name, anyN, listOf(anyN, anyN))
private fun IrBuiltIns.binOp(name: String) = defineOperator(name, anyN, listOf(anyN, anyN))
val jsObjectCreate: IrSimpleFunction = defineObjectCreateIntrinsic()
// Helpers:
// TODO: unify how we create intrinsic symbols
private fun defineObjectCreateIntrinsic(): IrSimpleFunction {
val typeParam = TypeParameterDescriptorImpl.createWithDefaultBound(
builtIns.any,
Annotations.EMPTY,
true,
Variance.INVARIANT,
Name.identifier("T"),
0
)
val returnType = KotlinTypeFactory.simpleType(Annotations.EMPTY, typeParam.typeConstructor, emptyList(), false)
val desc = SimpleFunctionDescriptorImpl.create(
module,
Annotations.EMPTY,
Name.identifier("Object\$create"),
CallableMemberDescriptor.Kind.SYNTHESIZED,
SourceElement.NO_SOURCE
).apply {
initialize(null, null, listOf(typeParam), emptyList(), returnType, Modality.FINAL, Visibilities.PUBLIC)
isInline = true
}
return stubBuilder.generateFunctionStub(desc)
}
private fun unOpBool(name: String) = irBuiltIns.run { defineOperator(name, bool, listOf(anyN, anyN)) }
private fun binOpBool(name: String) = irBuiltIns.run { defineOperator(name, bool, listOf(anyN, anyN)) }
private fun unOp(name: String) = irBuiltIns.run { defineOperator(name, anyN, listOf(anyN, anyN)) }
private fun binOp(name: String) = irBuiltIns.run { defineOperator(name, anyN, listOf(anyN, anyN)) }
}
@@ -9,27 +9,22 @@ import org.jetbrains.kotlin.backend.common.CommonBackendContext
import org.jetbrains.kotlin.backend.common.ReflectionTypes
import org.jetbrains.kotlin.backend.common.ir.Ir
import org.jetbrains.kotlin.backend.common.ir.Symbols
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinTypeFactory
import org.jetbrains.kotlin.types.Variance
class JsIrBackendContext(
val module: ModuleDescriptor,
@@ -38,7 +33,7 @@ class JsIrBackendContext(
symbolTable: SymbolTable
) : CommonBackendContext {
val intrinsics = JsIntrinsics(irBuiltIns)
val intrinsics = JsIntrinsics(module, irBuiltIns, symbolTable)
override val builtIns = module.builtIns
override val sharedVariablesManager = JsSharedVariablesManager(builtIns)
@@ -97,37 +92,6 @@ class JsIrBackendContext(
val secondaryConstructorsMap = mutableMapOf<IrConstructorSymbol, SecondaryCtorPair>()
private val stubBuilder = DeclarationStubGenerator(symbolTable, JsLoweredDeclarationOrigin.JS_INTRINSICS_STUB)
val objectCreate: IrSimpleFunction = defineObjectCreateIntrinsic()
private fun defineObjectCreateIntrinsic(): IrSimpleFunction {
val typeParam = TypeParameterDescriptorImpl.createWithDefaultBound(
builtIns.any,
Annotations.EMPTY,
true,
Variance.INVARIANT,
Name.identifier("T"),
0
)
val returnType = KotlinTypeFactory.simpleType(Annotations.EMPTY, typeParam.typeConstructor, emptyList(), false)
val desc = SimpleFunctionDescriptorImpl.create(
module,
Annotations.EMPTY,
Name.identifier("Object\$create"),
CallableMemberDescriptor.Kind.SYNTHESIZED,
SourceElement.NO_SOURCE
).apply {
initialize(null, null, listOf(typeParam), emptyList(), returnType, Modality.FINAL, Visibilities.PUBLIC)
isInline = true
}
return stubBuilder.generateFunctionStub(desc)
}
private fun find(memberScope: MemberScope, className: String): ClassDescriptor {
return find(memberScope, Name.identifier(className))
}
@@ -232,7 +232,7 @@ class SecondaryCtorLowering(val context: JsIrBackendContext) : IrElementTransfor
ctorOrig.origin, functionSymbol
)
val createFunctionIntrinsic = context.objectCreate
val createFunctionIntrinsic = context.intrinsics.jsObjectCreate
val irBuilder = context.createIrBuilder(functionSymbol, ctorOrig.startOffset, ctorOrig.endOffset).irBlockBody {
val thisVar = irTemporaryVar(
IrCallImpl(
@@ -83,14 +83,6 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer<JsEx
}
override fun visitCall(expression: IrCall, context: JsGenerationContext): JsExpression {
if (expression.symbol == context.staticContext.backendContext.objectCreate.symbol) {
// TODO: temporary workaround until there is no an intrinsic infrastructure
assert(expression.typeArgumentsCount == 1 && expression.valueArgumentsCount == 0)
val classToCreate = expression.getTypeArgument(0)!!
val prototype = prototypeOf(classToCreate.constructor.declarationDescriptor!!.name.toJsName().makeRef())
return JsInvocation(Namer.JS_OBJECT_CREATE_FUNCTION, prototype)
}
val symbol = expression.symbol
val dispatchReceiver = expression.dispatchReceiver?.accept(this, context)
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
import org.jetbrains.kotlin.ir.backend.js.JsIntrinsics
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.symbols.IrSymbol
@@ -32,12 +33,23 @@ class JsIntrinsicTransformers(intrinsics: JsIntrinsics) {
binOp(intrinsics.jsMult, JsBinaryOperator.MUL)
binOp(intrinsics.jsDiv, JsBinaryOperator.DIV)
binOp(intrinsics.jsMod, JsBinaryOperator.MOD)
add(intrinsics.jsObjectCreate) { call, _ ->
val classToCreate = call.getTypeArgument(0)!!
val prototype = prototypeOf(classToCreate.constructor.declarationDescriptor!!.name.toJsName().makeRef())
JsInvocation(Namer.JS_OBJECT_CREATE_FUNCTION, prototype)
}
}
}
operator fun get(symbol: IrSymbol): IrCallTransformer? = transformers[symbol]
}
private fun MutableMap<IrSymbol, IrCallTransformer>.add(function: IrFunction, t: IrCallTransformer) {
put(function.symbol, t)
}
private fun MutableMap<IrSymbol, IrCallTransformer>.binOp(function: IrFunction, op: JsBinaryOperator) {
put(function.symbol, { _, args -> JsBinaryOperation(op, args[0], args[1]) })
}