Basic support of source mapping in inliner
This commit is contained in:
@@ -16,9 +16,8 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.codegen
|
package org.jetbrains.kotlin.codegen
|
||||||
|
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
|
||||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||||
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
import org.jetbrains.kotlin.psi.KtFile
|
||||||
import org.jetbrains.kotlin.psi.KtNamedFunction
|
import org.jetbrains.kotlin.psi.KtNamedFunction
|
||||||
|
|
||||||
@@ -26,17 +25,24 @@ data class SourceInfo(val source: String, val pathOrCleanFQN: String, val linesI
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun createInfo(element: KtElement?, internalClassName: String): SourceInfo {
|
fun createInfo(element: KtElement?, internalClassName: String): SourceInfo {
|
||||||
assert(element != null) { "Couldn't create source mapper for null element " + internalClassName }
|
assert(element != null) { "Couldn't create source mapper for null element $internalClassName" }
|
||||||
val lineNumbers = CodegenUtil.getLineNumberForElement(element!!.containingFile, true)
|
val lineNumbers = CodegenUtil.getLineNumberForElement(element!!.containingFile, true)
|
||||||
assert(lineNumbers != null) { "Couldn't extract line count in " + element.containingFile }
|
?: error("Couldn't extract line count in ${element.containingFile}")
|
||||||
|
|
||||||
//TODO hack condition for package parts cleaning
|
//TODO hack condition for package parts cleaning
|
||||||
val isTopLevel = element is KtFile || (element is KtNamedFunction && element.getParent() is KtFile)
|
val isTopLevel = element is KtFile || (element is KtNamedFunction && element.getParent() is KtFile)
|
||||||
val cleanedClassFqName = if (!isTopLevel) internalClassName else internalClassName.substringBefore('$')
|
val cleanedClassFqName = if (!isTopLevel) internalClassName else internalClassName.substringBefore('$')
|
||||||
|
|
||||||
return SourceInfo(element.containingKtFile.name, cleanedClassFqName, lineNumbers!!)
|
return SourceInfo(element.containingKtFile.name, cleanedClassFqName, lineNumbers)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun createInfoForIr(lineNumbers: Int, internalClassName: String, containingFileName: String): SourceInfo {
|
||||||
|
//TODO cut topLevel names
|
||||||
|
// val isTopLevel = element is KtFile || (element is KtNamedFunction && element.getParent() is KtFile)
|
||||||
|
// val cleanedClassFqName = if (!isTopLevel) internalClassName else internalClassName.substringBefore('$')
|
||||||
|
|
||||||
|
return SourceInfo(containingFileName, internalClassName, lineNumbers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -274,7 +274,7 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
|||||||
|
|
||||||
//for maxLocals calculation
|
//for maxLocals calculation
|
||||||
val maxCalcAdapter = wrapWithMaxLocalCalc(node)
|
val maxCalcAdapter = wrapWithMaxLocalCalc(node)
|
||||||
val parentContext = context.parentContext ?: error("Context has no parent: $context")
|
val parentContext = context.parentContext ?: error("Context has no parent: " + context)
|
||||||
val methodContext = parentContext.intoFunction(callableDescriptor)
|
val methodContext = parentContext.intoFunction(callableDescriptor)
|
||||||
|
|
||||||
val smap = if (callDefault) {
|
val smap = if (callDefault) {
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
|||||||
|
|
||||||
class JvmBackendContext(
|
class JvmBackendContext(
|
||||||
val state: GenerationState,
|
val state: GenerationState,
|
||||||
psiSourceManager: PsiSourceManager,
|
val psiSourceManager: PsiSourceManager,
|
||||||
override val irBuiltIns: IrBuiltIns,
|
override val irBuiltIns: IrBuiltIns,
|
||||||
irModuleFragment: IrModuleFragment, symbolTable: SymbolTable
|
irModuleFragment: IrModuleFragment, symbolTable: SymbolTable
|
||||||
) : CommonBackendContext {
|
) : CommonBackendContext {
|
||||||
|
|||||||
+30
-5
@@ -16,12 +16,13 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmDescriptorWithExtraFlags
|
import org.jetbrains.kotlin.backend.jvm.descriptors.JvmDescriptorWithExtraFlags
|
||||||
import org.jetbrains.kotlin.codegen.*
|
import org.jetbrains.kotlin.codegen.*
|
||||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||||
|
import org.jetbrains.kotlin.codegen.inline.DefaultSourceMapper
|
||||||
|
import org.jetbrains.kotlin.codegen.inline.SourceMapper
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.*
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.util.dump
|
import org.jetbrains.kotlin.ir.util.dump
|
||||||
@@ -32,7 +33,6 @@ import org.jetbrains.kotlin.resolve.DescriptorUtils
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.isTopLevelDeclaration
|
import org.jetbrains.kotlin.resolve.DescriptorUtils.isTopLevelDeclaration
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
|
||||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
|
||||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||||
import org.jetbrains.kotlin.types.ErrorUtils
|
import org.jetbrains.kotlin.types.ErrorUtils
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
@@ -60,10 +60,16 @@ class ClassCodegen private constructor(
|
|||||||
descriptor.source.getPsi() as KtElement
|
descriptor.source.getPsi() as KtElement
|
||||||
) else typeMapper.mapType(descriptor)
|
) else typeMapper.mapType(descriptor)
|
||||||
|
|
||||||
|
private val sourceManager = context.psiSourceManager
|
||||||
|
|
||||||
|
private val fileEntry = sourceManager.getFileEntry(irClass.fileParent)
|
||||||
|
|
||||||
val psiElement = irClass.descriptor.psiElement!!
|
val psiElement = irClass.descriptor.psiElement!!
|
||||||
|
|
||||||
val visitor: ClassBuilder = state.factory.newVisitor(OtherOrigin(psiElement, descriptor), type, psiElement.containingFile)
|
val visitor: ClassBuilder = state.factory.newVisitor(OtherOrigin(psiElement, descriptor), type, psiElement.containingFile)
|
||||||
|
|
||||||
|
private var sourceMapper: DefaultSourceMapper? = null
|
||||||
|
|
||||||
fun generate() {
|
fun generate() {
|
||||||
val superClassInfo = SuperClassInfo.getSuperClassInfo(descriptor, typeMapper)
|
val superClassInfo = SuperClassInfo.getSuperClassInfo(descriptor, typeMapper)
|
||||||
val signature = ImplementationBodyCodegen.signature(descriptor, type, superClassInfo, typeMapper)
|
val signature = ImplementationBodyCodegen.signature(descriptor, type, superClassInfo, typeMapper)
|
||||||
@@ -83,8 +89,16 @@ class ClassCodegen private constructor(
|
|||||||
generateDeclaration(it)
|
generateDeclaration(it)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun done() {
|
||||||
writeInnerClasses()
|
writeInnerClasses()
|
||||||
|
|
||||||
|
sourceMapper?.let {
|
||||||
|
SourceMapper.flushToClassBuilder(it, visitor)
|
||||||
|
}
|
||||||
|
|
||||||
visitor.done()
|
visitor.done()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,6 +206,20 @@ class ClassCodegen private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun getOrCreateSourceMapper(): DefaultSourceMapper {
|
||||||
|
if (sourceMapper == null) {
|
||||||
|
sourceMapper = DefaultSourceMapper(
|
||||||
|
SourceInfo.createInfoForIr(
|
||||||
|
fileEntry.getSourceRangeInfo(irClass.startOffset, irClass.endOffset).endLineNumber + 1,
|
||||||
|
irClass.name.asString(),
|
||||||
|
fileEntry.name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return sourceMapper!!
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun ClassDescriptor.calculateClassFlags(): Int {
|
fun ClassDescriptor.calculateClassFlags(): Int {
|
||||||
@@ -269,9 +297,6 @@ private val MemberDescriptor.effectiveModality: Modality
|
|||||||
return modality
|
return modality
|
||||||
}
|
}
|
||||||
|
|
||||||
private val DeclarationDescriptorWithSource.psiElement: PsiElement?
|
|
||||||
get() = (source as? PsiSourceElement)?.psi
|
|
||||||
|
|
||||||
private val IrField.OtherOrigin: JvmDeclarationOrigin
|
private val IrField.OtherOrigin: JvmDeclarationOrigin
|
||||||
get() = OtherOrigin(descriptor.psiElement, this.descriptor)
|
get() = OtherOrigin(descriptor.psiElement, this.descriptor)
|
||||||
|
|
||||||
|
|||||||
+15
-9
@@ -23,10 +23,7 @@ import org.jetbrains.kotlin.codegen.signature.BothSignatureWriter
|
|||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor
|
||||||
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.IrTypeAlias
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
|
||||||
import org.jetbrains.kotlin.ir.expressions.*
|
import org.jetbrains.kotlin.ir.expressions.*
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.dump
|
import org.jetbrains.kotlin.ir.util.dump
|
||||||
@@ -109,11 +106,18 @@ class ExpressionCodegen(
|
|||||||
|
|
||||||
val state = classCodegen.state
|
val state = classCodegen.state
|
||||||
|
|
||||||
|
private val sourceManager = classCodegen.context.psiSourceManager
|
||||||
|
|
||||||
|
private val fileEntry = sourceManager.getFileEntry(irFunction.fileParent)
|
||||||
|
|
||||||
fun generate() {
|
fun generate() {
|
||||||
mv.visitCode()
|
mv.visitCode()
|
||||||
|
irFunction.markLineNumber(true)
|
||||||
val info = BlockInfo.create()
|
val info = BlockInfo.create()
|
||||||
val result = irFunction.body!!.accept(this, info)
|
val result = irFunction.body!!.accept(this, info)
|
||||||
|
|
||||||
|
irFunction.markLineNumber(false)
|
||||||
|
|
||||||
val returnType = typeMapper.mapReturnType(irFunction.descriptor)
|
val returnType = typeMapper.mapReturnType(irFunction.descriptor)
|
||||||
if (irFunction.body is IrExpressionBody) {
|
if (irFunction.body is IrExpressionBody) {
|
||||||
mv.areturn(returnType)
|
mv.areturn(returnType)
|
||||||
@@ -526,11 +530,6 @@ class ExpressionCodegen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fun markNewLabel(): Label {
|
|
||||||
return Label().apply { mv.visitLabel(this) }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitReturn(expression: IrReturn, data: BlockInfo): StackValue {
|
override fun visitReturn(expression: IrReturn, data: BlockInfo): StackValue {
|
||||||
val value = expression.value.apply {
|
val value = expression.value.apply {
|
||||||
gen(this, returnType, data)
|
gen(this, returnType, data)
|
||||||
@@ -539,6 +538,7 @@ class ExpressionCodegen(
|
|||||||
val afterReturnLabel = Label()
|
val afterReturnLabel = Label()
|
||||||
generateFinallyBlocksIfNeeded(returnType, afterReturnLabel, data)
|
generateFinallyBlocksIfNeeded(returnType, afterReturnLabel, data)
|
||||||
|
|
||||||
|
expression.markLineNumber(false)
|
||||||
mv.areturn(returnType)
|
mv.areturn(returnType)
|
||||||
mv.mark(afterReturnLabel)
|
mv.mark(afterReturnLabel)
|
||||||
mv.nop()/*TODO check RESTORE_STACK_IN_TRY_CATCH processor*/
|
mv.nop()/*TODO check RESTORE_STACK_IN_TRY_CATCH processor*/
|
||||||
@@ -1087,6 +1087,12 @@ class ExpressionCodegen(
|
|||||||
override fun markLineNumberAfterInlineIfNeeded() {
|
override fun markLineNumberAfterInlineIfNeeded() {
|
||||||
//TODO
|
//TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun markNewLabel() = Label().apply { mv.visitLabel(this) }
|
||||||
|
|
||||||
|
private fun IrElement.markLineNumber(startOffset: Boolean) {
|
||||||
|
mv.visitLineNumber(fileEntry.getLineNumber(if (startOffset) this.startOffset else endOffset) + 1, markNewLabel())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class DefaultArg(val index: Int)
|
private class DefaultArg(val index: Int)
|
||||||
|
|||||||
+4
-5
@@ -53,8 +53,9 @@ class IrSourceCompilerForInline(
|
|||||||
override val callElementText: String
|
override val callElementText: String
|
||||||
get() = callElement.toString()
|
get() = callElement.toString()
|
||||||
|
|
||||||
|
//TODO
|
||||||
override val callsiteFile: PsiFile?
|
override val callsiteFile: PsiFile?
|
||||||
get() = TODO("not implemented")
|
get() = callElement.descriptor.psiElement?.containingFile
|
||||||
|
|
||||||
override val contextKind: OwnerKind
|
override val contextKind: OwnerKind
|
||||||
get() = OwnerKind.getMemberOwnerKind(callElement.descriptor.containingDeclaration)
|
get() = OwnerKind.getMemberOwnerKind(callElement.descriptor.containingDeclaration)
|
||||||
@@ -63,21 +64,19 @@ class IrSourceCompilerForInline(
|
|||||||
get() = InlineCallSiteInfo("TODO", null, null)
|
get() = InlineCallSiteInfo("TODO", null, null)
|
||||||
|
|
||||||
override val lazySourceMapper: DefaultSourceMapper
|
override val lazySourceMapper: DefaultSourceMapper
|
||||||
get() = DefaultSourceMapper(SourceInfo("TODO", "TODO", 100))
|
get() = codegen.classCodegen.getOrCreateSourceMapper()
|
||||||
|
|
||||||
override fun generateLambdaBody(adapter: MethodVisitor, jvmMethodSignature: JvmMethodSignature, lambdaInfo: ExpressionLambda): SMAP {
|
override fun generateLambdaBody(adapter: MethodVisitor, jvmMethodSignature: JvmMethodSignature, lambdaInfo: ExpressionLambda): SMAP {
|
||||||
lambdaInfo as? IrExpressionLambda ?: error("Expecting ir lambda, but $lambdaInfo")
|
lambdaInfo as? IrExpressionLambda ?: error("Expecting ir lambda, but $lambdaInfo")
|
||||||
|
|
||||||
val functionCodegen = object : FunctionCodegen(lambdaInfo.function, codegen.classCodegen) {
|
val functionCodegen = object : FunctionCodegen(lambdaInfo.function, codegen.classCodegen) {
|
||||||
override fun createMethod(flags: Int, signature: JvmMethodGenericSignature): MethodVisitor {
|
override fun createMethod(flags: Int, signature: JvmMethodGenericSignature): MethodVisitor {
|
||||||
//TODO: to avoid smap assertion
|
|
||||||
adapter.visitLineNumber(1, Label())
|
|
||||||
return adapter
|
return adapter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
functionCodegen.generate()
|
functionCodegen.generate()
|
||||||
|
|
||||||
return SMAP(/*TODO*/listOf(FileMapping("TODO", "TODO").also { it.id = 1; it.addRangeMapping(RangeMapping(1, 1, 1)) }))
|
return SMAP(codegen.classCodegen.getOrCreateSourceMapper().resultMappings)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun doCreateMethodNodeFromSource(
|
override fun doCreateMethodNodeFromSource(
|
||||||
|
|||||||
+16
-4
@@ -5,14 +5,14 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||||
|
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
import org.jetbrains.kotlin.codegen.FrameMapBase
|
import org.jetbrains.kotlin.codegen.FrameMapBase
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptorWithSource
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
import org.jetbrains.kotlin.ir.declarations.*
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
|
||||||
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
|
|
||||||
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
import org.jetbrains.kotlin.ir.symbols.IrSymbol
|
||||||
import org.jetbrains.kotlin.ir.util.*
|
import org.jetbrains.kotlin.ir.util.*
|
||||||
import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME
|
import org.jetbrains.kotlin.resolve.annotations.JVM_STATIC_ANNOTATION_FQ_NAME
|
||||||
|
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
||||||
import org.jetbrains.org.objectweb.asm.Type
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
class IrFrameMap : FrameMapBase<IrSymbol>()
|
class IrFrameMap : FrameMapBase<IrSymbol>()
|
||||||
@@ -30,3 +30,15 @@ fun IrFrameMap.leave(irDeclaration: IrSymbolOwner): Int {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val IrClass.isJvmInterface get() = isAnnotationClass || isInterface
|
val IrClass.isJvmInterface get() = isAnnotationClass || isInterface
|
||||||
|
|
||||||
|
internal val IrDeclaration.fileParent: IrFile
|
||||||
|
get() {
|
||||||
|
val myParent = parent
|
||||||
|
return when (myParent) {
|
||||||
|
is IrFile -> myParent
|
||||||
|
else -> (myParent as IrDeclaration).fileParent
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal val DeclarationDescriptorWithSource.psiElement: PsiElement?
|
||||||
|
get() = (source as? PsiSourceElement)?.psi
|
||||||
|
|||||||
Reference in New Issue
Block a user