Added serialization/deserialization of DFG
This commit is contained in:
+3
-1
@@ -19,6 +19,7 @@ import llvm.LLVMLinkModules2
|
||||
import llvm.LLVMWriteBitcodeToFile
|
||||
import org.jetbrains.kotlin.backend.konan.library.impl.buildLibrary
|
||||
import org.jetbrains.kotlin.backend.konan.llvm.parseBitcodeFile
|
||||
import org.jetbrains.kotlin.backend.konan.util.getValueOrNull
|
||||
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
|
||||
|
||||
internal fun produceOutput(context: Context) {
|
||||
@@ -71,7 +72,8 @@ internal fun produceOutput(context: Context) {
|
||||
llvmModule,
|
||||
nopack,
|
||||
manifest,
|
||||
context.moduleEscapeAnalysisResult.build().toByteArray())
|
||||
context.escapeAnalysisResult.getValueOrNull()?.build()?.toByteArray(),
|
||||
context.dataFlowGraph)
|
||||
|
||||
context.library = library
|
||||
context.bitcodeFileName = library.mainBitcodeFileName
|
||||
|
||||
+2
-3
@@ -175,9 +175,8 @@ internal class Context(config: KonanConfig) : KonanBackendContext(config) {
|
||||
// But we have to wait until the code generation phase,
|
||||
// to dump this information into generated file.
|
||||
var serializedLinkData: LinkData? = null
|
||||
val moduleEscapeAnalysisResult: ModuleEscapeAnalysisResult.ModuleEAResult.Builder by lazy {
|
||||
ModuleEscapeAnalysisResult.ModuleEAResult.newBuilder()
|
||||
}
|
||||
val escapeAnalysisResult = lazy { ModuleEscapeAnalysisResult.ModuleEAResult.newBuilder() }
|
||||
var dataFlowGraph: ByteArray? = null
|
||||
|
||||
@Deprecated("")
|
||||
lateinit var psi2IrGeneratorContext: GeneratorContext
|
||||
|
||||
+1
-1
@@ -1334,7 +1334,7 @@ internal object EscapeAnalysis {
|
||||
functionEAResultBuilder.addPointsTo(pointsToMask)
|
||||
}
|
||||
functionEAResultBuilder.escapes = escapes
|
||||
context.moduleEscapeAnalysisResult.addFunctionEAResults(functionEAResultBuilder)
|
||||
context.escapeAnalysisResult.value.addFunctionEAResults(functionEAResultBuilder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+3
-1
@@ -60,7 +60,9 @@ enum class KonanPhase(val description: String,
|
||||
/* ... */ BITCODE("LLVM BitCode Generation"),
|
||||
/* ... ... */ RTTI("RTTI Generation"),
|
||||
/* ... ... */ BUILD_DFG("Data flow graph building"),
|
||||
/* ... ... */ ESCAPE_ANALYSIS("Escape analysis", BUILD_DFG),
|
||||
/* ... ... */ SERIALIZE_DFG("Data flow graph serializing", BUILD_DFG),
|
||||
/* ... ... */ DESERIALIZE_DFG("Data flow graph deserializing"),
|
||||
/* ... ... */ ESCAPE_ANALYSIS("Escape analysis", BUILD_DFG, DESERIALIZE_DFG),
|
||||
/* ... ... */ CODEGEN("Code Generation"),
|
||||
/* ... ... */ BITCODE_LINKER("Bitcode linking"),
|
||||
/* */ LINK_STAGE("Link stage"),
|
||||
|
||||
+2
@@ -45,6 +45,8 @@ interface KonanLibraryLayout {
|
||||
get() = File(linkdataDir, "module")
|
||||
val escapeAnalysisFile
|
||||
get() = File(linkdataDir, "module_escape_analysis")
|
||||
val dataFlowGraphFile
|
||||
get() = File(linkdataDir, "module_data_flow_graph")
|
||||
fun packageFile(packageName: String)
|
||||
= File(linkdataDir, if (packageName == "") "root_package.knm" else "package_$packageName.knm")
|
||||
}
|
||||
|
||||
+1
@@ -27,6 +27,7 @@ interface KonanLibraryReader {
|
||||
val includedPaths: List<String>
|
||||
val linkerOpts: List<String>
|
||||
val unresolvedDependencies: List<String>
|
||||
val dataFlowGraph: ByteArray?
|
||||
val escapeAnalysis: ByteArray?
|
||||
val isDefaultLibrary: Boolean get() = false
|
||||
val isNeededForLink: Boolean get() = true
|
||||
|
||||
+1
@@ -26,6 +26,7 @@ interface KonanLibraryWriter {
|
||||
fun addLinkDependencies(libraries: List<KonanLibraryReader>)
|
||||
fun addManifestAddend(path: String)
|
||||
fun addEscapeAnalysis(escapeAnalysis: ByteArray)
|
||||
fun addDataFlowGraph(dataFlowGraph: ByteArray)
|
||||
val mainBitcodeFileName: String
|
||||
fun commit()
|
||||
}
|
||||
|
||||
+2
-2
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.backend.konan.library.impl
|
||||
|
||||
import org.jetbrains.kotlin.backend.konan.KonanConfig
|
||||
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryReader
|
||||
import org.jetbrains.kotlin.backend.konan.createInteropLibrary
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.emptyPackages
|
||||
import org.jetbrains.kotlin.backend.konan.serialization.deserializeModule
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
@@ -52,7 +51,8 @@ class LibraryReaderImpl(var libraryFile: File, val currentAbiVersion: Int,
|
||||
}
|
||||
|
||||
val targetList = inPlace.targetsDir.listFiles.map{it.name}
|
||||
override val escapeAnalysis: ByteArray? by lazy { inPlace.escapeAnalysisFile.let { if (it.exists) it.readBytes() else null } }
|
||||
override val escapeAnalysis by lazy { inPlace.escapeAnalysisFile.let { if (it.exists) it.readBytes() else null } }
|
||||
override val dataFlowGraph by lazy { inPlace.dataFlowGraphFile.let { if (it.exists) it.readBytes() else null } }
|
||||
|
||||
override val libraryName
|
||||
get() = inPlace.libraryName
|
||||
|
||||
+7
-1
@@ -105,6 +105,10 @@ class LibraryWriterImpl(override val libDir: File, moduleName: String, currentAb
|
||||
escapeAnalysisFile.writeBytes(escapeAnalysis)
|
||||
}
|
||||
|
||||
override fun addDataFlowGraph(dataFlowGraph: ByteArray) {
|
||||
dataFlowGraphFile.writeBytes(dataFlowGraph)
|
||||
}
|
||||
|
||||
override fun commit() {
|
||||
manifestProperties.saveToFile(manifestFile)
|
||||
if (!nopack) {
|
||||
@@ -126,7 +130,8 @@ internal fun buildLibrary(
|
||||
llvmModule: LLVMModuleRef,
|
||||
nopack: Boolean,
|
||||
manifest: String?,
|
||||
escapeAnalysis: ByteArray?): KonanLibraryWriter {
|
||||
escapeAnalysis: ByteArray?,
|
||||
dataFlowGraph: ByteArray?): KonanLibraryWriter {
|
||||
|
||||
val library = LibraryWriterImpl(output, moduleName, abiVersion, target, nopack)
|
||||
|
||||
@@ -141,6 +146,7 @@ internal fun buildLibrary(
|
||||
manifest ?.let { library.addManifestAddend(it) }
|
||||
library.addLinkDependencies(linkDependencies)
|
||||
escapeAnalysis?.let { library.addEscapeAnalysis(it) }
|
||||
dataFlowGraph?.let { library.addDataFlowGraph(it) }
|
||||
|
||||
library.commit()
|
||||
return library
|
||||
|
||||
+9
@@ -81,6 +81,15 @@ internal fun emitLLVM(context: Context) {
|
||||
moduleDFG = ModuleDFGBuilder(context, irModule).build()
|
||||
}
|
||||
|
||||
phaser.phase(KonanPhase.SERIALIZE_DFG) {
|
||||
DFGSerializer.serialize(context, moduleDFG!!)
|
||||
}
|
||||
|
||||
var externalModulesDFG: ExternalModulesDFG? = null
|
||||
phaser.phase(KonanPhase.DESERIALIZE_DFG) {
|
||||
externalModulesDFG = DFGSerializer.deserialize(context, moduleDFG!!.symbolTable.privateTypeIndex, moduleDFG!!.symbolTable.privateFunIndex)
|
||||
}
|
||||
|
||||
val lifetimes = mutableMapOf<IrElement, Lifetime>()
|
||||
val codegenVisitor = CodeGeneratorVisitor(context, lifetimes)
|
||||
phaser.phase(KonanPhase.ESCAPE_ANALYSIS) {
|
||||
|
||||
+10
-2
@@ -197,6 +197,10 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
if (DEBUG > severity) block()
|
||||
}
|
||||
|
||||
private val TAKE_NAMES = false // Take fqNames for all functions and types (for debug purposes).
|
||||
|
||||
private inline fun takeName(block: () -> String) = if (TAKE_NAMES) block() else null
|
||||
|
||||
private val module = DataFlowIR.Module(irModule.descriptor)
|
||||
private val symbolTable = DataFlowIR.SymbolTable(context, irModule, module)
|
||||
|
||||
@@ -542,11 +546,13 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
is IrGetField -> {
|
||||
val receiver = value.receiver?.let { expressionToEdge(it) }
|
||||
val receiverType = value.receiver?.let { symbolTable.mapType(it.type) }
|
||||
val name = value.descriptor.name.asString()
|
||||
DataFlowIR.Node.FieldRead(
|
||||
receiver,
|
||||
DataFlowIR.Field(
|
||||
receiverType,
|
||||
value.descriptor.name.asString()
|
||||
name.localHash.value,
|
||||
takeName { name }
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -554,11 +560,13 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
|
||||
is IrSetField -> {
|
||||
val receiver = value.receiver?.let { expressionToEdge(it) }
|
||||
val receiverType = value.receiver?.let { symbolTable.mapType(it.type) }
|
||||
val name = value.descriptor.name.asString()
|
||||
DataFlowIR.Node.FieldWrite(
|
||||
receiver,
|
||||
DataFlowIR.Field(
|
||||
receiverType,
|
||||
value.descriptor.name.asString()
|
||||
name.localHash.value,
|
||||
takeName { name }
|
||||
),
|
||||
expressionToEdge(value.value)
|
||||
)
|
||||
|
||||
+1000
File diff suppressed because it is too large
Load Diff
+31
-26
@@ -31,20 +31,20 @@ internal object DataFlowIR {
|
||||
// Special marker type forbidding devirtualization on its instances.
|
||||
object Virtual : Declared(false, true)
|
||||
|
||||
class External(val name: String) : Type() {
|
||||
class External(val hash: Long, val name: String? = null) : Type() {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is External) return false
|
||||
|
||||
return name == other.name
|
||||
return hash == other.hash
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return name.hashCode()
|
||||
return hash.hashCode()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "ExternalType(name='$name')"
|
||||
return "ExternalType(hash='$hash', name='$name')"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,24 +54,24 @@ internal object DataFlowIR {
|
||||
val itable = mutableMapOf<Long, FunctionSymbol>()
|
||||
}
|
||||
|
||||
class Public(val name: String, isFinal: Boolean, isAbstract: Boolean) : Declared(isFinal, isAbstract) {
|
||||
class Public(val hash: Long, isFinal: Boolean, isAbstract: Boolean, val name: String? = null) : Declared(isFinal, isAbstract) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is Public) return false
|
||||
|
||||
return name == other.name
|
||||
return hash == other.hash
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return name.hashCode()
|
||||
return hash.hashCode()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "PublicType(name='$name')"
|
||||
return "PublicType(hash='$hash', name='$name')"
|
||||
}
|
||||
}
|
||||
|
||||
class Private(val name: String, val index: Int, isFinal: Boolean, isAbstract: Boolean) : Declared(isFinal, isAbstract) {
|
||||
class Private(val index: Int, isFinal: Boolean, isAbstract: Boolean, val name: String? = null) : Declared(isFinal, isAbstract) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is Private) return false
|
||||
@@ -94,43 +94,43 @@ internal object DataFlowIR {
|
||||
}
|
||||
|
||||
abstract class FunctionSymbol {
|
||||
class External(val name: String) : FunctionSymbol() {
|
||||
class External(val hash: Long, val name: String? = null) : FunctionSymbol() {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is External) return false
|
||||
|
||||
return name == other.name
|
||||
return hash == other.hash
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return name.hashCode()
|
||||
return hash.hashCode()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "ExternalFunction(name='$name')"
|
||||
return "ExternalFunction(hash='$hash', name='$name')"
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Declared(val module: Module, val symbolTableIndex: Int) : FunctionSymbol()
|
||||
|
||||
class Public(val name: String, module: Module, symbolTableIndex: Int) : Declared(module, symbolTableIndex) {
|
||||
class Public(val hash: Long, module: Module, symbolTableIndex: Int, val name: String? = null) : Declared(module, symbolTableIndex) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is Public) return false
|
||||
|
||||
return name == other.name
|
||||
return hash == other.hash
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return name.hashCode()
|
||||
return hash.hashCode()
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "PublicFunction(name='$name')"
|
||||
return "PublicFunction(hash='$hash', name='$name')"
|
||||
}
|
||||
}
|
||||
|
||||
class Private(val name: String, val index: Int, module: Module, symbolTableIndex: Int) : Declared(module, symbolTableIndex) {
|
||||
class Private(val index: Int, module: Module, symbolTableIndex: Int, val name: String? = null) : Declared(module, symbolTableIndex) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other !is Private) return false
|
||||
@@ -148,7 +148,7 @@ internal object DataFlowIR {
|
||||
}
|
||||
}
|
||||
|
||||
data class Field(val type: Type?, val name: String)
|
||||
data class Field(val type: Type?, val hash: Long, val name: String? = null)
|
||||
|
||||
class Edge(val castToType: Type?) {
|
||||
|
||||
@@ -316,6 +316,11 @@ internal object DataFlowIR {
|
||||
}
|
||||
|
||||
class SymbolTable(val context: Context, val irModule: IrModuleFragment, val module: Module) {
|
||||
|
||||
private val TAKE_NAMES = false // Take fqNames for all functions and types (for debug purposes).
|
||||
|
||||
private inline fun takeName(block: () -> String) = if (TAKE_NAMES) block() else null
|
||||
|
||||
val classMap = mutableMapOf<ClassDescriptor, Type>()
|
||||
val functionMap = mutableMapOf<CallableDescriptor, FunctionSymbol>()
|
||||
|
||||
@@ -354,16 +359,16 @@ internal object DataFlowIR {
|
||||
|
||||
val name = descriptor.fqNameSafe.asString()
|
||||
if (descriptor.module != irModule.descriptor)
|
||||
return classMap.getOrPut(descriptor) { Type.External(name) }
|
||||
return classMap.getOrPut(descriptor) { Type.External(name.localHash.value, takeName { name }) }
|
||||
|
||||
classMap[descriptor]?.let { return it }
|
||||
|
||||
val isFinal = descriptor.isFinal()
|
||||
val isAbstract = descriptor.isAbstract()
|
||||
val type = if (descriptor.isExported())
|
||||
Type.Public(name, isFinal, isAbstract)
|
||||
Type.Public(name.localHash.value, isFinal, isAbstract, takeName { name })
|
||||
else
|
||||
Type.Private(name, privateTypeIndex++, isFinal, isAbstract)
|
||||
Type.Private(privateTypeIndex++, isFinal, isAbstract, takeName { name })
|
||||
if (!descriptor.isInterface) {
|
||||
val vtableBuilder = context.getVtableBuilder(descriptor)
|
||||
type.vtable += vtableBuilder.vtableEntries.map { mapFunction(it.getImplementation(context)) }
|
||||
@@ -405,11 +410,11 @@ internal object DataFlowIR {
|
||||
functionMap.getOrPut(it) {
|
||||
when (it) {
|
||||
is PropertyDescriptor ->
|
||||
FunctionSymbol.Private("${it.symbolName}_init", privateFunIndex++, module, -1)
|
||||
FunctionSymbol.Private(privateFunIndex++, module, -1, takeName { "${it.symbolName}_init" })
|
||||
|
||||
is FunctionDescriptor -> {
|
||||
if (it.module != irModule.descriptor || it.externalOrIntrinsic())
|
||||
FunctionSymbol.External(it.symbolName)
|
||||
FunctionSymbol.External(it.symbolName.localHash.value, takeName { it.symbolName })
|
||||
else {
|
||||
val isAbstract = it.modality == Modality.ABSTRACT
|
||||
val classDescriptor = it.containingDeclaration as? ClassDescriptor
|
||||
@@ -420,9 +425,9 @@ internal object DataFlowIR {
|
||||
++module.numberOfFunctions
|
||||
val symbolTableIndex = if (!placeToFunctionsTable) -1 else couldBeCalledVirtuallyIndex++
|
||||
if (it.isExported())
|
||||
FunctionSymbol.Public(it.symbolName, module, symbolTableIndex)
|
||||
FunctionSymbol.Public(it.symbolName.localHash.value, module, symbolTableIndex, takeName { it.symbolName })
|
||||
else
|
||||
FunctionSymbol.Private(getFqName(it).asString() + "#internal", privateFunIndex++, module, symbolTableIndex)
|
||||
FunctionSymbol.Private(privateFunIndex++, module, symbolTableIndex, takeName { getFqName(it).asString() + "#internal" })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user