IR: copy each file before lowering.
Avoid inter-file dependencies while lowering.
This commit is contained in:
+8
-1
@@ -13,7 +13,8 @@ import org.jetbrains.kotlin.ir.builders.irCall
|
|||||||
import org.jetbrains.kotlin.ir.builders.irString
|
import org.jetbrains.kotlin.ir.builders.irString
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
import org.jetbrains.kotlin.ir.util.IdSignature
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
|
|
||||||
interface LoggingContext {
|
interface LoggingContext {
|
||||||
var inVerbosePhase: Boolean
|
var inVerbosePhase: Boolean
|
||||||
@@ -36,4 +37,10 @@ interface CommonBackendContext : BackendContext, LoggingContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val mapping: Mapping
|
val mapping: Mapping
|
||||||
|
|
||||||
|
// Adjust internal structures after a deep copy of some declarations.
|
||||||
|
fun handleDeepCopy(
|
||||||
|
classSymbolMap: MutableMap<IrClassSymbol, IrClassSymbol>,
|
||||||
|
functionSymbolMap: MutableMap<IrSimpleFunctionSymbol, IrSimpleFunctionSymbol>
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,9 @@ interface Mapping {
|
|||||||
operator fun setValue(thisRef: K, desc: KProperty<*>, value: V?) {
|
operator fun setValue(thisRef: K, desc: KProperty<*>, value: V?) {
|
||||||
set(thisRef, value)
|
set(thisRef, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract val keys: Set<K>
|
||||||
|
abstract val values: Collection<V>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,6 +60,12 @@ open class DefaultMapping : Mapping {
|
|||||||
map[key] = value
|
map[key] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val keys: Set<K>
|
||||||
|
get() = map.keys
|
||||||
|
|
||||||
|
override val values: Collection<V>
|
||||||
|
get() = map.values
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -13,7 +13,9 @@ class PhaserState<Data>(
|
|||||||
var depth: Int = 0,
|
var depth: Int = 0,
|
||||||
var phaseCount: Int = 0,
|
var phaseCount: Int = 0,
|
||||||
val stickyPostconditions: MutableSet<Checker<Data>> = mutableSetOf()
|
val stickyPostconditions: MutableSet<Checker<Data>> = mutableSetOf()
|
||||||
)
|
) {
|
||||||
|
fun copyOf() = PhaserState(alreadyDone.toMutableSet(), depth, phaseCount, stickyPostconditions)
|
||||||
|
}
|
||||||
|
|
||||||
// Copy state, forgetting the sticky postconditions (which will not be applicable to the new type)
|
// Copy state, forgetting the sticky postconditions (which will not be applicable to the new type)
|
||||||
fun <Input, Output> PhaserState<Input>.changeType() = PhaserState<Output>(alreadyDone, depth, phaseCount, mutableSetOf())
|
fun <Input, Output> PhaserState<Input>.changeType() = PhaserState<Output>(alreadyDone, depth, phaseCount, mutableSetOf())
|
||||||
|
|||||||
+93
-2
@@ -13,6 +13,17 @@ import org.jetbrains.kotlin.config.CommonConfigurationKeys
|
|||||||
import org.jetbrains.kotlin.ir.IrElement
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||||
|
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
|
||||||
|
import org.jetbrains.kotlin.ir.util.DeepCopySymbolRemapper
|
||||||
|
import org.jetbrains.kotlin.ir.util.copyTypeAndValueArgumentsFrom
|
||||||
|
import org.jetbrains.kotlin.ir.util.deepCopySavingMetadata
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
import java.util.concurrent.atomic.AtomicReference
|
import java.util.concurrent.atomic.AtomicReference
|
||||||
@@ -142,7 +153,7 @@ private class PerformByIrFilePhase<Context : CommonBackendContext>(
|
|||||||
CodegenUtil.reportBackendException(e, "IR lowering", irFile.fileEntry.name)
|
CodegenUtil.reportBackendException(e, "IR lowering", irFile.fileEntry.name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: no guarantee that module identity is preserved by `lower`
|
// TODO: no guarantee that module identity is preserved by `lower`
|
||||||
return input
|
return input
|
||||||
}
|
}
|
||||||
@@ -155,8 +166,13 @@ private class PerformByIrFilePhase<Context : CommonBackendContext>(
|
|||||||
// We can only report one exception through ISE
|
// We can only report one exception through ISE
|
||||||
val thrownFromThread = AtomicReference<Pair<Throwable, IrFile>?>(null)
|
val thrownFromThread = AtomicReference<Pair<Throwable, IrFile>?>(null)
|
||||||
|
|
||||||
|
val remappedFunctions = mutableMapOf<IrSimpleFunctionSymbol, IrSimpleFunctionSymbol>()
|
||||||
|
val remappedClasses = mutableMapOf<IrClassSymbol, IrClassSymbol>()
|
||||||
|
|
||||||
// Each thread needs its own copy of phaserState.alreadyDone
|
// Each thread needs its own copy of phaserState.alreadyDone
|
||||||
val filesAndStates = input.files.map { it to phaserState.clone() }
|
val filesAndStates = input.files.map {
|
||||||
|
it.copySavingMappings(remappedFunctions, remappedClasses) to phaserState.copyOf()
|
||||||
|
}
|
||||||
|
|
||||||
val executor = Executors.newFixedThreadPool(nThreads)
|
val executor = Executors.newFixedThreadPool(nThreads)
|
||||||
for ((irFile, state) in filesAndStates) {
|
for ((irFile, state) in filesAndStates) {
|
||||||
@@ -181,6 +197,13 @@ private class PerformByIrFilePhase<Context : CommonBackendContext>(
|
|||||||
// Presumably each thread has run through the same list of phases.
|
// Presumably each thread has run through the same list of phases.
|
||||||
phaserState.alreadyDone.addAll(filesAndStates[0].second.alreadyDone)
|
phaserState.alreadyDone.addAll(filesAndStates[0].second.alreadyDone)
|
||||||
|
|
||||||
|
input.files.clear()
|
||||||
|
input.files.addAll(filesAndStates.map { (irFile, _) -> irFile }.toMutableList())
|
||||||
|
|
||||||
|
adjustDefaultArgumentStubs(context, remappedFunctions)
|
||||||
|
input.transformChildrenVoid(CrossFileCallAdjuster(remappedFunctions))
|
||||||
|
context.handleDeepCopy(remappedClasses, remappedFunctions)
|
||||||
|
|
||||||
// TODO: no guarantee that module identity is preserved by `lower`
|
// TODO: no guarantee that module identity is preserved by `lower`
|
||||||
return input
|
return input
|
||||||
}
|
}
|
||||||
@@ -256,3 +279,71 @@ fun <Context : CommonBackendContext, OldData, NewData> transform(op: (OldData) -
|
|||||||
object : CompilerPhase<Context, OldData, NewData> {
|
object : CompilerPhase<Context, OldData, NewData> {
|
||||||
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<OldData>, context: Context, input: OldData) = op(input)
|
override fun invoke(phaseConfig: PhaseConfig, phaserState: PhaserState<OldData>, context: Context, input: OldData) = op(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We need to remap inline function calls after lowering files
|
||||||
|
|
||||||
|
fun IrFile.copySavingMappings(
|
||||||
|
remappedFunctions: MutableMap<IrSimpleFunctionSymbol, IrSimpleFunctionSymbol>,
|
||||||
|
remappedClasses: MutableMap<IrClassSymbol, IrClassSymbol>,
|
||||||
|
): IrFile {
|
||||||
|
val symbolRemapper = DeepCopySymbolRemapperSavingFunctions()
|
||||||
|
|
||||||
|
val newIrFile = deepCopySavingMetadata(symbolRemapper = symbolRemapper)
|
||||||
|
|
||||||
|
for (function in symbolRemapper.declaredFunctions) {
|
||||||
|
remappedFunctions[function] = symbolRemapper.getReferencedSimpleFunction(function)
|
||||||
|
}
|
||||||
|
for (klass in symbolRemapper.declaredClasses) {
|
||||||
|
remappedClasses[klass] = symbolRemapper.getReferencedClass(klass)
|
||||||
|
}
|
||||||
|
|
||||||
|
return newIrFile
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DeepCopySymbolRemapperSavingFunctions : DeepCopySymbolRemapper() {
|
||||||
|
val declaredFunctions = mutableSetOf<IrSimpleFunctionSymbol>()
|
||||||
|
val declaredClasses = mutableSetOf<IrClassSymbol>()
|
||||||
|
|
||||||
|
override fun getDeclaredFunction(symbol: IrSimpleFunctionSymbol): IrSimpleFunctionSymbol {
|
||||||
|
declaredFunctions.add(symbol)
|
||||||
|
return super.getDeclaredFunction(symbol)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getDeclaredClass(symbol: IrClassSymbol): IrClassSymbol {
|
||||||
|
declaredClasses.add(symbol)
|
||||||
|
return super.getDeclaredClass(symbol)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun adjustDefaultArgumentStubs(
|
||||||
|
context: CommonBackendContext,
|
||||||
|
remappedFunctions: MutableMap<IrSimpleFunctionSymbol, IrSimpleFunctionSymbol>,
|
||||||
|
) {
|
||||||
|
for (defaultStub in context.mapping.defaultArgumentsOriginalFunction.keys) {
|
||||||
|
if (defaultStub !is IrSimpleFunction) continue
|
||||||
|
val original = context.mapping.defaultArgumentsOriginalFunction[defaultStub] as? IrSimpleFunction ?: continue
|
||||||
|
val originalNew = remappedFunctions[original.symbol]?.owner ?: continue
|
||||||
|
val defaultStubNew = context.mapping.defaultArgumentsDispatchFunction[originalNew] ?: continue
|
||||||
|
remappedFunctions[defaultStub.symbol] = defaultStubNew.symbol as IrSimpleFunctionSymbol
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class CrossFileCallAdjuster(
|
||||||
|
val remappedFunctions: Map<IrSimpleFunctionSymbol, IrSimpleFunctionSymbol>
|
||||||
|
) : IrElementTransformerVoid() {
|
||||||
|
override fun visitCall(expression: IrCall): IrExpression {
|
||||||
|
expression.transformChildrenVoid(this)
|
||||||
|
return remappedFunctions[expression.symbol]?.let { newSymbol ->
|
||||||
|
with(expression) {
|
||||||
|
IrCallImpl(
|
||||||
|
startOffset, endOffset, type,
|
||||||
|
newSymbol,
|
||||||
|
typeArgumentsCount, valueArgumentsCount, origin,
|
||||||
|
superQualifierSymbol // TODO
|
||||||
|
).apply {
|
||||||
|
copyTypeAndValueArgumentsFrom(expression)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ?: expression
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -47,5 +47,11 @@ class JsMapping(private val irFactory: IrFactory) : DefaultMapping() {
|
|||||||
map[key] = value
|
map[key] = value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val keys: Set<K>
|
||||||
|
get() = map.keys
|
||||||
|
|
||||||
|
override val values: Collection<V>
|
||||||
|
get() = map.values
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,6 +154,25 @@ class JvmBackendContext(
|
|||||||
+irThrow(irNull())
|
+irThrow(irNull())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun handleDeepCopy(
|
||||||
|
classSymbolMap: MutableMap<IrClassSymbol, IrClassSymbol>,
|
||||||
|
functionSymbolMap: MutableMap<IrSimpleFunctionSymbol, IrSimpleFunctionSymbol>
|
||||||
|
) {
|
||||||
|
val oldClassesWithNameOverride = classNameOverride.keys.toList()
|
||||||
|
for (klass in oldClassesWithNameOverride) {
|
||||||
|
classSymbolMap[klass.symbol]?.let { newSymbol ->
|
||||||
|
classNameOverride[newSymbol.owner] = classNameOverride[klass]!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (multifileFacade in multifileFacadesToAdd) {
|
||||||
|
val oldPartClasses = multifileFacade.value
|
||||||
|
val newPartClasses = oldPartClasses.map { classSymbolMap[it.symbol]?.owner ?: it }
|
||||||
|
multifileFacade.setValue(newPartClasses.toMutableList())
|
||||||
|
}
|
||||||
|
|
||||||
|
super.handleDeepCopy(classSymbolMap, functionSymbolMap)
|
||||||
|
}
|
||||||
|
|
||||||
inner class JvmIr(
|
inner class JvmIr(
|
||||||
irModuleFragment: IrModuleFragment,
|
irModuleFragment: IrModuleFragment,
|
||||||
symbolTable: SymbolTable
|
symbolTable: SymbolTable
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* 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.util
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.ir.IrElement
|
||||||
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||||
|
|
||||||
|
fun <T : IrElement> T.deepCopySavingMetadata(
|
||||||
|
initialParent: IrDeclarationParent? = null,
|
||||||
|
symbolRemapper: DeepCopySymbolRemapper = DeepCopySymbolRemapper()
|
||||||
|
): T {
|
||||||
|
acceptVoid(symbolRemapper)
|
||||||
|
val typeRemapper = DeepCopyTypeRemapper(symbolRemapper)
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
return transform(DeepCopySavingMetadata(symbolRemapper, typeRemapper, SymbolRenamer.DEFAULT), null)
|
||||||
|
.patchDeclarationParents(initialParent) as T
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DeepCopySavingMetadata(
|
||||||
|
symbolRemapper: SymbolRemapper,
|
||||||
|
typeRemapper: TypeRemapper,
|
||||||
|
symbolRenamer: SymbolRenamer
|
||||||
|
) : DeepCopyIrTreeWithSymbols(symbolRemapper, typeRemapper, symbolRenamer) {
|
||||||
|
override fun visitFile(declaration: IrFile): IrFile =
|
||||||
|
super.visitFile(declaration).apply {
|
||||||
|
metadata = declaration.metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitClass(declaration: IrClass): IrClass =
|
||||||
|
super.visitClass(declaration).apply {
|
||||||
|
metadata = declaration.metadata
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitConstructor(declaration: IrConstructor): IrConstructor =
|
||||||
|
super.visitConstructor(declaration).apply {
|
||||||
|
metadata = declaration.metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitSimpleFunction(declaration: IrSimpleFunction): IrSimpleFunction =
|
||||||
|
super.visitSimpleFunction(declaration).apply {
|
||||||
|
metadata = declaration.metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitProperty(declaration: IrProperty): IrProperty =
|
||||||
|
super.visitProperty(declaration).apply {
|
||||||
|
metadata = declaration.metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitField(declaration: IrField): IrField =
|
||||||
|
super.visitField(declaration).apply {
|
||||||
|
metadata = declaration.metadata
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitLocalDelegatedProperty(declaration: IrLocalDelegatedProperty): IrLocalDelegatedProperty =
|
||||||
|
super.visitLocalDelegatedProperty(declaration).apply {
|
||||||
|
metadata = declaration.metadata
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user