[WASM] Implementation typeOf support

This commit is contained in:
Igor Yakovlev
2021-10-29 15:14:26 +02:00
committed by TeamCityServer
parent 39a389c49a
commit ee7f4c7278
31 changed files with 258 additions and 198 deletions
@@ -24,37 +24,12 @@ import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.DescriptorlessExternalPackageFragmentSymbol
import org.jetbrains.kotlin.ir.types.IrDynamicType
import org.jetbrains.kotlin.ir.types.IrTypeSystemContext
import org.jetbrains.kotlin.ir.types.IrTypeSystemContextImpl
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
class WasmIntrinsics(private val context: WasmBackendContext) : Intrinsics {
override val jsGetKClass: IrSimpleFunctionSymbol get() = context.wasmSymbols.jsGetKClass
override val jsGetKClassFromExpression: IrSimpleFunctionSymbol get() = context.wasmSymbols.jsGetKClassFromExpression
override val jsClass: IrSimpleFunctionSymbol get() = context.wasmSymbols.jsClass
override val createKType: IrSimpleFunctionSymbol?
get() = TODO("Not yet implemented")
override val createDynamicKType: IrSimpleFunctionSymbol?
get() = TODO("Not yet implemented")
override val createKTypeParameter: IrSimpleFunctionSymbol?
get() = TODO("Not yet implemented")
override val getStarKTypeProjection: IrSimpleFunctionSymbol?
get() = TODO("Not yet implemented")
override val createCovariantKTypeProjection: IrSimpleFunctionSymbol?
get() = TODO("Not yet implemented")
override val createInvariantKTypeProjection: IrSimpleFunctionSymbol?
get() = TODO("Not yet implemented")
override val createContravariantKTypeProjection: IrSimpleFunctionSymbol?
get() = TODO("Not yet implemented")
override val arrayLiteral: IrSimpleFunctionSymbol
get() = TODO("Not yet implemented")
}
class WasmBackendContext(
val module: ModuleDescriptor,
override val irBuiltIns: IrBuiltIns,
@@ -68,11 +43,6 @@ class WasmBackendContext(
override val scriptMode = false
override val irFactory: IrFactory = symbolTable.irFactory
//TODO
override val dynamicType: IrDynamicType get() = TODO()
override val primitiveClassesObject get() = wasmSymbols.primitiveClassesObject
//TODO!!!
// Place to store declarations excluded from code generation
private val excludedDeclarations = mutableMapOf<FqName, IrPackageFragment>()
@@ -132,6 +102,8 @@ class WasmBackendContext(
WasmSharedVariablesManager(this, irBuiltIns, internalPackageFragment)
val wasmSymbols: WasmSymbols = WasmSymbols(this@WasmBackendContext, symbolTable)
override val reflectionSymbols: ReflectionSymbols get() = wasmSymbols.reflectionSymbols
override val ir = object : Ir<WasmBackendContext>(this, irModuleFragment) {
override val symbols: Symbols<WasmBackendContext> = wasmSymbols
override fun shouldGenerateHandlerParameterForDefaultBodyFun() = true
@@ -199,6 +171,4 @@ class WasmBackendContext(
}
}
}
override val intrinsics: Intrinsics = WasmIntrinsics(this)
}
@@ -12,8 +12,7 @@ import org.jetbrains.kotlin.descriptors.PackageViewDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.backend.js.ReflectionSymbols
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
@@ -28,7 +27,6 @@ import org.jetbrains.kotlin.ir.util.render
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.util.OperatorNameConventions
import java.lang.IllegalArgumentException
class WasmSymbols(
@@ -45,11 +43,25 @@ class WasmSymbols(
private val kotlinTestPackage: PackageViewDescriptor =
context.module.getPackage(FqName("kotlin.test"))
val jsGetKClass: IrSimpleFunctionSymbol = getInternalFunction("getKClass")
val jsGetKClassFromExpression: IrSimpleFunctionSymbol = getInternalFunction("getKClassFromExpression")
val jsClass: IrSimpleFunctionSymbol = getInternalFunction("wasmGetTypeInfoData")
val wasmTypeInfoData: IrClassSymbol = getInternalClass("TypeInfoData")
val primitiveClassesObject = getInternalClass("PrimitiveClasses")
internal inner class WasmReflectionSymbols : ReflectionSymbols {
override val createKType: IrSimpleFunctionSymbol = getInternalFunction("createKType")
override val getClassData: IrSimpleFunctionSymbol = getInternalFunction("wasmGetTypeInfoData")
override val getKClass: IrSimpleFunctionSymbol = getInternalFunction("getKClass")
override val getKClassFromExpression: IrSimpleFunctionSymbol = getInternalFunction("getKClassFromExpression")
override val createDynamicKType: IrSimpleFunctionSymbol get() = error("Dynamic type is not supported by WASM")
override val createKTypeParameter: IrSimpleFunctionSymbol = getInternalFunction("createKTypeParameter")
override val getStarKTypeProjection = getInternalFunction("getStarKTypeProjection")
override val createCovariantKTypeProjection = getInternalFunction("createCovariantKTypeProjection")
override val createInvariantKTypeProjection = getInternalFunction("createInvariantKTypeProjection")
override val createContravariantKTypeProjection = getInternalFunction("createContravariantKTypeProjection")
override val primitiveClassesObject = getInternalClass("PrimitiveClasses")
override val kTypeClass: IrClassSymbol = getIrClass(FqName("kotlin.reflect.KClass"))
val wasmTypeInfoData: IrClassSymbol = getInternalClass("TypeInfoData")
}
internal val reflectionSymbols: WasmReflectionSymbols = WasmReflectionSymbols()
override val throwNullPointerException = getInternalFunction("THROW_NPE")
override val throwISE = getInternalFunction("THROW_ISE")
@@ -151,7 +163,6 @@ class WasmSymbols(
val wasmClassId = getInternalFunction("wasmClassId")
val wasmInterfaceId = getInternalFunction("wasmInterfaceId")
val wasmTypeId = getInternalFunction("wasmTypeId")
val getVirtualMethodId = getInternalFunction("getVirtualMethodId")
val getInterfaceImplId = getInternalFunction("getInterfaceImplId")
@@ -348,13 +348,6 @@ class BodyGenerator(val context: WasmFunctionCodegenContext) : IrElementVisitorV
body.buildConstI32Symbol(context.referenceInterfaceId(irInterface.symbol))
}
wasmSymbols.wasmTypeId -> {
val type = call.getTypeArgument(0)!!.getClass()
?: error("No class given for wasmClassId intrinsic")
val id = if (type.isInterface) context.referenceInterfaceId(type.symbol) else context.referenceClassId(type.symbol)
body.buildConstI32Symbol(id)
}
wasmSymbols.wasmRefCast -> {
val toType = call.getTypeArgument(0)!!
generateTypeRTT(toType)
@@ -9,6 +9,8 @@ import org.jetbrains.kotlin.backend.common.ir.isOverridableOrOverrides
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
import org.jetbrains.kotlin.backend.wasm.lower.wasmSignature
import org.jetbrains.kotlin.backend.wasm.utils.*
import org.jetbrains.kotlin.config.AnalysisFlags.allowFullyQualifiedNameInKClass
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.IrElement
@@ -276,7 +278,9 @@ class DeclarationGenerator(val context: WasmModuleCodegenContext) : IrElementVis
private fun binaryDataStruct(classMetadata: ClassMetadata): ConstantDataStruct {
val invalidIndex = -1
val packageName = classMetadata.klass.kotlinFqName.parentOrNull()?.asString() ?: ""
val fqnShouldBeEmitted = context.backendContext.configuration.languageVersionSettings.getFlag(allowFullyQualifiedNameInKClass)
//TODO("FqName for inner classes could be invalid due to topping it out from outer class")
val packageName = if (fqnShouldBeEmitted) classMetadata.klass.kotlinFqName.parentOrNull()?.asString() ?: "" else ""
val simpleName = classMetadata.klass.kotlinFqName.shortName().asString()
val typeInfo = ConstantDataStruct(
"TypeInfo",
@@ -10,6 +10,8 @@ import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.wasm.WasmBackendContext
import org.jetbrains.kotlin.config.AnalysisFlags
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.ir.backend.js.utils.isEqualsInheritedFromAny
import org.jetbrains.kotlin.ir.builders.irCall
import org.jetbrains.kotlin.ir.builders.irCallConstructor
@@ -128,22 +130,27 @@ class BuiltInsLowering(val context: WasmBackendContext) : FileLoweringPass {
val newSymbol = irBuiltins.suspendFunctionN(arity).getSimpleFunction("invoke")!!
return irCall(call, newSymbol, argumentsAsReceivers = true)
}
symbols.jsClass -> {
val infoDataCtor = symbols.wasmTypeInfoData.constructors.first()
symbols.reflectionSymbols.getClassData -> {
val infoDataCtor = symbols.reflectionSymbols.wasmTypeInfoData.constructors.first()
val type = call.getTypeArgument(0)!!
val isInterface = type.isInterface()
val fqName = type.classFqName!!
val packageName = fqName.parentOrNull()?.asString() ?: ""
val fqnShouldBeEmitted =
context.configuration.languageVersionSettings.getFlag(AnalysisFlags.allowFullyQualifiedNameInKClass)
val packageName = if (fqnShouldBeEmitted) fqName.parentOrNull()?.asString() ?: "" else ""
val typeName = fqName.shortName().asString()
return with(builder) {
val typeId = irCall(symbols.wasmTypeId).also {
val wasmIdGetter = if (type.isInterface()) symbols.wasmInterfaceId else symbols.wasmClassId
val typeId = irCall(wasmIdGetter).also {
it.putTypeArgument(0, type)
}
irCallConstructor(infoDataCtor, emptyList()).also {
it.putValueArgument(0, typeId)
it.putValueArgument(1, packageName.toIrConst(context.irBuiltIns.stringType))
it.putValueArgument(2, typeName.toIrConst(context.irBuiltIns.stringType))
it.putValueArgument(1, isInterface.toIrConst(context.irBuiltIns.booleanType))
it.putValueArgument(2, packageName.toIrConst(context.irBuiltIns.stringType))
it.putValueArgument(3, typeName.toIrConst(context.irBuiltIns.stringType))
}
}
}