[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 {
|
private val _typeConstructor: TypeConstructor by lazy {
|
||||||
LazyTypeConstructor(
|
LazyTypeConstructor(
|
||||||
this,
|
this,
|
||||||
{ emptyList() },
|
{ declaredTypeParameters },
|
||||||
{ owner.superTypes.map { it.toKotlinType() } },
|
{ owner.superTypes.map { it.toKotlinType() } },
|
||||||
LockBasedStorageManager.NO_LOCKS
|
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.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionReference
|
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.IrBlockBodyImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||||
@@ -386,6 +387,8 @@ fun IrClass.createImplicitParameterDeclarationWithWrappedDescriptor() {
|
|||||||
assert(descriptor.declaredTypeParameters.isEmpty())
|
assert(descriptor.declaredTypeParameters.isEmpty())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isElseBranch(branch: IrBranch) = branch is IrElseBranch || ((branch.condition as? IrConst<Boolean>)?.value == true)
|
||||||
|
|
||||||
fun IrSimpleFunction.isMethodOfAny() =
|
fun IrSimpleFunction.isMethodOfAny() =
|
||||||
((valueParameters.size == 0 && name.asString().let { it == "hashCode" || it == "toString" }) ||
|
((valueParameters.size == 0 && name.asString().let { it == "hashCode" || it == "toString" }) ||
|
||||||
(valueParameters.size == 1 && name.asString() == "equals" && valueParameters[0].type.isNullableAny()))
|
(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.IrSimpleType
|
||||||
import org.jetbrains.kotlin.ir.types.IrType
|
import org.jetbrains.kotlin.ir.types.IrType
|
||||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
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.util.defaultType
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
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}" }
|
assert(++numberOfCalls == 1) { "More than one delegating constructor call: ${symbol.owner}" }
|
||||||
val delegatingClass = expression.symbol.owner.parent as IrClass
|
val delegatingClass = expression.symbol.owner.parent as IrClass
|
||||||
// TODO: figure out why Lazy IR multiplies Declarations for descriptors and fix it
|
// 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
|
callsSuper = true
|
||||||
else if (delegatingClass.descriptor != constructedClass.descriptor)
|
else if (delegatingClass.descriptor != constructedClass.descriptor)
|
||||||
throw AssertionError(
|
throw AssertionError(
|
||||||
|
|||||||
@@ -6,42 +6,42 @@
|
|||||||
package org.jetbrains.kotlin.ir.backend.js
|
package org.jetbrains.kotlin.ir.backend.js
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project
|
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.CompilerPhaseManager
|
||||||
import org.jetbrains.kotlin.backend.common.output.OutputFile
|
import org.jetbrains.kotlin.backend.common.LoggingContext
|
||||||
import org.jetbrains.kotlin.backend.common.output.OutputFileCollection
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.backend.common.output.SimpleOutputBinaryFile
|
import org.jetbrains.kotlin.builtins.functions.functionInterfacePackageFragmentProvider
|
||||||
import org.jetbrains.kotlin.backend.common.output.SimpleOutputFileCollection
|
|
||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
|
import org.jetbrains.kotlin.backend.common.phaser.invokeToplevel
|
||||||
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
||||||
import org.jetbrains.kotlin.config.CompilerConfiguration
|
import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
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.descriptors.impl.ModuleDescriptorImpl
|
||||||
import org.jetbrains.kotlin.incremental.components.LookupTracker
|
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.serialization.metadata.*
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.coroutines.CoroutineIntrinsicLowering
|
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.backend.js.transformers.irToJs.IrModuleToJsTransformer
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
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.SymbolTable
|
||||||
|
import org.jetbrains.kotlin.ir.util.TypeTranslator
|
||||||
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
||||||
import org.jetbrains.kotlin.js.analyze.TopDownAnalyzerFacadeForJS
|
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.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStatus
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
|
import org.jetbrains.kotlin.psi2ir.Psi2IrTranslator
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
|
||||||
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
|
import org.jetbrains.kotlin.resolve.CompilerDeserializationConfiguration
|
||||||
import org.jetbrains.kotlin.serialization.js.JsSerializerProtocol
|
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager
|
||||||
import org.jetbrains.kotlin.utils.JsMetadataVersion
|
|
||||||
import org.jetbrains.kotlin.utils.KotlinJavascriptMetadataUtils
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import org.jetbrains.kotlin.utils.DFS
|
import org.jetbrains.kotlin.utils.DFS
|
||||||
|
|
||||||
|
data class Result(val moduleDescriptor: ModuleDescriptor, val generatedCode: String, val moduleFragment: IrModuleFragment?)
|
||||||
enum class ModuleType {
|
enum class ModuleType {
|
||||||
TEST_RUNTIME,
|
TEST_RUNTIME,
|
||||||
SECONDARY,
|
SECONDARY,
|
||||||
@@ -59,13 +59,6 @@ class CompiledModule(
|
|||||||
get() = moduleFragment!!.descriptor as ModuleDescriptorImpl
|
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(
|
fun compile(
|
||||||
project: Project,
|
project: Project,
|
||||||
files: List<KtFile>,
|
files: List<KtFile>,
|
||||||
@@ -92,7 +85,7 @@ fun compile(
|
|||||||
TopDownAnalyzerFacadeForJS.checkForErrors(files, analysisResult.bindingContext)
|
TopDownAnalyzerFacadeForJS.checkForErrors(files, analysisResult.bindingContext)
|
||||||
|
|
||||||
val symbolTable = SymbolTable()
|
val symbolTable = SymbolTable()
|
||||||
dependencies.forEach { symbolTable.loadModule(it.moduleFragment!!) }
|
// irDependencyModules.forEach { symbolTable.loadModule(it) }
|
||||||
|
|
||||||
val psi2IrTranslator = Psi2IrTranslator(configuration.languageVersionSettings)
|
val psi2IrTranslator = Psi2IrTranslator(configuration.languageVersionSettings)
|
||||||
val psi2IrContext = psi2IrTranslator.createGeneratorContext(analysisResult.moduleDescriptor, analysisResult.bindingContext, symbolTable)
|
val psi2IrContext = psi2IrTranslator.createGeneratorContext(analysisResult.moduleDescriptor, analysisResult.bindingContext, symbolTable)
|
||||||
@@ -111,82 +104,103 @@ fun compile(
|
|||||||
|
|
||||||
|
|
||||||
if (isKlibCompilation) {
|
if (isKlibCompilation) {
|
||||||
// val declarationTable = DeclarationTable(moduleFragment.irBuiltins, DescriptorTable())
|
val logggg = object : LoggingContext {
|
||||||
// val serializedIr = IrModuleSerializer(context, declarationTable/*, onlyForInlines = false*/).serializedIrModule(moduleFragment)
|
override fun log(message: () -> String) {}
|
||||||
// val serializer = KonanSerializationUtil(context, configuration.get(CommonConfigurationKeys.METADATA_VERSION)!!, declarationTable)
|
}
|
||||||
// val serializedData = serializer.serializeModule(analysisResult.moduleDescriptor, serializedIr)
|
|
||||||
// buildLibrary(serializedData)
|
|
||||||
//
|
|
||||||
|
|
||||||
// val declarationTable = DeclarationTable(moduleFragment.irBuiltins, DescriptorTable())
|
val declarationTable = DeclarationTable(moduleFragment.irBuiltins, DescriptorTable(), psi2IrContext.symbolTable)
|
||||||
// val serializedIr = IrModuleSerializer(context, declarationTable/*, onlyForInlines = false*/).serializedIrModule(moduleFragment)
|
|
||||||
|
val serializedIr = IrModuleSerializer(logggg, declarationTable/*, onlyForInlines = false*/).serializedIrModule(moduleFragment)
|
||||||
val serializer = JsKlibMetadataSerializationUtil
|
val serializer = JsKlibMetadataSerializationUtil
|
||||||
// val serializedData = serializer.serializeModule(analysisResult.moduleDescriptor, serializedIr)
|
|
||||||
val moduleName = configuration.get(CommonConfigurationKeys.MODULE_NAME) as String
|
val moduleName = configuration.get(CommonConfigurationKeys.MODULE_NAME) as String
|
||||||
val metadataVersion = configuration.get(CommonConfigurationKeys.METADATA_VERSION) as? JsKlibMetadataVersion
|
val metadataVersion = configuration.get(CommonConfigurationKeys.METADATA_VERSION) as? JsKlibMetadataVersion
|
||||||
?: JsKlibMetadataVersion.INSTANCE
|
?: JsKlibMetadataVersion.INSTANCE
|
||||||
val moduleDescription =
|
val moduleDescription =
|
||||||
JsKlibMetadataModuleDescriptor(moduleName, dependencies.map { it.name.asString() }, moduleFragment.descriptor)
|
JsKlibMetadataModuleDescriptor(moduleName, dependencies.map { it.name.asString() }, moduleFragment.descriptor)
|
||||||
var index = 0L
|
|
||||||
val serializedData = serializer.serializeMetadata(
|
val serializedData = serializer.serializeMetadata(
|
||||||
psi2IrContext.bindingContext,
|
psi2IrContext.bindingContext,
|
||||||
moduleDescription,
|
moduleDescription,
|
||||||
configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS)!!,
|
configuration.get(CommonConfigurationKeys.LANGUAGE_VERSION_SETTINGS)!!,
|
||||||
metadataVersion
|
metadataVersion
|
||||||
) {
|
) { declarationDescriptor ->
|
||||||
// val index = declarationTable.descriptorTable.get(it)
|
val index = declarationTable.descriptorTable.get(declarationDescriptor)
|
||||||
// index?.let { newDescriptorUniqId(it) }
|
index?.let { newDescriptorUniqId(it) }
|
||||||
JsKlibMetadataProtoBuf.DescriptorUniqId.newBuilder().setIndex(index++).build()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
// buildLibrary(serializedData)
|
|
||||||
//
|
|
||||||
|
|
||||||
val stdKlibDir = File("js/js.translator/testData/out/klibs/runtime/").also {
|
val stdKlibDir = File("js/js.translator/testData/out/klibs/runtime/").also {
|
||||||
it.deleteRecursively()
|
it.deleteRecursively()
|
||||||
it.mkdirs()
|
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())
|
it.writeBytes(serializedData.asByteArray())
|
||||||
}
|
}
|
||||||
|
|
||||||
val storageManager = LockBasedStorageManager("JsConfig")
|
val storageManager = LockBasedStorageManager("JsConfig")
|
||||||
// // CREATE NEW MODULE DESCRIPTOR HERE AND DESERIALIZE IT
|
|
||||||
|
|
||||||
val lookupTracker = configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER, LookupTracker.DO_NOTHING)
|
val lookupTracker = configuration.get(CommonConfigurationKeys.LOOKUP_TRACKER, LookupTracker.DO_NOTHING)
|
||||||
val parts = serializer.readModuleAsProto(metadata.readBytes())
|
val parts = serializer.readModuleAsProto(metadata.readBytes())
|
||||||
val md = ModuleDescriptorImpl(
|
val builtIns = object : KotlinBuiltIns(storageManager) {}//analysisResult.moduleDescriptor.builtIns
|
||||||
Name.special("<$moduleName>"), storageManager, JsPlatform.builtIns
|
val md = ModuleDescriptorImpl(Name.special("<$moduleName>"), storageManager, builtIns)
|
||||||
)
|
builtIns.builtInsModule = md
|
||||||
val provider = createJsKlibMetadataPackageFragmentProvider(
|
val packageProviders = listOf(
|
||||||
storageManager, md, parts.header, parts.body, metadataVersion,
|
functionInterfacePackageFragmentProvider(storageManager, md),
|
||||||
CompilerDeserializationConfiguration(configuration.languageVersionSettings),
|
createJsKlibMetadataPackageFragmentProvider(
|
||||||
lookupTracker
|
storageManager, md, parts.header, parts.body, metadataVersion,
|
||||||
|
CompilerDeserializationConfiguration(configuration.languageVersionSettings),
|
||||||
|
lookupTracker
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
md.initialize(provider)
|
md.initialize(CompositePackageFragmentProvider(packageProviders))
|
||||||
md.setDependencies(listOf(md, md.builtIns.builtInsModule))
|
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 {
|
} else {
|
||||||
|
|
||||||
// TODO: Split compilation into two steps: kt -> ir, ir -> js
|
// 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
|
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.DeclarationContainerLoweringPass
|
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.IrElement
|
||||||
import org.jetbrains.kotlin.ir.IrStatement
|
import org.jetbrains.kotlin.ir.IrStatement
|
||||||
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
import org.jetbrains.kotlin.ir.backend.js.JsIrBackendContext
|
||||||
@@ -366,8 +367,8 @@ class BlockDecomposerTransformer(private val context: JsIrBackendContext) : IrEl
|
|||||||
|
|
||||||
if (compositeCount == 0) {
|
if (compositeCount == 0) {
|
||||||
val branches = results.map { (cond, res, orig) ->
|
val branches = results.map { (cond, res, orig) ->
|
||||||
when (orig) {
|
when {
|
||||||
is IrElseBranch -> IrElseBranchImpl(orig.startOffset, orig.endOffset, cond, res)
|
isElseBranch(orig) -> IrElseBranchImpl(orig.startOffset, orig.endOffset, cond, res)
|
||||||
else /* IrBranch */ -> IrBranchImpl(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) }
|
appendBlock.statements += condStatements.run { subList(0, lastIndex) }
|
||||||
|
|
||||||
JsIrBuilder.buildBlock(unitType).also {
|
JsIrBuilder.buildBlock(unitType).also {
|
||||||
val elseBlock = if (orig is IrElseBranch) null else it
|
val elseBlock = if (isElseBranch(orig)) null else it
|
||||||
val ifElseNode =
|
val ifElseNode =
|
||||||
JsIrBuilder.buildIfElse(orig.startOffset, orig.endOffset, unitType, condValue, res, elseBlock, expression.origin)
|
JsIrBuilder.buildIfElse(orig.startOffset, orig.endOffset, unitType, condValue, res, elseBlock, expression.origin)
|
||||||
appendBlock.statements += ifElseNode
|
appendBlock.statements += ifElseNode
|
||||||
@@ -666,9 +667,9 @@ class BlockDecomposerTransformer(private val context: JsIrBackendContext) : IrEl
|
|||||||
|
|
||||||
val newBranches = decomposedResults.map { (branch, condition, result) ->
|
val newBranches = decomposedResults.map { (branch, condition, result) ->
|
||||||
val newResult = wrap(result, irVar)
|
val newResult = wrap(result, irVar)
|
||||||
when (branch) {
|
when {
|
||||||
is IrElseBranch -> IrElseBranchImpl(branch.startOffset, branch.endOffset, condition, newResult)
|
isElseBranch(branch) -> IrElseBranchImpl(branch.startOffset, branch.endOffset, condition, newResult)
|
||||||
else /* IrBranch */ -> IrBranchImpl(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)))
|
return JsIrBuilder.buildComposite(expression.type, listOf(irVar, newWhen, JsIrBuilder.buildGetValue(irVar.symbol)))
|
||||||
} else {
|
} else {
|
||||||
val newBranches = decomposedResults.map { (branch, condition, result) ->
|
val newBranches = decomposedResults.map { (branch, condition, result) ->
|
||||||
when (branch) {
|
when {
|
||||||
is IrElseBranch -> IrElseBranchImpl(branch.startOffset, branch.endOffset, condition, result)
|
isElseBranch(branch) -> IrElseBranchImpl(branch.startOffset, branch.endOffset, condition, result)
|
||||||
else /* IrBranch */ -> IrBranchImpl(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
|
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.ir.isSuspend
|
||||||
import org.jetbrains.kotlin.backend.common.peek
|
import org.jetbrains.kotlin.backend.common.peek
|
||||||
import org.jetbrains.kotlin.backend.common.pop
|
import org.jetbrains.kotlin.backend.common.pop
|
||||||
@@ -351,8 +352,8 @@ class StateMachineBuilder(
|
|||||||
if (it.result in suspendableNodes) {
|
if (it.result in suspendableNodes) {
|
||||||
suspendableNodes += wrapped
|
suspendableNodes += wrapped
|
||||||
}
|
}
|
||||||
when (it) {
|
when {
|
||||||
is IrElseBranch -> IrElseBranchImpl(it.startOffset, it.endOffset, it.condition, wrapped)
|
isElseBranch(it) -> IrElseBranchImpl(it.startOffset, it.endOffset, it.condition, wrapped)
|
||||||
else /* IrBranch */ -> IrBranchImpl(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
|
val rootBlock = currentBlock
|
||||||
|
|
||||||
for (branch in branches) {
|
for (branch in branches) {
|
||||||
if (branch !is IrElseBranch) {
|
if (!isElseBranch(branch)) {
|
||||||
branch.condition.acceptVoid(this)
|
branch.condition.acceptVoid(this)
|
||||||
val branchBlock = JsIrBuilder.buildComposite(branch.result.type)
|
val branchBlock = JsIrBuilder.buildComposite(branch.result.type)
|
||||||
val elseBlock = JsIrBuilder.buildComposite(expression.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.IrReturnableBlockImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
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.types.toKotlinType
|
||||||
import org.jetbrains.kotlin.ir.util.file
|
import org.jetbrains.kotlin.ir.util.file
|
||||||
import org.jetbrains.kotlin.ir.util.getArguments
|
import org.jetbrains.kotlin.ir.util.getArguments
|
||||||
@@ -124,6 +125,7 @@ internal class FunctionInlining(val context: Context): IrElementTransformerWithC
|
|||||||
//-------------------------------------------------------------------------//
|
//-------------------------------------------------------------------------//
|
||||||
|
|
||||||
fun inline(irModule: IrModuleFragment): IrElement {
|
fun inline(irModule: IrModuleFragment): IrElement {
|
||||||
|
irTypeKotlinBuiltIns = irModule.irBuiltins.builtIns
|
||||||
val transformedModule = irModule.accept(this, Ref(false))
|
val transformedModule = irModule.accept(this, Ref(false))
|
||||||
DescriptorSubstitutorForExternalScope(globalSubstituteMap, context).run(transformedModule) // Transform calls to object that might be returned from inline function call.
|
DescriptorSubstitutorForExternalScope(globalSubstituteMap, context).run(transformedModule) // Transform calls to object that might be returned from inline function call.
|
||||||
return transformedModule
|
return transformedModule
|
||||||
@@ -371,7 +373,7 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
|
|||||||
override fun visitElement(element: IrElement) = element.accept(this, null)
|
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? {
|
private fun createTypeSubstitutor(irCall: IrCall): TypeSubstitutor? {
|
||||||
if (irCall.typeArgumentsCount == 0) return null
|
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.getFunctionalClassKind
|
||||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
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.name.FqName
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
@@ -47,6 +51,15 @@ internal val FunctionDescriptor.isFunctionInvoke: Boolean
|
|||||||
this.isOperator && this.name == OperatorNameConventions.INVOKE
|
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",
|
// It is possible to declare "external inline fun",
|
||||||
// but it doesn't have much sense for native,
|
// but it doesn't have much sense for native,
|
||||||
// since externals don't have IR bodies.
|
// 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(),
|
emptyList(),
|
||||||
notFoundClasses,
|
notFoundClasses,
|
||||||
ContractDeserializerImpl(configuration, storageManager),
|
ContractDeserializerImpl(configuration, storageManager),
|
||||||
platformDependentDeclarationFilter = PlatformDependentDeclarationFilter.NoPlatformDependent,
|
platformDependentDeclarationFilter = PlatformDependentDeclarationFilter.All,
|
||||||
extensionRegistryLite = JsKlibMetadataSerializerProtocol.extensionRegistry
|
extensionRegistryLite = JsKlibMetadataSerializerProtocol.extensionRegistry
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
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.JsIrBackendContext
|
||||||
import org.jetbrains.kotlin.ir.backend.js.lower.coroutines.COROUTINE_SWITCH
|
import org.jetbrains.kotlin.ir.backend.js.lower.coroutines.COROUTINE_SWITCH
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
|
import org.jetbrains.kotlin.ir.backend.js.utils.JsGenerationContext
|
||||||
@@ -99,7 +100,7 @@ class IrElementToJsStatementTransformer : BaseIrElementToJsNodeTransformer<JsSta
|
|||||||
var expr: IrExpression? = null
|
var expr: IrExpression? = null
|
||||||
val cases = expression.branches.map {
|
val cases = expression.branches.map {
|
||||||
val body = it.result
|
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
|
val call = it.condition as IrCall
|
||||||
expr = call.getValueArgument(0) as IrExpression
|
expr = call.getValueArgument(0) as IrExpression
|
||||||
call.getValueArgument(1)
|
call.getValueArgument(1)
|
||||||
|
|||||||
+4
-2
@@ -102,8 +102,10 @@ class JsClassGenerator(private val irClass: IrClass, val context: JsGenerationCo
|
|||||||
private fun generateThrowableProperties(): List<JsStatement> {
|
private fun generateThrowableProperties(): List<JsStatement> {
|
||||||
val functions = irClass.declarations.filterIsInstance<IrSimpleFunction>()
|
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))
|
val msgProperty = defineProperty(classPrototypeRef, "message", getter = buildGetterFunction(messageGetter))
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
package org.jetbrains.kotlin.ir.backend.js.transformers.irToJs
|
||||||
|
|
||||||
import org.jetbrains.kotlin.backend.common.descriptors.isSuspend
|
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.JsGenerationContext
|
||||||
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
|
import org.jetbrains.kotlin.ir.backend.js.utils.Namer
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||||
@@ -24,7 +25,7 @@ fun <T : JsNode, D : JsGenerationContext> IrWhen.toJsNode(
|
|||||||
): T? =
|
): T? =
|
||||||
branches.foldRight<IrBranch, T?>(null) { br, n ->
|
branches.foldRight<IrBranch, T?>(null) { br, n ->
|
||||||
val body = br.result.accept(tr, data)
|
val body = br.result.accept(tr, data)
|
||||||
if (br is IrElseBranch) body
|
if (isElseBranch(br)) body
|
||||||
else {
|
else {
|
||||||
val condition = br.condition.accept(IrElementToJsExpressionTransformer(), data)
|
val condition = br.condition.accept(IrElementToJsExpressionTransformer(), data)
|
||||||
node(condition, body, n)
|
node(condition, body, n)
|
||||||
|
|||||||
@@ -99,4 +99,6 @@ object Namer {
|
|||||||
|
|
||||||
val THIS_SPECIAL_NAME = "<this>"
|
val THIS_SPECIAL_NAME = "<this>"
|
||||||
val SET_SPECIAL_NAME = "<set-?>"
|
val SET_SPECIAL_NAME = "<set-?>"
|
||||||
|
|
||||||
|
val DYNAMIC_FILE_NAME = "<dynamicDeclarations>"
|
||||||
}
|
}
|
||||||
+1
@@ -64,6 +64,7 @@ abstract class IrLazyDeclarationBase(
|
|||||||
}
|
}
|
||||||
is ClassDescriptor -> stubGenerator.generateClassStub(containingDeclaration)
|
is ClassDescriptor -> stubGenerator.generateClassStub(containingDeclaration)
|
||||||
is FunctionDescriptor -> stubGenerator.generateFunctionStub(containingDeclaration)
|
is FunctionDescriptor -> stubGenerator.generateFunctionStub(containingDeclaration)
|
||||||
|
is PropertyDescriptor -> stubGenerator.generateFunctionStub(containingDeclaration.run { getter ?: setter!! })
|
||||||
else -> throw AssertionError("Package or class expected: $containingDeclaration; for $currentDescriptor")
|
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.IrSimpleFunction
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
|
||||||
import org.jetbrains.kotlin.ir.symbols.impl.IrExternalPackageFragmentSymbolImpl
|
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.types.withHasQuestionMark
|
||||||
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
|
import org.jetbrains.kotlin.ir.util.DeclarationStubGenerator
|
||||||
import org.jetbrains.kotlin.ir.util.SymbolTable
|
import org.jetbrains.kotlin.ir.util.SymbolTable
|
||||||
@@ -72,68 +78,97 @@ class IrBuiltIns(
|
|||||||
private fun List<SimpleType>.defineComparisonOperatorForEachType(name: String) =
|
private fun List<SimpleType>.defineComparisonOperatorForEachType(name: String) =
|
||||||
associate { it to defineComparisonOperator(name, it) }
|
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 any = builtIns.anyType
|
||||||
val anyN = builtIns.nullableAnyType
|
val anyN = builtIns.nullableAnyType
|
||||||
val anyType = any.toIrType()
|
val anyType by lazy { any.toIrType() }
|
||||||
val anyClass = builtIns.any.toIrSymbol()
|
val anyClass by lazy { builtIns.any.toIrSymbol() }
|
||||||
val anyNType = anyType.withHasQuestionMark(true)
|
val anyNType by lazy { anyType.withHasQuestionMark(true) }
|
||||||
|
|
||||||
val bool = builtIns.booleanType
|
val bool = builtIns.booleanType
|
||||||
val booleanType = bool.toIrType()
|
val booleanType by lazy { bool.toIrType() }
|
||||||
val booleanClass = builtIns.boolean.toIrSymbol()
|
val booleanClass by lazy { builtIns.boolean.toIrSymbol() }
|
||||||
|
|
||||||
val char = builtIns.charType
|
val char = builtIns.charType
|
||||||
val charType = char.toIrType()
|
val charType by lazy { char.toIrType() }
|
||||||
val charClass = builtIns.char.toIrSymbol()
|
val charClass by lazy { builtIns.char.toIrSymbol() }
|
||||||
|
|
||||||
val number = builtIns.number.defaultType
|
val number = builtIns.number.defaultType
|
||||||
val numberType = number.toIrType()
|
val numberType by lazy { number.toIrType() }
|
||||||
val numberClass = builtIns.number.toIrSymbol()
|
val numberClass by lazy { builtIns.number.toIrSymbol() }
|
||||||
|
|
||||||
val byte = builtIns.byteType
|
val byte = builtIns.byteType
|
||||||
val byteType = byte.toIrType()
|
val byteType by lazy { byte.toIrType() }
|
||||||
val byteClass = builtIns.byte.toIrSymbol()
|
val byteClass by lazy { builtIns.byte.toIrSymbol() }
|
||||||
|
|
||||||
val short = builtIns.shortType
|
val short = builtIns.shortType
|
||||||
val shortType = short.toIrType()
|
val shortType by lazy { short.toIrType() }
|
||||||
val shortClass = builtIns.short.toIrSymbol()
|
val shortClass by lazy { builtIns.short.toIrSymbol() }
|
||||||
|
|
||||||
val int = builtIns.intType
|
val int = builtIns.intType
|
||||||
val intType = int.toIrType()
|
val intType by lazy { int.toIrType() }
|
||||||
val intClass = builtIns.int.toIrSymbol()
|
val intClass by lazy { builtIns.int.toIrSymbol() }
|
||||||
|
|
||||||
val long = builtIns.longType
|
val long = builtIns.longType
|
||||||
val longType = long.toIrType()
|
val longType by lazy { long.toIrType() }
|
||||||
val longClass = builtIns.long.toIrSymbol()
|
val longClass by lazy { builtIns.long.toIrSymbol() }
|
||||||
|
|
||||||
val float = builtIns.floatType
|
val float = builtIns.floatType
|
||||||
val floatType = float.toIrType()
|
val floatType by lazy { float.toIrType() }
|
||||||
val floatClass = builtIns.float.toIrSymbol()
|
val floatClass by lazy { builtIns.float.toIrSymbol() }
|
||||||
|
|
||||||
val double = builtIns.doubleType
|
val double = builtIns.doubleType
|
||||||
val doubleType = double.toIrType()
|
val doubleType by lazy { double.toIrType() }
|
||||||
val doubleClass = builtIns.double.toIrSymbol()
|
val doubleClass by lazy { builtIns.double.toIrSymbol() }
|
||||||
|
|
||||||
val nothing = builtIns.nothingType
|
val nothing = builtIns.nothingType
|
||||||
val nothingN = builtIns.nullableNothingType
|
val nothingN = builtIns.nullableNothingType
|
||||||
val nothingType = nothing.toIrType()
|
val nothingType by lazy { nothing.toIrType() }
|
||||||
val nothingClass = builtIns.nothing.toIrSymbol()
|
val nothingClass by lazy { builtIns.nothing.toIrSymbol() }
|
||||||
val nothingNType = nothingType.withHasQuestionMark(true)
|
val nothingNType by lazy { nothingType.withHasQuestionMark(true) }
|
||||||
|
|
||||||
val unit = builtIns.unitType
|
val unit = builtIns.unitType
|
||||||
val unitType = unit.toIrType()
|
val unitType by lazy { unit.toIrType() }
|
||||||
val unitClass = builtIns.unit.toIrSymbol()
|
val unitClass by lazy { builtIns.unit.toIrSymbol() }
|
||||||
|
|
||||||
val string = builtIns.stringType
|
val string = builtIns.stringType
|
||||||
val stringType = string.toIrType()
|
val stringType by lazy { string.toIrType() }
|
||||||
val stringClass = builtIns.string.toIrSymbol()
|
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 throwableType by lazy { builtIns.throwable.defaultType.toIrType() }
|
||||||
val throwableClass = builtIns.throwable.toIrSymbol()
|
val throwableClass by lazy { builtIns.throwable.toIrSymbol() }
|
||||||
|
|
||||||
val kCallableClass = builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.kCallable.toSafe()).toIrSymbol()
|
val kCallableClass = builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.kCallable.toSafe()).toIrSymbol()
|
||||||
val kPropertyClass = builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.kPropertyFqName.toSafe()).toIrSymbol()
|
val kPropertyClass = builtIns.getBuiltInClassByFqName(KotlinBuiltIns.FQ_NAMES.kPropertyFqName.toSafe()).toIrSymbol()
|
||||||
|
|||||||
@@ -5,9 +5,11 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.ir.types
|
package org.jetbrains.kotlin.ir.types
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
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.IrClass
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
@@ -68,6 +70,8 @@ fun IrType.makeNullable(addKotlinType:Boolean = true) =
|
|||||||
else
|
else
|
||||||
this
|
this
|
||||||
|
|
||||||
|
var irTypeKotlinBuiltIns: KotlinBuiltIns? = null
|
||||||
|
|
||||||
fun IrType.toKotlinType(): KotlinType {
|
fun IrType.toKotlinType(): KotlinType {
|
||||||
originalKotlinType?.let {
|
originalKotlinType?.let {
|
||||||
return it
|
return it
|
||||||
@@ -75,6 +79,7 @@ fun IrType.toKotlinType(): KotlinType {
|
|||||||
|
|
||||||
return when (this) {
|
return when (this) {
|
||||||
is IrSimpleType -> makeKotlinType(classifier, arguments, hasQuestionMark)
|
is IrSimpleType -> makeKotlinType(classifier, arguments, hasQuestionMark)
|
||||||
|
is IrDynamicType -> createDynamicType(irTypeKotlinBuiltIns!!)
|
||||||
else -> TODO(toString())
|
else -> TODO(toString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,16 +21,21 @@ import org.jetbrains.kotlin.descriptors.*
|
|||||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrFieldImpl
|
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.IrPropertyImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
import org.jetbrains.kotlin.ir.declarations.impl.IrValueParameterImpl
|
||||||
import org.jetbrains.kotlin.ir.declarations.lazy.*
|
import org.jetbrains.kotlin.ir.declarations.lazy.*
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrErrorExpressionImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
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.load.java.descriptors.JavaCallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.hasBackingField
|
import org.jetbrains.kotlin.resolve.hasBackingField
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.Variance
|
||||||
|
import org.jetbrains.kotlin.types.isDynamic
|
||||||
|
|
||||||
class DeclarationStubGenerator(
|
class DeclarationStubGenerator(
|
||||||
moduleDescriptor: ModuleDescriptor,
|
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_metadata.proto"),
|
||||||
ProtoPath("core/metadata.jvm/src/jvm_module.proto"),
|
ProtoPath("core/metadata.jvm/src/jvm_module.proto"),
|
||||||
ProtoPath("build-common/src/java_descriptors.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")
|
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.ir.backend.js.compile
|
||||||
import org.jetbrains.kotlin.js.test.JsIrTestRuntime
|
import org.jetbrains.kotlin.js.test.JsIrTestRuntime
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
fun buildConfiguration(environment: KotlinCoreEnvironment): CompilerConfiguration {
|
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 stdKlibFile = File("js/js.translator/testData/out/klibs/stdlib.klib")
|
||||||
|
|
||||||
|
private val resultJs = "js/js.translator/testData/out/klibs/result.js"
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
|
|
||||||
val environment = KotlinCoreEnvironment.createForTests(Disposable { }, CompilerConfiguration(), EnvironmentConfigFiles.JS_CONFIG_FILES)
|
val environment = KotlinCoreEnvironment.createForTests(Disposable { }, CompilerConfiguration(), EnvironmentConfigFiles.JS_CONFIG_FILES)
|
||||||
@@ -53,7 +56,7 @@ fun main() {
|
|||||||
|
|
||||||
val result = compile(
|
val result = compile(
|
||||||
environment.project,
|
environment.project,
|
||||||
JsIrTestRuntime.FULL.sources.map(::createPsiFile),
|
(JsIrTestRuntime.FULL.sources).map(::createPsiFile),
|
||||||
buildConfiguration(environment),
|
buildConfiguration(environment),
|
||||||
null,
|
null,
|
||||||
true,
|
true,
|
||||||
@@ -61,5 +64,7 @@ fun main() {
|
|||||||
emptyList()
|
emptyList()
|
||||||
)
|
)
|
||||||
|
|
||||||
TODO("Write library into $stdKlibFile")
|
File(resultJs).writeText(result.generatedCode)
|
||||||
|
|
||||||
|
// TODO("Write library into $stdKlibFile")
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user