JVM_IR: Implement some BE diagnostics

TODO proper diagnostics tests with BE diagnostics
This commit is contained in:
Dmitry Petrov
2020-01-31 14:29:24 +03:00
parent c9df17f2f1
commit 8ef79f932c
14 changed files with 138 additions and 43 deletions
@@ -16,37 +16,36 @@
package org.jetbrains.kotlin.codegen
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.codegen.inline.InlineCall
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
class InlineCycleReporter(private val diagnostics: DiagnosticSink) {
private val processingFunctions = linkedMapOf<PsiElement, CallableDescriptor>()
private val processingFunctions = linkedMapOf<Any, InlineCall>()
fun enterIntoInlining(call: ResolvedCall<*>?): Boolean {
//null call for default method inlining
if (call != null) {
val callElement = call.call.callElement
if (processingFunctions.contains(callElement)) {
val cycle = processingFunctions.asSequence().dropWhile { it.key != callElement }
cycle.forEach {
diagnostics.report(Errors.INLINE_CALL_CYCLE.on(it.key, it.value))
fun enterIntoInlining(call: InlineCall?): Boolean {
// null call for default method inlining
val id = call?.id
if (id != null) {
if (processingFunctions.contains(id)) {
val cycle = processingFunctions.values.dropWhile { it.id != id }
for (cycleCall in cycle) {
val callPsiElement = cycleCall.callElement
if (callPsiElement != null) {
diagnostics.report(Errors.INLINE_CALL_CYCLE.on(callPsiElement, cycleCall.calleeDescriptor))
}
}
return false
}
processingFunctions.put(callElement, call.resultingDescriptor.original)
processingFunctions[id] = call
}
return true
}
fun exitFromInliningOf(call: ResolvedCall<*>?) {
fun exitFromInliningOf(call: InlineCall?) {
if (call != null) {
val callElement = call.call.callElement
processingFunctions.remove(callElement)
processingFunctions.remove(call.id)
}
}
}
@@ -16,12 +16,12 @@ class GlobalInlineContext(diagnostics: DiagnosticSink) {
private val typesUsedInInlineFunctions = LinkedList<MutableSet<String>>()
fun enterIntoInlining(call: ResolvedCall<*>?) =
fun enterIntoInlining(call: InlineCall?) =
inlineCycleReporter.enterIntoInlining(call).also {
if (it) typesUsedInInlineFunctions.push(hashSetOf())
}
fun exitFromInliningOf(call: ResolvedCall<*>?) {
fun exitFromInliningOf(call: InlineCall?) {
inlineCycleReporter.exitFromInliningOf(call)
val pop = typesUsedInInlineFunctions.pop()
typesUsedInInlineFunctions.peek()?.addAll(pop)
@@ -0,0 +1,32 @@
/*
* 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.codegen.inline
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
interface InlineCall {
val id: Any
val calleeDescriptor: CallableDescriptor
val callElement: PsiElement?
}
class InlineCallImpl(
override val calleeDescriptor: CallableDescriptor,
override val callElement: PsiElement
) : InlineCall {
override val id: Any
get() = callElement
companion object {
fun of(resolvedCall: ResolvedCall<*>?) =
resolvedCall?.run {
InlineCallImpl(resultingDescriptor.original, call.callElement)
}
}
}
@@ -60,14 +60,15 @@ class PsiInlineCodegen(
callDefault: Boolean,
codegen: ExpressionCodegen
) {
if (!state.globalInlineContext.enterIntoInlining(resolvedCall)) {
val inlineCall = InlineCallImpl.of(resolvedCall)
if (!state.globalInlineContext.enterIntoInlining(inlineCall)) {
generateStub(resolvedCall, codegen)
return
}
try {
performInline(resolvedCall?.typeArguments?.keys?.toList(), callDefault, callDefault, codegen.typeSystem)
} finally {
state.globalInlineContext.exitFromInliningOf(resolvedCall)
state.globalInlineContext.exitFromInliningOf(inlineCall)
}
}