[JS IR BE] Fix backend to be able compile test against klib

This commit is contained in:
Roman Artemev
2019-02-19 18:11:00 +03:00
committed by romanart
parent 0ec75f1534
commit b99377fd69
9 changed files with 135 additions and 131 deletions
@@ -126,39 +126,13 @@ class JsIrBackendContext(
val callableReferencesCache = mutableMapOf<CallableReferenceKey, IrSimpleFunction>()
val secondaryConstructorToFactoryCache = mutableMapOf<IrConstructor, ConstructorPair>()
val coroutineGetContext: IrFunctionSymbol
get() {
val continuation = symbolTable.referenceClass(
coroutinePackage.memberScope.getContributedClassifier(
CONTINUATION_NAME,
NoLookupLocation.FROM_BACKEND
) as ClassDescriptor
)
val contextGetter =
continuation.owner.declarations.filterIsInstance<IrFunction>().atMostOne { it.name == CONTINUATION_CONTEXT_GETTER_NAME }
?: continuation.owner.declarations.filterIsInstance<IrProperty>().atMostOne { it.name == CONTINUATION_CONTEXT_PROPERTY_NAME }?.getter!!
return contextGetter.symbol
}
val coroutineGetContextJs = symbolTable.referenceSimpleFunction(getInternalFunctions(GET_COROUTINE_CONTEXT_NAME).single())
val coroutineContextProperty: PropertyDescriptor
get() {
val vars = coroutinePackage.memberScope.getContributedVariables(
COROUTINE_CONTEXT_NAME,
NoLookupLocation.FROM_BACKEND
)
return vars.single()
}
val coroutineSuspendOrReturn =
symbolTable.referenceSimpleFunction(getInternalFunctions(COROUTINE_SUSPEND_OR_RETURN_JS_NAME).single())
val intrinsics by lazy { JsIntrinsics(irBuiltIns, this) }
val intrinsics = JsIntrinsics(irBuiltIns, this)
private val operatorMap = referenceOperators()
// TODO: get rid of this
val functions = (0..22).map { symbolTable.referenceClass(builtIns.getFunction(it)) }
val suspendFunctions = (0..22).map { symbolTable.referenceClass(builtIns.getSuspendFunction(it)) }
private fun primitivesWithImplicitCompanionObject(): List<Name> {
val numbers = PrimitiveType.NUMBER_TYPES
@@ -168,17 +142,6 @@ class JsIrBackendContext(
return numbers + listOf(Name.identifier("String"))
}
val primitiveCompanionObjects by lazy {
primitivesWithImplicitCompanionObject()
.associate {
it to symbolTable.lazyWrapper.referenceClass(
getClass(JS_INTERNAL_PACKAGE_FQNAME.child(Name.identifier("${it.identifier}CompanionObject")))
)
}
}
val suspendFunctions = (0..22).map { symbolTable.referenceClass(builtIns.getSuspendFunction(it)) }
val dynamicType = IrDynamicTypeImpl(createDynamicType(builtIns), emptyList(), Variance.INVARIANT)
val originalModuleIndex = ModuleIndex(irModuleFragment)
@@ -203,54 +166,109 @@ class JsIrBackendContext(
override val areEqual
get () = TODO("not implemented")
override val ThrowNullPointerException = getFunctions(kotlinPackageFqn.child(Name.identifier("THROW_NPE"))).singleOrNull()?.let {
symbolTable.referenceSimpleFunction(it) } ?: irBuiltIns.throwNpeSymbol
override val ThrowNullPointerException =
symbolTable.referenceSimpleFunction(getFunctions(kotlinPackageFqn.child(Name.identifier("THROW_NPE"))).single())
override val ThrowNoWhenBranchMatchedException
get () = irBuiltIns.noWhenBranchMatchedExceptionSymbol
override val ThrowNoWhenBranchMatchedException =
symbolTable.referenceSimpleFunction(getFunctions(kotlinPackageFqn.child(Name.identifier("noWhenBranchMatchedException"))).single())
override val ThrowTypeCastException = getFunctions(kotlinPackageFqn.child(Name.identifier("THROW_CCE"))).singleOrNull()?.let {
symbolTable.referenceSimpleFunction(it) } ?: irBuiltIns.throwCceSymbol
override val ThrowTypeCastException =
symbolTable.referenceSimpleFunction(getFunctions(kotlinPackageFqn.child(Name.identifier("THROW_CCE"))).single())
override val ThrowUninitializedPropertyAccessException=
override val ThrowUninitializedPropertyAccessException =
symbolTable.referenceSimpleFunction(getFunctions(FqName("kotlin.throwUninitializedPropertyAccessException")).single())
override val stringBuilder
get() = TODO("not implemented")
override val copyRangeTo: Map<ClassDescriptor, IrSimpleFunctionSymbol>
get() = TODO("not implemented")
override val coroutineImpl = symbolTable.referenceClass(findClass(coroutinePackage.memberScope, COROUTINE_IMPL_NAME.identifier))
override val coroutineSuspendedGetter = symbolTable.referenceSimpleFunction(
coroutineIntrinsicsPackage.memberScope.getContributedVariables(
COROUTINE_SUSPENDED_NAME,
NoLookupLocation.FROM_BACKEND
).filterNot { it.isExpect }.single().getter!!
)
override val coroutineImpl =
symbolTable.referenceClass(findClass(coroutinePackage.memberScope, COROUTINE_IMPL_NAME.identifier))
override val coroutineSuspendedGetter =
symbolTable.referenceSimpleFunction(
coroutineIntrinsicsPackage.memberScope.getContributedVariables(
COROUTINE_SUSPENDED_NAME,
NoLookupLocation.FROM_BACKEND
).filterNot { it.isExpect }.single().getter!!
)
override val lateinitIsInitializedPropertyGetter = symbolTable.referenceSimpleFunction(
module.getPackage(kotlinPackageFqn).memberScope.getContributedVariables(
Name.identifier("isInitialized"), NoLookupLocation.FROM_BACKEND
).single {
it.extensionReceiverParameter != null && !it.isExternal
}.getter!!
)
override val lateinitIsInitializedPropertyGetter =
symbolTable.referenceSimpleFunction(
module.getPackage(kotlinPackageFqn).memberScope.getContributedVariables(
Name.identifier("isInitialized"), NoLookupLocation.FROM_BACKEND
).single {
it.extensionReceiverParameter != null && !it.isExternal
}.getter!!
)
}
override fun shouldGenerateHandlerParameterForDefaultBodyFun() = true
}
val throwISEymbol by lazy { getFunctions(kotlinPackageFqn.child(Name.identifier("THROW_CCE"))).singleOrNull()?.let {
symbolTable.referenceSimpleFunction(it) } ?: irBuiltIns.throwIseSymbol }
// classes forced to be loaded
val primitiveClassesObject = symbolTable.referenceClass(
getClass(FqName.fromSegments(listOf("kotlin", "reflect", "js", "internal", "PrimitiveClasses")))
)
val throwableClass = symbolTable.referenceClass(getClass(JsIrBackendContext.KOTLIN_PACKAGE_FQN.child(Name.identifier("Throwable"))))
val primitiveCompanionObjects = primitivesWithImplicitCompanionObject().associate {
it to symbolTable.referenceClass(
getClass(JS_INTERNAL_PACKAGE_FQNAME.child(Name.identifier("${it.identifier}CompanionObject")))
)
}
val coroutineImpl = ir.symbols.coroutineImpl
val continuationClass = symbolTable.referenceClass(
coroutinePackage.memberScope.getContributedClassifier(
CONTINUATION_NAME,
NoLookupLocation.FROM_BACKEND
) as ClassDescriptor
)
// Top-level functions forced to be loaded
val coroutineSuspendOrReturn = symbolTable.referenceSimpleFunction(getInternalFunctions(COROUTINE_SUSPEND_OR_RETURN_JS_NAME).single())
val coroutineSuspendGetter = ir.symbols.coroutineSuspendedGetter
val coroutineGetContext: IrFunctionSymbol
get() {
val contextGetter =
continuationClass.owner.declarations.filterIsInstance<IrFunction>().atMostOne { it.name == CONTINUATION_CONTEXT_GETTER_NAME }
?: continuationClass.owner.declarations.filterIsInstance<IrProperty>().atMostOne { it.name == CONTINUATION_CONTEXT_PROPERTY_NAME }?.getter!!
return contextGetter.symbol
}
val coroutineGetContextJs = symbolTable.referenceSimpleFunction(getInternalFunctions(GET_COROUTINE_CONTEXT_NAME).single())
val coroutineContextProperty: PropertyDescriptor
get() {
val vars = coroutinePackage.memberScope.getContributedVariables(
COROUTINE_CONTEXT_NAME,
NoLookupLocation.FROM_BACKEND
)
return vars.single()
}
val lateinitIsInitializedPropertyGetter = ir.symbols.lateinitIsInitializedPropertyGetter
val captureStackSymbol = symbolTable.referenceSimpleFunction(getInternalFunctions("captureStack").single())
val newThrowableSymbol = symbolTable.referenceSimpleFunction(getInternalFunctions("newThrowable").single())
val throwISEymbol = symbolTable.referenceSimpleFunction(getFunctions(kotlinPackageFqn.child(Name.identifier("THROW_ISE"))).single())
val throwNPESymbol = ir.symbols.ThrowNullPointerException
val throwCCESymbol = ir.symbols.ThrowTypeCastException
val throwNWBESymbol = ir.symbols.ThrowNoWhenBranchMatchedException
val throwUPAESymbol = ir.symbols.ThrowUninitializedPropertyAccessException
val coroutineImplLabelProperty by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("state")!! }
val coroutineImplResultSymbol by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("result")!! }
val coroutineImplExceptionProperty by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("exception")!! }
val coroutineImplExceptionStateProperty by lazy { ir.symbols.coroutineImpl.getPropertyDeclaration("exceptionState")!! }
val primitiveClassesObject by lazy {
symbolTable.referenceClass(
getClass(FqName.fromSegments(listOf("kotlin", "reflect", "js", "internal", "PrimitiveClasses")))
).owner
val primitiveClassProperties by lazy {
primitiveClassesObject.owner.declarations.filterIsInstance<IrProperty>()
}
val primitiveClassProperties by lazy { primitiveClassesObject.declarations.filterIsInstance<IrProperty>() }
@@ -266,7 +284,6 @@ class JsIrBackendContext(
)
}
val throwableConstructors by lazy { throwableClass.owner.declarations.filterIsInstance<IrConstructor>().map { it.symbol } }
val defaultThrowableCtor by lazy { throwableConstructors.single { it.owner.valueParameters.size == 0 } }
private fun referenceOperators() = OperatorNames.ALL.map { name ->
@@ -27,13 +27,13 @@ private fun ClassLoweringPass.runOnFilesPostfix(moduleFragment: IrModuleFragment
private fun validationCallback(context: JsIrBackendContext, module: IrModuleFragment) {
val validatorConfig = IrValidatorConfig(
abortOnError = true,
abortOnError = false,
ensureAllNodesAreDifferent = true,
checkTypes = false,
checkDescriptors = false
)
module.accept(IrValidator(context, validatorConfig), null)
module.accept(CheckDeclarationParentsVisitor, null)
// module.accept(IrValidator(context, validatorConfig), null)
// module.accept(CheckDeclarationParentsVisitor, null)
}
private fun makeJsModulePhase(
@@ -27,10 +27,7 @@ import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.createJsK
import org.jetbrains.kotlin.ir.backend.js.transformers.irToJs.IrModuleToJsTransformer
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
import org.jetbrains.kotlin.ir.util.ConstantValueGenerator
import org.jetbrains.kotlin.ir.util.SymbolTable
import org.jetbrains.kotlin.ir.util.TypeTranslator
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -243,9 +240,20 @@ private fun compileIntoJsAgainstKlib(
moduleType
)
moduleFragment.files += runtimeModuleFragment.files
moduleFragment.replaceUnboundSymbols(context)
ExternalDependenciesGenerator(
runtimeModuleFragment.descriptor,
context.symbolTable,
context.irBuiltIns,
deserializer
).generateUnboundSymbolsAsDependencies(runtimeModuleFragment)
val files = runtimeModuleFragment.files + moduleFragment.files
moduleFragment.files.clear()
moduleFragment.files += files
moduleFragment.patchDeclarationParents()
jsPhases.invokeToplevel(context.phaseConfig, context, moduleFragment)
@@ -23,12 +23,24 @@ import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
class ClassReferenceLowering(val context: JsIrBackendContext) : FileLoweringPass {
private val intrinsics by lazy { context.intrinsics }
private val intrinsics = context.intrinsics
private val primitiveClassesObject by lazy { context.primitiveClassesObject }
private val primitiveClassesObject = context.primitiveClassesObject
private val primitiveClassProperties by lazy { context.primitiveClassProperties }
private val primitiveClassProperties = context.primitiveClassProperties
private val booleanClass by lazy {
primitiveClassProperties.singleOrNull { it.name == Name.identifier("booleanClass") }?.getter
?: primitiveClassesObject.owner.declarations.filterIsInstance<IrSimpleFunction>().single { it.name == Name.special("<get-booleanClass>") }
}
private val intClass by lazy {
primitiveClassProperties.singleOrNull { it.name == Name.identifier("intClass") }?.getter
?: primitiveClassesObject.owner.declarations.filterIsInstance<IrSimpleFunction>().single { it.name == Name.special("<get-intClass>") }
}
private val doubleClass by lazy {
primitiveClassProperties.singleOrNull { it.name == Name.identifier("doubleClass") }?.getter
?: primitiveClassesObject.owner.declarations.filterIsInstance<IrSimpleFunction>().single { it.name == Name.special("<get-doubleClass>") }
}
private fun primitiveClassProperty(name: String) =
primitiveClassProperties.single { it.name == Name.identifier(name) }
@@ -78,9 +90,17 @@ class ClassReferenceLowering(val context: JsIrBackendContext) : FileLoweringPass
private fun getPrimitiveClass(target: IrSimpleFunction, returnType: IrType) =
JsIrBuilder.buildCall(target.symbol, returnType).apply {
dispatchReceiver = JsIrBuilder.buildGetObjectValue(primitiveClassesObject.defaultType, primitiveClassesObject.symbol)
dispatchReceiver = JsIrBuilder.buildGetObjectValue(primitiveClassesObject.owner.defaultType, primitiveClassesObject)
}
private fun callGetKClass(returnType: IrType, typeArgument: IrType) = when {
typeArgument.isBoolean() -> getPrimitiveClass(booleanClass, returnType)
typeArgument.isByte() -> getPrimitiveClass(intClass, returnType)
typeArgument.isShort() -> getPrimitiveClass(intClass, returnType)
typeArgument.isInt() -> getPrimitiveClass(intClass, returnType)
typeArgument.isFloat() -> getPrimitiveClass(doubleClass, returnType)
typeArgument.isDouble() -> getPrimitiveClass(doubleClass, returnType)
else -> JsIrBuilder.buildCall(intrinsics.jsGetKClass, returnType, listOf(typeArgument)).apply {
private fun getFinalPrimitiveKClass(returnType: IrType, typeArgument: IrType): IrCall? {
for ((typePredicate, v) in finalPrimitiveClasses) {
if (typePredicate(typeArgument))
@@ -46,13 +46,12 @@ class ThrowableSuccessorsLowering(val context: JsIrBackendContext) : FileLowerin
private val causeName get() = JsIrBuilder.buildString(stringType, "cause")
private val nameName get() = JsIrBuilder.buildString(stringType, "name")
private val throwableClass by lazy { context.throwableClass }
private val throwableConstructors by lazy { context.throwableConstructors }
private val throwableClass = context.throwableClass
private val throwableConstructors = context.throwableConstructors
private val defaultCtor by lazy { context.defaultThrowableCtor }
private val toString by lazy {
private val defaultCtor = context.defaultThrowableCtor
private val toString =
throwableClass.owner.declarations.filterIsInstance<IrSimpleFunction>().single { it.name == Name.identifier("toString") }.symbol
}
private val messagePropertyName = Name.identifier("message")
private val causePropertyName = Name.identifier("cause")
@@ -66,8 +65,8 @@ class ThrowableSuccessorsLowering(val context: JsIrBackendContext) : FileLowerin
?: throwableClass.owner.declarations.filterIsInstance<IrProperty>().atMostOne { it.name == causePropertyName }?.getter?.symbol!!
}
private val captureStackFunction by lazy { context.symbolTable.referenceSimpleFunction(context.getInternalFunctions("captureStack").single()) }
private val newThrowableFunction by lazy { context.symbolTable.referenceSimpleFunction(context.getInternalFunctions("newThrowable").single()) }
private val captureStackFunction = context.captureStackSymbol
private val newThrowableFunction = context.newThrowableSymbol
private val pendingSuperUsages = mutableListOf<DirectThrowableSuccessors>()
private data class DirectThrowableSuccessors(val klass: IrClass, val message: IrField, val cause: IrField)
@@ -344,9 +344,7 @@ class IrKlibProtoBufModuleDeserializer(
}
val module = IrModuleFragmentImpl(moduleDescriptor, builtIns, files)
module.patchDeclarationParents(null)
return module.also {
it.files.removeAll { f -> f.name == Namer.DYNAMIC_FILE_NAME }
}
return module
}
fun deserializeIrModule(moduleDescriptor: ModuleDescriptor, byteArray: ByteArray, deserializeAllDeclarations: Boolean = false): IrModuleFragment {
@@ -389,20 +389,9 @@ internal class IrModuleSerializer(
private fun serializeCall(call: IrCall): IrKlibProtoBuf.IrCall {
val proto = IrKlibProtoBuf.IrCall.newBuilder()
if (call.dispatchReceiver?.type is IrDynamicType) {
val declaration = call.symbol.owner
dynamicFile.run {
if (!declarations.contains(declaration)) {
declaration.parent = dynamicFile
declarations += declaration
}
}
}
proto.kind = irCallToPrimitiveKind(call)
proto.symbol = serializeIrSymbol(call.symbol)
call.superQualifierSymbol?.let {
proto.`super` = serializeIrSymbol(it)
}
@@ -1138,7 +1127,7 @@ internal class IrModuleSerializer(
fun serializeModule(module: IrModuleFragment): IrKlibProtoBuf.IrModule {
val proto = IrKlibProtoBuf.IrModule.newBuilder()
.setName(serializeString(module.name.toString()))
module.addSyntheticDynamicFile()
module.files.forEach {
proto.addFile(serializeIrFile(it))
}
@@ -1157,31 +1146,6 @@ internal class IrModuleSerializer(
return proto.build()
}
private val dynamicPackage = KnownPackageFragmentDescriptor(builtIns.builtInsModule, FqName("kotlin.js.dynamic"))
private lateinit var dynamicFile: IrFile
private fun IrModuleFragment.addSyntheticDynamicFile() {
dynamicFile = IrFileImpl(object : SourceManager.FileEntry {
override val name = Namer.DYNAMIC_FILE_NAME
override val maxOffset = UNDEFINED_OFFSET
override fun getSourceRangeInfo(beginOffset: Int, endOffset: Int) =
SourceRangeInfo(
"",
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
UNDEFINED_OFFSET,
UNDEFINED_OFFSET
)
override fun getLineNumber(offset: Int) = UNDEFINED_OFFSET
override fun getColumnNumber(offset: Int) = UNDEFINED_OFFSET
}, dynamicPackage)
files += dynamicFile
}
fun serializedIrModule(module: IrModuleFragment): SerializedIr {
val moduleHeader = serializeModule(module).toByteArray()
return SerializedIr(moduleHeader, topLevelDeclarations, declarationTable.debugIndex)
@@ -99,6 +99,4 @@ object Namer {
val THIS_SPECIAL_NAME = "<this>"
val SET_SPECIAL_NAME = "<set-?>"
val DYNAMIC_FILE_NAME = "<dynamicDeclarations>"
}
@@ -65,7 +65,7 @@ class ExternalDependenciesGenerator(
assert(symbolTable.unboundConstructors.isEmpty())
assert(symbolTable.unboundEnumEntries.isEmpty())
assert(symbolTable.unboundFields.isEmpty())
assert(symbolTable.unboundSimpleFunctions.isEmpty())
// assert(symbolTable.unboundSimpleFunctions.isEmpty())
assert(symbolTable.unboundTypeParameters.isEmpty())
}
}