[FIR2IR] Recognize postfix inc/dec blocks in sequence of statements
This commit is contained in:
committed by
TeamCityServer
parent
c13822a2c5
commit
489c9ae11f
@@ -542,8 +542,56 @@ class Fir2IrVisitor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun List<FirStatement>.mapToIrStatements(): List<IrStatement?> {
|
private fun List<FirStatement>.mapToIrStatements(recognizePostfixIncDec: Boolean = true): List<IrStatement?> {
|
||||||
return map { it.toIrStatement() }
|
var index = 0
|
||||||
|
val result = ArrayList<IrStatement?>(size)
|
||||||
|
while (index < size) {
|
||||||
|
var irStatement: IrStatement? = null
|
||||||
|
if (recognizePostfixIncDec) {
|
||||||
|
val statementsOrigin = getStatementsOrigin(index)
|
||||||
|
if (statementsOrigin != null) {
|
||||||
|
val subStatements = this.subList(index, index + 3).mapNotNull { it.toIrStatement() }
|
||||||
|
irStatement = IrBlockImpl(
|
||||||
|
subStatements[0].startOffset,
|
||||||
|
subStatements[2].endOffset,
|
||||||
|
(subStatements[0] as IrVariable).type,
|
||||||
|
statementsOrigin,
|
||||||
|
subStatements
|
||||||
|
)
|
||||||
|
index += 3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (irStatement == null) {
|
||||||
|
irStatement = this[index].toIrStatement()
|
||||||
|
index++
|
||||||
|
}
|
||||||
|
result.add(irStatement)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun List<FirStatement>.getStatementsOrigin(index: Int): IrStatementOrigin? {
|
||||||
|
if (index + 3 > size) return null
|
||||||
|
|
||||||
|
val statement0 = this[index]
|
||||||
|
if (statement0 !is FirProperty || !statement0.isLocal) return null
|
||||||
|
val unarySymbol = statement0.symbol
|
||||||
|
if (unarySymbol.callableId.callableName != SpecialNames.UNARY) return null
|
||||||
|
val variable = statement0.initializer?.toResolvedCallableSymbol() ?: return null
|
||||||
|
|
||||||
|
val statement2 = this[index + 2]
|
||||||
|
if (statement2 !is FirPropertyAccessExpression) return null
|
||||||
|
if (statement2.calleeReference.toResolvedCallableSymbol() != unarySymbol) return null
|
||||||
|
|
||||||
|
val incrementStatement = this[index + 1]
|
||||||
|
if (incrementStatement !is FirVariableAssignment) return null
|
||||||
|
|
||||||
|
if (incrementStatement.lValue.toResolvedCallableSymbol() != variable) return null
|
||||||
|
|
||||||
|
val origin = incrementStatement.getIrAssignmentOrigin()
|
||||||
|
return if (origin == IrStatementOrigin.EQ) null else origin
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun convertToIrBlockBody(block: FirBlock): IrBlockBody {
|
internal fun convertToIrBlockBody(block: FirBlock): IrBlockBody {
|
||||||
@@ -591,37 +639,25 @@ class Fir2IrVisitor(
|
|||||||
else
|
else
|
||||||
(lastOrNull() as? FirExpression)?.typeRef?.toIrType() ?: irBuiltIns.unitType
|
(lastOrNull() as? FirExpression)?.typeRef?.toIrType() ?: irBuiltIns.unitType
|
||||||
return source.convertWithOffsets { startOffset, endOffset ->
|
return source.convertWithOffsets { startOffset, endOffset ->
|
||||||
val itStatements = mapToIrStatements().filterNotNull()
|
|
||||||
if (origin == IrStatementOrigin.DO_WHILE_LOOP) {
|
if (origin == IrStatementOrigin.DO_WHILE_LOOP) {
|
||||||
IrCompositeImpl(startOffset, endOffset, type, origin, itStatements)
|
IrCompositeImpl(
|
||||||
|
startOffset, endOffset, type, origin,
|
||||||
|
mapToIrStatements(recognizePostfixIncDec = false).filterNotNull()
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
IrBlockImpl(startOffset, endOffset, type, getStatementsOrigin() ?: origin, itStatements)
|
val irStatements = mapToIrStatements()
|
||||||
|
val singleStatement = irStatements.singleOrNull()
|
||||||
|
if (singleStatement is IrBlock &&
|
||||||
|
(singleStatement.origin == IrStatementOrigin.POSTFIX_INCR || singleStatement.origin == IrStatementOrigin.POSTFIX_DECR)
|
||||||
|
) {
|
||||||
|
singleStatement
|
||||||
|
} else {
|
||||||
|
IrBlockImpl(startOffset, endOffset, type, origin, irStatements.filterNotNull())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun List<FirStatement>.getStatementsOrigin(): IrStatementOrigin? {
|
|
||||||
if (size != 3) return null
|
|
||||||
|
|
||||||
val statement0 = this[0]
|
|
||||||
if (statement0 !is FirProperty || !statement0.isLocal) return null
|
|
||||||
val unarySymbol = statement0.symbol
|
|
||||||
if (unarySymbol.callableId.callableName != SpecialNames.UNARY) return null
|
|
||||||
|
|
||||||
val statement2 = this[2]
|
|
||||||
if (statement2 !is FirPropertyAccessExpression) return null
|
|
||||||
if (statement2.calleeReference.toResolvedCallableSymbol() != unarySymbol) return null
|
|
||||||
|
|
||||||
val incrementStatement = this[1]
|
|
||||||
if (incrementStatement !is FirVariableAssignment) return null
|
|
||||||
|
|
||||||
val variable = statement0.initializer?.toResolvedCallableSymbol() ?: return null
|
|
||||||
if (incrementStatement.lValue.toResolvedCallableSymbol() != variable) return null
|
|
||||||
|
|
||||||
val origin = incrementStatement.getIrAssignmentOrigin()
|
|
||||||
return if (origin == IrStatementOrigin.EQ) null else origin
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun visitErrorExpression(errorExpression: FirErrorExpression, data: Any?): IrElement {
|
override fun visitErrorExpression(errorExpression: FirErrorExpression, data: Any?): IrElement {
|
||||||
return errorExpression.convertWithOffsets { startOffset, endOffset ->
|
return errorExpression.convertWithOffsets { startOffset, endOffset ->
|
||||||
IrErrorExpressionImpl(
|
IrErrorExpressionImpl(
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ FILE fqName:<root> fileName:/localFunction.kt
|
|||||||
CONST Int type=kotlin.Int value=0
|
CONST Int type=kotlin.Int value=0
|
||||||
FUN LOCAL_FUNCTION name:local visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
FUN LOCAL_FUNCTION name:local visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Int [val]
|
|
||||||
GET_VAR 'var x: kotlin.Int [var] declared in <root>.outer' type=kotlin.Int origin=null
|
|
||||||
SET_VAR 'var x: kotlin.Int [var] declared in <root>.outer' type=kotlin.Unit origin=POSTFIX_INCR
|
|
||||||
CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
|
|
||||||
$this: GET_VAR 'val tmp_0: kotlin.Int [val] declared in <root>.outer.local' type=kotlin.Int origin=null
|
|
||||||
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
|
TYPE_OP type=kotlin.Unit origin=IMPLICIT_COERCION_TO_UNIT typeOperand=kotlin.Unit
|
||||||
GET_VAR 'val tmp_0: kotlin.Int [val] declared in <root>.outer.local' type=kotlin.Int origin=null
|
BLOCK type=kotlin.Int origin=POSTFIX_INCR
|
||||||
|
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Int [val]
|
||||||
|
GET_VAR 'var x: kotlin.Int [var] declared in <root>.outer' type=kotlin.Int origin=null
|
||||||
|
SET_VAR 'var x: kotlin.Int [var] declared in <root>.outer' type=kotlin.Unit origin=POSTFIX_INCR
|
||||||
|
CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
|
||||||
|
$this: GET_VAR 'val tmp_0: kotlin.Int [val] declared in <root>.outer.local' type=kotlin.Int origin=null
|
||||||
|
GET_VAR 'val tmp_0: kotlin.Int [val] declared in <root>.outer.local' type=kotlin.Int origin=null
|
||||||
CALL 'local final fun local (): kotlin.Unit declared in <root>.outer' type=kotlin.Unit origin=null
|
CALL 'local final fun local (): kotlin.Unit declared in <root>.outer' type=kotlin.Unit origin=null
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
fun outer() {
|
fun outer() {
|
||||||
var x: Int = 0
|
var x: Int = 0
|
||||||
local fun local() {
|
local fun local() {
|
||||||
val <unary>: Int = x
|
{ // BLOCK
|
||||||
x = <unary>.inc()
|
val <unary>: Int = x
|
||||||
<unary> /*~> Unit */
|
x = <unary>.inc()
|
||||||
|
<unary>
|
||||||
|
} /*~> Unit */
|
||||||
}
|
}
|
||||||
|
|
||||||
local()
|
local()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,11 +26,12 @@ FILE fqName:<root> fileName:/coercionInLoop.kt
|
|||||||
STRING_CONCATENATION type=kotlin.String
|
STRING_CONCATENATION type=kotlin.String
|
||||||
CONST String type=kotlin.String value="Fail "
|
CONST String type=kotlin.String value="Fail "
|
||||||
GET_VAR 'var i: kotlin.Int [var] declared in <root>.box' type=kotlin.Int origin=null
|
GET_VAR 'var i: kotlin.Int [var] declared in <root>.box' type=kotlin.Int origin=null
|
||||||
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Int [val]
|
BLOCK type=kotlin.Int origin=POSTFIX_INCR
|
||||||
GET_VAR 'var i: kotlin.Int [var] declared in <root>.box' type=kotlin.Int origin=null
|
VAR IR_TEMPORARY_VARIABLE name:tmp_0 type:kotlin.Int [val]
|
||||||
SET_VAR 'var i: kotlin.Int [var] declared in <root>.box' type=kotlin.Unit origin=POSTFIX_INCR
|
GET_VAR 'var i: kotlin.Int [var] declared in <root>.box' type=kotlin.Int origin=null
|
||||||
CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
|
SET_VAR 'var i: kotlin.Int [var] declared in <root>.box' type=kotlin.Unit origin=POSTFIX_INCR
|
||||||
$this: GET_VAR 'val tmp_0: kotlin.Int [val] declared in <root>.box' type=kotlin.Int origin=null
|
CALL 'public final fun inc (): kotlin.Int [operator] declared in kotlin.Int' type=kotlin.Int origin=null
|
||||||
GET_VAR 'val tmp_0: kotlin.Int [val] declared in <root>.box' type=kotlin.Int origin=null
|
$this: GET_VAR 'val tmp_0: kotlin.Int [val] declared in <root>.box' type=kotlin.Int origin=null
|
||||||
|
GET_VAR 'val tmp_0: kotlin.Int [val] declared in <root>.box' type=kotlin.Int origin=null
|
||||||
RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in <root>'
|
RETURN type=kotlin.Nothing from='public final fun box (): kotlin.String declared in <root>'
|
||||||
CONST String type=kotlin.String value="OK"
|
CONST String type=kotlin.String value="OK"
|
||||||
|
|||||||
@@ -6,9 +6,12 @@ fun box(): String {
|
|||||||
when {
|
when {
|
||||||
ieee754equals(arg0 = a.get(index = i), arg1 = x.next()).not() -> return "Fail " + i
|
ieee754equals(arg0 = a.get(index = i), arg1 = x.next()).not() -> return "Fail " + i
|
||||||
}
|
}
|
||||||
val <unary>: Int = i
|
{ // BLOCK
|
||||||
i = <unary>.inc()
|
val <unary>: Int = i
|
||||||
<unary>
|
i = <unary>.inc()
|
||||||
|
<unary>
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user