@@ -15,6 +15,7 @@ import org.jacodb.ets.base.EtsBitOrExpr
1515import org.jacodb.ets.base.EtsBitXorExpr
1616import org.jacodb.ets.base.EtsBooleanConstant
1717import org.jacodb.ets.base.EtsCastExpr
18+ import org.jacodb.ets.base.EtsClassType
1819import org.jacodb.ets.base.EtsCommaExpr
1920import org.jacodb.ets.base.EtsDeleteExpr
2021import org.jacodb.ets.base.EtsDivExpr
@@ -68,6 +69,9 @@ import org.jacodb.ets.base.EtsUnsignedRightShiftExpr
6869import org.jacodb.ets.base.EtsValue
6970import org.jacodb.ets.base.EtsVoidExpr
7071import org.jacodb.ets.base.EtsYieldExpr
72+ import org.jacodb.ets.base.UNKNOWN_CLASS_NAME
73+ import org.jacodb.ets.model.EtsField
74+ import org.jacodb.ets.model.EtsFieldSignature
7175import org.jacodb.ets.model.EtsMethod
7276import org.jacodb.ets.model.EtsMethodSignature
7377import org.usvm.UAddressSort
@@ -93,7 +97,6 @@ import org.usvm.machine.types.mkFakeValue
9397import org.usvm.memory.ULValue
9498import org.usvm.memory.URegisterStackLValue
9599import org.usvm.sizeSort
96- import org.usvm.util.fieldLookUp
97100import org.usvm.util.throwExceptionWithoutStackFrameDrop
98101
99102private val logger = KotlinLogging .logger {}
@@ -407,11 +410,7 @@ class TsExprResolver(
407410 argumentTypes = { expr.method.parameters.map { it.type } },
408411 ) { args ->
409412 doWithState {
410- val method = ctx.scene
411- .projectAndSdkClasses
412- .flatMap { it.methods }
413- .singleOrNull { it.signature == expr.method }
414- ? : error(" Couldn't find a unique method with the signature ${expr.method} " )
413+ val method = resolveInstanceCall(expr.instance, expr.method)
415414
416415 pushSortsForArguments(expr.instance, expr.args, localToIdx)
417416
@@ -447,6 +446,33 @@ class TsExprResolver(
447446 TODO (" Not supported ${expr::class .simpleName} : $expr " )
448447 }
449448
449+ private fun resolveInstanceCall (
450+ instance : EtsLocal ,
451+ method : EtsMethodSignature ,
452+ ): EtsMethod {
453+ // Perfect signature:
454+ if (method.enclosingClass.name != UNKNOWN_CLASS_NAME ) {
455+ val clazz = ctx.scene.projectAndSdkClasses.single { it.name == method.enclosingClass.name }
456+ return clazz.methods.single { it.name == method.name }
457+ }
458+
459+ // Unknown signature:
460+ val instanceType = instance.type
461+ if (instanceType is EtsClassType ) {
462+ val classes = ctx.scene.projectAndSdkClasses.filter { it.name == instanceType.signature.name }
463+ if (classes.size == 1 ) {
464+ val clazz = classes.single()
465+ return clazz.methods.single { it.name == method.name }
466+ }
467+ val methods = classes.flatMap { it.methods }.filter { it.name == method.name }
468+ if (methods.size == 1 ) return methods.single()
469+ } else {
470+ val methods = ctx.scene.projectAndSdkClasses.flatMap { it.methods }.filter { it.name == method.name }
471+ if (methods.size == 1 ) return methods.single()
472+ }
473+ error(" Cannot resolve method $method " )
474+ }
475+
450476 private inline fun resolveInvoke (
451477 method : EtsMethodSignature ,
452478 instance : EtsLocal ? ,
@@ -540,6 +566,32 @@ class TsExprResolver(
540566 state.throwExceptionWithoutStackFrameDrop(address, type)
541567 }
542568
569+ private fun resolveInstanceField (instance : EtsLocal , field : EtsFieldSignature ): EtsField {
570+
571+ // Perfect signature:
572+ if (field.enclosingClass.name != UNKNOWN_CLASS_NAME ) {
573+ val clazz = ctx.scene.projectAndSdkClasses.single { it.name == field.enclosingClass.name }
574+ val fields = clazz.fields.filter { it.name == field.name }
575+ if (fields.size == 1 ) return fields.single()
576+ }
577+
578+ // Unknown signature:
579+ val instanceType = instance.type
580+ if (instanceType is EtsClassType ) {
581+ val classes = ctx.scene.projectAndSdkClasses.filter { it.name == instanceType.signature.name }
582+ if (classes.size == 1 ) {
583+ val clazz = classes.single()
584+ return clazz.fields.single { it.name == field.name }
585+ }
586+ val fields = classes.flatMap { it.fields.filter { it.name == field.name } }
587+ if (fields.size == 1 ) return fields.single()
588+ } else {
589+ val fields = ctx.scene.projectAndSdkClasses.flatMap { it.fields.filter { it.name == field.name } }
590+ if (fields.size == 1 ) return fields.single()
591+ }
592+ error(" Cannot resolve field $field " )
593+ }
594+
543595 override fun visit (value : EtsInstanceFieldRef ): UExpr <out USort >? = with (ctx) {
544596 val instanceRef = resolve(value.instance)?.asExpr(addressSort) ? : return null
545597
@@ -555,8 +607,8 @@ class TsExprResolver(
555607 return mkBvToFpExpr(fp64Sort, fpRoundingModeSortDefaultValue(), expr.asExpr(sizeSort), signed = true )
556608 }
557609
558- val fieldType = scene.fieldLookUp (value.field).type
559- val sort = typeToSort(fieldType )
610+ val field = resolveInstanceField (value.instance, value. field)
611+ val sort = typeToSort(field.type )
560612 val lValue = UFieldLValue (sort, instanceRef, value.field.name)
561613 val expr = scope.calcOnState { memory.read(lValue) }
562614
0 commit comments