Build function -> file map

Serialize/deserialize file name
Define FileEntryImpl
Provide IrReturnableBlock with information about source file
Move file iteration in NoJavaUtil
Insert future description comments
Move debug info (source file name) from IrFunction to IrDeclaration
This commit is contained in:
Konstantin Anisimov
2017-06-21 14:34:41 +07:00
committed by KonstantinAnisimov
parent db4388a343
commit 0582d8f1bd
9 changed files with 142 additions and 28 deletions
@@ -481,12 +481,13 @@ internal class DeepCopyIrTreeWithDescriptors(val targetDescriptor: FunctionDescr
override fun visitBlock(expression: IrBlock): IrBlock { override fun visitBlock(expression: IrBlock): IrBlock {
return if (expression is IrReturnableBlock) { return if (expression is IrReturnableBlock) {
IrReturnableBlockImpl( IrReturnableBlockImpl(
startOffset = expression.startOffset, startOffset = expression.startOffset,
endOffset = expression.endOffset, endOffset = expression.endOffset,
type = expression.type, type = expression.type,
descriptor = expression.descriptor, descriptor = expression.descriptor,
origin = mapStatementOrigin(expression.origin), origin = mapStatementOrigin(expression.origin),
statements = expression.statements.map { it.transform(this, null) } statements = expression.statements.map { it.transform(this, null) },
sourceFileName = expression.sourceFileName
) )
} else { } else {
super.visitBlock(expression) super.visitBlock(expression)
@@ -40,7 +40,8 @@ open class DeepCopyIrTreeWithReturnableBlockSymbols(
expression.startOffset, expression.endOffset, expression.startOffset, expression.endOffset,
expression.type, expression.type,
expression.descriptor, expression.descriptor,
expression.origin expression.origin,
expression.sourceFileName
).also { ).also {
transformedReturnableBlocks.put(expression, it) transformedReturnableBlocks.put(expression, it)
it.statements.addAll(expression.statements.map { it.transform() }) it.statements.addAll(expression.statements.map { it.transform() })
@@ -16,8 +16,15 @@
package org.jetbrains.kotlin.backend.konan.ir package org.jetbrains.kotlin.backend.konan.ir
import org.jetbrains.kotlin.backend.konan.util.File
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.SourceManager
import org.jetbrains.kotlin.ir.SourceRangeInfo
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
import org.jetbrains.kotlin.ir.declarations.IrVariable import org.jetbrains.kotlin.ir.declarations.IrVariable
import org.jetbrains.kotlin.ir.expressions.IrBlock import org.jetbrains.kotlin.ir.expressions.IrBlock
@@ -26,6 +33,7 @@ import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
import org.jetbrains.kotlin.ir.expressions.impl.IrContainerExpressionBase import org.jetbrains.kotlin.ir.expressions.impl.IrContainerExpressionBase
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBase import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBase
import org.jetbrains.kotlin.ir.symbols.IrBindableSymbol import org.jetbrains.kotlin.ir.symbols.IrBindableSymbol
import org.jetbrains.kotlin.ir.symbols.IrFileSymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.impl.IrBindableSymbolBase import org.jetbrains.kotlin.ir.symbols.impl.IrBindableSymbolBase
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
@@ -39,6 +47,7 @@ interface IrReturnableBlockSymbol : IrFunctionSymbol, IrBindableSymbol<FunctionD
interface IrReturnableBlock: IrBlock, IrSymbolOwner { interface IrReturnableBlock: IrBlock, IrSymbolOwner {
override val symbol: IrReturnableBlockSymbol override val symbol: IrReturnableBlockSymbol
val descriptor: FunctionDescriptor val descriptor: FunctionDescriptor
val sourceFileName: String
} }
class IrReturnableBlockSymbolImpl(descriptor: FunctionDescriptor) : class IrReturnableBlockSymbolImpl(descriptor: FunctionDescriptor) :
@@ -46,24 +55,23 @@ class IrReturnableBlockSymbolImpl(descriptor: FunctionDescriptor) :
IrReturnableBlockSymbol IrReturnableBlockSymbol
class IrReturnableBlockImpl(startOffset: Int, endOffset: Int, type: KotlinType, class IrReturnableBlockImpl(startOffset: Int, endOffset: Int, type: KotlinType,
override val symbol: IrReturnableBlockSymbol, origin: IrStatementOrigin? = null) override val symbol: IrReturnableBlockSymbol, origin: IrStatementOrigin? = null, override val sourceFileName: String = "no source file")
: IrContainerExpressionBase(startOffset, endOffset, type, origin), IrReturnableBlock { : IrContainerExpressionBase(startOffset, endOffset, type, origin), IrReturnableBlock {
override val descriptor = symbol.descriptor override val descriptor = symbol.descriptor
constructor(startOffset: Int, endOffset: Int, type: KotlinType, constructor(startOffset: Int, endOffset: Int, type: KotlinType,
symbol: IrReturnableBlockSymbol, origin: IrStatementOrigin?, statements: List<IrStatement>) : symbol: IrReturnableBlockSymbol, origin: IrStatementOrigin?, statements: List<IrStatement>, sourceFileName: String = "no source file") :
this(startOffset, endOffset, type, symbol, origin) { this(startOffset, endOffset, type, symbol, origin, sourceFileName) {
this.statements.addAll(statements) this.statements.addAll(statements)
} }
constructor(startOffset: Int, endOffset: Int, type: KotlinType, constructor(startOffset: Int, endOffset: Int, type: KotlinType,
descriptor: FunctionDescriptor, origin: IrStatementOrigin? = null) : descriptor: FunctionDescriptor, origin: IrStatementOrigin? = null, sourceFileName: String = "no source file") :
this(startOffset, endOffset, type, IrReturnableBlockSymbolImpl(descriptor), origin) this(startOffset, endOffset, type, IrReturnableBlockSymbolImpl(descriptor), origin, sourceFileName)
constructor(startOffset: Int, endOffset: Int, type: KotlinType, constructor(startOffset: Int, endOffset: Int, type: KotlinType,
descriptor: FunctionDescriptor, origin: IrStatementOrigin?, statements: List<IrStatement>) : descriptor: FunctionDescriptor, origin: IrStatementOrigin?, statements: List<IrStatement>, sourceFileName: String = "no source file") :
this(startOffset, endOffset, type, descriptor, origin) { this(startOffset, endOffset, type, descriptor, origin, sourceFileName) {
this.statements.addAll(statements) this.statements.addAll(statements)
} }
@@ -85,6 +93,97 @@ class IrReturnableBlockImpl(startOffset: Int, endOffset: Int, type: KotlinType,
} }
} }
//-----------------------------------------------------------------------------//
/**
* TODO
* FileEntry provides mapping file offset to pair line and column which are used in debug information generation.
* NaiveSourceBasedFileEntryImpl implements the functionality with calculation lines and columns at compile time,
* that obligates user to have sources of all dependencies, that not always possible and intuitively clear. Instead new
* version should rely on serialized mapping (offset to pair line and column), which should be generated at library
* 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) {
val buffer = mutableListOf<Int>()
var currentOffset = 0
file.forEachLine { line ->
buffer.add(currentOffset)
currentOffset += line.length
}
lineStartOffsets = buffer.toIntArray()
} else {
lineStartOffsets = IntArray(0)
}
}
//-------------------------------------------------------------------------//
override fun getLineNumber(offset: Int): Int {
val index = lineStartOffsets.binarySearch(offset)
return if (index >= 0) index else -index - 1
}
//-------------------------------------------------------------------------//
override fun getColumnNumber(offset: Int): Int {
var lineNumber = getLineNumber(offset)
if (lineNumber >= lineStartOffsets.size) {
lineNumber = lineStartOffsets.size - 1
}
if (lineNumber < 0) lineNumber = 0
if (lineStartOffsets.size == 0) return offset
return offset - lineStartOffsets[lineNumber]
}
//-------------------------------------------------------------------------//
override val maxOffset: Int
get() = TODO("not implemented")
override fun getSourceRangeInfo(beginOffset: Int, endOffset: Int): SourceRangeInfo {
TODO("not implemented")
}
}
//-----------------------------------------------------------------------------//
class IrFileImpl(fileName: String) : IrFile {
override val fileEntry = NaiveSourceBasedFileEntryImpl(fileName)
//-------------------------------------------------------------------------//
override val fileAnnotations: MutableList<AnnotationDescriptor>
get() = TODO("not implemented")
override val symbol: IrFileSymbol
get() = TODO("not implemented")
override val packageFragmentDescriptor: PackageFragmentDescriptor
get() = TODO("not implemented")
override val endOffset: Int
get() = TODO("not implemented")
override val startOffset: Int
get() = TODO("not implemented")
override val declarations: MutableList<IrDeclaration>
get() = TODO("not implemented")
override fun <D> acceptChildren(visitor: IrElementVisitor<Unit, D>, data: D) {
TODO("not implemented")
}
override fun <D> transformChildren(transformer: IrElementTransformer<D>, data: D) {
TODO("not implemented")
}
override fun <R, D> accept(visitor: IrElementVisitor<R, D>, data: D): R {
TODO("not implemented")
}
}
//-----------------------------------------------------------------------------// //-----------------------------------------------------------------------------//
interface IrSuspensionPoint : IrExpression { interface IrSuspensionPoint : IrExpression {
@@ -17,17 +17,17 @@
package org.jetbrains.kotlin.backend.konan.ir package org.jetbrains.kotlin.backend.konan.ir
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid import org.jetbrains.kotlin.ir.visitors.acceptVoid
class ModuleIndex(val module: IrModuleFragment) { class ModuleIndex(val module: IrModuleFragment) {
var currentFile: IrFile? = null
/** /**
* Contains all classes declared in [module] * Contains all classes declared in [module]
*/ */
@@ -37,6 +37,7 @@ class ModuleIndex(val module: IrModuleFragment) {
* Contains all functions declared in [module] * Contains all functions declared in [module]
*/ */
val functions = mutableMapOf<FunctionDescriptor, IrFunction>() val functions = mutableMapOf<FunctionDescriptor, IrFunction>()
val declarationToFile = mutableMapOf<DeclarationDescriptor, String>()
init { init {
val map = mutableMapOf<ClassDescriptor, IrClass>() val map = mutableMapOf<ClassDescriptor, IrClass>()
@@ -46,6 +47,11 @@ class ModuleIndex(val module: IrModuleFragment) {
element.acceptChildrenVoid(this) element.acceptChildrenVoid(this)
} }
override fun visitFile(declaration: IrFile) {
currentFile = declaration
super.visitFile(declaration)
}
override fun visitClass(declaration: IrClass) { override fun visitClass(declaration: IrClass) {
super.visitClass(declaration) super.visitClass(declaration)
@@ -54,11 +60,13 @@ class ModuleIndex(val module: IrModuleFragment) {
override fun visitFunction(declaration: IrFunction) { override fun visitFunction(declaration: IrFunction) {
super.visitFunction(declaration) super.visitFunction(declaration)
functions[declaration.descriptor] = declaration
val functionDescriptor = declaration.descriptor
functions[functionDescriptor] = declaration
} }
override fun visitDeclaration(declaration: IrDeclaration) {
super.visitDeclaration(declaration)
declarationToFile[declaration.descriptor] = currentFile!!.name
}
}) })
classes = map classes = map
@@ -24,8 +24,6 @@ import org.jetbrains.kotlin.backend.common.ir.ir2string
import org.jetbrains.kotlin.backend.konan.* import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.backend.konan.descriptors.* import org.jetbrains.kotlin.backend.konan.descriptors.*
import org.jetbrains.kotlin.backend.konan.ir.* import org.jetbrains.kotlin.backend.konan.ir.*
import org.jetbrains.kotlin.backend.konan.library.LinkData
import org.jetbrains.kotlin.backend.konan.library.KonanLibraryWriter
import org.jetbrains.kotlin.backend.konan.library.impl.buildLibrary import org.jetbrains.kotlin.backend.konan.library.impl.buildLibrary
import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.*
@@ -1416,7 +1414,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
private inner class ReturnableBlockScope(val returnableBlock: IrReturnableBlockImpl) : InnerScopeImpl() { private inner class ReturnableBlockScope(val returnableBlock: IrReturnableBlockImpl) : FileScope(IrFileImpl(returnableBlock.sourceFileName)) {
var bbExit : LLVMBasicBlockRef? = null var bbExit : LLVMBasicBlockRef? = null
var resultPhi : LLVMValueRef? = null var resultPhi : LLVMValueRef? = null
@@ -1452,7 +1450,7 @@ internal class CodeGeneratorVisitor(val context: Context) : IrElementVisitorVoid
//-------------------------------------------------------------------------// //-------------------------------------------------------------------------//
private inner class FileScope(val file:IrFile) : InnerScopeImpl() { private open inner class FileScope(val file:IrFile) : InnerScopeImpl() {
override fun fileScope(): CodeContext? = this override fun fileScope(): CodeContext? = this
} }
@@ -132,13 +132,15 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
val statements = (copyFunctionDeclaration.body as IrBlockBody).statements // IR statements from function copy. val statements = (copyFunctionDeclaration.body as IrBlockBody).statements // IR statements from function copy.
val returnType = copyFunctionDeclaration.descriptor.returnType!! // Substituted return type. val returnType = copyFunctionDeclaration.descriptor.returnType!! // Substituted return type.
val sourceFileName = context.ir.originalModuleIndex.declarationToFile[functionDeclaration.descriptor.original]?:""
val inlineFunctionBody = IrReturnableBlockImpl( // Create new IR element to replace "call". val inlineFunctionBody = IrReturnableBlockImpl( // Create new IR element to replace "call".
startOffset = copyFunctionDeclaration.startOffset, startOffset = copyFunctionDeclaration.startOffset,
endOffset = copyFunctionDeclaration.endOffset, endOffset = copyFunctionDeclaration.endOffset,
type = returnType, type = returnType,
descriptor = copyFunctionDeclaration.descriptor.original, descriptor = copyFunctionDeclaration.descriptor.original,
origin = null, origin = null,
statements = statements statements = statements,
sourceFileName = sourceFileName
) )
val transformer = ParameterSubstitutor() val transformer = ParameterSubstitutor()
@@ -321,6 +321,7 @@ message IrDeclaration {
required Coordinates coordinates = 2; required Coordinates coordinates = 2;
required IrDeclarator declarator = 3; required IrDeclarator declarator = 3;
repeated IrDeclaration nested = 4; repeated IrDeclaration nested = 4;
required string file_name = 5;
} }
/* ------- IrStatements --------------------------------------------- */ /* ------- IrStatements --------------------------------------------- */
@@ -512,7 +512,6 @@ internal class IrSerializer(val context: Context,
proto.addDefaultArgument(pair) proto.addDefaultArgument(pair)
} }
} }
return proto.build() return proto.build()
} }
@@ -638,6 +637,8 @@ internal class IrSerializer(val context: Context,
proto.setDeclarator(declarator) proto.setDeclarator(declarator)
val fileName = context.ir.originalModuleIndex.declarationToFile[declaration.descriptor]
proto.setFileName(fileName)
return proto.build() return proto.build()
} }
@@ -1111,7 +1112,6 @@ internal class IrDeserializer(val context: Context,
descriptor.valueParameters.get(it.position), descriptor.valueParameters.get(it.position),
IrExpressionBodyImpl(start, end, expr)) IrExpressionBodyImpl(start, end, expr))
} }
return function return function
} }
@@ -1169,6 +1169,9 @@ internal class IrDeserializer(val context: Context,
} }
} }
val sourceFileName = proto.fileName
context.ir.originalModuleIndex.declarationToFile[declaration.descriptor.original] = sourceFileName
if (!(descriptor is VariableDescriptor) && descriptor != rootFunction) if (!(descriptor is VariableDescriptor) && descriptor != rootFunction)
localDeserializer.popContext(descriptor) localDeserializer.popContext(descriptor)
context.log{"### Deserialized declaration: ${ir2string(declaration)}"} context.log{"### Deserialized declaration: ${ir2string(declaration)}"}
@@ -59,6 +59,7 @@ class File(val path: String) {
fun readBytes() = javaFile.readBytes() fun readBytes() = javaFile.readBytes()
fun writeText(text: String) = javaFile.writeText(text) fun writeText(text: String) = javaFile.writeText(text)
fun writeBytes(bytes: ByteArray) = javaFile.writeBytes(bytes) fun writeBytes(bytes: ByteArray) = javaFile.writeBytes(bytes)
fun forEachLine(action: (String) -> Unit) { javaFile.forEachLine { action(it) } }
override fun toString() = path override fun toString() = path