Moved to IrReturnableBlock version with proper IrFile instead of String file name.
This commit is contained in:
committed by
Vasily Levchenko
parent
72af75f3a2
commit
67d6d47e5f
+74
-30
@@ -9,24 +9,49 @@ import org.jetbrains.kotlin.backend.konan.SYNTHETIC_OFFSET
|
||||
import org.jetbrains.kotlin.backend.konan.optimizations.DataFlowIR
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.SourceManager
|
||||
import org.jetbrains.kotlin.ir.SourceManager.FileEntry
|
||||
import org.jetbrains.kotlin.ir.SourceRangeInfo
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrClassReference
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrContainerExpressionBase
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBase
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrTerminalDeclarationReferenceBase
|
||||
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFileSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrReturnableBlockSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.konan.file.File
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
|
||||
val File.lineStartOffsets: IntArray get() {
|
||||
// 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
|
||||
this.forEachLine { line ->
|
||||
buffer.add(currentOffset)
|
||||
currentOffset += line.length + separatorLength
|
||||
}
|
||||
buffer.add(currentOffset)
|
||||
return buffer.toIntArray()
|
||||
}
|
||||
|
||||
val FileEntry.lineStartOffsets get() = File(name).let {
|
||||
if (it.exists && it.isFile) it.lineStartOffsets else IntArray(0)
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------//
|
||||
/**
|
||||
* TODO
|
||||
@@ -37,33 +62,7 @@ import org.jetbrains.kotlin.name.FqName
|
||||
* compilation stage (perhaps in or before inline face)
|
||||
*/
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
class NaiveSourceBasedFileEntryImpl(override val name: String, val lineStartOffsets: IntArray = IntArray(0)) : SourceManager.FileEntry {
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
|
||||
@@ -216,4 +215,49 @@ internal class IrPrivateClassReferenceImpl(startOffset: Int,
|
||||
{
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||
visitor.visitClassReference(this, data)
|
||||
}
|
||||
|
||||
class KonanIrReturnableBlockImpl(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
type: IrType,
|
||||
override val symbol: IrReturnableBlockSymbol,
|
||||
origin: IrStatementOrigin? = null,
|
||||
val sourceFile: IrFile? = null
|
||||
) :
|
||||
IrContainerExpressionBase(startOffset, endOffset, type, origin),
|
||||
IrReturnableBlock {
|
||||
|
||||
override val descriptor = symbol.descriptor
|
||||
|
||||
constructor(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
type: IrType,
|
||||
symbol: IrReturnableBlockSymbol,
|
||||
origin: IrStatementOrigin?,
|
||||
statements: List<IrStatement>,
|
||||
sourceFile: IrFile? = null
|
||||
) : this(startOffset, endOffset, type, symbol, origin, sourceFile) {
|
||||
this.statements.addAll(statements)
|
||||
}
|
||||
|
||||
override val sourceFileName: String = sourceFile?.fileEntry?.name ?: "no source file"
|
||||
|
||||
init {
|
||||
symbol.bind(this)
|
||||
}
|
||||
|
||||
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R =
|
||||
visitor.visitBlock(this, data)
|
||||
|
||||
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
|
||||
statements.forEach { it.accept(visitor, data) }
|
||||
}
|
||||
|
||||
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
|
||||
statements.forEachIndexed { i, irStatement ->
|
||||
statements[i] = irStatement.transform(transformer, data)
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -193,11 +193,11 @@ val IrDeclaration.isSetter get() = this is IrSimpleFunction && this == this.corr
|
||||
|
||||
val IrDeclaration.isAccessor get() = this.isGetter || this.isSetter
|
||||
|
||||
val IrDeclaration.fileEntry: SourceManager.FileEntry get() = parent.let {
|
||||
val IrDeclaration.file: IrFile get() = parent.let {
|
||||
when (it) {
|
||||
is IrFile -> it.fileEntry
|
||||
is IrFile -> it
|
||||
is IrPackageFragment -> TODO("Unknown file")
|
||||
is IrDeclaration -> it.fileEntry
|
||||
is IrDeclaration -> it.file
|
||||
else -> TODO("Unexpected declaration parent")
|
||||
}
|
||||
}
|
||||
+3
-8
@@ -27,7 +27,6 @@ import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrPropertyDelegateDescriptor
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.*
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
@@ -857,7 +856,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
is IrWhen -> return evaluateWhen (value)
|
||||
is IrThrow -> return evaluateThrow (value)
|
||||
is IrTry -> return evaluateTry (value)
|
||||
is IrReturnableBlockImpl -> return evaluateReturnableBlock (value)
|
||||
is IrReturnableBlock -> return evaluateReturnableBlock (value)
|
||||
is IrContainerExpression -> return evaluateContainerExpression (value)
|
||||
is IrWhileLoop -> return evaluateWhileLoop (value)
|
||||
is IrDoWhileLoop -> return evaluateDoWhileLoop (value)
|
||||
@@ -1661,14 +1660,10 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------//
|
||||
fun getFileEntry(sourceFileName: String): SourceManager.FileEntry =
|
||||
// We must cache file entries, otherwise we reparse same file many times.
|
||||
context.fileEntryCache.getOrPut(sourceFileName) {
|
||||
NaiveSourceBasedFileEntryImpl(sourceFileName)
|
||||
}
|
||||
val dummyFile = IrFileImpl(NaiveSourceBasedFileEntryImpl("no source file"))
|
||||
|
||||
private inner class ReturnableBlockScope(val returnableBlock: IrReturnableBlock) :
|
||||
FileScope(IrFileImpl(getFileEntry(returnableBlock.sourceFileName))) {
|
||||
FileScope((returnableBlock as? KonanIrReturnableBlockImpl)?.sourceFile ?: dummyFile) {
|
||||
|
||||
var bbExit : LLVMBasicBlockRef? = null
|
||||
var resultPhi : LLVMValueRef? = null
|
||||
|
||||
+4
-2
@@ -10,6 +10,8 @@ import org.jetbrains.kotlin.backend.common.*
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedSimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.descriptors.WrappedVariableDescriptor
|
||||
import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.ir.KonanIrReturnableBlockImpl
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.file
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
@@ -93,7 +95,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
}
|
||||
|
||||
override fun visitContainerExpression(expression: IrContainerExpression): IrExpression {
|
||||
if (expression !is IrReturnableBlockImpl)
|
||||
if (expression !is IrReturnableBlock)
|
||||
return super.visitContainerExpression(expression)
|
||||
|
||||
using(ReturnableScope(expression.symbol)) {
|
||||
@@ -292,7 +294,7 @@ internal class FinallyBlocksLowering(val context: Context): FileLoweringPass, Ir
|
||||
|
||||
private inline fun IrBuilderWithScope.irReturnableBlock(symbol: IrReturnableBlockSymbol,
|
||||
type: IrType, body: IrBlockBuilder.() -> Unit) =
|
||||
IrReturnableBlockImpl(startOffset, endOffset, type, symbol, null,
|
||||
KonanIrReturnableBlockImpl(startOffset, endOffset, type, symbol, null,
|
||||
IrBlockBuilder(context, scope, startOffset, endOffset, null, type)
|
||||
.block(body).statements)
|
||||
}
|
||||
+6
-6
@@ -17,8 +17,9 @@ import org.jetbrains.kotlin.backend.konan.Context
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isFunctionInvoke
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.needsInlining
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.resolveFakeOverride
|
||||
import org.jetbrains.kotlin.backend.konan.ir.KonanIrReturnableBlockImpl
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.constructedClass
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.fileEntry
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.file
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.isInlineParameter
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
@@ -33,7 +34,6 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrReturnableBlockImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrVarargImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.impl.IrReturnableBlockSymbolImpl
|
||||
@@ -118,7 +118,7 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
|
||||
}
|
||||
}
|
||||
|
||||
private fun inlineFunction(callSite: IrCall, callee: IrFunction): IrReturnableBlockImpl {
|
||||
private fun inlineFunction(callSite: IrCall, callee: IrFunction): KonanIrReturnableBlockImpl {
|
||||
val copiedCallee = copyIrElement.copy(callee) as IrFunction
|
||||
|
||||
val evaluationStatements = evaluateArguments(callSite, copiedCallee)
|
||||
@@ -149,7 +149,7 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
|
||||
}
|
||||
}
|
||||
|
||||
val sourceFileName = callee.fileEntry.name
|
||||
val sourceFile = callee.file
|
||||
|
||||
val transformer = ParameterSubstitutor()
|
||||
statements.transform { it.transform(transformer, data = null) }
|
||||
@@ -158,14 +158,14 @@ internal class FunctionInlining(val context: Context) : IrElementTransformerVoid
|
||||
val isCoroutineIntrinsicCall = callSite.descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(
|
||||
context.config.configuration.languageVersionSettings)
|
||||
|
||||
return IrReturnableBlockImpl(
|
||||
return KonanIrReturnableBlockImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
type = callSite.type,
|
||||
symbol = irReturnableBlockSymbol,
|
||||
origin = if (isCoroutineIntrinsicCall) CoroutineIntrinsicLambdaOrigin else null,
|
||||
statements = statements,
|
||||
sourceFileName = sourceFileName
|
||||
sourceFile = sourceFile
|
||||
).apply {
|
||||
transformChildrenVoid(object : IrElementTransformerVoid() {
|
||||
override fun visitReturn(expression: IrReturn): IrExpression {
|
||||
|
||||
+4
-2
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.backend.konan.descriptors.isInterface
|
||||
import org.jetbrains.kotlin.backend.konan.ir.IrPrivateClassReferenceImpl
|
||||
import org.jetbrains.kotlin.backend.konan.ir.IrPrivateFunctionCall
|
||||
import org.jetbrains.kotlin.backend.konan.ir.IrPrivateFunctionCallImpl
|
||||
import org.jetbrains.kotlin.backend.konan.ir.KonanIrReturnableBlockImpl
|
||||
import org.jetbrains.kotlin.backend.konan.irasdescriptors.getErasedTypeClass
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
@@ -1374,6 +1375,7 @@ internal object Devirtualization {
|
||||
}
|
||||
return when (expression) {
|
||||
is IrReturnableBlock -> {
|
||||
check(expression is KonanIrReturnableBlockImpl) // TODO: need to obtain IrFile rather than just sourceFileName
|
||||
val foldedReturnableBlockValues = returnableBlockValues[expression]!!.associate {
|
||||
it to fold(it, coercion, cast, false)
|
||||
}
|
||||
@@ -1385,14 +1387,14 @@ internal object Devirtualization {
|
||||
val oldSymbol = expression.symbol
|
||||
val newSymbol = IrReturnableBlockSymbolImpl(expression.descriptor)
|
||||
val transformedReturnableBlock = with(expression) {
|
||||
IrReturnableBlockImpl(
|
||||
KonanIrReturnableBlockImpl(
|
||||
startOffset = startOffset,
|
||||
endOffset = endOffset,
|
||||
type = coercion.type,
|
||||
symbol = newSymbol,
|
||||
origin = origin,
|
||||
statements = statements,
|
||||
sourceFileName = sourceFileName)
|
||||
sourceFile = sourceFile)
|
||||
}
|
||||
transformedReturnableBlock.transformChildrenVoid(object: IrElementTransformerVoid() {
|
||||
override fun visitExpression(expression: IrExpression): IrExpression {
|
||||
|
||||
+3
-1
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.backend.common.ir.ir2string
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.findTopLevelDeclaration
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember
|
||||
import org.jetbrains.kotlin.backend.konan.descriptors.isSerializableExpectClass
|
||||
import org.jetbrains.kotlin.backend.konan.ir.lineStartOffsets
|
||||
import org.jetbrains.kotlin.backend.konan.library.SerializedIr
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind.*
|
||||
@@ -1046,6 +1047,7 @@ internal class IrModuleSerializer(
|
||||
|
||||
fun serializeFileEntry(entry: SourceManager.FileEntry) = KonanIr.FileEntry.newBuilder()
|
||||
.setName(serializeString(entry.name))
|
||||
.addAllLineStartOffsets(entry.lineStartOffsets.asIterable())
|
||||
.build()
|
||||
|
||||
val topLevelDeclarations = mutableMapOf<UniqId, ByteArray>()
|
||||
@@ -1053,7 +1055,7 @@ internal class IrModuleSerializer(
|
||||
fun serializeIrFile(file: IrFile): KonanIr.IrFile {
|
||||
val proto = KonanIr.IrFile.newBuilder()
|
||||
.setFileEntry(serializeFileEntry(file.fileEntry))
|
||||
.setFqName(file.fqName.toString())
|
||||
.setFqName(serializeString(file.fqName.toString()))
|
||||
|
||||
file.declarations.forEach {
|
||||
if (it is IrTypeAlias) return@forEach
|
||||
|
||||
+3
-3
@@ -80,15 +80,15 @@ message IrDeclarationContainer {
|
||||
repeated IrDeclaration declaration = 1;
|
||||
}
|
||||
|
||||
message FileEntry { // TODO: extend me.
|
||||
message FileEntry {
|
||||
required String name = 1;
|
||||
repeated int32 line_start_offsets = 2;
|
||||
}
|
||||
|
||||
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;
|
||||
required String fq_name = 3;
|
||||
}
|
||||
|
||||
message IrModule {
|
||||
|
||||
+5
-2
@@ -310,10 +310,13 @@ class KonanIrModuleDeserializer(
|
||||
}
|
||||
|
||||
fun deserializeIrFile(fileProto: KonanIr.IrFile, moduleDescriptor: ModuleDescriptor, deserializeAllDeclarations: Boolean): IrFile {
|
||||
val fileEntry = NaiveSourceBasedFileEntryImpl(deserializeString(fileProto.fileEntry.name))
|
||||
val fileEntry = NaiveSourceBasedFileEntryImpl(
|
||||
deserializeString(fileProto.fileEntry.name),
|
||||
fileProto.fileEntry.lineStartOffsetsList.toIntArray()
|
||||
)
|
||||
|
||||
// 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 fqName = deserializeString(fileProto.fqName).let { if (it == "<root>") FqName.ROOT else FqName(it) }
|
||||
|
||||
val packageFragmentDescriptor = EmptyPackageFragmentDescriptor(moduleDescriptor, fqName)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user