Generate "raw" IR in Psi2IrTranslator.
This commit is contained in:
committed by
Dmitry Petrov
parent
ba85e714e3
commit
05b9eda809
@@ -21,30 +21,18 @@ import org.jetbrains.kotlin.ir.declarations.IrModule
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
|
||||
import org.jetbrains.kotlin.psi2ir.generators.ModuleGenerator
|
||||
import org.jetbrains.kotlin.psi2ir.transformations.foldStringConcatenation
|
||||
import org.jetbrains.kotlin.psi2ir.transformations.inlineDesugaredBlocks
|
||||
import org.jetbrains.kotlin.psi2ir.transformations.inlineSafeCallChains
|
||||
import org.jetbrains.kotlin.psi2ir.transformations.insertImplicitCasts
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
|
||||
class Psi2IrTranslator(val configuration: Configuration = Configuration()) {
|
||||
class Configuration(
|
||||
val shouldInlineDesugaredBlocks: Boolean = false,
|
||||
val shouldFoldStringConcatenation: Boolean = true,
|
||||
val shouldInlineSafeCallChains: Boolean = true
|
||||
)
|
||||
|
||||
class Psi2IrTranslator() {
|
||||
fun generateModule(moduleDescriptor: ModuleDescriptor, ktFiles: List<KtFile>, bindingContext: BindingContext): IrModule {
|
||||
val context = GeneratorContext(moduleDescriptor, bindingContext)
|
||||
val irModule = ModuleGenerator(context).generateModule(ktFiles)
|
||||
postprocess(irModule, context)
|
||||
postprocess(irModule)
|
||||
return irModule
|
||||
}
|
||||
|
||||
private fun postprocess(irModule: IrModule, context: GeneratorContext) {
|
||||
insertImplicitCasts(irModule.irBuiltins.builtIns, irModule)
|
||||
if (configuration.shouldInlineDesugaredBlocks) inlineDesugaredBlocks(irModule)
|
||||
if (configuration.shouldFoldStringConcatenation) foldStringConcatenation(irModule)
|
||||
if (configuration.shouldInlineSafeCallChains) inlineSafeCallChains(context, irModule)
|
||||
private fun postprocess(irModule: IrModule) {
|
||||
insertImplicitCasts(irModule.descriptor.builtIns, irModule)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +24,7 @@ import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.CallBuilder
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.getValueArgumentsInParameterOrder
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.isValueArgumentReorderingRequired
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.IntermediateValue
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.createRematerializableOrTemporary
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.*
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import java.util.*
|
||||
@@ -63,7 +59,9 @@ class CallGenerator(statementGenerator: StatementGenerator): StatementGeneratorE
|
||||
call: CallBuilder
|
||||
): IrExpression {
|
||||
return call.callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
IrGetterCallImpl(startOffset, endOffset, descriptor.getter!!,
|
||||
val getter = descriptor.getter ?:
|
||||
throw AssertionError("No getter for property $descriptor")
|
||||
IrGetterCallImpl(startOffset, endOffset, getter,
|
||||
dispatchReceiverValue?.load(),
|
||||
extensionReceiverValue?.load(),
|
||||
IrOperator.GET_PROPERTY,
|
||||
@@ -126,7 +124,7 @@ class CallGenerator(statementGenerator: StatementGenerator): StatementGeneratorE
|
||||
for (valueArgument in valueArgumentsInEvaluationOrder) {
|
||||
val valueParameter = valueArgumentsToValueParameters[valueArgument]!!
|
||||
val irArgument = call.getValueArgument(valueParameter) ?: continue
|
||||
val irArgumentValue = createRematerializableOrTemporary(scope, irArgument, irBlock, valueParameter.name.asString())
|
||||
val irArgumentValue = scope.createTemporaryVariableInBlock(irArgument, irBlock, valueParameter.name.asString())
|
||||
irArgumentValues[valueParameter] = irArgumentValue
|
||||
}
|
||||
|
||||
|
||||
+5
-10
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.createRematerializableOrTemporary
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.createTemporaryVariableInBlock
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
@@ -112,7 +112,7 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
|
||||
val irArgument1 = statementGenerator.generateExpression(expression.right!!)
|
||||
|
||||
val irBlock = IrBlockImpl(expression.startOffset, expression.endOffset, returnType, IrOperator.ELVIS)
|
||||
val irArgument0Value = createRematerializableOrTemporary(scope, irArgument0, irBlock, "elvis_lhs")
|
||||
val irArgument0Value = scope.createTemporaryVariableInBlock(irArgument0, irBlock, "elvis_lhs")
|
||||
irBlock.addStatement(IrIfThenElseImpl(
|
||||
expression.startOffset, expression.endOffset, returnType,
|
||||
context.equalsNull(expression.startOffset, expression.endOffset, irArgument0Value.load()),
|
||||
@@ -222,19 +222,14 @@ class OperatorExpressionGenerator(statementGenerator: StatementGenerator) : Stat
|
||||
|
||||
val resultType = irArgument.type.makeNotNullable()
|
||||
val irBlock = IrBlockImpl(ktOperator.startOffset, ktOperator.endOffset, resultType, irOperator)
|
||||
val argumentValue = createRematerializableOrTemporary(scope, irArgument, irBlock, "notnull")
|
||||
val argumentValue = scope.createTemporaryVariableInBlock(irArgument, irBlock, "notnull")
|
||||
val irIfThenElse = IrIfThenElseImpl(ktOperator.startOffset, ktOperator.endOffset, resultType,
|
||||
context.equalsNull(ktOperator.startOffset, ktOperator.endOffset, argumentValue.load()),
|
||||
context.throwNpe(ktOperator.startOffset, ktOperator.endOffset, irOperator),
|
||||
argumentValue.load())
|
||||
|
||||
return if (irBlock.statements.isEmpty()) {
|
||||
irIfThenElse
|
||||
}
|
||||
else {
|
||||
irBlock.addStatement(irIfThenElse)
|
||||
irBlock
|
||||
}
|
||||
irBlock.addStatement(irIfThenElse)
|
||||
return irBlock
|
||||
}
|
||||
|
||||
private fun generatePrefixOperatorAsCall(expression: KtPrefixExpression, irOperator: IrOperator): IrExpression {
|
||||
|
||||
+2
-2
@@ -27,7 +27,7 @@ import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
||||
import org.jetbrains.kotlin.psi2ir.deparenthesize
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.IntermediateValue
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.createRematerializableOrTemporary
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.createTemporaryVariableInBlock
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.setExplicitReceiverValue
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingContextUtils
|
||||
@@ -81,7 +81,7 @@ class StatementGenerator(
|
||||
val irBlock = IrBlockImpl(multiDeclaration.startOffset, multiDeclaration.endOffset,
|
||||
context.builtIns.unitType, IrOperator.DESTRUCTURING_DECLARATION)
|
||||
val ktInitializer = multiDeclaration.initializer!!
|
||||
val containerValue = createRematerializableOrTemporary(scope, ktInitializer.genExpr(), irBlock, "container")
|
||||
val containerValue = scope.createTemporaryVariableInBlock(ktInitializer.genExpr(), irBlock, "container")
|
||||
|
||||
declareComponentVariablesInBlock(multiDeclaration, irBlock, containerValue)
|
||||
|
||||
|
||||
+2
-2
@@ -40,10 +40,10 @@ class ArrayAccessAssignmentReceiver(
|
||||
val resultType = if (hasResult) type else callGenerator.context.builtIns.unitType
|
||||
val irBlock = IrBlockImpl(startOffset, endOffset, resultType, operator)
|
||||
|
||||
val irArrayValue = createRematerializableOrTemporary(callGenerator.scope, irArray, irBlock, "array")
|
||||
val irArrayValue = callGenerator.scope.createTemporaryVariableInBlock(irArray, irBlock, "array")
|
||||
|
||||
val irIndexValues = irIndices.mapIndexed { i, irIndex ->
|
||||
createRematerializableOrTemporary(callGenerator.scope, irIndex, irBlock, "index$i")
|
||||
callGenerator.scope.createTemporaryVariableInBlock(irIndex, irBlock, "index$i")
|
||||
}
|
||||
|
||||
indexedGetCall?.fillArrayAndIndexArguments(irArrayValue, irIndexValues)
|
||||
|
||||
+7
-24
@@ -16,8 +16,9 @@
|
||||
|
||||
package org.jetbrains.kotlin.psi2ir.intermediate
|
||||
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBlockImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpressionWithCopy
|
||||
import org.jetbrains.kotlin.psi2ir.generators.Scope
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
|
||||
@@ -27,26 +28,8 @@ class RematerializableValue(val irExpression: IrExpressionWithCopy) : Intermedia
|
||||
override fun load(): IrExpression = irExpression.copy()
|
||||
}
|
||||
|
||||
fun createRematerializableValue(irExpression: IrExpression): IntermediateValue? =
|
||||
(irExpression as? IrExpressionWithCopy)?.let { RematerializableValue(it) }
|
||||
|
||||
inline fun createRematerializableOrTemporary(
|
||||
scope: Scope,
|
||||
irExpression: IrExpression,
|
||||
nameHint: String? = null,
|
||||
addVariable: (IrVariable) -> Unit
|
||||
): IntermediateValue {
|
||||
val rematerializable = createRematerializableValue(irExpression)
|
||||
if (rematerializable != null) {
|
||||
return rematerializable
|
||||
}
|
||||
|
||||
val temporaryVariable = scope.createTemporaryVariable(irExpression, nameHint)
|
||||
addVariable(temporaryVariable)
|
||||
fun Scope.createTemporaryVariableInBlock(irExpression: IrExpression, block: IrBlockImpl, nameHint: String? = null): IntermediateValue {
|
||||
val temporaryVariable = createTemporaryVariable(irExpression, nameHint)
|
||||
block.addStatement(temporaryVariable)
|
||||
return VariableLValue(temporaryVariable)
|
||||
}
|
||||
|
||||
fun createRematerializableOrTemporary(scope: Scope, irExpression: IrExpression, block: IrBlockImpl, nameHint: String? = null): IntermediateValue =
|
||||
createRematerializableOrTemporary(scope, irExpression, nameHint) {
|
||||
block.addStatement(it)
|
||||
}
|
||||
}
|
||||
+1
-13
@@ -62,21 +62,9 @@ class SimplePropertyLValue(
|
||||
return callReceiver.call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
val variablesForReceivers = SmartList<IrVariable>()
|
||||
|
||||
val tmpDispatchReceiverValue = dispatchReceiverValue?.load()?.let {
|
||||
createRematerializableOrTemporary(scope, it, "this") {
|
||||
irVar -> variablesForReceivers.add(irVar)
|
||||
}
|
||||
}
|
||||
|
||||
val tmpExtensionReceiverValue = extensionReceiverValue?.load()?.let {
|
||||
createRematerializableOrTemporary(scope, it, "receiver") {
|
||||
irVar -> variablesForReceivers.add(irVar)
|
||||
}
|
||||
}
|
||||
|
||||
val irResultExpression = withLValue(
|
||||
SimplePropertyLValue(scope, startOffset, endOffset, irOperator, descriptor,
|
||||
SimpleCallReceiver(tmpDispatchReceiverValue, tmpExtensionReceiverValue),
|
||||
SimpleCallReceiver(dispatchReceiverValue, extensionReceiverValue),
|
||||
superQualifier)
|
||||
)
|
||||
|
||||
|
||||
-119
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2016 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.psi2ir.transformations
|
||||
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.detach
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.replaceWith
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
import org.jetbrains.kotlin.psi2ir.containsNull
|
||||
import org.jetbrains.kotlin.psi2ir.defaultLoad
|
||||
import org.jetbrains.kotlin.psi2ir.generators.GeneratorContext
|
||||
import org.jetbrains.kotlin.psi2ir.generators.constNull
|
||||
import org.jetbrains.kotlin.psi2ir.generators.equalsNull
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.OnceExpressionValue
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.createRematerializableValue
|
||||
|
||||
fun inlineSafeCallChains(context: GeneratorContext, element: IrElement) {
|
||||
element.accept(InlineSafeCallChains(context), null)
|
||||
element.accept(InlineSafeCallStableReceiverValues(context), null)
|
||||
}
|
||||
|
||||
class InlineSafeCallChains(val context: GeneratorContext) : IrElementVisitor<Unit, Nothing?> {
|
||||
override fun visitElement(element: IrElement, data: Nothing?) {
|
||||
element.acceptChildren(this, data)
|
||||
}
|
||||
|
||||
override fun visitBlock(expression: IrBlock, data: Nothing?) {
|
||||
expression.acceptChildren(this, data)
|
||||
|
||||
if (expression.operator == IrOperator.SAFE_CALL) {
|
||||
val safeCall = getSafeCallInfo(expression) ?: return
|
||||
val innerSafeCall = (safeCall.receiverValue as? IrBlock)?.let { getSafeCallInfo(it) } ?: return
|
||||
rewriteSafeCallChain(safeCall, innerSafeCall)
|
||||
}
|
||||
}
|
||||
|
||||
private fun rewriteSafeCallChain(outer: SafeCallInfo, inner: SafeCallInfo) {
|
||||
val innerNestedCallReturnType = inner.nestedCall.type
|
||||
if (innerNestedCallReturnType.containsNull()) return
|
||||
|
||||
outer.root.replaceWith {
|
||||
val newBlock = IrBlockImpl(it.startOffset, it.endOffset, it.type, IrOperator.SAFE_CALL)
|
||||
newBlock.addStatement(inner.receiverVariable.detach())
|
||||
|
||||
val replaceWithValue = OnceExpressionValue(inner.nestedCall.detach())
|
||||
outer.nestedCall.acceptChildren(ReplaceTemporaryVariable(outer.receiverVariable, replaceWithValue), null)
|
||||
newBlock.addStatement(IrIfThenElseImpl(
|
||||
it.startOffset, it.endOffset, it.type,
|
||||
context.equalsNull(it.startOffset, it.endOffset, inner.receiverVariable.defaultLoad()),
|
||||
context.constNull(it.startOffset, it.endOffset),
|
||||
outer.nestedCall.detach(),
|
||||
IrOperator.SAFE_CALL))
|
||||
|
||||
newBlock
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
internal class SafeCallInfo(val root: IrBlock, val receiverVariable: IrVariable, val ifThenElse: IrWhen, val nestedCall: IrExpression) {
|
||||
val receiverValue = receiverVariable.initializer!!
|
||||
}
|
||||
|
||||
internal fun getSafeCallInfo(block: IrBlock): SafeCallInfo? {
|
||||
if (block.operator != IrOperator.SAFE_CALL) return null
|
||||
val receiverVariable = block.statements[0] as? IrVariable ?: return null
|
||||
if (receiverVariable.initializer == null) return null
|
||||
val irWhen = (block.statements[1] as? IrWhen) ?: return null
|
||||
val nestedCall = irWhen.elseBranch ?: return null
|
||||
return SafeCallInfo(block, receiverVariable, irWhen, nestedCall)
|
||||
}
|
||||
|
||||
class InlineSafeCallStableReceiverValues(val context: GeneratorContext) : IrElementVisitor<Unit, Nothing?> {
|
||||
override fun visitElement(element: IrElement, data: Nothing?) {
|
||||
element.acceptChildren(this, data)
|
||||
}
|
||||
|
||||
override fun visitBlock(expression: IrBlock, data: Nothing?) {
|
||||
expression.acceptChildren(this, data)
|
||||
|
||||
if (expression.operator == IrOperator.SAFE_CALL) {
|
||||
val safeCall = getSafeCallInfo(expression) ?: return
|
||||
if (isOkToInlineReceiverValue(safeCall.receiverValue)) {
|
||||
expression.replaceWith {
|
||||
val replaceWithValue = createRematerializableValue(safeCall.receiverValue) ?: return
|
||||
safeCall.ifThenElse.acceptChildren(ReplaceTemporaryVariable(safeCall.receiverVariable, replaceWithValue), null)
|
||||
safeCall.ifThenElse.detach()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isOkToInlineReceiverValue(receiverValue: IrExpression): Boolean {
|
||||
return if (receiverValue is IrGetVariable) {
|
||||
!receiverValue.descriptor.isVar
|
||||
}
|
||||
else {
|
||||
// For now, IrExpressionWithCopy has stable instances only.
|
||||
receiverValue is IrExpressionWithCopy
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,13 +24,17 @@ FILE /arrayAugmentedAssignment1.kt
|
||||
VAR var x: kotlin.IntArray
|
||||
CALL .foo type=kotlin.IntArray operator=null
|
||||
BLOCK type=kotlin.Unit operator=PLUSEQ
|
||||
VAR val tmp0_array: kotlin.IntArray
|
||||
GET_VAR x type=kotlin.IntArray operator=null
|
||||
VAR val tmp1_index0: kotlin.Int
|
||||
CONST Int type=kotlin.Int value='0'
|
||||
CALL .set type=kotlin.Unit operator=PLUSEQ
|
||||
$this: GET_VAR x type=kotlin.IntArray operator=null
|
||||
index: CONST Int type=kotlin.Int value='0'
|
||||
$this: GET_VAR tmp0_array type=kotlin.IntArray operator=null
|
||||
index: GET_VAR tmp1_index0 type=kotlin.Int operator=null
|
||||
value: CALL .plus type=kotlin.Int operator=PLUSEQ
|
||||
$this: CALL .get type=kotlin.Int operator=PLUSEQ
|
||||
$this: GET_VAR x type=kotlin.IntArray operator=null
|
||||
index: CONST Int type=kotlin.Int value='0'
|
||||
$this: GET_VAR tmp0_array type=kotlin.IntArray operator=null
|
||||
index: GET_VAR tmp1_index0 type=kotlin.Int operator=null
|
||||
other: CONST Int type=kotlin.Int value='1'
|
||||
FUN public fun testCall(): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
@@ -53,13 +57,15 @@ FILE /arrayAugmentedAssignment1.kt
|
||||
VAR val tmp0_array: kotlin.IntArray
|
||||
CALL .<get-x> type=kotlin.IntArray operator=GET_PROPERTY
|
||||
$this: GET_VAR c type=C operator=null
|
||||
VAR val tmp1: kotlin.Int
|
||||
VAR val tmp1_index0: kotlin.Int
|
||||
CONST Int type=kotlin.Int value='0'
|
||||
VAR val tmp2: kotlin.Int
|
||||
CALL .get type=kotlin.Int operator=POSTFIX_INCR
|
||||
$this: GET_VAR tmp0_array type=kotlin.IntArray operator=null
|
||||
index: CONST Int type=kotlin.Int value='0'
|
||||
index: GET_VAR tmp1_index0 type=kotlin.Int operator=null
|
||||
CALL .set type=kotlin.Unit operator=POSTFIX_INCR
|
||||
$this: GET_VAR tmp0_array type=kotlin.IntArray operator=null
|
||||
index: CONST Int type=kotlin.Int value='0'
|
||||
index: GET_VAR tmp1_index0 type=kotlin.Int operator=null
|
||||
value: CALL .inc type=kotlin.Int operator=POSTFIX_INCR
|
||||
$this: GET_VAR tmp1 type=kotlin.Int operator=null
|
||||
GET_VAR tmp1 type=kotlin.Int operator=null
|
||||
$this: GET_VAR tmp2 type=kotlin.Int operator=null
|
||||
GET_VAR tmp2 type=kotlin.Int operator=null
|
||||
|
||||
@@ -6,12 +6,16 @@ FILE /arrayAugmentedAssignment2.kt
|
||||
FUN public fun IB.test(/*0*/ a: IA): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
BLOCK type=kotlin.Unit operator=PLUSEQ
|
||||
VAR val tmp0_array: IA
|
||||
GET_VAR a type=IA operator=null
|
||||
VAR val tmp1_index0: kotlin.String
|
||||
CONST String type=kotlin.String value=''
|
||||
CALL .set type=kotlin.Unit operator=PLUSEQ
|
||||
$this: $RECEIVER of: test type=IB
|
||||
$receiver: GET_VAR a type=IA operator=null
|
||||
index: CONST String type=kotlin.String value=''
|
||||
$receiver: GET_VAR tmp0_array type=IA operator=null
|
||||
index: GET_VAR tmp1_index0 type=kotlin.String operator=null
|
||||
value: CALL .plus type=kotlin.Int operator=PLUSEQ
|
||||
$this: CALL .get type=kotlin.Int operator=PLUSEQ
|
||||
$this: GET_VAR a type=IA operator=null
|
||||
index: CONST String type=kotlin.String value=''
|
||||
$this: GET_VAR tmp0_array type=IA operator=null
|
||||
index: GET_VAR tmp1_index0 type=kotlin.String operator=null
|
||||
other: CONST Int type=kotlin.Int value='42'
|
||||
|
||||
+19
-13
@@ -2,24 +2,30 @@ FILE /bangbang.kt
|
||||
FUN public fun test1(/*0*/ a: kotlin.Any?): kotlin.Any
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=test1
|
||||
WHEN type=kotlin.Any operator=null
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR a type=kotlin.Any? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CALL .THROW_NPE type=kotlin.Nothing operator=EXCLEXCL
|
||||
else: GET_VAR a type=kotlin.Any? operator=null
|
||||
BLOCK type=kotlin.Any operator=EXCLEXCL
|
||||
VAR val tmp0_notnull: kotlin.Any?
|
||||
GET_VAR a type=kotlin.Any? operator=null
|
||||
WHEN type=kotlin.Any operator=null
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp0_notnull type=kotlin.Any? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CALL .THROW_NPE type=kotlin.Nothing operator=EXCLEXCL
|
||||
else: GET_VAR tmp0_notnull type=kotlin.Any? operator=null
|
||||
FUN public fun test2(/*0*/ a: kotlin.Any?): kotlin.Int
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=test2
|
||||
BLOCK type=kotlin.Int operator=EXCLEXCL
|
||||
VAR val tmp1_notnull: kotlin.Int?
|
||||
WHEN type=kotlin.Int? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR a type=kotlin.Any? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .hashCode type=kotlin.Int operator=null
|
||||
$this: GET_VAR a type=kotlin.Any? operator=null
|
||||
BLOCK type=kotlin.Int? operator=SAFE_CALL
|
||||
VAR val tmp0_safe_receiver: kotlin.Any?
|
||||
GET_VAR a type=kotlin.Any? operator=null
|
||||
WHEN type=kotlin.Int? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp0_safe_receiver type=kotlin.Any? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .hashCode type=kotlin.Int operator=null
|
||||
$this: GET_VAR tmp0_safe_receiver type=kotlin.Any? operator=null
|
||||
WHEN type=kotlin.Int operator=null
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp1_notnull type=kotlin.Int? operator=null
|
||||
|
||||
@@ -31,8 +31,10 @@ FILE /callWithReorderedArguments.kt
|
||||
a: GET_VAR tmp1_a type=kotlin.Int operator=null
|
||||
b: GET_VAR tmp0_b type=kotlin.Int operator=null
|
||||
BLOCK type=kotlin.Unit operator=ARGUMENTS_REORDERING_FOR_CALL
|
||||
VAR val tmp2_a: kotlin.Int
|
||||
VAR val tmp2_b: kotlin.Int
|
||||
CONST Int type=kotlin.Int value='1'
|
||||
VAR val tmp3_a: kotlin.Int
|
||||
CALL .reordered2 type=kotlin.Int operator=null
|
||||
CALL .foo type=kotlin.Unit operator=null
|
||||
a: GET_VAR tmp2_a type=kotlin.Int operator=null
|
||||
b: CONST Int type=kotlin.Int value='1'
|
||||
a: GET_VAR tmp3_a type=kotlin.Int operator=null
|
||||
b: GET_VAR tmp2_b type=kotlin.Int operator=null
|
||||
|
||||
+31
-12
@@ -14,20 +14,39 @@ FILE /chainOfSafeCalls.kt
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=test
|
||||
BLOCK type=C? operator=SAFE_CALL
|
||||
VAR val tmp2_safe_receiver: C?
|
||||
WHEN type=C? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR nc type=C? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .bar type=C? operator=null
|
||||
$this: CALL .foo type=C operator=null
|
||||
$this: GET_VAR nc type=C? operator=null
|
||||
VAR val tmp3_safe_receiver: C?
|
||||
BLOCK type=C? operator=SAFE_CALL
|
||||
VAR val tmp2_safe_receiver: C?
|
||||
BLOCK type=C? operator=SAFE_CALL
|
||||
VAR val tmp1_safe_receiver: C?
|
||||
BLOCK type=C? operator=SAFE_CALL
|
||||
VAR val tmp0_safe_receiver: C?
|
||||
GET_VAR nc type=C? operator=null
|
||||
WHEN type=C? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp0_safe_receiver type=C? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .foo type=C operator=null
|
||||
$this: GET_VAR tmp0_safe_receiver type=C? operator=null
|
||||
WHEN type=C? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp1_safe_receiver type=C? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .bar type=C? operator=null
|
||||
$this: GET_VAR tmp1_safe_receiver type=C? operator=null
|
||||
WHEN type=C? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp2_safe_receiver type=C? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .foo type=C operator=null
|
||||
$this: GET_VAR tmp2_safe_receiver type=C? operator=null
|
||||
WHEN type=C? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp2_safe_receiver type=C? operator=null
|
||||
arg0: GET_VAR tmp3_safe_receiver type=C? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .foo type=C operator=null
|
||||
$this: CALL .foo type=C operator=null
|
||||
$this: GET_VAR tmp2_safe_receiver type=C? operator=null
|
||||
$this: GET_VAR tmp3_safe_receiver type=C? operator=null
|
||||
|
||||
+10
-7
@@ -7,10 +7,13 @@ FILE /dotQualified.kt
|
||||
FUN public fun lengthN(/*0*/ s: kotlin.String?): kotlin.Int?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=lengthN
|
||||
WHEN type=kotlin.Int? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR s type=kotlin.String? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .<get-length> type=kotlin.Int operator=GET_PROPERTY
|
||||
$this: GET_VAR s type=kotlin.String? operator=null
|
||||
BLOCK type=kotlin.Int? operator=SAFE_CALL
|
||||
VAR val tmp0_safe_receiver: kotlin.String?
|
||||
GET_VAR s type=kotlin.String? operator=null
|
||||
WHEN type=kotlin.Int? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp0_safe_receiver type=kotlin.String? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .<get-length> type=kotlin.Int operator=GET_PROPERTY
|
||||
$this: GET_VAR tmp0_safe_receiver type=kotlin.String? operator=null
|
||||
|
||||
+12
-6
@@ -10,22 +10,26 @@ FILE /elvis.kt
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=test1
|
||||
BLOCK type=kotlin.Any operator=ELVIS
|
||||
VAR val tmp0_elvis_lhs: kotlin.Any?
|
||||
GET_VAR a type=kotlin.Any? operator=null
|
||||
WHEN type=kotlin.Any operator=null
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR a type=kotlin.Any? operator=null
|
||||
arg0: GET_VAR tmp0_elvis_lhs type=kotlin.Any? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: GET_VAR b type=kotlin.Any operator=null
|
||||
else: GET_VAR a type=kotlin.Any? operator=null
|
||||
else: GET_VAR tmp0_elvis_lhs type=kotlin.Any? operator=null
|
||||
FUN public fun test2(/*0*/ a: kotlin.String?, /*1*/ b: kotlin.Any): kotlin.Any
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=test2
|
||||
BLOCK type=kotlin.Any operator=ELVIS
|
||||
VAR val tmp0_elvis_lhs: kotlin.String?
|
||||
GET_VAR a type=kotlin.String? operator=null
|
||||
WHEN type=kotlin.Any operator=null
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR a type=kotlin.String? operator=null
|
||||
arg0: GET_VAR tmp0_elvis_lhs type=kotlin.String? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: GET_VAR b type=kotlin.Any operator=null
|
||||
else: GET_VAR a type=kotlin.String? operator=null
|
||||
else: GET_VAR tmp0_elvis_lhs type=kotlin.String? operator=null
|
||||
FUN public fun test3(/*0*/ a: kotlin.Any?, /*1*/ b: kotlin.Any?): kotlin.String
|
||||
BLOCK_BODY
|
||||
WHEN type=kotlin.Unit operator=IF
|
||||
@@ -40,14 +44,16 @@ FILE /elvis.kt
|
||||
CONST String type=kotlin.String value=''
|
||||
RETURN type=kotlin.Nothing from=test3
|
||||
BLOCK type=kotlin.String operator=ELVIS
|
||||
VAR val tmp0_elvis_lhs: kotlin.Any?
|
||||
GET_VAR a type=kotlin.Any? operator=null
|
||||
WHEN type=kotlin.String operator=null
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR a type=kotlin.Any? operator=null
|
||||
arg0: GET_VAR tmp0_elvis_lhs type=kotlin.Any? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String
|
||||
GET_VAR b type=kotlin.Any? operator=null
|
||||
else: TYPE_OP operator=IMPLICIT_CAST typeOperand=kotlin.String
|
||||
GET_VAR a type=kotlin.Any? operator=null
|
||||
GET_VAR tmp0_elvis_lhs type=kotlin.Any? operator=null
|
||||
FUN public fun test4(/*0*/ x: kotlin.Any): kotlin.Any
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=test4
|
||||
|
||||
+34
-26
@@ -91,57 +91,65 @@ FILE /incrementDecrement.kt
|
||||
BLOCK type=kotlin.Int operator=PREFIX_INCR
|
||||
VAR val tmp0_array: kotlin.IntArray
|
||||
CALL .<get-arr> type=kotlin.IntArray operator=GET_PROPERTY
|
||||
VAR val tmp1: kotlin.Int
|
||||
VAR val tmp1_index0: kotlin.Int
|
||||
CONST Int type=kotlin.Int value='0'
|
||||
VAR val tmp2: kotlin.Int
|
||||
CALL .inc type=kotlin.Int operator=PREFIX_INCR
|
||||
$this: CALL .get type=kotlin.Int operator=PREFIX_INCR
|
||||
$this: GET_VAR tmp0_array type=kotlin.IntArray operator=null
|
||||
index: CONST Int type=kotlin.Int value='0'
|
||||
index: GET_VAR tmp1_index0 type=kotlin.Int operator=null
|
||||
CALL .set type=kotlin.Unit operator=PREFIX_INCR
|
||||
$this: GET_VAR tmp0_array type=kotlin.IntArray operator=null
|
||||
index: CONST Int type=kotlin.Int value='0'
|
||||
value: GET_VAR tmp1 type=kotlin.Int operator=null
|
||||
GET_VAR tmp1 type=kotlin.Int operator=null
|
||||
index: GET_VAR tmp1_index0 type=kotlin.Int operator=null
|
||||
value: GET_VAR tmp2 type=kotlin.Int operator=null
|
||||
GET_VAR tmp2 type=kotlin.Int operator=null
|
||||
VAR val a2: kotlin.Int
|
||||
BLOCK type=kotlin.Int operator=PREFIX_DECR
|
||||
VAR val tmp2_array: kotlin.IntArray
|
||||
VAR val tmp3_array: kotlin.IntArray
|
||||
CALL .<get-arr> type=kotlin.IntArray operator=GET_PROPERTY
|
||||
VAR val tmp3: kotlin.Int
|
||||
VAR val tmp4_index0: kotlin.Int
|
||||
CONST Int type=kotlin.Int value='0'
|
||||
VAR val tmp5: kotlin.Int
|
||||
CALL .dec type=kotlin.Int operator=PREFIX_DECR
|
||||
$this: CALL .get type=kotlin.Int operator=PREFIX_DECR
|
||||
$this: GET_VAR tmp2_array type=kotlin.IntArray operator=null
|
||||
index: CONST Int type=kotlin.Int value='0'
|
||||
$this: GET_VAR tmp3_array type=kotlin.IntArray operator=null
|
||||
index: GET_VAR tmp4_index0 type=kotlin.Int operator=null
|
||||
CALL .set type=kotlin.Unit operator=PREFIX_DECR
|
||||
$this: GET_VAR tmp2_array type=kotlin.IntArray operator=null
|
||||
index: CONST Int type=kotlin.Int value='0'
|
||||
value: GET_VAR tmp3 type=kotlin.Int operator=null
|
||||
GET_VAR tmp3 type=kotlin.Int operator=null
|
||||
$this: GET_VAR tmp3_array type=kotlin.IntArray operator=null
|
||||
index: GET_VAR tmp4_index0 type=kotlin.Int operator=null
|
||||
value: GET_VAR tmp5 type=kotlin.Int operator=null
|
||||
GET_VAR tmp5 type=kotlin.Int operator=null
|
||||
FUN public fun testArrayPostfix(): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
VAR val a1: kotlin.Int
|
||||
BLOCK type=kotlin.Int operator=POSTFIX_INCR
|
||||
VAR val tmp0_array: kotlin.IntArray
|
||||
CALL .<get-arr> type=kotlin.IntArray operator=GET_PROPERTY
|
||||
VAR val tmp1: kotlin.Int
|
||||
VAR val tmp1_index0: kotlin.Int
|
||||
CONST Int type=kotlin.Int value='0'
|
||||
VAR val tmp2: kotlin.Int
|
||||
CALL .get type=kotlin.Int operator=POSTFIX_INCR
|
||||
$this: GET_VAR tmp0_array type=kotlin.IntArray operator=null
|
||||
index: CONST Int type=kotlin.Int value='0'
|
||||
index: GET_VAR tmp1_index0 type=kotlin.Int operator=null
|
||||
CALL .set type=kotlin.Unit operator=POSTFIX_INCR
|
||||
$this: GET_VAR tmp0_array type=kotlin.IntArray operator=null
|
||||
index: CONST Int type=kotlin.Int value='0'
|
||||
index: GET_VAR tmp1_index0 type=kotlin.Int operator=null
|
||||
value: CALL .inc type=kotlin.Int operator=POSTFIX_INCR
|
||||
$this: GET_VAR tmp1 type=kotlin.Int operator=null
|
||||
GET_VAR tmp1 type=kotlin.Int operator=null
|
||||
$this: GET_VAR tmp2 type=kotlin.Int operator=null
|
||||
GET_VAR tmp2 type=kotlin.Int operator=null
|
||||
VAR val a2: kotlin.Int
|
||||
BLOCK type=kotlin.Int operator=POSTFIX_DECR
|
||||
VAR val tmp2_array: kotlin.IntArray
|
||||
VAR val tmp3_array: kotlin.IntArray
|
||||
CALL .<get-arr> type=kotlin.IntArray operator=GET_PROPERTY
|
||||
VAR val tmp3: kotlin.Int
|
||||
VAR val tmp4_index0: kotlin.Int
|
||||
CONST Int type=kotlin.Int value='0'
|
||||
VAR val tmp5: kotlin.Int
|
||||
CALL .get type=kotlin.Int operator=POSTFIX_DECR
|
||||
$this: GET_VAR tmp2_array type=kotlin.IntArray operator=null
|
||||
index: CONST Int type=kotlin.Int value='0'
|
||||
$this: GET_VAR tmp3_array type=kotlin.IntArray operator=null
|
||||
index: GET_VAR tmp4_index0 type=kotlin.Int operator=null
|
||||
CALL .set type=kotlin.Unit operator=POSTFIX_DECR
|
||||
$this: GET_VAR tmp2_array type=kotlin.IntArray operator=null
|
||||
index: CONST Int type=kotlin.Int value='0'
|
||||
$this: GET_VAR tmp3_array type=kotlin.IntArray operator=null
|
||||
index: GET_VAR tmp4_index0 type=kotlin.Int operator=null
|
||||
value: CALL .dec type=kotlin.Int operator=POSTFIX_DECR
|
||||
$this: GET_VAR tmp3 type=kotlin.Int operator=null
|
||||
GET_VAR tmp3 type=kotlin.Int operator=null
|
||||
$this: GET_VAR tmp5 type=kotlin.Int operator=null
|
||||
GET_VAR tmp5 type=kotlin.Int operator=null
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fun test1() {
|
||||
// System.out.println("test1")
|
||||
}
|
||||
+44
-33
@@ -12,13 +12,16 @@ FILE /safeCallWithIncrementDecrement.kt
|
||||
FUN public operator fun kotlin.Int?.inc(): kotlin.Int?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=inc
|
||||
WHEN type=kotlin.Int? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: $RECEIVER of: inc type=kotlin.Int?
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .inc type=kotlin.Int operator=null
|
||||
$this: $RECEIVER of: inc type=kotlin.Int?
|
||||
BLOCK type=kotlin.Int? operator=SAFE_CALL
|
||||
VAR val tmp0_safe_receiver: kotlin.Int?
|
||||
$RECEIVER of: inc type=kotlin.Int?
|
||||
WHEN type=kotlin.Int? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp0_safe_receiver type=kotlin.Int? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .inc type=kotlin.Int operator=null
|
||||
$this: GET_VAR tmp0_safe_receiver type=kotlin.Int? operator=null
|
||||
FUN public operator fun kotlin.Int?.get(/*0*/ index: kotlin.Int): kotlin.Int
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=get
|
||||
@@ -27,38 +30,46 @@ FILE /safeCallWithIncrementDecrement.kt
|
||||
BLOCK_BODY
|
||||
FUN public fun testProperty(/*0*/ nc: test.C?): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
WHEN type=kotlin.Int? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR nc type=test.C? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: BLOCK type=kotlin.Int operator=POSTFIX_INCR
|
||||
VAR val tmp1: kotlin.Int
|
||||
CALL .<get-p> type=kotlin.Int operator=POSTFIX_INCR
|
||||
$this: GET_VAR nc type=test.C? operator=null
|
||||
CALL .<set-p> type=kotlin.Unit operator=POSTFIX_INCR
|
||||
$this: GET_VAR nc type=test.C? operator=null
|
||||
value: CALL .inc type=kotlin.Int? operator=POSTFIX_INCR
|
||||
$receiver: GET_VAR tmp1 type=kotlin.Int operator=null
|
||||
GET_VAR tmp1 type=kotlin.Int operator=null
|
||||
BLOCK type=kotlin.Int? operator=SAFE_CALL
|
||||
VAR val tmp0_safe_receiver: test.C?
|
||||
GET_VAR nc type=test.C? operator=null
|
||||
WHEN type=kotlin.Int? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp0_safe_receiver type=test.C? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: BLOCK type=kotlin.Int operator=POSTFIX_INCR
|
||||
VAR val tmp1: kotlin.Int
|
||||
CALL .<get-p> type=kotlin.Int operator=POSTFIX_INCR
|
||||
$this: GET_VAR tmp0_safe_receiver type=test.C? operator=null
|
||||
CALL .<set-p> type=kotlin.Unit operator=POSTFIX_INCR
|
||||
$this: GET_VAR tmp0_safe_receiver type=test.C? operator=null
|
||||
value: CALL .inc type=kotlin.Int? operator=POSTFIX_INCR
|
||||
$receiver: GET_VAR tmp1 type=kotlin.Int operator=null
|
||||
GET_VAR tmp1 type=kotlin.Int operator=null
|
||||
FUN public fun testArrayAccess(/*0*/ nc: test.C?): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
BLOCK type=kotlin.Int operator=POSTFIX_INCR
|
||||
VAR val tmp3_array: kotlin.Int?
|
||||
WHEN type=kotlin.Int? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR nc type=test.C? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .<get-p> type=kotlin.Int operator=GET_PROPERTY
|
||||
$this: GET_VAR nc type=test.C? operator=null
|
||||
VAR val tmp4: kotlin.Int
|
||||
BLOCK type=kotlin.Int? operator=SAFE_CALL
|
||||
VAR val tmp0_safe_receiver: test.C?
|
||||
GET_VAR nc type=test.C? operator=null
|
||||
WHEN type=kotlin.Int? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp0_safe_receiver type=test.C? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .<get-p> type=kotlin.Int operator=GET_PROPERTY
|
||||
$this: GET_VAR tmp0_safe_receiver type=test.C? operator=null
|
||||
VAR val tmp4_index0: kotlin.Int
|
||||
CONST Int type=kotlin.Int value='0'
|
||||
VAR val tmp5: kotlin.Int
|
||||
CALL .get type=kotlin.Int operator=POSTFIX_INCR
|
||||
$receiver: GET_VAR tmp3_array type=kotlin.Int? operator=null
|
||||
index: CONST Int type=kotlin.Int value='0'
|
||||
index: GET_VAR tmp4_index0 type=kotlin.Int operator=null
|
||||
CALL .set type=kotlin.Unit operator=POSTFIX_INCR
|
||||
$receiver: GET_VAR tmp3_array type=kotlin.Int? operator=null
|
||||
index: CONST Int type=kotlin.Int value='0'
|
||||
index: GET_VAR tmp4_index0 type=kotlin.Int operator=null
|
||||
value: CALL .inc type=kotlin.Int operator=POSTFIX_INCR
|
||||
$this: GET_VAR tmp4 type=kotlin.Int operator=null
|
||||
GET_VAR tmp4 type=kotlin.Int operator=null
|
||||
$this: GET_VAR tmp5 type=kotlin.Int operator=null
|
||||
GET_VAR tmp5 type=kotlin.Int operator=null
|
||||
|
||||
+53
-38
@@ -16,52 +16,67 @@ FILE /safeCalls.kt
|
||||
FUN public fun test1(/*0*/ x: kotlin.String?): kotlin.Int?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=test1
|
||||
WHEN type=kotlin.Int? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR x type=kotlin.String? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .<get-length> type=kotlin.Int operator=GET_PROPERTY
|
||||
$this: GET_VAR x type=kotlin.String? operator=null
|
||||
BLOCK type=kotlin.Int? operator=SAFE_CALL
|
||||
VAR val tmp0_safe_receiver: kotlin.String?
|
||||
GET_VAR x type=kotlin.String? operator=null
|
||||
WHEN type=kotlin.Int? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp0_safe_receiver type=kotlin.String? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .<get-length> type=kotlin.Int operator=GET_PROPERTY
|
||||
$this: GET_VAR tmp0_safe_receiver type=kotlin.String? operator=null
|
||||
FUN public fun test2(/*0*/ x: kotlin.String?): kotlin.Int?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=test2
|
||||
WHEN type=kotlin.Int? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR x type=kotlin.String? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .hashCode type=kotlin.Int operator=null
|
||||
$this: GET_VAR x type=kotlin.String? operator=null
|
||||
BLOCK type=kotlin.Int? operator=SAFE_CALL
|
||||
VAR val tmp0_safe_receiver: kotlin.String?
|
||||
GET_VAR x type=kotlin.String? operator=null
|
||||
WHEN type=kotlin.Int? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp0_safe_receiver type=kotlin.String? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .hashCode type=kotlin.Int operator=null
|
||||
$this: GET_VAR tmp0_safe_receiver type=kotlin.String? operator=null
|
||||
FUN public fun test3(/*0*/ x: kotlin.String?, /*1*/ y: kotlin.Any?): kotlin.Boolean?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=test3
|
||||
WHEN type=kotlin.Boolean? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR x type=kotlin.String? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .equals type=kotlin.Boolean operator=null
|
||||
$this: GET_VAR x type=kotlin.String? operator=null
|
||||
other: GET_VAR y type=kotlin.Any? operator=null
|
||||
BLOCK type=kotlin.Boolean? operator=SAFE_CALL
|
||||
VAR val tmp0_safe_receiver: kotlin.String?
|
||||
GET_VAR x type=kotlin.String? operator=null
|
||||
WHEN type=kotlin.Boolean? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp0_safe_receiver type=kotlin.String? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .equals type=kotlin.Boolean operator=null
|
||||
$this: GET_VAR tmp0_safe_receiver type=kotlin.String? operator=null
|
||||
other: GET_VAR y type=kotlin.Any? operator=null
|
||||
FUN public fun test4(/*0*/ x: Ref?): kotlin.Unit
|
||||
BLOCK_BODY
|
||||
WHEN type=kotlin.Unit? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR x type=Ref? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .<set-value> type=kotlin.Unit operator=EQ
|
||||
$this: GET_VAR x type=Ref? operator=null
|
||||
<set-?>: CONST Int type=kotlin.Int value='0'
|
||||
BLOCK type=kotlin.Unit? operator=SAFE_CALL
|
||||
VAR val tmp0_safe_receiver: Ref?
|
||||
GET_VAR x type=Ref? operator=null
|
||||
WHEN type=kotlin.Unit? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp0_safe_receiver type=Ref? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .<set-value> type=kotlin.Unit operator=EQ
|
||||
$this: GET_VAR tmp0_safe_receiver type=Ref? operator=null
|
||||
<set-?>: CONST Int type=kotlin.Int value='0'
|
||||
FUN public fun IHost.test5(/*0*/ s: kotlin.String?): kotlin.Int?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=test5
|
||||
WHEN type=kotlin.Int? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR s type=kotlin.String? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .extLength type=kotlin.Int operator=null
|
||||
$this: $RECEIVER of: test5 type=IHost
|
||||
$receiver: GET_VAR s type=kotlin.String? operator=null
|
||||
BLOCK type=kotlin.Int? operator=SAFE_CALL
|
||||
VAR val tmp0_safe_receiver: kotlin.String?
|
||||
GET_VAR s type=kotlin.String? operator=null
|
||||
WHEN type=kotlin.Int? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp0_safe_receiver type=kotlin.String? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .extLength type=kotlin.Int operator=null
|
||||
$this: $RECEIVER of: test5 type=IHost
|
||||
$receiver: GET_VAR tmp0_safe_receiver type=kotlin.String? operator=null
|
||||
|
||||
@@ -16,10 +16,12 @@ FILE /smartCastsWithDestructuring.kt
|
||||
GET_VAR x type=I1 operator=null
|
||||
then: RETURN type=kotlin.Nothing from=test
|
||||
BLOCK type=kotlin.Unit operator=DESTRUCTURING_DECLARATION
|
||||
VAR val tmp0_container: I1
|
||||
GET_VAR x type=I1 operator=null
|
||||
VAR val c1: kotlin.Int
|
||||
CALL .component1 type=kotlin.Int operator=COMPONENT_N(index=1)
|
||||
$receiver: GET_VAR x type=I1 operator=null
|
||||
$receiver: GET_VAR tmp0_container type=I1 operator=null
|
||||
VAR val c2: kotlin.String
|
||||
CALL .component2 type=kotlin.String operator=COMPONENT_N(index=2)
|
||||
$receiver: TYPE_OP operator=IMPLICIT_CAST typeOperand=I2
|
||||
GET_VAR x type=I1 operator=null
|
||||
GET_VAR tmp0_container type=I1 operator=null
|
||||
|
||||
+17
-14
@@ -2,23 +2,26 @@ FILE /stringPlus.kt
|
||||
FUN public fun test1(/*0*/ a: kotlin.String, /*1*/ b: kotlin.Any): kotlin.String
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=test1
|
||||
STRING_CONCATENATION type=kotlin.String
|
||||
GET_VAR a type=kotlin.String operator=null
|
||||
GET_VAR b type=kotlin.Any operator=null
|
||||
CALL .plus type=kotlin.String operator=PLUS
|
||||
$this: GET_VAR a type=kotlin.String operator=null
|
||||
other: GET_VAR b type=kotlin.Any operator=null
|
||||
FUN public fun test2(/*0*/ a: kotlin.String, /*1*/ b: kotlin.Int): kotlin.String
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=test2
|
||||
STRING_CONCATENATION type=kotlin.String
|
||||
GET_VAR a type=kotlin.String operator=null
|
||||
CONST String type=kotlin.String value='+'
|
||||
GET_VAR b type=kotlin.Int operator=null
|
||||
CALL .plus type=kotlin.String operator=PLUS
|
||||
$this: CALL .plus type=kotlin.String operator=PLUS
|
||||
$this: GET_VAR a type=kotlin.String operator=null
|
||||
other: CONST String type=kotlin.String value='+'
|
||||
other: GET_VAR b type=kotlin.Int operator=null
|
||||
FUN public fun test3(/*0*/ a: kotlin.String, /*1*/ b: kotlin.Int): kotlin.String
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=test3
|
||||
STRING_CONCATENATION type=kotlin.String
|
||||
GET_VAR a type=kotlin.String operator=null
|
||||
CONST String type=kotlin.String value='+'
|
||||
CALL .plus type=kotlin.Int operator=PLUS
|
||||
$this: GET_VAR b type=kotlin.Int operator=null
|
||||
other: CONST Int type=kotlin.Int value='1'
|
||||
GET_VAR a type=kotlin.String operator=null
|
||||
CALL .plus type=kotlin.String operator=PLUS
|
||||
$this: CALL .plus type=kotlin.String operator=PLUS
|
||||
$this: CALL .plus type=kotlin.String operator=PLUS
|
||||
$this: GET_VAR a type=kotlin.String operator=null
|
||||
other: CONST String type=kotlin.String value='+'
|
||||
other: CALL .plus type=kotlin.Int operator=PLUS
|
||||
$this: GET_VAR b type=kotlin.Int operator=null
|
||||
other: CONST Int type=kotlin.Int value='1'
|
||||
other: GET_VAR a type=kotlin.String operator=null
|
||||
|
||||
@@ -28,11 +28,22 @@ FILE /variableAsFunctionCall.kt
|
||||
FUN public fun test4(/*0*/ ns: kotlin.String?): kotlin.String?
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from=test4
|
||||
WHEN type=kotlin.String? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR ns type=kotlin.String? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .invoke type=kotlin.String operator=null
|
||||
$this: CALL .k type=() -> kotlin.String operator=null
|
||||
$this: GET_VAR ns type=kotlin.String? operator=null
|
||||
BLOCK type=kotlin.String? operator=SAFE_CALL
|
||||
VAR val tmp1_safe_receiver: (() -> kotlin.String)?
|
||||
BLOCK type=(() -> kotlin.String)? operator=SAFE_CALL
|
||||
VAR val tmp0_safe_receiver: kotlin.String?
|
||||
GET_VAR ns type=kotlin.String? operator=null
|
||||
WHEN type=(() -> kotlin.String)? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp0_safe_receiver type=kotlin.String? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .k type=() -> kotlin.String operator=null
|
||||
$this: GET_VAR tmp0_safe_receiver type=kotlin.String? operator=null
|
||||
WHEN type=kotlin.String? operator=SAFE_CALL
|
||||
if: CALL .EQEQ type=kotlin.Boolean operator=EQEQ
|
||||
arg0: GET_VAR tmp1_safe_receiver type=(() -> kotlin.String)? operator=null
|
||||
arg1: CONST Null type=kotlin.Nothing? value='null'
|
||||
then: CONST Null type=kotlin.Nothing? value='null'
|
||||
else: CALL .invoke type=kotlin.String operator=null
|
||||
$this: GET_VAR tmp1_safe_receiver type=(() -> kotlin.String)? operator=null
|
||||
|
||||
@@ -286,6 +286,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("jvmStaticFieldReference.kt")
|
||||
public void testJvmStaticFieldReference() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/jvmStaticFieldReference.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("literals.kt")
|
||||
public void testLiterals() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/expressions/literals.kt");
|
||||
|
||||
Reference in New Issue
Block a user