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 {
return if (expression is IrReturnableBlock) {
IrReturnableBlockImpl(
startOffset = expression.startOffset,
endOffset = expression.endOffset,
type = expression.type,
descriptor = expression.descriptor,
origin = mapStatementOrigin(expression.origin),
statements = expression.statements.map { it.transform(this, null) }
startOffset = expression.startOffset,
endOffset = expression.endOffset,
type = expression.type,
descriptor = expression.descriptor,
origin = mapStatementOrigin(expression.origin),
statements = expression.statements.map { it.transform(this, null) },
sourceFileName = expression.sourceFileName
)
} else {
super.visitBlock(expression)
@@ -40,7 +40,8 @@ open class DeepCopyIrTreeWithReturnableBlockSymbols(
expression.startOffset, expression.endOffset,
expression.type,
expression.descriptor,
expression.origin
expression.origin,
expression.sourceFileName
).also {
transformedReturnableBlocks.put(expression, it)
it.statements.addAll(expression.statements.map { it.transform() })
@@ -16,8 +16,15 @@
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.PackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
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.IrVariable
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.IrExpressionBase
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.impl.IrBindableSymbolBase
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
@@ -39,6 +47,7 @@ interface IrReturnableBlockSymbol : IrFunctionSymbol, IrBindableSymbol<FunctionD
interface IrReturnableBlock: IrBlock, IrSymbolOwner {
override val symbol: IrReturnableBlockSymbol
val descriptor: FunctionDescriptor
val sourceFileName: String
}
class IrReturnableBlockSymbolImpl(descriptor: FunctionDescriptor) :
@@ -46,24 +55,23 @@ class IrReturnableBlockSymbolImpl(descriptor: FunctionDescriptor) :
IrReturnableBlockSymbol
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 {
override val descriptor = symbol.descriptor
constructor(startOffset: Int, endOffset: Int, type: KotlinType,
symbol: IrReturnableBlockSymbol, origin: IrStatementOrigin?, statements: List<IrStatement>) :
this(startOffset, endOffset, type, symbol, origin) {
symbol: IrReturnableBlockSymbol, origin: IrStatementOrigin?, statements: List<IrStatement>, sourceFileName: String = "no source file") :
this(startOffset, endOffset, type, symbol, origin, sourceFileName) {
this.statements.addAll(statements)
}
constructor(startOffset: Int, endOffset: Int, type: KotlinType,
descriptor: FunctionDescriptor, origin: IrStatementOrigin? = null) :
this(startOffset, endOffset, type, IrReturnableBlockSymbolImpl(descriptor), origin)
descriptor: FunctionDescriptor, origin: IrStatementOrigin? = null, sourceFileName: String = "no source file") :
this(startOffset, endOffset, type, IrReturnableBlockSymbolImpl(descriptor), origin, sourceFileName)
constructor(startOffset: Int, endOffset: Int, type: KotlinType,
descriptor: FunctionDescriptor, origin: IrStatementOrigin?, statements: List<IrStatement>) :
this(startOffset, endOffset, type, descriptor, origin) {
descriptor: FunctionDescriptor, origin: IrStatementOrigin?, statements: List<IrStatement>, sourceFileName: String = "no source file") :
this(startOffset, endOffset, type, descriptor, origin, sourceFileName) {
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 {
@@ -17,17 +17,17 @@
package org.jetbrains.kotlin.backend.konan.ir
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
import org.jetbrains.kotlin.ir.visitors.acceptVoid
class ModuleIndex(val module: IrModuleFragment) {
var currentFile: IrFile? = null
/**
* Contains all classes declared in [module]
*/
@@ -37,6 +37,7 @@ class ModuleIndex(val module: IrModuleFragment) {
* Contains all functions declared in [module]
*/
val functions = mutableMapOf<FunctionDescriptor, IrFunction>()
val declarationToFile = mutableMapOf<DeclarationDescriptor, String>()
init {
val map = mutableMapOf<ClassDescriptor, IrClass>()
@@ -46,6 +47,11 @@ class ModuleIndex(val module: IrModuleFragment) {
element.acceptChildrenVoid(this)
}
override fun visitFile(declaration: IrFile) {
currentFile = declaration
super.visitFile(declaration)
}
override fun visitClass(declaration: IrClass) {
super.visitClass(declaration)
@@ -54,11 +60,13 @@ class ModuleIndex(val module: IrModuleFragment) {
override fun visitFunction(declaration: IrFunction) {
super.visitFunction(declaration)
val functionDescriptor = declaration.descriptor
functions[functionDescriptor] = declaration
functions[declaration.descriptor] = declaration
}
override fun visitDeclaration(declaration: IrDeclaration) {
super.visitDeclaration(declaration)
declarationToFile[declaration.descriptor] = currentFile!!.name
}
})
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.descriptors.*
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.builtins.KotlinBuiltIns
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 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
}
@@ -132,13 +132,15 @@ private class Inliner(val globalSubstituteMap: MutableMap<DeclarationDescriptor,
val statements = (copyFunctionDeclaration.body as IrBlockBody).statements // IR statements from function copy.
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".
startOffset = copyFunctionDeclaration.startOffset,
endOffset = copyFunctionDeclaration.endOffset,
type = returnType,
descriptor = copyFunctionDeclaration.descriptor.original,
origin = null,
statements = statements
statements = statements,
sourceFileName = sourceFileName
)
val transformer = ParameterSubstitutor()
@@ -321,6 +321,7 @@ message IrDeclaration {
required Coordinates coordinates = 2;
required IrDeclarator declarator = 3;
repeated IrDeclaration nested = 4;
required string file_name = 5;
}
/* ------- IrStatements --------------------------------------------- */
@@ -512,7 +512,6 @@ internal class IrSerializer(val context: Context,
proto.addDefaultArgument(pair)
}
}
return proto.build()
}
@@ -638,6 +637,8 @@ internal class IrSerializer(val context: Context,
proto.setDeclarator(declarator)
val fileName = context.ir.originalModuleIndex.declarationToFile[declaration.descriptor]
proto.setFileName(fileName)
return proto.build()
}
@@ -1111,7 +1112,6 @@ internal class IrDeserializer(val context: Context,
descriptor.valueParameters.get(it.position),
IrExpressionBodyImpl(start, end, expr))
}
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)
localDeserializer.popContext(descriptor)
context.log{"### Deserialized declaration: ${ir2string(declaration)}"}
@@ -59,6 +59,7 @@ class File(val path: String) {
fun readBytes() = javaFile.readBytes()
fun writeText(text: String) = javaFile.writeText(text)
fun writeBytes(bytes: ByteArray) = javaFile.writeBytes(bytes)
fun forEachLine(action: (String) -> Unit) { javaFile.forEachLine { action(it) } }
override fun toString() = path