[JS IR BE] Move IrSerializer from native to JS
* Fix issues
This commit is contained in:
+1
-1
@@ -583,7 +583,7 @@ open class WrappedClassDescriptor(
|
||||
private val _typeConstructor: TypeConstructor by lazy {
|
||||
LazyTypeConstructor(
|
||||
this,
|
||||
{ emptyList() },
|
||||
{ declaredTypeParameters },
|
||||
{ owner.superTypes.map { it.toKotlinType() } },
|
||||
LockBasedStorageManager.NO_LOCKS
|
||||
)
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
@@ -386,6 +387,8 @@ fun IrClass.createImplicitParameterDeclarationWithWrappedDescriptor() {
|
||||
assert(descriptor.declaredTypeParameters.isEmpty())
|
||||
}
|
||||
|
||||
fun isElseBranch(branch: IrBranch) = branch is IrElseBranch || ((branch.condition as? IrConst<Boolean>)?.value == true)
|
||||
|
||||
fun IrSimpleFunction.isMethodOfAny() =
|
||||
((valueParameters.size == 0 && name.asString().let { it == "hashCode" || it == "toString" }) ||
|
||||
(valueParameters.size == 1 && name.asString() == "equals" && valueParameters[0].type.isNullableAny()))
|
||||
|
||||
+4
-1
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.types.isAny
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
@@ -209,7 +210,9 @@ fun IrConstructor.callsSuper(irBuiltIns: IrBuiltIns): Boolean {
|
||||
assert(++numberOfCalls == 1) { "More than one delegating constructor call: ${symbol.owner}" }
|
||||
val delegatingClass = expression.symbol.owner.parent as IrClass
|
||||
// TODO: figure out why Lazy IR multiplies Declarations for descriptors and fix it
|
||||
if (delegatingClass.descriptor == superClass.classifierOrFail.descriptor)
|
||||
if (delegatingClass.descriptor == superClass.classifierOrFail.descriptor || (
|
||||
delegatingClass.defaultType.isAny() && superClass.isAny()
|
||||
))
|
||||
callsSuper = true
|
||||
else if (delegatingClass.descriptor != constructedClass.descriptor)
|
||||
throw AssertionError(
|
||||
|
||||
@@ -6,42 +6,42 @@
|
||||
package org.jetbrains.kotlin.ir.backend.js
|
||||
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import org.jetbrains.kotlin.backend.common.CompilerPhaseManager
|
||||
import org.jetbrains.kotlin.backend.common.output.OutputFile
|
||||
import org.jetbrains.kotlin.backend.common.output.OutputFileCollection
|
||||
import org.jetbrains.kotlin.backend.common.output.SimpleOutputBinaryFile
|
||||
import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection
|
||||
import org.jetbrains.kotlin.backend.common.LoggingContext
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.functions.functionInterfacePackageFragmentProvider
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
|
||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider
|
||||
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.inline.replaceUnboundSymbols
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir.*
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.*
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.coroutines.CoroutineIntrinsicLowering
|
||||
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.deepCopyWithSymbols
|
||||
import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS
|
||||
import org.jetbrains.kotlin.js.resolve.JsPlatform
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
|
||||
import org.jetbrains.kotlin.serialization.js.JsSerializerProtocol
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||
import org.jetbrains.kotlin.utils.JsMetadataVersion
|
||||
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
|
||||
import java.io.File
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
|
||||
data class Result(val moduleDescriptor: ModuleDescriptor, val generatedCode: String, val moduleFragment: IrModuleFragment?)
|
||||
enum class ModuleType {
|
||||
TEST_RUNTIME,
|
||||
SECONDARY,
|
||||
@@ -59,13 +59,6 @@ class CompiledModule(
|
||||
get() = moduleFragment!!.descriptor as ModuleDescriptorImpl
|
||||
}
|
||||
|
||||
fun OutputFileCollection.writeAll(outputDir: File) {
|
||||
for (file in asList()) {
|
||||
val output = File(outputDir, file.relativePath)
|
||||
FileUtil.writeToFile(output, file.asByteArray())
|
||||
}
|
||||
}
|
||||
|
||||
fun compile(
|
||||
project: Project,
|
||||
files: List<KtFile>,
|
||||
@@ -92,7 +85,7 @@ fun compile(
|
||||
TopDownAnalyzerFacadeForJS.checkForErrors(files, analysisResult.bindingContext)
|
||||
|
||||
val symbolTable = SymbolTable()
|
||||
dependencies.forEach { symbolTable.loadModule(it.moduleFragment!!) }
|
||||
// irDependencyModules.forEach { symbolTable.loadModule(it) }
|
||||
|
||||
val psi2IrTranslator = Psi2IrTranslator(configuration.languageVersionSettings)
|
||||
val psi2IrContext = psi2IrTranslator.createGeneratorContext(analysisResult.moduleDescriptor, analysisResult.bindingContext, symbolTable)
|
||||
@@ -111,82 +104,103 @@ fun compile(
|
||||
|
||||
|
||||
if (isKlibCompilation) {
|
||||
// val declarationTable = DeclarationTable(moduleFragment.irBuiltins, DescriptorTable())
|
||||
// val serializedIr = IrModuleSerializer(context, declarationTable/*, onlyForInlines = false*/).serializedIrModule(moduleFragment)
|
||||
// val serializer = KonanSerializationUtil(context, configuration.get(CommonConfigurationKeys.METADATA_VERSION)!!, declarationTable)
|
||||
// val serializedData = serializer.serializeModule(analysisResult.moduleDescriptor, serializedIr)
|
||||
// buildLibrary(serializedData)
|
||||
//
|
||||
val logggg = object : LoggingContext {
|
||||
override fun log(message: () -> String) {}
|
||||
}
|
||||
|
||||
// val declarationTable = DeclarationTable(moduleFragment.irBuiltins, DescriptorTable())
|
||||
// val serializedIr = IrModuleSerializer(context, declarationTable/*, onlyForInlines = false*/).serializedIrModule(moduleFragment)
|
||||
val declarationTable = DeclarationTable(moduleFragment.irBuiltins, DescriptorTable(), psi2IrContext.symbolTable)
|
||||
|
||||
val serializedIr = IrModuleSerializer(logggg, declarationTable/*, onlyForInlines = false*/).serializedIrModule(moduleFragment)
|
||||
val serializer = JsKlibMetadataSerializationUtil
|
||||
// val serializedData = serializer.serializeModule(analysisResult.moduleDescriptor, serializedIr)
|
||||
|
||||
val moduleName = configuration.get(CommonConfigurationKeys.MODULE_NAME) as String
|
||||
val metadataVersion = configuration.get(CommonConfigurationKeys.METADATA_VERSION) as? JsKlibMetadataVersion
|
||||
?: JsKlibMetadataVersion.INSTANCE
|
||||
val moduleDescription =
|
||||
JsKlibMetadataModuleDescriptor(moduleName, dependencies.map { it.name.asString() }, moduleFragment.descriptor)
|
||||
var index = 0L
|
||||
val serializedData = serializer.serializeMetadata(
|
||||
psi2IrContext.bindingContext,
|
||||
moduleDescription,
|
||||
configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS)!!,
|
||||
metadataVersion
|
||||
) {
|
||||
// val index = declarationTable.descriptorTable.get(it)
|
||||
// index?.let { newDescriptorUniqId(it) }
|
||||
JsKlibMetadataProtoBuf.DescriptorUniqId.newBuilder().setIndex(index++).build()
|
||||
|
||||
) { declarationDescriptor ->
|
||||
val index = declarationTable.descriptorTable.get(declarationDescriptor)
|
||||
index?.let { newDescriptorUniqId(it) }
|
||||
}
|
||||
// buildLibrary(serializedData)
|
||||
//
|
||||
|
||||
val stdKlibDir = File("js/js.translator/testData/out/klibs/runtime/").also {
|
||||
it.deleteRecursively()
|
||||
it.mkdirs()
|
||||
}
|
||||
//
|
||||
// val moduleFile = File(stdKlibDir, "module.kji")
|
||||
// moduleFile.writeBytes(serializedIr.module)
|
||||
//
|
||||
// for ((id, data) in serializedIr.declarations) {
|
||||
// val file = File(stdKlibDir, "${id.index}${if (id.isLocal) "L" else "G"}.kjd")
|
||||
// file.writeBytes(data)
|
||||
// }
|
||||
//
|
||||
//
|
||||
// val debugFile = File(stdKlibDir, "debug.txt")
|
||||
//
|
||||
// for ((id, data) in serializedIr.debugIndex) {
|
||||
// debugFile.appendText(id.toString())
|
||||
// debugFile.appendText(" --- ")
|
||||
// debugFile.appendText(data)
|
||||
// debugFile.appendText("\n")
|
||||
// }
|
||||
|
||||
val metadata = File(stdKlibDir, "${moduleDescription.name}${JsKlibMetadataSerializationUtil.CLASS_METADATA_FILE_EXTENSION}").also {
|
||||
val moduleFile = File(stdKlibDir, "module.kji")
|
||||
moduleFile.writeBytes(serializedIr.module)
|
||||
|
||||
val irDeclarationDir = File(stdKlibDir, "ir/").also { it.mkdir() }
|
||||
|
||||
for ((id, data) in serializedIr.declarations) {
|
||||
val file = File(irDeclarationDir, id.declarationFileName)
|
||||
file.writeBytes(data)
|
||||
}
|
||||
|
||||
|
||||
val debugFile = File(stdKlibDir, "debug.txt")
|
||||
|
||||
for ((id, data) in serializedIr.debugIndex) {
|
||||
debugFile.appendText(id.toString())
|
||||
debugFile.appendText(" --- ")
|
||||
debugFile.appendText(data)
|
||||
debugFile.appendText("\n")
|
||||
}
|
||||
|
||||
val metadata = File(stdKlibDir, "${moduleDescription.name}.${JsKlibMetadataSerializationUtil.CLASS_METADATA_FILE_EXTENSION}").also {
|
||||
it.writeBytes(serializedData.asByteArray())
|
||||
}
|
||||
|
||||
val storageManager = LockBasedStorageManager("JsConfig")
|
||||
// // CREATE NEW MODULE DESCRIPTOR HERE AND DESERIALIZE IT
|
||||
|
||||
val lookupTracker = configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER, LookupTracker.DO_NOTHING)
|
||||
val parts = serializer.readModuleAsProto(metadata.readBytes())
|
||||
val md = ModuleDescriptorImpl(
|
||||
Name.special("<$moduleName>"), storageManager, JsPlatform.builtIns
|
||||
)
|
||||
val provider = createJsKlibMetadataPackageFragmentProvider(
|
||||
storageManager, md, parts.header, parts.body, metadataVersion,
|
||||
CompilerDeserializationConfiguration(configuration.languageVersionSettings),
|
||||
lookupTracker
|
||||
val builtIns = object : KotlinBuiltIns(storageManager) {}//analysisResult.moduleDescriptor.builtIns
|
||||
val md = ModuleDescriptorImpl(Name.special("<$moduleName>"), storageManager, builtIns)
|
||||
builtIns.builtInsModule = md
|
||||
val packageProviders = listOf(
|
||||
functionInterfacePackageFragmentProvider(storageManager, md),
|
||||
createJsKlibMetadataPackageFragmentProvider(
|
||||
storageManager, md, parts.header, parts.body, metadataVersion,
|
||||
CompilerDeserializationConfiguration(configuration.languageVersionSettings),
|
||||
lookupTracker
|
||||
)
|
||||
)
|
||||
|
||||
md.initialize(provider)
|
||||
md.setDependencies(listOf(md, md.builtIns.builtInsModule))
|
||||
md.initialize(CompositePackageFragmentProvider(packageProviders))
|
||||
md.setDependencies(listOf(md/*, builtIns.builtInsModule*/))
|
||||
|
||||
TODO("Implemenet IrSerialization")
|
||||
|
||||
val st = SymbolTable()
|
||||
|
||||
val typeTranslator = TypeTranslator(st, configuration.languageVersionSettings).also {
|
||||
it.constantValueGenerator = ConstantValueGenerator(md, st)
|
||||
}
|
||||
|
||||
val irBuiltIns = IrBuiltIns(md.builtIns, typeTranslator, st)
|
||||
|
||||
val deserializer = IrKlibProtoBufModuleDeserializer(
|
||||
md,
|
||||
logggg,
|
||||
irBuiltIns,
|
||||
stdKlibDir,
|
||||
st,
|
||||
null
|
||||
)
|
||||
val deserializedModuleFragment = deserializer.deserializeIrModule(md, moduleFile.readBytes(), true)
|
||||
|
||||
val context = JsIrBackendContext(md, irBuiltIns, st, deserializedModuleFragment, configuration, irDependencyModules)
|
||||
|
||||
deserializedModuleFragment.replaceUnboundSymbols(context)
|
||||
|
||||
jsPhases.invokeToplevel(context.phaseConfig, context, moduleFragment)
|
||||
|
||||
return Result(md, context.jsProgram.toString(), null)
|
||||
} else {
|
||||
|
||||
// TODO: Split compilation into two steps: kt -> ir, ir -> js
|
||||
@@ -211,9 +225,17 @@ fun compile(
|
||||
}
|
||||
}
|
||||
|
||||
jsPhases.invokeToplevel(context.phaseConfig, context, moduleFragment)
|
||||
val context = JsIrBackendContext(
|
||||
analysisResult.moduleDescriptor,
|
||||
psi2IrContext.irBuiltIns,
|
||||
psi2IrContext.symbolTable,
|
||||
moduleFragment,
|
||||
configuration,
|
||||
irDependencyModules
|
||||
)
|
||||
|
||||
val jsProgram = moduleFragment.accept(IrModuleToJsTransformer(context), null)
|
||||
val jsProgram = moduleFragment.accept(IrModuleToJsTransformer(context), null)
|
||||
|
||||
return CompiledModule(moduleName, jsProgram.toString(), context.moduleFragmentCopy, moduleType, dependencies)
|
||||
return CompiledModule(moduleName, jsProgram.toString(), context.moduleFragmentCopy, moduleType, dependencies)
|
||||
}
|
||||
}
|
||||
|
||||
+10
-9
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.ir.isElseBranch
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
@@ -366,8 +367,8 @@ class BlockDecomposerTransformer(private val context: JsIrBackendContext) : IrEl
|
||||
|
||||
if (compositeCount == 0) {
|
||||
val branches = results.map { (cond, res, orig) ->
|
||||
when (orig) {
|
||||
is IrElseBranch -> IrElseBranchImpl(orig.startOffset, orig.endOffset, cond, res)
|
||||
when {
|
||||
isElseBranch(orig) -> IrElseBranchImpl(orig.startOffset, orig.endOffset, cond, res)
|
||||
else /* IrBranch */ -> IrBranchImpl(orig.startOffset, orig.endOffset, cond, res)
|
||||
}
|
||||
}
|
||||
@@ -384,7 +385,7 @@ class BlockDecomposerTransformer(private val context: JsIrBackendContext) : IrEl
|
||||
appendBlock.statements += condStatements.run { subList(0, lastIndex) }
|
||||
|
||||
JsIrBuilder.buildBlock(unitType).also {
|
||||
val elseBlock = if (orig is IrElseBranch) null else it
|
||||
val elseBlock = if (isElseBranch(orig)) null else it
|
||||
val ifElseNode =
|
||||
JsIrBuilder.buildIfElse(orig.startOffset, orig.endOffset, unitType, condValue, res, elseBlock, expression.origin)
|
||||
appendBlock.statements += ifElseNode
|
||||
@@ -666,9 +667,9 @@ class BlockDecomposerTransformer(private val context: JsIrBackendContext) : IrEl
|
||||
|
||||
val newBranches = decomposedResults.map { (branch, condition, result) ->
|
||||
val newResult = wrap(result, irVar)
|
||||
when (branch) {
|
||||
is IrElseBranch -> IrElseBranchImpl(branch.startOffset, branch.endOffset, condition, newResult)
|
||||
else /* IrBranch */ -> IrBranchImpl(branch.startOffset, branch.endOffset, condition, newResult)
|
||||
when {
|
||||
isElseBranch(branch) -> IrElseBranchImpl(branch.startOffset, branch.endOffset, condition, newResult)
|
||||
else /* IrBranch */ -> IrBranchImpl(branch.startOffset, branch.endOffset, condition, newResult)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -679,9 +680,9 @@ class BlockDecomposerTransformer(private val context: JsIrBackendContext) : IrEl
|
||||
return JsIrBuilder.buildComposite(expression.type, listOf(irVar, newWhen, JsIrBuilder.buildGetValue(irVar.symbol)))
|
||||
} else {
|
||||
val newBranches = decomposedResults.map { (branch, condition, result) ->
|
||||
when (branch) {
|
||||
is IrElseBranch -> IrElseBranchImpl(branch.startOffset, branch.endOffset, condition, result)
|
||||
else /* IrBranch */ -> IrBranchImpl(branch.startOffset, branch.endOffset, condition, result)
|
||||
when {
|
||||
isElseBranch(branch) -> IrElseBranchImpl(branch.startOffset, branch.endOffset, condition, result)
|
||||
else /* IrBranch */ -> IrBranchImpl(branch.startOffset, branch.endOffset, condition, result)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-3
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js.lower.coroutines
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ir.isElseBranch
|
||||
import org.jetbrains.kotlin.backend.common.ir.isSuspend
|
||||
import org.jetbrains.kotlin.backend.common.peek
|
||||
import org.jetbrains.kotlin.backend.common.pop
|
||||
@@ -351,8 +352,8 @@ class StateMachineBuilder(
|
||||
if (it.result in suspendableNodes) {
|
||||
suspendableNodes += wrapped
|
||||
}
|
||||
when (it) {
|
||||
is IrElseBranch -> IrElseBranchImpl(it.startOffset, it.endOffset, it.condition, wrapped)
|
||||
when {
|
||||
isElseBranch(it) -> IrElseBranchImpl(it.startOffset, it.endOffset, it.condition, wrapped)
|
||||
else /* IrBranch */ -> IrBranchImpl(it.startOffset, it.endOffset, it.condition, wrapped)
|
||||
}
|
||||
}
|
||||
@@ -365,7 +366,7 @@ class StateMachineBuilder(
|
||||
val rootBlock = currentBlock
|
||||
|
||||
for (branch in branches) {
|
||||
if (branch !is IrElseBranch) {
|
||||
if (!isElseBranch(branch)) {
|
||||
branch.condition.acceptVoid(this)
|
||||
val branchBlock = JsIrBuilder.buildComposite(branch.result.type)
|
||||
val elseBlock = JsIrBuilder.buildComposite(expression.type)
|
||||
|
||||
+3
-1
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.irTypeKotlinBuiltIns
|
||||
import org.jetbrains.kotlin.ir.types.toKotlinType
|
||||
import org.jetbrains.kotlin.ir.util.file
|
||||
import org.jetbrains.kotlin.ir.util.getArguments
|
||||
@@ -124,6 +125,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerWithC
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
fun inline(irModule: IrModuleFragment): IrElement {
|
||||
irTypeKotlinBuiltIns = irModule.irBuiltins.builtIns
|
||||
val transformedModule = irModule.accept(this, Ref(false))
|
||||
DescriptorSubstitutorForExternalScope(globalSubstituteMap, context).run(transformedModule) // Transform calls to object that might be returned from inline function call.
|
||||
return transformedModule
|
||||
@@ -371,7 +373,7 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
||||
override fun visitElement(element: IrElement) = element.accept(this, null)
|
||||
}
|
||||
|
||||
private fun isLambdaCall(irCall: IrCall) = irCall.descriptor.isFunctionInvoke && irCall.dispatchReceiver is IrGetValue
|
||||
private fun isLambdaCall(irCall: IrCall) = irCall.symbol.owner.isFunctionInvoke && irCall.dispatchReceiver is IrGetValue
|
||||
|
||||
private fun createTypeSubstitutor(irCall: IrCall): TypeSubstitutor? {
|
||||
if (irCall.typeArgumentsCount == 0) return null
|
||||
|
||||
+13
@@ -9,6 +9,10 @@ import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||
import org.jetbrains.kotlin.builtins.getFunctionalClassKind
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.util.isFunctionOrKFunction
|
||||
import org.jetbrains.kotlin.ir.util.isFunctionTypeOrSubtype
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -47,6 +51,15 @@ internal val FunctionDescriptor.isFunctionInvoke: Boolean
|
||||
this.isOperator && this.name == OperatorNameConventions.INVOKE
|
||||
}
|
||||
|
||||
internal val IrFunction.isFunctionInvoke: Boolean
|
||||
get() {
|
||||
val dispatchReceiver = dispatchReceiverParameter ?: return false
|
||||
assert(!dispatchReceiver.type.isFunctionTypeOrSubtype())
|
||||
|
||||
return dispatchReceiver.type.isFunctionTypeOrSubtype() &&
|
||||
/*this.isOperator &&*/ this.name == OperatorNameConventions.INVOKE
|
||||
}
|
||||
|
||||
// It is possible to declare "external inline fun",
|
||||
// but it doesn't have much sense for native,
|
||||
// since externals don't have IR bodies.
|
||||
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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 org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.atMostOne
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.types.isMarkedNullable
|
||||
import org.jetbrains.kotlin.ir.util.explicitParameters
|
||||
import org.jetbrains.kotlin.ir.util.isFunction
|
||||
import org.jetbrains.kotlin.ir.util.isInterface
|
||||
import org.jetbrains.kotlin.ir.util.isSuspendFunction
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedPropertyDescriptor
|
||||
|
||||
val IrConstructor.constructedClass get() = this.parent as IrClass
|
||||
|
||||
val <T : IrDeclaration> T.original get() = this
|
||||
val IrDeclaration.containingDeclaration get() = this.parent
|
||||
|
||||
val IrDeclarationParent.fqNameSafe: FqName
|
||||
get() = when (this) {
|
||||
is IrPackageFragment -> this.fqName
|
||||
is IrDeclaration -> this.parent.fqNameSafe.child(this.name)
|
||||
|
||||
else -> error(this)
|
||||
}
|
||||
|
||||
val IrClass.classId: ClassId?
|
||||
get() {
|
||||
val parent = this.parent
|
||||
return when (parent) {
|
||||
is IrClass -> parent.classId?.createNestedClassId(this.name)
|
||||
is IrPackageFragment -> ClassId.topLevel(parent.fqName.child(this.name))
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
val IrDeclaration.name: Name
|
||||
get() = when (this) {
|
||||
is IrSimpleFunction -> this.name
|
||||
is IrClass -> this.name
|
||||
is IrEnumEntry -> this.name
|
||||
is IrProperty -> this.name
|
||||
is IrLocalDelegatedProperty -> this.name
|
||||
is IrField -> this.name
|
||||
is IrVariable -> this.name
|
||||
is IrConstructor -> SPECIAL_INIT_NAME
|
||||
is IrValueParameter -> this.name
|
||||
else -> error(this)
|
||||
}
|
||||
|
||||
private val SPECIAL_INIT_NAME = Name.special("<init>")
|
||||
|
||||
val IrField.fqNameSafe: FqName get() = this.parent.fqNameSafe.child(this.name)
|
||||
|
||||
/**
|
||||
* @return naturally-ordered list of all parameters available inside the function body.
|
||||
*/
|
||||
val IrFunction.allParameters: List<IrValueParameter>
|
||||
get() = if (this is IrConstructor) {
|
||||
listOf(this.constructedClass.thisReceiver
|
||||
?: error(this.descriptor)
|
||||
) + explicitParameters
|
||||
} else {
|
||||
explicitParameters
|
||||
}
|
||||
|
||||
val IrValueParameter.isVararg get() = this.varargElementType != null
|
||||
|
||||
val IrFunction.isSuspend get() = this is IrSimpleFunction && this.isSuspend
|
||||
|
||||
fun IrClass.isUnit() = this.fqNameSafe == KotlinBuiltIns.FQ_NAMES.unit.toSafe()
|
||||
|
||||
fun IrClass.isKotlinArray() = this.fqNameSafe == KotlinBuiltIns.FQ_NAMES.array.toSafe()
|
||||
|
||||
val IrClass.superClasses get() = this.superTypes.map { it.classifierOrFail as IrClassSymbol }
|
||||
fun IrClass.getSuperClassNotAny() = this.superClasses.map { it.owner }.atMostOne { !it.isInterface && !it.isAny() }
|
||||
|
||||
fun IrClass.isAny() = this.fqNameSafe == KotlinBuiltIns.FQ_NAMES.any.toSafe()
|
||||
fun IrClass.isNothing() = this.fqNameSafe == KotlinBuiltIns.FQ_NAMES.nothing.toSafe()
|
||||
|
||||
fun IrClass.getSuperInterfaces() = this.superClasses.map { it.owner }.filter { it.isInterface }
|
||||
|
||||
val IrProperty.konanBackingField: IrField?
|
||||
get() {
|
||||
assert(this.isReal)
|
||||
this.backingField?.let { return it }
|
||||
|
||||
// (this.descriptor as? DeserializedPropertyDescriptor)?.konanBackingField?.let { backingFieldDescriptor ->
|
||||
// val result = IrFieldImpl(
|
||||
// this.startOffset,
|
||||
// this.endOffset,
|
||||
// IrDeclarationOrigin.PROPERTY_BACKING_FIELD,
|
||||
// backingFieldDescriptor,
|
||||
// this.getter!!.returnType
|
||||
// ).also {
|
||||
// it.parent = this.parent
|
||||
// }
|
||||
// this.backingField = result
|
||||
// return result
|
||||
// }
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
val IrField.containingClass get() = this.parent as? IrClass
|
||||
|
||||
val IrFunction.isReal get() = this.origin != IrDeclarationOrigin.FAKE_OVERRIDE
|
||||
|
||||
// Note: psi2ir doesn't set `origin = FAKE_OVERRIDE` for fields and properties yet.
|
||||
val IrProperty.isReal: Boolean get() = this.descriptor.kind.isReal
|
||||
val IrField.isReal: Boolean get() = this.descriptor.kind.isReal
|
||||
|
||||
val IrSimpleFunction.isOverridable: Boolean
|
||||
get() = visibility != Visibilities.PRIVATE
|
||||
&& modality != Modality.FINAL
|
||||
&& (parent as? IrClass)?.isFinalClass != true
|
||||
|
||||
val IrFunction.isOverridable get() = this is IrSimpleFunction && this.isOverridable
|
||||
|
||||
val IrFunction.isOverridableOrOverrides
|
||||
get() = this is IrSimpleFunction && (this.isOverridable || this.overriddenSymbols.isNotEmpty())
|
||||
|
||||
val IrClass.isFinalClass: Boolean
|
||||
get() = modality == Modality.FINAL && kind != ClassKind.ENUM_CLASS
|
||||
|
||||
fun IrSimpleFunction.overrides(other: IrSimpleFunction): Boolean {
|
||||
if (this == other) return true
|
||||
|
||||
this.overriddenSymbols.forEach {
|
||||
if (it.owner.overrides(other)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
fun IrClass.isSpecialClassWithNoSupertypes() = this.isAny() || this.isNothing()
|
||||
|
||||
internal val IrValueParameter.isValueParameter get() = this.index >= 0
|
||||
|
||||
private val IrCall.annotationClass
|
||||
get() = (this.symbol.owner as IrConstructor).constructedClass
|
||||
|
||||
fun List<IrCall>.hasAnnotation(fqName: FqName): Boolean =
|
||||
this.any { it.annotationClass.fqNameSafe == fqName }
|
||||
|
||||
fun IrAnnotationContainer.hasAnnotation(fqName: FqName) =
|
||||
this.annotations.hasAnnotation(fqName)
|
||||
|
||||
fun List<IrCall>.findAnnotation(fqName: FqName): IrCall? = this.firstOrNull {
|
||||
it.annotationClass.fqNameSafe == fqName
|
||||
}
|
||||
|
||||
fun <T> IrDeclaration.getAnnotationArgumentValue(fqName: FqName, argumentName: String): T? {
|
||||
val annotation = this.annotations.findAnnotation(fqName)
|
||||
if (annotation == null) {
|
||||
// As a last resort try searching the descriptor.
|
||||
// This is needed for a period while we don't have IR for platform libraries.
|
||||
return this.descriptor.annotations
|
||||
.findAnnotation(fqName)
|
||||
?.getArgumentValueOrNull<T>(argumentName)
|
||||
}
|
||||
for (index in 0 until annotation.valueArgumentsCount) {
|
||||
val parameter = annotation.symbol.owner.valueParameters[index]
|
||||
if (parameter.name == Name.identifier(argumentName)) {
|
||||
val actual = annotation.getValueArgument(index) as? IrConst<T>
|
||||
return actual?.value
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun IrValueParameter.isInlineParameter(): Boolean =
|
||||
!this.isNoinline && (this.type.isFunction() || this.type.isSuspendFunction()) && !this.type.isMarkedNullable()
|
||||
|
||||
val IrDeclaration.parentDeclarationsWithSelf: Sequence<IrDeclaration>
|
||||
get() = generateSequence(this, { it.parent as? IrDeclaration })
|
||||
|
||||
fun IrClass.companionObject() = this.declarations.singleOrNull {it is IrClass && it.isCompanion }
|
||||
|
||||
val IrDeclaration.isGetter get() = this is IrSimpleFunction && this == this.correspondingProperty?.getter
|
||||
|
||||
val IrDeclaration.isSetter get() = this is IrSimpleFunction && this == this.correspondingProperty?.setter
|
||||
|
||||
val IrDeclaration.isAccessor get() = this.isGetter || this.isSetter
|
||||
+169
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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 org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
|
||||
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionInvokeDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.ir.SourceManager
|
||||
import org.jetbrains.kotlin.ir.SourceRangeInfo
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi2ir.findFirstFunction
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import java.io.File
|
||||
import java.util.regex.Pattern
|
||||
|
||||
internal val IrDeclaration.isAnonymousObject get() = DescriptorUtils.isAnonymousObject(this.descriptor)
|
||||
internal val IrDeclaration.isLocal get() = DescriptorUtils.isLocal(this.descriptor)
|
||||
|
||||
internal val IrDeclaration.module get() = this.descriptor.module
|
||||
|
||||
@Deprecated("Do not call this method in the compiler front-end.")
|
||||
internal val IrField.isDelegate
|
||||
get() = @Suppress("DEPRECATION") this.descriptor.isDelegated
|
||||
|
||||
internal const val SYNTHETIC_OFFSET = -2
|
||||
|
||||
class NaiveSourceBasedFileEntryImpl(override val name: String) : SourceManager.FileEntry {
|
||||
|
||||
private val lineStartOffsets: IntArray
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
init {
|
||||
val file = File(name)
|
||||
if (file.isFile) {
|
||||
// TODO: could be incorrect, if file is not in system's line terminator format.
|
||||
// Maybe use (0..document.lineCount - 1)
|
||||
// .map { document.getLineStartOffset(it) }
|
||||
// .toIntArray()
|
||||
// as in PSI.
|
||||
val separatorLength = System.lineSeparator().length
|
||||
val buffer = mutableListOf<Int>()
|
||||
var currentOffset = 0
|
||||
file.forEachLine { line ->
|
||||
buffer.add(currentOffset)
|
||||
currentOffset += line.length + separatorLength
|
||||
}
|
||||
buffer.add(currentOffset)
|
||||
lineStartOffsets = buffer.toIntArray()
|
||||
} else {
|
||||
lineStartOffsets = IntArray(0)
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
override fun getLineNumber(offset: Int): Int {
|
||||
assert(offset != UNDEFINED_OFFSET)
|
||||
if (offset == SYNTHETIC_OFFSET) return 0
|
||||
val index = lineStartOffsets.binarySearch(offset)
|
||||
return if (index >= 0) index else -index - 2
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
override fun getColumnNumber(offset: Int): Int {
|
||||
assert(offset != UNDEFINED_OFFSET)
|
||||
if (offset == SYNTHETIC_OFFSET) return 0
|
||||
var lineNumber = getLineNumber(offset)
|
||||
return offset - lineStartOffsets[lineNumber]
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
override val maxOffset: Int
|
||||
//get() = TODO("not implemented")
|
||||
get() = UNDEFINED_OFFSET
|
||||
|
||||
override fun getSourceRangeInfo(beginOffset: Int, endOffset: Int): SourceRangeInfo {
|
||||
//TODO("not implemented")
|
||||
return SourceRangeInfo(name, beginOffset, -1, -1, endOffset, -1, -1)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private val functionPattern = Pattern.compile("^K?(Suspend)?Function\\d+$")
|
||||
|
||||
private val kotlinFqn = FqName("kotlin")
|
||||
|
||||
private val functionalPackages =
|
||||
listOf(kotlinFqn, kotlinFqn.child(Name.identifier("coroutines")), kotlinFqn.child(Name.identifier("reflect")))
|
||||
|
||||
internal val BUILT_IN_FUNCTION_CLASS_COUNT = 4
|
||||
internal val BUILT_IN_FUNCTION_ARITY_COUNT = 256
|
||||
internal val BUILT_IN_UNIQ_ID_GAP = 2 * BUILT_IN_FUNCTION_ARITY_COUNT * BUILT_IN_FUNCTION_CLASS_COUNT
|
||||
internal val BUILT_IN_UNIQ_ID_CLASS_OFFSET = BUILT_IN_FUNCTION_CLASS_COUNT * BUILT_IN_FUNCTION_ARITY_COUNT
|
||||
|
||||
internal fun isBuiltInFunction(value: IrDeclaration): Boolean = when (value) {
|
||||
is IrSimpleFunction -> value.name.asString() == "invoke" && (value.parent as? IrClass)?.let { isBuiltInFunction(it) } == true
|
||||
is IrClass -> {
|
||||
val fqn = value.parent.fqNameSafe
|
||||
functionalPackages.any { it == fqn } && value.name.asString().let { functionPattern.matcher(it).find() }
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
|
||||
|
||||
private fun builtInOffset(function: IrSimpleFunction): Long {
|
||||
val isK = function.parentAsClass.name.asString().startsWith("K")
|
||||
return when {
|
||||
isK && function.isSuspend -> 3
|
||||
isK -> 2
|
||||
function.isSuspend -> 1
|
||||
else -> 0
|
||||
}
|
||||
}
|
||||
|
||||
internal fun builtInFunctionId(value: IrDeclaration): Long = when (value) {
|
||||
is IrSimpleFunction -> {
|
||||
value.run { valueParameters.size + builtInOffset(value) * BUILT_IN_FUNCTION_ARITY_COUNT }.toLong()
|
||||
}
|
||||
is IrClass -> {
|
||||
BUILT_IN_UNIQ_ID_CLASS_OFFSET + builtInFunctionId(value.declarations.first { it.name.asString() == "invoke" })
|
||||
}
|
||||
else -> error("Only class or function is expected")
|
||||
}
|
||||
|
||||
|
||||
internal fun isBuiltInFunction(value: DeclarationDescriptor): Boolean = when (value) {
|
||||
is FunctionInvokeDescriptor -> isBuiltInFunction(value.containingDeclaration)
|
||||
is ClassDescriptor -> {
|
||||
val fqn = (value.containingDeclaration as? PackageFragmentDescriptor)?.fqName
|
||||
functionalPackages.any { it == fqn } && value.name.asString().let { functionPattern.matcher(it).find() }
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
|
||||
private fun builtInOffset(function: FunctionInvokeDescriptor): Long {
|
||||
val isK = function.containingDeclaration.name.asString().startsWith("K")
|
||||
return when {
|
||||
isK && function.isSuspend -> 3
|
||||
isK -> 2
|
||||
function.isSuspend -> 1
|
||||
else -> 0
|
||||
}
|
||||
}
|
||||
|
||||
internal fun builtInFunctionId(value: DeclarationDescriptor): Long = when (value) {
|
||||
is FunctionInvokeDescriptor -> {
|
||||
value.run { valueParameters.size + builtInOffset(value) * BUILT_IN_FUNCTION_ARITY_COUNT }.toLong()
|
||||
}
|
||||
is ClassDescriptor -> {
|
||||
BUILT_IN_UNIQ_ID_CLASS_OFFSET + builtInFunctionId(value.findFirstFunction("invoke") { true })
|
||||
}
|
||||
else -> error("Only class or function is expected")
|
||||
}
|
||||
+252
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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 org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.isInlined
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
|
||||
// This file describes the ABI for Kotlin descriptors of exported declarations.
|
||||
// TODO: revise the naming scheme to ensure it produces unique names.
|
||||
// TODO: do not serialize descriptors of non-exported declarations.
|
||||
|
||||
/**
|
||||
* Defines whether the declaration is exported, i.e. visible from other modules.
|
||||
*
|
||||
* Exported declarations must have predictable and stable ABI
|
||||
* that doesn't depend on any internal transformations (e.g. IR lowering),
|
||||
* and so should be computable from the descriptor itself without checking a backend state.
|
||||
*/
|
||||
internal tailrec fun IrDeclaration.isExported(): Boolean {
|
||||
// TODO: revise
|
||||
val descriptorAnnotations = this.descriptor.annotations
|
||||
// if (descriptorAnnotations.hasAnnotation(symbolNameAnnotation)) {
|
||||
// // Treat any `@SymbolName` declaration as exported.
|
||||
// return true
|
||||
// }
|
||||
// if (descriptorAnnotations.hasAnnotation(exportForCppRuntimeAnnotation)) {
|
||||
// // Treat any `@ExportForCppRuntime` declaration as exported.
|
||||
// return true
|
||||
// }
|
||||
// if (descriptorAnnotations.hasAnnotation(cnameAnnotation)) {
|
||||
// // Treat `@CName` declaration as exported.
|
||||
// return true
|
||||
// }
|
||||
// if (descriptorAnnotations.hasAnnotation(exportForCompilerAnnotation)) {
|
||||
// return true
|
||||
// }
|
||||
if (descriptorAnnotations.hasAnnotation(publishedApiAnnotation)){
|
||||
return true
|
||||
}
|
||||
|
||||
if (this.isAnonymousObject)
|
||||
return false
|
||||
|
||||
if (this is IrConstructor && constructedClass.kind.isSingleton) {
|
||||
// Currently code generator can access the constructor of the singleton,
|
||||
// so ignore visibility of the constructor itself.
|
||||
return constructedClass.isExported()
|
||||
}
|
||||
|
||||
if (this is IrFunction) {
|
||||
val descriptor = this.descriptor
|
||||
// TODO: this code is required because accessor doesn't have a reference to property.
|
||||
if (descriptor is PropertyAccessorDescriptor) {
|
||||
val property = descriptor.correspondingProperty
|
||||
if (property.annotations.hasAnnotation(publishedApiAnnotation)) return true
|
||||
}
|
||||
}
|
||||
|
||||
val visibility = when (this) {
|
||||
is IrClass -> this.visibility
|
||||
is IrFunction -> this.visibility
|
||||
is IrProperty -> this.visibility
|
||||
is IrField -> this.visibility
|
||||
else -> null
|
||||
}
|
||||
|
||||
/**
|
||||
* note: about INTERNAL - with support of friend modules we let frontend to deal with internal declarations.
|
||||
*/
|
||||
if (visibility != null && !visibility.isPublicAPI && visibility != Visibilities.INTERNAL) {
|
||||
// If the declaration is explicitly marked as non-public,
|
||||
// then it must not be accessible from other modules.
|
||||
return false
|
||||
}
|
||||
|
||||
val parent = this.parent
|
||||
if (parent is IrDeclaration) {
|
||||
return parent.isExported()
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private val publishedApiAnnotation = FqName("kotlin.PublishedApi")
|
||||
|
||||
private fun acyclicTypeMangler(visited: MutableSet<IrTypeParameter>, type: IrType): String {
|
||||
val descriptor = (type.classifierOrNull as? IrTypeParameterSymbol)?.owner
|
||||
if (descriptor != null) {
|
||||
val upperBounds = if (visited.contains(descriptor)) "" else {
|
||||
|
||||
visited.add(descriptor)
|
||||
|
||||
descriptor.superTypes.map {
|
||||
val bound = acyclicTypeMangler(visited, it)
|
||||
if (bound == "kotlin.Any?") "" else "_$bound"
|
||||
}.joinToString("")
|
||||
}
|
||||
return "#GENERIC${if (type.isMarkedNullable()) "?" else ""}$upperBounds"
|
||||
}
|
||||
|
||||
var hashString = type.getClass()?.run { fqNameSafe.asString() } ?: "<dynamic>"
|
||||
// if (type !is IrSimpleType) error(type)
|
||||
when (type) {
|
||||
is IrSimpleType -> {
|
||||
if (!type.arguments.isEmpty()) {
|
||||
hashString += "<${type.arguments.map {
|
||||
when (it) {
|
||||
is IrStarProjection -> "#STAR"
|
||||
is IrTypeProjection -> {
|
||||
val variance = it.variance.label
|
||||
val projection = if (variance == "") "" else "${variance}_"
|
||||
projection + acyclicTypeMangler(visited, it.type)
|
||||
}
|
||||
else -> error(it)
|
||||
}
|
||||
}.joinToString(",")}>"
|
||||
}
|
||||
|
||||
if (type.hasQuestionMark) hashString += "?"
|
||||
}
|
||||
!is IrDynamicType -> { error(type) }
|
||||
}
|
||||
return hashString
|
||||
}
|
||||
|
||||
private fun typeToHashString(type: IrType) = acyclicTypeMangler(mutableSetOf(), type)
|
||||
|
||||
internal val IrValueParameter.extensionReceiverNamePart: String
|
||||
get() = "@${typeToHashString(this.type)}."
|
||||
|
||||
private val IrFunction.signature: String
|
||||
get() {
|
||||
val extensionReceiverPart = this.extensionReceiverParameter?.extensionReceiverNamePart ?: ""
|
||||
val argsPart = this.valueParameters.map {
|
||||
|
||||
// TODO: there are clashes originating from ObjectiveC interop.
|
||||
// kotlinx.cinterop.ObjCClassOf<T>.create(format: kotlin.String): T defined in platform.Foundation in file Foundation.kt
|
||||
// and
|
||||
// kotlinx.cinterop.ObjCClassOf<T>.create(string: kotlin.String): T defined in platform.Foundation in file Foundation.kt
|
||||
|
||||
val argName = /*if (this.hasObjCMethodAnnotation || this.hasObjCFactoryAnnotation || this.isObjCClassMethod()) "${it.name}:" else */""
|
||||
"$argName${typeToHashString(it.type)}${if (it.isVararg) "_VarArg" else ""}"
|
||||
}.joinToString(";")
|
||||
// Distinguish value types and references - it's needed for calling virtual methods through bridges.
|
||||
// Also is function has type arguments - frontend allows exactly matching overrides.
|
||||
val signatureSuffix =
|
||||
when {
|
||||
this.typeParameters.isNotEmpty() -> "Generic"
|
||||
returnType.isInlined() -> "ValueType"
|
||||
!returnType.isUnitOrNullableUnit() -> typeToHashString(returnType)
|
||||
else -> ""
|
||||
}
|
||||
return "$extensionReceiverPart($argsPart)$signatureSuffix"
|
||||
}
|
||||
|
||||
// TODO: rename to indicate that it has signature included
|
||||
internal val IrFunction.functionName: String
|
||||
get() {
|
||||
with(this.original) { // basic support for generics
|
||||
// (if (this is IrConstructor && this.isObjCConstructor) this.getObjCInitMethod() else this)?.getObjCMethodInfo()?.let {
|
||||
// return buildString {
|
||||
// if (extensionReceiverParameter != null) {
|
||||
// append(extensionReceiverParameter!!.type.getClass()!!.name)
|
||||
// append(".")
|
||||
// }
|
||||
//
|
||||
// append("objc:")
|
||||
// append(it.selector)
|
||||
// if (this@with is IrConstructor && this@with.isObjCConstructor) append("#Constructor")
|
||||
//
|
||||
// // We happen to have the clashing combinations such as
|
||||
// //@ObjCMethod("issueChallengeToPlayers:message:", "objcKniBridge1165")
|
||||
// //external fun GKScore.issueChallengeToPlayers(playerIDs: List<*>?, message: String?): Unit
|
||||
// //@ObjCMethod("issueChallengeToPlayers:message:", "objcKniBridge1172")
|
||||
// //external fun GKScore.issueChallengeToPlayers(playerIDs: List<*>?, message: String?): Unit
|
||||
// // So disambiguate by the name of the bridge for now.
|
||||
// // TODO: idealy we'd never generate such identical declarations.
|
||||
//
|
||||
// if (this@with is IrSimpleFunction && this@with.hasObjCMethodAnnotation()) {
|
||||
// this@with.objCMethodArgValue("selector") ?.let { append("#$it") }
|
||||
// this@with.objCMethodArgValue("bridge") ?.let { append("#$it") }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
val name = this.name.mangleIfInternal(this.module, this.visibility)
|
||||
|
||||
return "$name$signature"
|
||||
}
|
||||
}
|
||||
|
||||
private fun Name.mangleIfInternal(moduleDescriptor: ModuleDescriptor, visibility: Visibility): String =
|
||||
if (visibility != Visibilities.INTERNAL) {
|
||||
this.asString()
|
||||
} else {
|
||||
val moduleName = moduleDescriptor.name.asString()
|
||||
.let { it.substring(1, it.lastIndex) } // Remove < and >.
|
||||
|
||||
"$this\$$moduleName"
|
||||
}
|
||||
|
||||
internal val IrFunction.symbolName: String
|
||||
get() {
|
||||
if (!this.isExported()) {
|
||||
throw AssertionError(this.descriptor.toString())
|
||||
}
|
||||
|
||||
if (isExternal) {
|
||||
this.descriptor.externalSymbolOrThrow()?.let {
|
||||
return it
|
||||
}
|
||||
}
|
||||
|
||||
// this.descriptor.annotations.findAnnotation(exportForCppRuntimeAnnotation)?.let {
|
||||
// val name = getAnnotationValue(it) ?: this.name.asString()
|
||||
// return name // no wrapping currently required
|
||||
// }
|
||||
|
||||
val parent = this.parent
|
||||
|
||||
val containingDeclarationPart = parent.fqNameSafe.let {
|
||||
if (it.isRoot) "" else "$it."
|
||||
}
|
||||
return "kfun:$containingDeclarationPart$functionName"
|
||||
}
|
||||
|
||||
internal val IrField.symbolName: String
|
||||
get() {
|
||||
val containingDeclarationPart = parent.fqNameSafe.let {
|
||||
if (it.isRoot) "" else "$it."
|
||||
}
|
||||
return "kfield:$containingDeclarationPart$name"
|
||||
|
||||
}
|
||||
|
||||
internal val IrClass.typeInfoSymbolName: String
|
||||
get() {
|
||||
assert (this.isExported())
|
||||
return "ktype:" + this.fqNameSafe.toString()
|
||||
}
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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 org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.getFunction
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrAnonymousInitializerImpl
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.jvm.modules.KOTLIN_STDLIB_MODULE_NAME
|
||||
import java.util.regex.Pattern
|
||||
|
||||
fun <K, V> MutableMap<K, V>.putOnce(k:K, v: V): Unit {
|
||||
assert(!this.containsKey(k) || this[k] == v) {
|
||||
"adding $v for $k, but it is already ${this[k]} for $k"
|
||||
}
|
||||
this.put(k, v)
|
||||
}
|
||||
|
||||
class DescriptorTable {
|
||||
private val descriptors = mutableMapOf<DeclarationDescriptor, Long>()
|
||||
fun put(descriptor: DeclarationDescriptor, uniqId: UniqId) {
|
||||
descriptors.putOnce(descriptor, uniqId.index)
|
||||
}
|
||||
fun get(descriptor: DeclarationDescriptor) = descriptors[descriptor]
|
||||
}
|
||||
|
||||
// TODO: We don't manage id clashes anyhow now.
|
||||
class DeclarationTable(val builtIns: IrBuiltIns, val descriptorTable: DescriptorTable, val symbolTable: SymbolTable) {
|
||||
|
||||
private val table = mutableMapOf<IrDeclaration, UniqId>()
|
||||
val debugIndex = mutableMapOf<UniqId, String>()
|
||||
val descriptors = descriptorTable
|
||||
private var currentIndex = 0x1_0000_0000L
|
||||
|
||||
private val FUNCTION_INDEX_START: Long
|
||||
|
||||
init {
|
||||
val known = builtIns.knownBuiltins
|
||||
known.forEach {
|
||||
table.put(it, UniqId(currentIndex++, false))
|
||||
}
|
||||
|
||||
FUNCTION_INDEX_START = currentIndex
|
||||
currentIndex += BUILT_IN_UNIQ_ID_GAP
|
||||
}
|
||||
|
||||
fun uniqIdByDeclaration(value: IrDeclaration): UniqId {
|
||||
val index = table.getOrPut(value) {
|
||||
|
||||
if (isBuiltInFunction(value)) {
|
||||
UniqId(FUNCTION_INDEX_START + builtInFunctionId(value), false)
|
||||
} else if (value.origin == IrDeclarationOrigin.FAKE_OVERRIDE ||
|
||||
!value.isExported()
|
||||
|| value is IrVariable
|
||||
|| value is IrTypeParameter
|
||||
|| value is IrValueParameter
|
||||
|| value is IrAnonymousInitializerImpl
|
||||
) {
|
||||
|
||||
val desc = value.descriptor
|
||||
if (desc is CallableDescriptor) {
|
||||
if (desc.visibility == Visibilities.PUBLIC || value.origin != IrDeclarationOrigin.FAKE_OVERRIDE) {
|
||||
fun foo(){}
|
||||
foo()
|
||||
}
|
||||
}
|
||||
UniqId(currentIndex++, true)
|
||||
} else {
|
||||
UniqId(value.uniqIdIndex, false)
|
||||
}
|
||||
}
|
||||
|
||||
debugIndex.put(index, "${if (index.isLocal) "" else value.uniqSymbolName()} descriptor = ${value.descriptor}")
|
||||
|
||||
return index
|
||||
}
|
||||
}
|
||||
|
||||
// This is what we pre-populate tables with
|
||||
val IrBuiltIns.knownBuiltins
|
||||
get() = irBuiltInsExternalPackageFragment.declarations
|
||||
+206
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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 org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperInterfaces
|
||||
import org.jetbrains.kotlin.types.SimpleType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
|
||||
/**
|
||||
* List of all implemented interfaces (including those which implemented by a super class)
|
||||
*/
|
||||
internal val IrClass.implementedInterfaces: List<IrClass>
|
||||
get() {
|
||||
val superClassImplementedInterfaces = this.getSuperClassNotAny()?.implementedInterfaces ?: emptyList()
|
||||
val superInterfaces = this.getSuperInterfaces()
|
||||
val superInterfacesImplementedInterfaces = superInterfaces.flatMap { it.implementedInterfaces }
|
||||
return (superClassImplementedInterfaces +
|
||||
superInterfacesImplementedInterfaces +
|
||||
superInterfaces).distinct()
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Implementation of given method.
|
||||
*
|
||||
* TODO: this method is actually a part of resolve and probably duplicates another one
|
||||
*/
|
||||
internal fun IrSimpleFunction.resolveFakeOverride(allowAbstract: Boolean = false): IrSimpleFunction {
|
||||
if (this.isReal) {
|
||||
return this
|
||||
}
|
||||
|
||||
val visited = mutableSetOf<IrSimpleFunction>()
|
||||
val realSupers = mutableSetOf<IrSimpleFunction>()
|
||||
|
||||
fun findRealSupers(function: IrSimpleFunction) {
|
||||
if (function in visited) return
|
||||
visited += function
|
||||
if (function.isReal) {
|
||||
realSupers += function
|
||||
} else {
|
||||
function.overriddenSymbols.forEach { findRealSupers(it.owner) }
|
||||
}
|
||||
}
|
||||
|
||||
findRealSupers(this)
|
||||
|
||||
if (realSupers.size > 1) {
|
||||
visited.clear()
|
||||
|
||||
fun excludeOverridden(function: IrSimpleFunction) {
|
||||
if (function in visited) return
|
||||
visited += function
|
||||
function.overriddenSymbols.forEach {
|
||||
realSupers.remove(it.owner)
|
||||
excludeOverridden(it.owner)
|
||||
}
|
||||
}
|
||||
|
||||
realSupers.toList().forEach { excludeOverridden(it) }
|
||||
}
|
||||
|
||||
return realSupers.first { allowAbstract || it.modality != Modality.ABSTRACT }
|
||||
}
|
||||
|
||||
// TODO: don't forget to remove descriptor access here.
|
||||
//internal val FunctionDescriptor.isTypedIntrinsic: Boolean
|
||||
// get() = this.descriptor.isTypedIntrinsic
|
||||
//
|
||||
//internal val DeclarationDescriptor.isFrozen: Boolean
|
||||
// get() = this.descriptor.isFrozen
|
||||
|
||||
internal val arrayTypes = setOf(
|
||||
"kotlin.Array",
|
||||
"kotlin.ByteArray",
|
||||
"kotlin.CharArray",
|
||||
"kotlin.ShortArray",
|
||||
"kotlin.IntArray",
|
||||
"kotlin.LongArray",
|
||||
"kotlin.FloatArray",
|
||||
"kotlin.DoubleArray",
|
||||
"kotlin.BooleanArray",
|
||||
"kotlin.native.ImmutableBlob",
|
||||
"kotlin.native.internal.NativePtrArray"
|
||||
)
|
||||
|
||||
|
||||
internal val IrClass.isArray: Boolean
|
||||
get() = this.fqNameSafe.asString() in arrayTypes
|
||||
|
||||
|
||||
internal val IrClass.isInterface: Boolean
|
||||
get() = (this.kind == ClassKind.INTERFACE)
|
||||
|
||||
fun IrClass.isAbstract() = this.modality == Modality.SEALED || this.modality == Modality.ABSTRACT
|
||||
|| this.kind == ClassKind.ENUM_CLASS
|
||||
|
||||
//internal fun FunctionDescriptor.hasValueTypeAt(index: Int): Boolean {
|
||||
// when (index) {
|
||||
// 0 -> return !isSuspend && returnType.let { (it.isInlined() || it.isUnit()) }
|
||||
// 1 -> return dispatchReceiverParameter.let { it != null && it.type.isInlined() }
|
||||
// 2 -> return extensionReceiverParameter.let { it != null && it.type.isInlined() }
|
||||
// else -> return this.valueParameters[index - 3].type.isInlined()
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//internal fun FunctionDescriptor.hasReferenceAt(index: Int): Boolean {
|
||||
// when (index) {
|
||||
// 0 -> return isSuspend || returnType.let { !it.isInlined() && !it.isUnit() }
|
||||
// 1 -> return dispatchReceiverParameter.let { it != null && !it.type.isInlined() }
|
||||
// 2 -> return extensionReceiverParameter.let { it != null && !it.type.isInlined() }
|
||||
// else -> return !this.valueParameters[index - 3].type.isInlined()
|
||||
// }
|
||||
//}
|
||||
|
||||
//private fun FunctionDescriptor.needBridgeToAt(target: FunctionDescriptor, index: Int)
|
||||
// = hasValueTypeAt(index) xor target.hasValueTypeAt(index)
|
||||
|
||||
//internal fun FunctionDescriptor.needBridgeTo(target: FunctionDescriptor)
|
||||
// = (0..this.valueParameters.size + 2).any { needBridgeToAt(target, it) }
|
||||
|
||||
internal val IrSimpleFunction.target: IrSimpleFunction
|
||||
get() = (if (modality == Modality.ABSTRACT) this else resolveFakeOverride()).original
|
||||
|
||||
internal val IrFunction.target: IrFunction get() = when (this) {
|
||||
is IrSimpleFunction -> this.target
|
||||
is IrConstructor -> this
|
||||
else -> error(this)
|
||||
}
|
||||
|
||||
//private fun FunctionDescriptor.bridgeDirectionToAt(target: FunctionDescriptor, index: Int)
|
||||
// = when {
|
||||
// hasValueTypeAt(index) && target.hasReferenceAt(index) -> BridgeDirection.FROM_VALUE_TYPE
|
||||
// hasReferenceAt(index) && target.hasValueTypeAt(index) -> BridgeDirection.TO_VALUE_TYPE
|
||||
// else -> BridgeDirection.NOT_NEEDED
|
||||
//}
|
||||
|
||||
val IrSimpleFunction.allOverriddenDescriptors: Set<IrSimpleFunction>
|
||||
get() {
|
||||
val result = mutableSetOf<IrSimpleFunction>()
|
||||
|
||||
fun traverse(function: IrSimpleFunction) {
|
||||
if (function in result) return
|
||||
result += function
|
||||
function.overriddenSymbols.forEach { traverse(it.owner) }
|
||||
}
|
||||
|
||||
traverse(this)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
//internal fun IrSimpleFunction.bridgeDirectionsTo(
|
||||
// overriddenDescriptor: IrSimpleFunction
|
||||
//): BridgeDirections {
|
||||
// val ourDirections = BridgeDirections(this.valueParameters.size)
|
||||
// for (index in ourDirections.array.indices)
|
||||
// ourDirections.array[index] = this.bridgeDirectionToAt(overriddenDescriptor, index)
|
||||
//
|
||||
// val target = this.target
|
||||
// if (!this.isReal && modality != Modality.ABSTRACT
|
||||
// && target.overrides(overriddenDescriptor)
|
||||
// && ourDirections == target.bridgeDirectionsTo(overriddenDescriptor)) {
|
||||
// // Bridge is inherited from superclass.
|
||||
// return BridgeDirections(this.valueParameters.size)
|
||||
// }
|
||||
//
|
||||
// return ourDirections
|
||||
//}
|
||||
|
||||
tailrec internal fun IrDeclaration.findPackage(): IrPackageFragment {
|
||||
val parent = this.parent
|
||||
return parent as? IrPackageFragment
|
||||
?: (parent as IrDeclaration).findPackage()
|
||||
}
|
||||
|
||||
fun IrFunction.isComparisonDescriptor(map: Map<SimpleType, IrSimpleFunction>): Boolean =
|
||||
this in map.values
|
||||
|
||||
val IrDeclaration.isPropertyAccessor get() =
|
||||
this is IrSimpleFunction && this.correspondingProperty != null
|
||||
|
||||
val IrDeclaration.isPropertyField get() =
|
||||
this is IrField && this.correspondingProperty != null
|
||||
|
||||
val IrDeclaration.isTopLevelDeclaration get() =
|
||||
parent !is IrDeclaration && !this.isPropertyAccessor && !this.isPropertyField
|
||||
|
||||
fun IrDeclaration.findTopLevelDeclaration(): IrDeclaration = when {
|
||||
this.isTopLevelDeclaration ->
|
||||
this
|
||||
this.isPropertyAccessor ->
|
||||
(this as IrSimpleFunction).correspondingProperty!!.findTopLevelDeclaration()
|
||||
this.isPropertyField ->
|
||||
(this as IrField).correspondingProperty!!.findTopLevelDeclaration()
|
||||
else ->
|
||||
(this.parent as IrDeclaration).findTopLevelDeclaration()
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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 org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameUnsafe
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
||||
|
||||
class DescriptorReferenceDeserializer(val currentModule: ModuleDescriptor, val resolvedForwardDeclarations: MutableMap<UniqIdKey, UniqIdKey>) {
|
||||
|
||||
fun deserializeDescriptorReference(
|
||||
proto: IrKlibProtoBuf.DescriptorReference,
|
||||
checkerDesc: (DeclarationDescriptor) -> Long?,
|
||||
checkerID: (Long) -> Boolean,
|
||||
descriptorResolver: (FqName) -> DeclarationDescriptor
|
||||
): DeclarationDescriptor {
|
||||
val packageFqName =
|
||||
if (proto.packageFqName == "<root>") FqName.ROOT else FqName(proto.packageFqName) // TODO: whould we store an empty string in the protobuf?
|
||||
val classFqName = FqName(proto.classFqName)
|
||||
val protoIndex = if (proto.hasUniqId()) proto.uniqId.index else null
|
||||
|
||||
val (clazz, members) = if (proto.classFqName == "") {
|
||||
Pair(null, currentModule.getPackage(packageFqName).memberScope.getContributedDescriptors())
|
||||
} else {
|
||||
val clazz = currentModule.findClassAcrossModuleDependencies(ClassId(packageFqName, classFqName, false))!!
|
||||
Pair(clazz, clazz.unsubstitutedMemberScope.getContributedDescriptors() + clazz.getConstructors())
|
||||
}
|
||||
|
||||
if (proto.packageFqName.startsWith("cnames.") || proto.packageFqName.startsWith("objcnames.")) {
|
||||
val descriptor =
|
||||
currentModule.findClassAcrossModuleDependencies(ClassId(packageFqName, FqName(proto.name), false))!!
|
||||
if (!descriptor.fqNameUnsafe.asString().startsWith("cnames") && !descriptor.fqNameUnsafe.asString().startsWith(
|
||||
"objcnames"
|
||||
)
|
||||
) {
|
||||
if (descriptor is DeserializedClassDescriptor) {
|
||||
val uniqId = UniqId(descriptor.getUniqId()!!.index, false)
|
||||
val newKey = UniqIdKey(null, uniqId)
|
||||
val oldKey = UniqIdKey(null, UniqId(protoIndex!!, false))
|
||||
|
||||
resolvedForwardDeclarations.put(oldKey, newKey)
|
||||
} else {
|
||||
/* ??? */
|
||||
}
|
||||
}
|
||||
return descriptor
|
||||
}
|
||||
|
||||
if (proto.isEnumEntry) {
|
||||
val name = proto.name
|
||||
val memberScope = (clazz as DeserializedClassDescriptor).getUnsubstitutedMemberScope()
|
||||
return memberScope.getContributedClassifier(Name.identifier(name), NoLookupLocation.FROM_BACKEND)!!
|
||||
}
|
||||
|
||||
if (proto.isEnumSpecial) {
|
||||
val name = proto.name
|
||||
return clazz!!.getStaticScope()
|
||||
.getContributedFunctions(Name.identifier(name), NoLookupLocation.FROM_BACKEND).single()
|
||||
}
|
||||
|
||||
if (protoIndex?.let { checkerID(it) } == true) {
|
||||
return descriptorResolver(packageFqName.child(Name.identifier(proto.name)))
|
||||
}
|
||||
|
||||
members.forEach { member ->
|
||||
if (proto.isDefaultConstructor && member is ClassConstructorDescriptor) return member
|
||||
|
||||
val realMembers =
|
||||
if (proto.isFakeOverride && member is CallableMemberDescriptor && member.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE)
|
||||
member.resolveFakeOverrideMaybeAbstract().map { it.original }
|
||||
else
|
||||
setOf(member)
|
||||
|
||||
val memberIndices = realMembers.map { it.getUniqId()?.index ?: checkerDesc(it) }.filterNotNull()
|
||||
|
||||
if (memberIndices.contains(protoIndex)) {
|
||||
return when {
|
||||
member is PropertyDescriptor && proto.isSetter -> member.setter!!
|
||||
member is PropertyDescriptor && proto.isGetter -> member.getter!!
|
||||
else -> member
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
error("Could not find serialized descriptor for index: ${proto.uniqId.index} ${proto.packageFqName},${proto.classFqName},${proto.name}")
|
||||
}
|
||||
}
|
||||
+57304
File diff suppressed because it is too large
Load Diff
+337
@@ -0,0 +1,337 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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 org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.LoggingContext
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.JsKlibMetadataSerializerProtocol
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor
|
||||
import java.io.File
|
||||
|
||||
class IrKlibProtoBufModuleDeserializer(
|
||||
currentModule: ModuleDescriptor,
|
||||
logger: LoggingContext,
|
||||
builtIns: IrBuiltIns,
|
||||
libraryDir: File,
|
||||
symbolTable: SymbolTable,
|
||||
val forwardModuleDescriptor: ModuleDescriptor?)
|
||||
: IrModuleDeserializer(logger, builtIns, symbolTable) {
|
||||
|
||||
val deserializedSymbols = mutableMapOf<UniqIdKey, IrSymbol>()
|
||||
val knownBuiltInsDescriptors = mutableMapOf<DeclarationDescriptor, UniqId>()
|
||||
val reachableTopLevels = mutableSetOf<UniqIdKey>()
|
||||
val deserializedTopLevels = mutableSetOf<UniqIdKey>()
|
||||
val forwardDeclarations = mutableSetOf<IrSymbol>()
|
||||
|
||||
var deserializedModuleDescriptor: ModuleDescriptor? = null
|
||||
var deserializedModuleProtoSymbolTables = mutableMapOf<ModuleDescriptor, IrKlibProtoBuf.IrSymbolTable>()
|
||||
var deserializedModuleProtoTypeTables = mutableMapOf<ModuleDescriptor, IrKlibProtoBuf.IrTypeTable>()
|
||||
|
||||
val resolvedForwardDeclarations = mutableMapOf<UniqIdKey, UniqIdKey>()
|
||||
val descriptorReferenceDeserializer = DescriptorReferenceDeserializer(currentModule, resolvedForwardDeclarations)
|
||||
|
||||
val moduleRoot = libraryDir
|
||||
val irDirectory = File(libraryDir, "ir/")
|
||||
|
||||
|
||||
private val FUNCTION_INDEX_START: Long
|
||||
|
||||
init {
|
||||
var currentIndex = 0x1_0000_0000L
|
||||
builtIns.knownBuiltins.forEach {
|
||||
require(it is IrFunction)
|
||||
deserializedSymbols.put(UniqIdKey(null, UniqId(currentIndex, isLocal = false)), it.symbol)
|
||||
assert(symbolTable.referenceSimpleFunction(it.descriptor) == it.symbol)
|
||||
currentIndex++
|
||||
}
|
||||
|
||||
FUNCTION_INDEX_START = currentIndex
|
||||
}
|
||||
|
||||
private fun referenceDeserializedSymbol(proto: IrKlibProtoBuf.IrSymbolData, descriptor: DeclarationDescriptor?): IrSymbol = when (proto.kind) {
|
||||
IrKlibProtoBuf.IrSymbolKind.ANONYMOUS_INIT_SYMBOL ->
|
||||
IrAnonymousInitializerSymbolImpl(
|
||||
descriptor as ClassDescriptor?
|
||||
?: WrappedClassDescriptor()
|
||||
)
|
||||
IrKlibProtoBuf.IrSymbolKind.CLASS_SYMBOL ->
|
||||
symbolTable.referenceClass(
|
||||
descriptor as ClassDescriptor?
|
||||
?: WrappedClassDescriptor()
|
||||
)
|
||||
IrKlibProtoBuf.IrSymbolKind.CONSTRUCTOR_SYMBOL ->
|
||||
symbolTable.referenceConstructor(
|
||||
descriptor as ClassConstructorDescriptor?
|
||||
?: WrappedClassConstructorDescriptor()
|
||||
)
|
||||
IrKlibProtoBuf.IrSymbolKind.TYPE_PARAMETER_SYMBOL ->
|
||||
symbolTable.referenceTypeParameter(
|
||||
descriptor as TypeParameterDescriptor?
|
||||
?: WrappedTypeParameterDescriptor()
|
||||
)
|
||||
IrKlibProtoBuf.IrSymbolKind.ENUM_ENTRY_SYMBOL ->
|
||||
symbolTable.referenceEnumEntry(
|
||||
descriptor as ClassDescriptor?
|
||||
?: WrappedEnumEntryDescriptor()
|
||||
)
|
||||
IrKlibProtoBuf.IrSymbolKind.STANDALONE_FIELD_SYMBOL ->
|
||||
IrFieldSymbolImpl(WrappedFieldDescriptor())
|
||||
|
||||
IrKlibProtoBuf.IrSymbolKind.FIELD_SYMBOL ->
|
||||
symbolTable.referenceField(
|
||||
descriptor as PropertyDescriptor?
|
||||
?: WrappedPropertyDescriptor()
|
||||
)
|
||||
IrKlibProtoBuf.IrSymbolKind.FUNCTION_SYMBOL ->
|
||||
symbolTable.referenceSimpleFunction(
|
||||
descriptor as FunctionDescriptor?
|
||||
?: WrappedSimpleFunctionDescriptor()
|
||||
)
|
||||
IrKlibProtoBuf.IrSymbolKind.VARIABLE_SYMBOL ->
|
||||
IrVariableSymbolImpl(
|
||||
descriptor as VariableDescriptor?
|
||||
?: WrappedVariableDescriptor()
|
||||
)
|
||||
IrKlibProtoBuf.IrSymbolKind.VALUE_PARAMETER_SYMBOL ->
|
||||
IrValueParameterSymbolImpl(
|
||||
descriptor as ParameterDescriptor?
|
||||
?: WrappedValueParameterDescriptor()
|
||||
)
|
||||
IrKlibProtoBuf.IrSymbolKind.RECEIVER_PARAMETER_SYMBOL ->
|
||||
IrValueParameterSymbolImpl(
|
||||
descriptor as ParameterDescriptor? ?: WrappedReceiverParameterDescriptor()
|
||||
)
|
||||
else -> TODO("Unexpected classifier symbol kind: ${proto.kind}")
|
||||
}
|
||||
|
||||
override fun deserializeIrSymbol(proto: IrKlibProtoBuf.IrSymbol): IrSymbol {
|
||||
val symbolData =
|
||||
deserializedModuleProtoSymbolTables[deserializedModuleDescriptor]!!.getSymbols(proto.index)
|
||||
return deserializeIrSymbolData(symbolData)
|
||||
}
|
||||
|
||||
override fun deserializeIrType(proto: IrKlibProtoBuf.IrTypeIndex): IrType {
|
||||
val typeData =
|
||||
deserializedModuleProtoTypeTables[deserializedModuleDescriptor]!!.getTypes(proto.index)
|
||||
return deserializeIrTypeData(typeData)
|
||||
}
|
||||
|
||||
fun deserializeIrSymbolData(proto: IrKlibProtoBuf.IrSymbolData): IrSymbol {
|
||||
val key = proto.uniqId.uniqIdKey(deserializedModuleDescriptor!!)
|
||||
val topLevelKey = proto.topLevelUniqId.uniqIdKey(deserializedModuleDescriptor!!)
|
||||
|
||||
if (!deserializedTopLevels.contains(topLevelKey)) reachableTopLevels.add(topLevelKey)
|
||||
|
||||
val symbol = deserializedSymbols.getOrPut(key) {
|
||||
val descriptor = if (proto.hasDescriptorReference()) {
|
||||
deserializeDescriptorReference(proto.descriptorReference)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
resolvedForwardDeclarations[key]?.let {
|
||||
if (!deserializedTopLevels.contains(it)) reachableTopLevels.add(it) // Assuming forward declarations are always top levels.
|
||||
}
|
||||
|
||||
referenceDeserializedSymbol(proto, descriptor)
|
||||
}
|
||||
|
||||
if (symbol.descriptor is ClassDescriptor &&
|
||||
symbol.descriptor !is WrappedDeclarationDescriptor<*>/* &&
|
||||
symbol.descriptor.module.isForwardDeclarationModule*/
|
||||
) {
|
||||
forwardDeclarations.add(symbol)
|
||||
}
|
||||
|
||||
return symbol
|
||||
}
|
||||
|
||||
override fun deserializeDescriptorReference(proto: IrKlibProtoBuf.DescriptorReference) =
|
||||
descriptorReferenceDeserializer.deserializeDescriptorReference(proto, {
|
||||
knownBuiltInsDescriptors[it]?.index ?: if (isBuiltInFunction(it)) FUNCTION_INDEX_START + builtInFunctionId(it) else null
|
||||
}, { (FUNCTION_INDEX_START + BUILT_IN_UNIQ_ID_CLASS_OFFSET) <= it && it < (FUNCTION_INDEX_START + BUILT_IN_UNIQ_ID_GAP) }, {
|
||||
builtIns.builtIns.getBuiltInClassByFqName(it)
|
||||
})
|
||||
|
||||
private val ByteArray.codedInputStream: org.jetbrains.kotlin.protobuf.CodedInputStream
|
||||
get() {
|
||||
val codedInputStream = org.jetbrains.kotlin.protobuf.CodedInputStream.newInstance(this)
|
||||
codedInputStream.setRecursionLimit(65535) // The default 64 is blatantly not enough for IR.
|
||||
return codedInputStream
|
||||
}
|
||||
|
||||
private val reversedFileIndex = mutableMapOf<UniqIdKey, IrFile>()
|
||||
|
||||
private val UniqIdKey.moduleOfOrigin get() =
|
||||
this.moduleDescriptor ?: reversedFileIndex[this]?.packageFragmentDescriptor?.containingDeclaration
|
||||
|
||||
private fun deserializeTopLevelDeclaration(uniqIdKey: UniqIdKey): IrDeclaration {
|
||||
val proto = loadTopLevelDeclarationProto(uniqIdKey)
|
||||
return deserializeDeclaration(proto, reversedFileIndex[uniqIdKey]!!)
|
||||
}
|
||||
|
||||
private fun loadTopLevelDeclarationProto(uniqIdKey: UniqIdKey): IrKlibProtoBuf.IrDeclaration {
|
||||
val file = File(irDirectory, uniqIdKey.uniqId.declarationFileName)
|
||||
return IrKlibProtoBuf.IrDeclaration.parseFrom(file.readBytes().codedInputStream, JsKlibMetadataSerializerProtocol.extensionRegistry)
|
||||
}
|
||||
|
||||
private fun findDeserializedDeclarationForDescriptor(descriptor: DeclarationDescriptor): DeclarationDescriptor? {
|
||||
val topLevelDescriptor = descriptor.findTopLevelDescriptor()
|
||||
|
||||
// if (topLevelDescriptor.module.isForwardDeclarationModule) return null
|
||||
|
||||
if (topLevelDescriptor !is DeserializedClassDescriptor && topLevelDescriptor !is DeserializedCallableMemberDescriptor) {
|
||||
return null
|
||||
}
|
||||
|
||||
val descriptorUniqId = topLevelDescriptor.getUniqId()
|
||||
?: error("could not get descriptor uniq id for $topLevelDescriptor")
|
||||
val uniqId = UniqId(descriptorUniqId.index, isLocal = false)
|
||||
val topLevelKey = UniqIdKey(topLevelDescriptor.module, uniqId)
|
||||
|
||||
// This top level descriptor doesn't have a serialized IR declaration.
|
||||
if (topLevelKey.moduleOfOrigin == null) return null
|
||||
|
||||
reachableTopLevels.add(topLevelKey)
|
||||
|
||||
do {
|
||||
val key = reachableTopLevels.first()
|
||||
|
||||
if (deserializedSymbols[key]?.isBound == true ||
|
||||
// The key.moduleOrigin is null for uniqIds that we haven't seen in any of the library headers.
|
||||
// Just skip it for now and handle it elsewhere.
|
||||
key.moduleOfOrigin == null) {
|
||||
|
||||
reachableTopLevels.remove(key)
|
||||
deserializedTopLevels.add(key)
|
||||
continue
|
||||
}
|
||||
|
||||
deserializedModuleDescriptor = key.moduleOfOrigin
|
||||
val reachable = deserializeTopLevelDeclaration(key)
|
||||
reversedFileIndex[key]!!.declarations.add(reachable)
|
||||
|
||||
reachableTopLevels.remove(key)
|
||||
deserializedTopLevels.add(key)
|
||||
} while (reachableTopLevels.isNotEmpty())
|
||||
|
||||
return topLevelDescriptor
|
||||
}
|
||||
|
||||
override fun findDeserializedDeclaration(symbol: IrSymbol): IrDeclaration? {
|
||||
|
||||
if (!symbol.isBound) {
|
||||
val topLevelDesecriptor = findDeserializedDeclarationForDescriptor(symbol.descriptor)
|
||||
if (topLevelDesecriptor == null) return null
|
||||
}
|
||||
|
||||
assert(symbol.isBound) {
|
||||
"findDeserializedDeclaration: symbol ${symbol} is unbound, descriptor = ${symbol.descriptor}, hash = ${symbol.descriptor.hashCode()}"
|
||||
}
|
||||
|
||||
return symbol.owner as IrDeclaration
|
||||
}
|
||||
|
||||
override fun findDeserializedDeclaration(propertyDescriptor: PropertyDescriptor): IrProperty? {
|
||||
val topLevelDesecriptor = findDeserializedDeclarationForDescriptor(propertyDescriptor)
|
||||
if (topLevelDesecriptor == null) return null
|
||||
|
||||
return symbolTable.propertyTable[propertyDescriptor]
|
||||
?: error("findDeserializedDeclaration: property descriptor $propertyDescriptor} is not present in propertyTable after deserialization}")
|
||||
}
|
||||
|
||||
override fun declareForwardDeclarations() {
|
||||
if (forwardModuleDescriptor == null) return
|
||||
|
||||
val packageFragments = forwardDeclarations.map { it.descriptor.findPackage() }.distinct()
|
||||
|
||||
// We don't bother making a real IR module here, as we have no need in it any later.
|
||||
// All we need is just to declare forward declarations in the symbol table
|
||||
// In case you need a full fledged module, turn the forEach into a map and collect
|
||||
// produced files into an IrModuleFragment.
|
||||
|
||||
packageFragments.forEach { packageFragment ->
|
||||
val symbol = IrFileSymbolImpl(packageFragment)
|
||||
val file = IrFileImpl(NaiveSourceBasedFileEntryImpl("forward declarations pseudo-file"), symbol)
|
||||
val symbols = forwardDeclarations
|
||||
.filter { !it.isBound }
|
||||
.filter { it.descriptor.findPackage() == packageFragment }
|
||||
val declarations = symbols.map {
|
||||
|
||||
val classDescriptor = it.descriptor as ClassDescriptor
|
||||
val declaration = symbolTable.declareClass(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irrelevantOrigin,
|
||||
classDescriptor,
|
||||
classDescriptor.modality
|
||||
) { symbol: IrClassSymbol -> IrClassImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, irrelevantOrigin, symbol) }
|
||||
declaration
|
||||
|
||||
}
|
||||
file.declarations.addAll(declarations)
|
||||
}
|
||||
}
|
||||
|
||||
fun deserializeIrFile(fileProto: IrKlibProtoBuf.IrFile, moduleDescriptor: ModuleDescriptor, deserializeAllDeclarations: Boolean): IrFile {
|
||||
val fileEntry = NaiveSourceBasedFileEntryImpl(fileProto.fileEntry.name)
|
||||
|
||||
// TODO: we need to store "" in protobuf, I suppose. Or better yet, reuse fqname storage from metadata.
|
||||
val fqName = if (fileProto.fqName == "<root>") FqName.ROOT else FqName(fileProto.fqName)
|
||||
|
||||
val packageFragmentDescriptor = EmptyPackageFragmentDescriptor(moduleDescriptor, fqName)
|
||||
|
||||
val symbol = IrFileSymbolImpl(packageFragmentDescriptor)
|
||||
val file = IrFileImpl(fileEntry, symbol, fqName)
|
||||
|
||||
fileProto.declarationIdList.forEach {
|
||||
val uniqIdKey = it.uniqIdKey(moduleDescriptor)
|
||||
reversedFileIndex.put(uniqIdKey, file)
|
||||
|
||||
if (deserializeAllDeclarations) {
|
||||
file.declarations.add(deserializeTopLevelDeclaration(uniqIdKey))
|
||||
}
|
||||
}
|
||||
|
||||
return file
|
||||
}
|
||||
|
||||
fun deserializeIrModule(proto: IrKlibProtoBuf.IrModule, moduleDescriptor: ModuleDescriptor, deserializeAllDeclarations: Boolean): IrModuleFragment {
|
||||
|
||||
deserializedModuleDescriptor = moduleDescriptor
|
||||
deserializedModuleProtoSymbolTables.put(moduleDescriptor, proto.symbolTable)
|
||||
deserializedModuleProtoTypeTables.put(moduleDescriptor, proto.typeTable)
|
||||
|
||||
var i = 0
|
||||
val files = proto.fileList.map {
|
||||
i++
|
||||
// if (i >= 41)
|
||||
// descriptorReferenceDeserializer.doCrash = true
|
||||
deserializeIrFile(it, moduleDescriptor, deserializeAllDeclarations)
|
||||
}
|
||||
val module = IrModuleFragmentImpl(moduleDescriptor, builtIns, files)
|
||||
module.patchDeclarationParents(null)
|
||||
return module
|
||||
}
|
||||
|
||||
fun deserializeIrModule(moduleDescriptor: ModuleDescriptor, byteArray: ByteArray, deserializeAllDeclarations: Boolean = false): IrModuleFragment {
|
||||
val proto = IrKlibProtoBuf.IrModule.parseFrom(byteArray.codedInputStream, JsKlibMetadataSerializerProtocol.extensionRegistry)
|
||||
return deserializeIrModule(proto, moduleDescriptor, deserializeAllDeclarations)
|
||||
}
|
||||
}
|
||||
+1131
File diff suppressed because it is too large
Load Diff
+1153
File diff suppressed because it is too large
Load Diff
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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 org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||
|
||||
// TODO: move me somewhere
|
||||
|
||||
/**
|
||||
* Implementation of given method.
|
||||
*
|
||||
* TODO: this method is actually a part of resolve and probably duplicates another one
|
||||
*/
|
||||
internal fun IrSimpleFunction.resolveFakeOverrideMaybeAbstract() = this.resolveFakeOverride(allowAbstract = true)
|
||||
|
||||
internal fun IrProperty.resolveFakeOverrideMaybeAbstract() = this.getter!!.resolveFakeOverrideMaybeAbstract().correspondingProperty!!
|
||||
|
||||
internal fun IrField.resolveFakeOverrideMaybeAbstract() = this.correspondingProperty!!.getter!!.resolveFakeOverrideMaybeAbstract().correspondingProperty!!.backingField
|
||||
|
||||
/**
|
||||
* Implementation of given method.
|
||||
*
|
||||
* TODO: this method is actually a part of resolve and probably duplicates another one
|
||||
*/
|
||||
internal fun <T : CallableMemberDescriptor> T.resolveFakeOverrideMaybeAbstract(): Set<T> {
|
||||
if (this.kind.isReal) {
|
||||
return setOf(this)
|
||||
} else {
|
||||
val overridden = OverridingUtil.getOverriddenDeclarations(this)
|
||||
val filtered = OverridingUtil.filterOutOverridden(overridden)
|
||||
// TODO: is it correct to take first?
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return filtered as Set<T>
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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 org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
|
||||
|
||||
class SerializedIr (
|
||||
val module: ByteArray,
|
||||
val declarations: Map<UniqId, ByteArray>,
|
||||
val debugIndex: Map<UniqId, String>
|
||||
)
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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 org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.serialization.StringTableImpl
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getAllSuperClassifiers
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import java.io.OutputStream
|
||||
|
||||
class KonanStringTable : StringTableImpl() {
|
||||
|
||||
fun getClassOrPackageFqNameIndex(descriptor: ClassOrPackageFragmentDescriptor): Int {
|
||||
when (descriptor) {
|
||||
is PackageFragmentDescriptor ->
|
||||
return getPackageFqNameIndex(descriptor.fqName)
|
||||
|
||||
is ClassDescriptor ->
|
||||
return getFqNameIndex(descriptor as ClassifierDescriptorWithTypeParameters)
|
||||
else -> error("Can not get fqNameIndex for $descriptor")
|
||||
}
|
||||
}
|
||||
|
||||
override fun getLocalClassIdReplacement(descriptor: ClassifierDescriptorWithTypeParameters): ClassId? {
|
||||
return if (descriptor.containingDeclaration is CallableMemberDescriptor) {
|
||||
val superClassifiers = descriptor.getAllSuperClassifiers()
|
||||
.mapNotNull { it as ClassifierDescriptorWithTypeParameters }
|
||||
.filter { it != descriptor }
|
||||
.toList()
|
||||
if (superClassifiers.size == 1) {
|
||||
superClassifiers[0].classId
|
||||
} else {
|
||||
val superClass = superClassifiers.find { !DescriptorUtils.isInterface(it) }
|
||||
superClass?.classId ?: ClassId.topLevel(descriptor.module.builtIns.any.fqNameSafe)
|
||||
}
|
||||
} else {
|
||||
super.getLocalClassIdReplacement(descriptor)
|
||||
}
|
||||
}
|
||||
|
||||
fun serializeTo(output: OutputStream) {
|
||||
val (strings, qualifiedNames) = buildProto()
|
||||
strings.writeDelimitedTo(output)
|
||||
qualifiedNames.writeDelimitedTo(output)
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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 org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.atMostOne
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.propertyIfAccessor
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.constants.StringValue
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.ifNotEmpty
|
||||
|
||||
internal val DeclarationDescriptor.isExpectMember: Boolean
|
||||
get() = this is MemberDescriptor && this.isExpect
|
||||
|
||||
internal val DeclarationDescriptor.isSerializableExpectClass: Boolean
|
||||
get() = this is ClassDescriptor && ExpectedActualDeclarationChecker.shouldGenerateExpectClass(this)
|
||||
|
||||
fun <T> AnnotationDescriptor.getArgumentValueOrNull(name: String): T? {
|
||||
val constantValue = this.allValueArguments.entries.atMostOne {
|
||||
it.key.asString() == name
|
||||
}?.value
|
||||
return constantValue?.value as T?
|
||||
}
|
||||
|
||||
private val symbolNameAnnotation = FqName("kotlin.native.SymbolName")
|
||||
|
||||
fun getAnnotationValue(annotation: AnnotationDescriptor): String? {
|
||||
return annotation.allValueArguments.values.ifNotEmpty {
|
||||
val stringValue = single() as? StringValue
|
||||
stringValue?.value
|
||||
}
|
||||
}
|
||||
|
||||
fun CallableMemberDescriptor.externalSymbolOrThrow(): String? {
|
||||
this.annotations.findAnnotation(symbolNameAnnotation)?.let {
|
||||
return getAnnotationValue(it)!!
|
||||
}
|
||||
|
||||
throw Error("external function ${this} must have @TypedIntrinsic, @SymbolName or @ObjCMethod annotation")
|
||||
}
|
||||
|
||||
tailrec internal fun DeclarationDescriptor.findPackage(): PackageFragmentDescriptor {
|
||||
return if (this is PackageFragmentDescriptor) this
|
||||
else this.containingDeclaration!!.findPackage()
|
||||
}
|
||||
|
||||
fun DeclarationDescriptor.findTopLevelDescriptor(): DeclarationDescriptor {
|
||||
return if (this.containingDeclaration is org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor) this.propertyIfAccessor
|
||||
else this.containingDeclaration!!.findTopLevelDescriptor()
|
||||
}
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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 org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.classId
|
||||
|
||||
|
||||
class DescriptorReferenceSerializer(val declarationTable: DeclarationTable) {
|
||||
|
||||
// Not all exported descriptors are deserialized, some a synthesized anew during metadata deserialization.
|
||||
// Those created descriptors can't carry the uniqIdIndex, since it is available only for deserialized descriptors.
|
||||
// So we record the uniq id of some other "discoverable" descriptor for which we know for sure that it will be
|
||||
// available as deserialized descriptor, plus the path to find the needed descriptor from that one.
|
||||
fun serializeDescriptorReference(declaration: IrDeclaration): IrKlibProtoBuf.DescriptorReference? {
|
||||
|
||||
val descriptor = declaration.descriptor
|
||||
|
||||
if (!declaration.isExported() && !((declaration as? IrDeclarationWithVisibility)?.visibility == Visibilities.INVISIBLE_FAKE)) {
|
||||
return null
|
||||
}
|
||||
if (declaration is IrAnonymousInitializer) return null
|
||||
|
||||
if (descriptor is ParameterDescriptor || (descriptor is VariableDescriptor && descriptor !is PropertyDescriptor) || descriptor is TypeParameterDescriptor) return null
|
||||
|
||||
val containingDeclaration = descriptor.containingDeclaration!!
|
||||
|
||||
val (packageFqName, classFqName) = when (containingDeclaration) {
|
||||
is ClassDescriptor -> {
|
||||
val classId = containingDeclaration.classId ?: return null
|
||||
Pair(classId.packageFqName.toString(), classId.relativeClassName.toString())
|
||||
}
|
||||
is PackageFragmentDescriptor -> Pair(containingDeclaration.fqName.toString(), "")
|
||||
else -> return null
|
||||
}
|
||||
|
||||
val isAccessor = declaration.isAccessor
|
||||
val isBackingField = declaration is IrField && declaration.correspondingProperty != null
|
||||
val isFakeOverride = declaration.origin == IrDeclarationOrigin.FAKE_OVERRIDE
|
||||
val isDefaultConstructor =
|
||||
descriptor is ClassConstructorDescriptor && containingDeclaration is ClassDescriptor && containingDeclaration.kind == ClassKind.OBJECT
|
||||
val isEnumEntry = descriptor is ClassDescriptor && descriptor.kind == ClassKind.ENUM_ENTRY
|
||||
val isEnumSpecial = declaration.origin == IrDeclarationOrigin.ENUM_CLASS_SPECIAL_MEMBER
|
||||
|
||||
|
||||
val realDeclaration = if (isFakeOverride) {
|
||||
when (declaration) {
|
||||
is IrSimpleFunction -> declaration.resolveFakeOverrideMaybeAbstract()
|
||||
is IrField -> declaration.resolveFakeOverrideMaybeAbstract()
|
||||
is IrProperty -> declaration.resolveFakeOverrideMaybeAbstract()
|
||||
else -> error("Unexpected fake override declaration")
|
||||
}
|
||||
} else {
|
||||
declaration
|
||||
}
|
||||
|
||||
val discoverableDescriptorsDeclaration: IrDeclaration? = if (isAccessor) {
|
||||
(realDeclaration as IrSimpleFunction).correspondingProperty!!
|
||||
} else if (isBackingField) {
|
||||
(realDeclaration as IrField).correspondingProperty!!
|
||||
} else if (isDefaultConstructor || isEnumEntry) {
|
||||
null
|
||||
} else {
|
||||
realDeclaration
|
||||
}
|
||||
|
||||
val uniqId = discoverableDescriptorsDeclaration?.let { declarationTable.uniqIdByDeclaration(it) }
|
||||
uniqId?.let { declarationTable.descriptors.put(discoverableDescriptorsDeclaration.descriptor, it) }
|
||||
|
||||
val proto = IrKlibProtoBuf.DescriptorReference.newBuilder()
|
||||
.setPackageFqName(packageFqName)
|
||||
.setClassFqName(classFqName)
|
||||
.setName(descriptor.name.toString())
|
||||
|
||||
if (uniqId != null) proto.setUniqId(protoUniqId(uniqId))
|
||||
|
||||
if (isFakeOverride) {
|
||||
proto.setIsFakeOverride(true)
|
||||
}
|
||||
|
||||
if (isBackingField) {
|
||||
proto.setIsBackingField(true)
|
||||
}
|
||||
|
||||
if (isAccessor) {
|
||||
if (declaration.isGetter)
|
||||
proto.setIsGetter(true)
|
||||
else if (declaration.isSetter)
|
||||
proto.setIsSetter(true)
|
||||
else
|
||||
error("A property accessor which is neither a getter, nor a setter: $descriptor")
|
||||
} else if (isDefaultConstructor) {
|
||||
proto.setIsDefaultConstructor(true)
|
||||
} else if (isEnumEntry) {
|
||||
proto.setIsEnumEntry(true)
|
||||
} else if (isEnumSpecial) {
|
||||
proto.setIsEnumSpecial(true)
|
||||
}
|
||||
|
||||
return proto.build()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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 org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf.QualifiedNameTable.QualifiedName
|
||||
import org.jetbrains.kotlin.metadata.deserialization.NameResolverImpl
|
||||
import org.jetbrains.kotlin.serialization.deserialization.getClassId
|
||||
|
||||
// TODO Come up with a better file name.
|
||||
|
||||
internal fun NameResolverImpl.getDescriptorByFqNameIndex(
|
||||
module: ModuleDescriptor,
|
||||
nameTable: ProtoBuf.QualifiedNameTable,
|
||||
fqNameIndex: Int): DeclarationDescriptor {
|
||||
|
||||
if (fqNameIndex == -1) return module.getPackage(FqName.ROOT)
|
||||
val packageName = this.getPackageFqName(fqNameIndex)
|
||||
// TODO: Here we are using internals of NameresolverImpl.
|
||||
// Consider extending NameResolver.
|
||||
val proto = nameTable.getQualifiedName(fqNameIndex)
|
||||
when (proto.kind!!) {
|
||||
QualifiedName.Kind.CLASS,
|
||||
QualifiedName.Kind.LOCAL ->
|
||||
return module.findClassAcrossModuleDependencies(this.getClassId(fqNameIndex))!!
|
||||
QualifiedName.Kind.PACKAGE ->
|
||||
return module.getPackage(FqName(packageName))
|
||||
}
|
||||
}
|
||||
|
||||
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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 org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.serialization.metadata.JsKlibMetadataProtoBuf
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.*
|
||||
import org.jetbrains.kotlin.protobuf.GeneratedMessageLite
|
||||
|
||||
// This is an abstract uniqIdIndex any serialized IR declarations gets.
|
||||
// It is either isLocal and then just gets and ordinary number within its module.
|
||||
// Or is visible across modules and then gets a hash of mangled name as its index.
|
||||
data class UniqId (
|
||||
val index: Long,
|
||||
val isLocal: Boolean
|
||||
)
|
||||
|
||||
// isLocal=true in UniqId is good while we dealing with a single current module.
|
||||
// To disambiguate module local declarations of different modules we use UniqIdKey.
|
||||
// It has moduleDescriptor specified for isLocal=true uniqIds.
|
||||
data class UniqIdKey private constructor(val uniqId: UniqId, val moduleDescriptor: ModuleDescriptor?) {
|
||||
constructor(moduleDescriptor: ModuleDescriptor?, uniqId: UniqId)
|
||||
: this(uniqId, if (uniqId.isLocal) moduleDescriptor!! else null)
|
||||
}
|
||||
|
||||
internal val IrDeclaration.uniqIdIndex: Long
|
||||
get() = this.uniqSymbolName().hashCode().toLong()
|
||||
|
||||
fun protoUniqId(uniqId: UniqId): IrKlibProtoBuf.UniqId =
|
||||
IrKlibProtoBuf.UniqId.newBuilder()
|
||||
.setIndex(uniqId.index)
|
||||
.setIsLocal(uniqId.isLocal)
|
||||
.build()
|
||||
|
||||
fun IrKlibProtoBuf.UniqId.uniqId(): UniqId = UniqId(this.index, this.isLocal)
|
||||
fun IrKlibProtoBuf.UniqId.uniqIdKey(moduleDescriptor: ModuleDescriptor) =
|
||||
UniqIdKey(moduleDescriptor, this.uniqId())
|
||||
|
||||
fun <T, M:GeneratedMessageLite.ExtendableMessage<M>> M.tryGetExtension(extension: GeneratedMessageLite.GeneratedExtension<M, T>)
|
||||
= if (this.hasExtension(extension)) this.getExtension<T>(extension) else null
|
||||
|
||||
fun DeclarationDescriptor.getUniqId(): JsKlibMetadataProtoBuf.DescriptorUniqId? = when (this) {
|
||||
is DeserializedClassDescriptor -> this.classProto.tryGetExtension(JsKlibMetadataProtoBuf.classUniqId)
|
||||
is DeserializedSimpleFunctionDescriptor -> this.proto.tryGetExtension(JsKlibMetadataProtoBuf.functionUniqId)
|
||||
is DeserializedPropertyDescriptor -> this.proto.tryGetExtension(JsKlibMetadataProtoBuf.propertyUniqId)
|
||||
is DeserializedClassConstructorDescriptor -> this.proto.tryGetExtension(JsKlibMetadataProtoBuf.constructorUniqId)
|
||||
else -> null
|
||||
}
|
||||
|
||||
fun newDescriptorUniqId(index: Long): JsKlibMetadataProtoBuf.DescriptorUniqId =
|
||||
JsKlibMetadataProtoBuf.DescriptorUniqId.newBuilder().setIndex(index).build()
|
||||
|
||||
val UniqId.declarationFileName: String get() = "$index${if (isLocal) "L" else "G"}.kjd"
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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 org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir
|
||||
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
// This is a little extension over what's used in real mangling
|
||||
// since some declarations never appear in the bitcode symbols.
|
||||
|
||||
internal fun IrDeclaration.uniqSymbolName(): String = when (this) {
|
||||
is IrFunction
|
||||
-> this.uniqFunctionName
|
||||
is IrProperty
|
||||
-> this.symbolName
|
||||
is IrClass
|
||||
-> this.typeInfoSymbolName
|
||||
is IrField
|
||||
-> this.symbolName
|
||||
is IrEnumEntry
|
||||
-> this.symbolName
|
||||
else -> error("Unexpected exported declaration: $this")
|
||||
}
|
||||
|
||||
private val IrDeclarationParent.fqNameUnique: FqName
|
||||
get() = when(this) {
|
||||
is IrPackageFragment -> this.fqName
|
||||
is IrDeclaration -> this.parent.fqNameUnique.child(this.uniqName)
|
||||
else -> error(this)
|
||||
}
|
||||
|
||||
private val IrDeclaration.uniqName: Name
|
||||
get() = when (this) {
|
||||
is IrSimpleFunction -> Name.special("<${this.uniqFunctionName}>")
|
||||
else -> this.name
|
||||
}
|
||||
|
||||
private val IrProperty.symbolName: String
|
||||
get() {
|
||||
val extensionReceiver: String = getter!!.extensionReceiverParameter ?. extensionReceiverNamePart ?: ""
|
||||
|
||||
val containingDeclarationPart = parent.fqNameSafe.let {
|
||||
if (it.isRoot) "" else "$it."
|
||||
}
|
||||
return "kprop:$containingDeclarationPart$extensionReceiver$name"
|
||||
}
|
||||
|
||||
private val IrEnumEntry.symbolName: String
|
||||
get() {
|
||||
val containingDeclarationPart = parent.fqNameSafe.let {
|
||||
if (it.isRoot) "" else "$it."
|
||||
}
|
||||
return "kenumentry:$containingDeclarationPart$name"
|
||||
}
|
||||
|
||||
// This is basicly the same as .symbolName, but disambiguates external functions with the same C name.
|
||||
// In addition functions appearing in fq sequence appear as <full signature>.
|
||||
private val IrFunction.uniqFunctionName: String
|
||||
get() {
|
||||
val parent = this.parent
|
||||
|
||||
val containingDeclarationPart = parent.fqNameUnique.let {
|
||||
if (it.isRoot) "" else "$it."
|
||||
}
|
||||
|
||||
return "kfun:$containingDeclarationPart#$functionName"
|
||||
}
|
||||
+606
@@ -0,0 +1,606 @@
|
||||
syntax = "proto2";
|
||||
package org.jetbrains.kotlin.ir.backend.js.lower.serialization.ir;
|
||||
|
||||
option java_outer_classname = "IrKlibProtoBuf";
|
||||
option optimize_for = LITE_RUNTIME;
|
||||
|
||||
message DescriptorReference {
|
||||
required string package_fq_name = 1;
|
||||
required string class_fq_name = 2;
|
||||
required string name = 3;
|
||||
optional UniqId uniq_id = 4;
|
||||
optional bool is_getter = 5 [default = false];
|
||||
optional bool is_setter = 6 [default = false];
|
||||
optional bool is_backing_field = 7 [default = false];
|
||||
optional bool is_fake_override = 8 [default = false];
|
||||
optional bool is_default_constructor = 9 [default = false];
|
||||
optional bool is_enum_entry = 10 [default = false];
|
||||
optional bool is_enum_special = 11 [default = false];
|
||||
}
|
||||
|
||||
message UniqId {
|
||||
required uint64 index = 1;
|
||||
required bool isLocal = 2;
|
||||
}
|
||||
|
||||
message Coordinates {
|
||||
required int32 start_offset = 1;
|
||||
required int32 end_offset = 2;
|
||||
}
|
||||
|
||||
/* ------ Top Level---------------------------------------------- */
|
||||
|
||||
message IrDeclarationContainer {
|
||||
repeated IrDeclaration declaration = 1;
|
||||
}
|
||||
|
||||
message FileEntry { // TODO: extend me.
|
||||
required string name = 1;
|
||||
}
|
||||
|
||||
message IrFile {
|
||||
repeated UniqId declaration_id = 1;
|
||||
required FileEntry file_entry = 2;
|
||||
// TODO: we need a better string management. See metadata serialization as an example.
|
||||
required string fq_name = 3;
|
||||
}
|
||||
|
||||
message IrModule {
|
||||
required string name = 1;
|
||||
repeated IrFile file = 2;
|
||||
required IrSymbolTable symbol_table = 3;
|
||||
required IrTypeTable type_table = 4;
|
||||
}
|
||||
|
||||
/* ------ IrSymbols --------------------------------------------- */
|
||||
|
||||
enum IrSymbolKind {
|
||||
FUNCTION_SYMBOL = 1;
|
||||
CONSTRUCTOR_SYMBOL = 2;
|
||||
ENUM_ENTRY_SYMBOL = 3;
|
||||
FIELD_SYMBOL = 4;
|
||||
VALUE_PARAMETER_SYMBOL = 5;
|
||||
RETURNABLE_BLOCK_SYMBOL = 6;
|
||||
CLASS_SYMBOL = 7;
|
||||
TYPE_PARAMETER_SYMBOL = 8;
|
||||
VARIABLE_SYMBOL = 9;
|
||||
ANONYMOUS_INIT_SYMBOL = 10;
|
||||
|
||||
STANDALONE_FIELD_SYMBOL = 11; // For fields without properties. WrappedFieldDescriptor, rather than WrappedPropertyDescriptor.
|
||||
RECEIVER_PARAMETER_SYMBOL = 12; // ReceiverParameterDescriptor rather than ValueParameterDescriptor.
|
||||
}
|
||||
|
||||
message IrSymbolData {
|
||||
required IrSymbolKind kind = 1;
|
||||
required UniqId uniq_id = 2;
|
||||
required UniqId top_level_uniq_id = 3;
|
||||
optional string fqname = 4;
|
||||
optional DescriptorReference descriptor_reference = 5;
|
||||
}
|
||||
|
||||
message IrSymbol {
|
||||
required int32 index = 1;
|
||||
}
|
||||
|
||||
message IrSymbolTable {
|
||||
repeated IrSymbolData symbols = 1;
|
||||
}
|
||||
|
||||
/* ------ IrTypes --------------------------------------------- */
|
||||
|
||||
enum IrTypeVariance { // Should we import metadata variance, or better stay separate?
|
||||
IN = 0;
|
||||
OUT = 1;
|
||||
INV = 2;
|
||||
}
|
||||
|
||||
message Annotations {
|
||||
repeated IrCall annotation = 1;
|
||||
}
|
||||
|
||||
message TypeArguments {
|
||||
repeated IrTypeIndex type_argument = 1;
|
||||
}
|
||||
|
||||
message IrStarProjection {
|
||||
optional bool void = 1;
|
||||
}
|
||||
|
||||
message IrTypeProjection {
|
||||
required IrTypeVariance variance = 1;
|
||||
required IrTypeIndex type = 2;
|
||||
}
|
||||
|
||||
message IrTypeArgument {
|
||||
oneof kind {
|
||||
IrStarProjection star = 1;
|
||||
IrTypeProjection type = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message IrSimpleType {
|
||||
required Annotations annotations = 1;
|
||||
required IrSymbol classifier = 2;
|
||||
required bool has_question_mark = 3;
|
||||
repeated IrTypeArgument argument = 4;
|
||||
}
|
||||
|
||||
message IrDynamicType {
|
||||
required Annotations annotations = 1;
|
||||
}
|
||||
|
||||
message IrErrorType {
|
||||
required Annotations annotations = 1;
|
||||
}
|
||||
|
||||
message IrType {
|
||||
oneof kind {
|
||||
IrSimpleType simple = 1;
|
||||
IrDynamicType dynamic = 2;
|
||||
IrErrorType error = 3;
|
||||
}
|
||||
}
|
||||
|
||||
message IrTypeTable {
|
||||
repeated IrType types = 1;
|
||||
}
|
||||
|
||||
message IrTypeIndex {
|
||||
required int32 index = 1;
|
||||
}
|
||||
|
||||
/* ------ IrExpressions --------------------------------------------- */
|
||||
|
||||
message IrBreak {
|
||||
required int32 loop_id = 1;
|
||||
optional string label = 2;
|
||||
}
|
||||
|
||||
message IrBlock {
|
||||
required bool is_lambda_origin = 1;
|
||||
repeated IrStatement statement = 2;
|
||||
}
|
||||
|
||||
message MemberAccessCommon {
|
||||
optional IrExpression dispatch_receiver = 1;
|
||||
optional IrExpression extension_receiver = 2;
|
||||
repeated NullableIrExpression value_argument = 3;
|
||||
required TypeArguments type_arguments = 4;
|
||||
}
|
||||
|
||||
message IrCall {
|
||||
enum Primitive {
|
||||
NOT_PRIMITIVE = 1;
|
||||
NULLARY = 2;
|
||||
UNARY = 3;
|
||||
BINARY = 4;
|
||||
}
|
||||
required Primitive kind = 1;
|
||||
required IrSymbol symbol = 2;
|
||||
required MemberAccessCommon member_access = 3;
|
||||
optional IrSymbol super = 4;
|
||||
}
|
||||
|
||||
message IrFunctionReference {
|
||||
required IrSymbol symbol = 1;
|
||||
optional string origin = 2;
|
||||
required MemberAccessCommon member_access = 3;
|
||||
}
|
||||
|
||||
|
||||
message IrPropertyReference {
|
||||
optional IrSymbol field = 1;
|
||||
optional IrSymbol getter = 2;
|
||||
optional IrSymbol setter = 3;
|
||||
optional string origin = 4;
|
||||
required MemberAccessCommon member_access = 5;
|
||||
}
|
||||
|
||||
message IrComposite {
|
||||
repeated IrStatement statement = 1;
|
||||
}
|
||||
|
||||
message IrClassReference {
|
||||
required IrSymbol class_symbol = 1;
|
||||
required IrTypeIndex class_type = 2;
|
||||
}
|
||||
|
||||
message IrConst {
|
||||
oneof value {
|
||||
bool null = 1;
|
||||
bool boolean = 2;
|
||||
int32 char = 3;
|
||||
int32 byte = 4;
|
||||
int32 short = 5;
|
||||
int32 int = 6;
|
||||
int64 long = 7;
|
||||
float float = 8;
|
||||
double double = 9;
|
||||
string string = 10;
|
||||
}
|
||||
}
|
||||
|
||||
message IrContinue {
|
||||
required int32 loop_id = 1;
|
||||
optional string label = 2;
|
||||
}
|
||||
|
||||
message IrDelegatingConstructorCall {
|
||||
required IrSymbol symbol = 1;
|
||||
required MemberAccessCommon member_access = 2;
|
||||
}
|
||||
|
||||
message IrDoWhile {
|
||||
required Loop loop = 1;
|
||||
}
|
||||
|
||||
message IrEnumConstructorCall {
|
||||
required IrSymbol symbol = 1;
|
||||
required MemberAccessCommon member_access = 2;
|
||||
}
|
||||
|
||||
message IrGetClass {
|
||||
required IrExpression argument = 1;
|
||||
}
|
||||
|
||||
message IrGetEnumValue {
|
||||
required IrSymbol symbol = 2;
|
||||
}
|
||||
|
||||
message FieldAccessCommon {
|
||||
required IrSymbol symbol = 1;
|
||||
optional IrSymbol super = 2;
|
||||
optional IrExpression receiver = 3;
|
||||
}
|
||||
|
||||
message IrGetField {
|
||||
required FieldAccessCommon field_access = 1;
|
||||
}
|
||||
|
||||
message IrGetValue {
|
||||
required IrSymbol symbol = 1;
|
||||
}
|
||||
|
||||
message IrGetObject {
|
||||
required IrSymbol symbol = 1;
|
||||
}
|
||||
|
||||
message IrInstanceInitializerCall {
|
||||
required IrSymbol symbol = 1;
|
||||
}
|
||||
|
||||
message Loop {
|
||||
required int32 loop_id = 1;
|
||||
required IrExpression condition = 2;
|
||||
optional string label = 3;
|
||||
optional IrExpression body = 4;
|
||||
}
|
||||
|
||||
message IrReturn {
|
||||
required IrSymbol return_target = 1;
|
||||
required IrExpression value = 2;
|
||||
}
|
||||
|
||||
message IrSetField {
|
||||
required FieldAccessCommon field_access = 1;
|
||||
required IrExpression value = 2;
|
||||
}
|
||||
|
||||
message IrSetVariable {
|
||||
required IrSymbol symbol = 1;
|
||||
required IrExpression value = 2;
|
||||
}
|
||||
|
||||
message IrSpreadElement {
|
||||
required IrExpression expression = 1;
|
||||
required Coordinates coordinates = 2;
|
||||
}
|
||||
|
||||
message IrStringConcat {
|
||||
repeated IrExpression argument = 1;
|
||||
}
|
||||
|
||||
message IrThrow {
|
||||
required IrExpression value = 1;
|
||||
}
|
||||
|
||||
message IrTry {
|
||||
required IrExpression result = 1;
|
||||
repeated IrStatement catch = 2;
|
||||
optional IrExpression finally = 3;
|
||||
}
|
||||
|
||||
message IrTypeOp {
|
||||
required IrTypeOperator operator = 1;
|
||||
required IrTypeIndex operand = 2;
|
||||
required IrExpression argument = 3;
|
||||
}
|
||||
|
||||
message IrVararg {
|
||||
required IrTypeIndex element_type = 1;
|
||||
repeated IrVarargElement element = 2;
|
||||
}
|
||||
|
||||
message IrVarargElement {
|
||||
oneof vararg_element {
|
||||
IrExpression expression = 1;
|
||||
IrSpreadElement spread_element = 2;
|
||||
}
|
||||
}
|
||||
|
||||
message IrWhen {
|
||||
repeated IrStatement branch = 1;
|
||||
}
|
||||
|
||||
message IrWhile {
|
||||
required Loop loop = 1;
|
||||
}
|
||||
|
||||
// TODO: we need an extension mechanism to accomodate new
|
||||
// IR operators in upcoming releases.
|
||||
message IrOperation {
|
||||
oneof operation {
|
||||
IrBlock block = 1;
|
||||
IrBreak break = 2;
|
||||
IrCall call = 3;
|
||||
IrClassReference class_reference = 4;
|
||||
IrComposite composite = 5;
|
||||
IrConst const = 6;
|
||||
IrContinue continue = 7;
|
||||
IrDelegatingConstructorCall delegating_constructor_call = 8;
|
||||
IrDoWhile do_while = 9;
|
||||
IrEnumConstructorCall enum_constructor_call = 10;
|
||||
IrFunctionReference function_reference = 11;
|
||||
IrGetClass get_class = 12;
|
||||
IrGetEnumValue get_enum_value = 13;
|
||||
IrGetField get_field = 14;
|
||||
IrGetObject get_object = 15;
|
||||
IrGetValue get_value = 16;
|
||||
IrInstanceInitializerCall instance_initializer_call = 17;
|
||||
IrPropertyReference property_reference = 18;
|
||||
IrReturn return = 19;
|
||||
IrSetField set_field = 20;
|
||||
IrSetVariable set_variable = 21;
|
||||
IrStringConcat string_concat = 22;
|
||||
IrThrow throw = 23;
|
||||
IrTry try = 24;
|
||||
IrTypeOp type_op = 25;
|
||||
IrVararg vararg = 26;
|
||||
IrWhen when = 27;
|
||||
IrWhile while = 28;
|
||||
}
|
||||
}
|
||||
|
||||
enum IrTypeOperator {
|
||||
CAST = 1;
|
||||
IMPLICIT_CAST = 2;
|
||||
IMPLICIT_NOTNULL = 3;
|
||||
IMPLICIT_COERCION_TO_UNIT = 4;
|
||||
IMPLICIT_INTEGER_COERCION = 5;
|
||||
SAFE_CAST = 6;
|
||||
INSTANCEOF = 7;
|
||||
NOT_INSTANCEOF = 8;
|
||||
SAM_CONVERSION = 9;
|
||||
}
|
||||
|
||||
|
||||
message IrExpression {
|
||||
required IrOperation operation = 1;
|
||||
required IrTypeIndex type = 2;
|
||||
required Coordinates coordinates = 3;
|
||||
}
|
||||
|
||||
message NullableIrExpression {
|
||||
optional IrExpression expression = 1;
|
||||
}
|
||||
|
||||
/* ------ Declarations --------------------------------------------- */
|
||||
|
||||
message IrTypeAlias {
|
||||
// Nothing for now.
|
||||
}
|
||||
|
||||
message IrFunction {
|
||||
required IrSymbol symbol = 1;
|
||||
required IrFunctionBase base = 2;
|
||||
required ModalityKind modality = 3;
|
||||
required bool is_tailrec = 4;
|
||||
required bool is_suspend = 5;
|
||||
repeated IrSymbol overridden = 6;
|
||||
//optional UniqId corresponding_property = 7;
|
||||
}
|
||||
|
||||
message IrFunctionBase {
|
||||
required string name = 1;
|
||||
required string visibility = 2;
|
||||
required bool is_inline = 3;
|
||||
required bool is_external = 4;
|
||||
required IrTypeParameterContainer type_parameters = 5;
|
||||
optional IrDeclaration dispatch_receiver = 6;
|
||||
optional IrDeclaration extension_receiver = 7;
|
||||
repeated IrDeclaration value_parameter = 8;
|
||||
optional IrStatement body = 9;
|
||||
required IrTypeIndex return_type = 10;
|
||||
}
|
||||
|
||||
message IrConstructor {
|
||||
required IrSymbol symbol = 1;
|
||||
required IrFunctionBase base = 2;
|
||||
required bool is_primary = 3;
|
||||
|
||||
}
|
||||
|
||||
message IrField {
|
||||
required IrSymbol symbol = 1;
|
||||
optional IrExpression initializer = 2;
|
||||
required string name = 3;
|
||||
required string visibility = 4;
|
||||
required bool is_final = 5;
|
||||
required bool is_external = 6;
|
||||
required bool is_static = 7;
|
||||
required IrTypeIndex type = 8;
|
||||
}
|
||||
|
||||
message IrProperty {
|
||||
optional DescriptorReference descriptor = 1; // IrProperty doesn't have a symbol at all. Preserve this rudiment for now.
|
||||
required string name = 2;
|
||||
required string visibility = 3;
|
||||
required ModalityKind modality = 4;
|
||||
required bool is_var = 5;
|
||||
required bool is_const = 6;
|
||||
required bool is_lateinit = 7;
|
||||
required bool is_delegated = 8;
|
||||
required bool is_external = 9;
|
||||
optional IrField backing_field = 10;
|
||||
optional IrFunction getter = 11;
|
||||
optional IrFunction setter = 12;
|
||||
}
|
||||
|
||||
message IrVariable {
|
||||
required string name = 1;
|
||||
required IrSymbol symbol = 2;
|
||||
required IrTypeIndex type = 3;
|
||||
required bool is_var = 4;
|
||||
required bool is_const = 5;
|
||||
required bool is_lateinit = 6;
|
||||
optional IrExpression initializer = 7;
|
||||
}
|
||||
|
||||
enum ClassKind {
|
||||
CLASS = 1;
|
||||
INTERFACE = 2;
|
||||
ENUM_CLASS = 3;
|
||||
ENUM_ENTRY = 4;
|
||||
ANNOTATION_CLASS = 5;
|
||||
OBJECT = 6;
|
||||
}
|
||||
|
||||
enum ModalityKind { // It is ModalityKind to not clash with Modality in descriptor metadata.
|
||||
FINAL_MODALITY = 1;
|
||||
SEALED_MODALITY = 2;
|
||||
OPEN_MODALITY = 3;
|
||||
ABSTRACT_MODALITY = 4;
|
||||
}
|
||||
|
||||
message IrValueParameter {
|
||||
required IrSymbol symbol = 1;
|
||||
required string name = 2;
|
||||
required int32 index = 3;
|
||||
required IrTypeIndex type = 4;
|
||||
optional IrTypeIndex vararg_element_type = 5;
|
||||
required bool is_crossinline = 6;
|
||||
required bool is_noinline = 7;
|
||||
optional IrExpression default_value = 8;
|
||||
}
|
||||
|
||||
message IrTypeParameter {
|
||||
required IrSymbol symbol = 1;
|
||||
required string name = 2;
|
||||
required int32 index = 3;
|
||||
required IrTypeVariance variance = 4;
|
||||
repeated IrTypeIndex super_type = 5;
|
||||
required bool is_reified = 6;
|
||||
}
|
||||
|
||||
message IrTypeParameterContainer {
|
||||
repeated IrDeclaration type_parameter = 1;
|
||||
}
|
||||
|
||||
message IrClass {
|
||||
required IrSymbol symbol = 1;
|
||||
required string name = 2;
|
||||
required ClassKind kind = 3;
|
||||
required string visibility = 4;
|
||||
required ModalityKind modality = 5;
|
||||
// TODO: consider using flags for the booleans.
|
||||
required bool is_companion = 6;
|
||||
required bool is_inner = 7;
|
||||
required bool is_data = 8;
|
||||
required bool is_external = 9;
|
||||
required bool is_inline = 10;
|
||||
optional IrDeclaration this_receiver = 11;
|
||||
required IrTypeParameterContainer type_parameters = 12;
|
||||
required IrDeclarationContainer declaration_container = 13;
|
||||
repeated IrTypeIndex super_type = 14;
|
||||
}
|
||||
|
||||
message IrEnumEntry {
|
||||
required IrSymbol symbol = 1;
|
||||
optional IrExpression initializer = 2;
|
||||
optional IrDeclaration corresponding_class = 3;
|
||||
required string name = 4;
|
||||
}
|
||||
|
||||
message IrAnonymousInit {
|
||||
required IrSymbol symbol = 1;
|
||||
required IrStatement body = 2;
|
||||
}
|
||||
|
||||
// TODO: we need an extension mechanism to accomodate new
|
||||
// IR operators in upcoming releases.
|
||||
message IrDeclarator {
|
||||
oneof declarator {
|
||||
IrAnonymousInit ir_anonymous_init = 1;
|
||||
IrClass ir_class = 2;
|
||||
IrConstructor ir_constructor = 3;
|
||||
IrEnumEntry ir_enum_entry = 4;
|
||||
IrField ir_field = 5;
|
||||
IrFunction ir_function = 6;
|
||||
IrProperty ir_property = 7;
|
||||
IrTypeAlias ir_type_alias = 8;
|
||||
IrTypeParameter ir_type_parameter = 9;
|
||||
IrVariable ir_variable = 10;
|
||||
IrValueParameter ir_value_parameter = 11;
|
||||
}
|
||||
}
|
||||
|
||||
message IrDeclarationOrigin {
|
||||
required string name = 1;
|
||||
}
|
||||
|
||||
message IrDeclaration {
|
||||
required IrDeclarationOrigin origin = 1;
|
||||
required Coordinates coordinates = 2;
|
||||
required Annotations annotations = 3;
|
||||
required IrDeclarator declarator = 4;
|
||||
//repeated IrDeclaration nested = 5;
|
||||
required string file_name = 5; // TODO: files should be communicated some other way, I suppose.
|
||||
}
|
||||
|
||||
/* ------- IrStatements --------------------------------------------- */
|
||||
|
||||
message IrBranch {
|
||||
required IrExpression condition = 1;
|
||||
required IrExpression result = 2;
|
||||
}
|
||||
|
||||
message IrBlockBody {
|
||||
repeated IrStatement statement = 1;
|
||||
}
|
||||
|
||||
message IrCatch {
|
||||
required IrDeclaration catch_parameter = 1;
|
||||
required IrExpression result = 2;
|
||||
}
|
||||
|
||||
enum IrSyntheticBodyKind {
|
||||
ENUM_VALUES = 1;
|
||||
ENUM_VALUEOF = 2;
|
||||
}
|
||||
|
||||
message IrSyntheticBody {
|
||||
required IrSyntheticBodyKind kind = 1;
|
||||
}
|
||||
|
||||
// Let's try to map IrElement as well as IrStatement to IrStatement.
|
||||
message IrStatement {
|
||||
required Coordinates coordinates = 1;
|
||||
oneof statement {
|
||||
IrDeclaration declaration = 2;
|
||||
IrExpression expression = 3;
|
||||
IrBlockBody block_body = 4;
|
||||
IrBranch branch = 5;
|
||||
IrCatch catch = 6;
|
||||
IrSyntheticBody synthetic_body = 7;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -64,7 +64,7 @@ fun createJsKlibMetadataPackageFragmentProvider(
|
||||
emptyList(),
|
||||
notFoundClasses,
|
||||
ContractDeserializerImpl(configuration, storageManager),
|
||||
platformDependentDeclarationFilter = PlatformDependentDeclarationFilter.NoPlatformDependent,
|
||||
platformDependentDeclarationFilter = PlatformDependentDeclarationFilter.All,
|
||||
extensionRegistryLite = JsKlibMetadataSerializerProtocol.extensionRegistry
|
||||
)
|
||||
|
||||
|
||||
+2
-1
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ir.isElseBranch
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.coroutines.COROUTINE_SWITCH
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
|
||||
@@ -99,7 +100,7 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
|
||||
var expr: IrExpression? = null
|
||||
val cases = expression.branches.map {
|
||||
val body = it.result
|
||||
val id = if (it is IrElseBranch) null else {
|
||||
val id = if (isElseBranch(it)) null else {
|
||||
val call = it.condition as IrCall
|
||||
expr = call.getValueArgument(0) as IrExpression
|
||||
call.getValueArgument(1)
|
||||
|
||||
+4
-2
@@ -102,8 +102,10 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
||||
private fun generateThrowableProperties(): List<JsStatement> {
|
||||
val functions = irClass.declarations.filterIsInstance<IrSimpleFunction>()
|
||||
|
||||
val messageGetter = functions.single { it.name == Name.special("<get-message>") }
|
||||
val causeGetter = functions.single { it.name == Name.special("<get-cause>") }
|
||||
|
||||
// TODO: Fix `Name.special` deserialization
|
||||
val messageGetter = functions.single { it.name.asString() == "<get-message>" }
|
||||
val causeGetter = functions.single { it.name.asString() == "<get-cause>" }
|
||||
|
||||
val msgProperty = defineProperty(classPrototypeRef, "message", getter = buildGetterFunction(messageGetter))
|
||||
|
||||
|
||||
+2
-1
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.isSuspend
|
||||
import org.jetbrains.kotlin.backend.common.ir.isElseBranch
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
@@ -24,7 +25,7 @@ fun <T : JsNode, D : JsGenerationContext> IrWhen.toJsNode(
|
||||
): T? =
|
||||
branches.foldRight<IrBranch, T?>(null) { br, n ->
|
||||
val body = br.result.accept(tr, data)
|
||||
if (br is IrElseBranch) body
|
||||
if (isElseBranch(br)) body
|
||||
else {
|
||||
val condition = br.condition.accept(IrElementToJsExpressionTransformer(), data)
|
||||
node(condition, body, n)
|
||||
|
||||
@@ -99,4 +99,6 @@ object Namer {
|
||||
|
||||
val THIS_SPECIAL_NAME = "<this>"
|
||||
val SET_SPECIAL_NAME = "<set-?>"
|
||||
|
||||
val DYNAMIC_FILE_NAME = "<dynamicDeclarations>"
|
||||
}
|
||||
+1
@@ -64,6 +64,7 @@ abstract class IrLazyDeclarationBase(
|
||||
}
|
||||
is ClassDescriptor -> stubGenerator.generateClassStub(containingDeclaration)
|
||||
is FunctionDescriptor -> stubGenerator.generateFunctionStub(containingDeclaration)
|
||||
is PropertyDescriptor -> stubGenerator.generateFunctionStub(containingDeclaration.run { getter ?: setter!! })
|
||||
else -> throw AssertionError("Package or class expected: $containingDeclaration; for $currentDescriptor")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,12 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationOrigin
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrSimpleTypeImpl
|
||||
import org.jetbrains.kotlin.ir.types.withHasQuestionMark
|
||||
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
|
||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||
@@ -72,68 +78,97 @@ class IrBuiltIns(
|
||||
private fun List<SimpleType>.defineComparisonOperatorForEachType(name: String) =
|
||||
associate { it to defineComparisonOperator(name, it) }
|
||||
|
||||
private class IrTypeMapper(val type: () -> IrType, val nType: () -> IrType)
|
||||
|
||||
private fun buildNullableType(irType: IrType) = with(irType as IrSimpleType) {
|
||||
IrSimpleTypeImpl(classifier, true, arguments, annotations)
|
||||
}
|
||||
|
||||
private val primitiveTypesLazyMapping = mapOf<ClassifierDescriptor, IrTypeMapper>(
|
||||
builtIns.any to IrTypeMapper({ anyType }, { anyNType }),
|
||||
builtIns.boolean to IrTypeMapper({ booleanType }, { buildNullableType(booleanType) }),
|
||||
builtIns.char to IrTypeMapper({ charType }, { buildNullableType(charType) }),
|
||||
builtIns.number to IrTypeMapper({ numberType }, { buildNullableType(numberType) }),
|
||||
builtIns.byte to IrTypeMapper({ byteType }, { buildNullableType(byteType) }),
|
||||
builtIns.short to IrTypeMapper({ shortType }, { buildNullableType(shortType) }),
|
||||
builtIns.int to IrTypeMapper({ intType }, { buildNullableType(intType) }),
|
||||
builtIns.long to IrTypeMapper({ longType }, { buildNullableType(longType) }),
|
||||
builtIns.float to IrTypeMapper({ floatType }, { buildNullableType(floatType) }),
|
||||
builtIns.double to IrTypeMapper({ doubleType }, { buildNullableType(doubleType) }),
|
||||
builtIns.nothing to IrTypeMapper({ nothingType }, { nothingNType }),
|
||||
builtIns.unit to IrTypeMapper({ unitType }, { buildNullableType(unitType) }),
|
||||
builtIns.string to IrTypeMapper({ stringType }, { buildNullableType(stringType) }),
|
||||
builtIns.throwable to IrTypeMapper({ throwableType }, { buildNullableType(throwableType) })
|
||||
// builtIns.array to { arrayClass.owner.defaultType }
|
||||
)
|
||||
|
||||
fun getPrimitiveTypeOrNullByDescriptor(descriptor: ClassifierDescriptor, isNullable: Boolean) =
|
||||
primitiveTypesLazyMapping[descriptor]?.let {
|
||||
if (isNullable) it.nType() else it.type()
|
||||
} as IrSimpleType?
|
||||
|
||||
val any = builtIns.anyType
|
||||
val anyN = builtIns.nullableAnyType
|
||||
val anyType = any.toIrType()
|
||||
val anyClass = builtIns.any.toIrSymbol()
|
||||
val anyNType = anyType.withHasQuestionMark(true)
|
||||
val anyType by lazy { any.toIrType() }
|
||||
val anyClass by lazy { builtIns.any.toIrSymbol() }
|
||||
val anyNType by lazy { anyType.withHasQuestionMark(true) }
|
||||
|
||||
val bool = builtIns.booleanType
|
||||
val booleanType = bool.toIrType()
|
||||
val booleanClass = builtIns.boolean.toIrSymbol()
|
||||
val booleanType by lazy { bool.toIrType() }
|
||||
val booleanClass by lazy { builtIns.boolean.toIrSymbol() }
|
||||
|
||||
val char = builtIns.charType
|
||||
val charType = char.toIrType()
|
||||
val charClass = builtIns.char.toIrSymbol()
|
||||
val charType by lazy { char.toIrType() }
|
||||
val charClass by lazy { builtIns.char.toIrSymbol() }
|
||||
|
||||
val number = builtIns.number.defaultType
|
||||
val numberType = number.toIrType()
|
||||
val numberClass = builtIns.number.toIrSymbol()
|
||||
val numberType by lazy { number.toIrType() }
|
||||
val numberClass by lazy { builtIns.number.toIrSymbol() }
|
||||
|
||||
val byte = builtIns.byteType
|
||||
val byteType = byte.toIrType()
|
||||
val byteClass = builtIns.byte.toIrSymbol()
|
||||
val byteType by lazy { byte.toIrType() }
|
||||
val byteClass by lazy { builtIns.byte.toIrSymbol() }
|
||||
|
||||
val short = builtIns.shortType
|
||||
val shortType = short.toIrType()
|
||||
val shortClass = builtIns.short.toIrSymbol()
|
||||
val shortType by lazy { short.toIrType() }
|
||||
val shortClass by lazy { builtIns.short.toIrSymbol() }
|
||||
|
||||
val int = builtIns.intType
|
||||
val intType = int.toIrType()
|
||||
val intClass = builtIns.int.toIrSymbol()
|
||||
val intType by lazy { int.toIrType() }
|
||||
val intClass by lazy { builtIns.int.toIrSymbol() }
|
||||
|
||||
val long = builtIns.longType
|
||||
val longType = long.toIrType()
|
||||
val longClass = builtIns.long.toIrSymbol()
|
||||
val longType by lazy { long.toIrType() }
|
||||
val longClass by lazy { builtIns.long.toIrSymbol() }
|
||||
|
||||
val float = builtIns.floatType
|
||||
val floatType = float.toIrType()
|
||||
val floatClass = builtIns.float.toIrSymbol()
|
||||
val floatType by lazy { float.toIrType() }
|
||||
val floatClass by lazy { builtIns.float.toIrSymbol() }
|
||||
|
||||
val double = builtIns.doubleType
|
||||
val doubleType = double.toIrType()
|
||||
val doubleClass = builtIns.double.toIrSymbol()
|
||||
val doubleType by lazy { double.toIrType() }
|
||||
val doubleClass by lazy { builtIns.double.toIrSymbol() }
|
||||
|
||||
val nothing = builtIns.nothingType
|
||||
val nothingN = builtIns.nullableNothingType
|
||||
val nothingType = nothing.toIrType()
|
||||
val nothingClass = builtIns.nothing.toIrSymbol()
|
||||
val nothingNType = nothingType.withHasQuestionMark(true)
|
||||
val nothingType by lazy { nothing.toIrType() }
|
||||
val nothingClass by lazy { builtIns.nothing.toIrSymbol() }
|
||||
val nothingNType by lazy { nothingType.withHasQuestionMark(true) }
|
||||
|
||||
val unit = builtIns.unitType
|
||||
val unitType = unit.toIrType()
|
||||
val unitClass = builtIns.unit.toIrSymbol()
|
||||
val unitType by lazy { unit.toIrType() }
|
||||
val unitClass by lazy { builtIns.unit.toIrSymbol() }
|
||||
|
||||
val string = builtIns.stringType
|
||||
val stringType = string.toIrType()
|
||||
val stringClass = builtIns.string.toIrSymbol()
|
||||
val stringType by lazy { string.toIrType() }
|
||||
val stringClass by lazy { builtIns.string.toIrSymbol() }
|
||||
|
||||
val collectionClass = builtIns.collection.toIrSymbol()
|
||||
val collectionClass by lazy { builtIns.collection.toIrSymbol() }
|
||||
|
||||
val arrayClass = builtIns.array.toIrSymbol()
|
||||
val arrayClass by lazy { builtIns.array.toIrSymbol() }
|
||||
|
||||
val throwableType = builtIns.throwable.defaultType.toIrType()
|
||||
val throwableClass = builtIns.throwable.toIrSymbol()
|
||||
val throwableType by lazy { builtIns.throwable.defaultType.toIrType() }
|
||||
val throwableClass by lazy { builtIns.throwable.toIrSymbol() }
|
||||
|
||||
val kCallableClass = builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.kCallable.toSafe()).toIrSymbol()
|
||||
val kPropertyClass = builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.kPropertyFqName.toSafe()).toIrSymbol()
|
||||
|
||||
@@ -5,9 +5,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.ir.types
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||
@@ -68,6 +70,8 @@ fun IrType.makeNullable(addKotlinType:Boolean = true) =
|
||||
else
|
||||
this
|
||||
|
||||
var irTypeKotlinBuiltIns: KotlinBuiltIns? = null
|
||||
|
||||
fun IrType.toKotlinType(): KotlinType {
|
||||
originalKotlinType?.let {
|
||||
return it
|
||||
@@ -75,6 +79,7 @@ fun IrType.toKotlinType(): KotlinType {
|
||||
|
||||
return when (this) {
|
||||
is IrSimpleType -> makeKotlinType(classifier, arguments, hasQuestionMark)
|
||||
is IrDynamicType -> createDynamicType(irTypeKotlinBuiltIns!!)
|
||||
else -> TODO(toString())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,16 +21,21 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFunctionImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrPropertyImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||
import org.jetbrains.kotlin.ir.declarations.lazy.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrValueParameterSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.impl.IrDynamicTypeImpl
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.hasBackingField
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.isDynamic
|
||||
|
||||
class DeclarationStubGenerator(
|
||||
moduleDescriptor: ModuleDescriptor,
|
||||
|
||||
@@ -58,7 +58,8 @@ val PROTO_PATHS: List<ProtoPath> = listOf(
|
||||
ProtoPath("core/metadata.jvm/src/jvm_metadata.proto"),
|
||||
ProtoPath("core/metadata.jvm/src/jvm_module.proto"),
|
||||
ProtoPath("build-common/src/java_descriptors.proto"),
|
||||
ProtoPath("compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/metadata/js.proto")
|
||||
// ProtoPath("compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/metadata/js.proto"),
|
||||
ProtoPath("compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/serialization/ir/ir.proto")
|
||||
)
|
||||
|
||||
private val EXT_OPTIONS_PROTO_PATH = ProtoPath("core/metadata/src/ext_options.proto")
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.ir.backend.js.compile
|
||||
import org.jetbrains.kotlin.js.test.JsIrTestRuntime
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||
import java.io.File
|
||||
|
||||
fun buildConfiguration(environment: KotlinCoreEnvironment): CompilerConfiguration {
|
||||
@@ -38,6 +39,8 @@ fun buildConfiguration(environment: KotlinCoreEnvironment): CompilerConfiguratio
|
||||
|
||||
private val stdKlibFile = File("js/js.translator/testData/out/klibs/stdlib.klib")
|
||||
|
||||
private val resultJs = "js/js.translator/testData/out/klibs/result.js"
|
||||
|
||||
fun main() {
|
||||
|
||||
val environment = KotlinCoreEnvironment.createForTests(Disposable { }, CompilerConfiguration(), EnvironmentConfigFiles.JS_CONFIG_FILES)
|
||||
@@ -53,7 +56,7 @@ fun main() {
|
||||
|
||||
val result = compile(
|
||||
environment.project,
|
||||
JsIrTestRuntime.FULL.sources.map(::createPsiFile),
|
||||
(JsIrTestRuntime.FULL.sources).map(::createPsiFile),
|
||||
buildConfiguration(environment),
|
||||
null,
|
||||
true,
|
||||
@@ -61,5 +64,7 @@ fun main() {
|
||||
emptyList()
|
||||
)
|
||||
|
||||
TODO("Write library into $stdKlibFile")
|
||||
File(resultJs).writeText(result.generatedCode)
|
||||
|
||||
// TODO("Write library into $stdKlibFile")
|
||||
}
|
||||
Reference in New Issue
Block a user