Skip to content

Commit c427abf

Browse files
committed
Add call/field resolver, disable AA type inference
1 parent d023b91 commit c427abf

File tree

3 files changed

+61
-17
lines changed

3 files changed

+61
-17
lines changed

usvm-ts/src/main/kotlin/org/usvm/machine/expr/TsExprResolver.kt

Lines changed: 60 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import org.jacodb.ets.base.EtsBitOrExpr
1515
import org.jacodb.ets.base.EtsBitXorExpr
1616
import org.jacodb.ets.base.EtsBooleanConstant
1717
import org.jacodb.ets.base.EtsCastExpr
18+
import org.jacodb.ets.base.EtsClassType
1819
import org.jacodb.ets.base.EtsCommaExpr
1920
import org.jacodb.ets.base.EtsDeleteExpr
2021
import org.jacodb.ets.base.EtsDivExpr
@@ -68,6 +69,9 @@ import org.jacodb.ets.base.EtsUnsignedRightShiftExpr
6869
import org.jacodb.ets.base.EtsValue
6970
import org.jacodb.ets.base.EtsVoidExpr
7071
import 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
7175
import org.jacodb.ets.model.EtsMethod
7276
import org.jacodb.ets.model.EtsMethodSignature
7377
import org.usvm.UAddressSort
@@ -93,7 +97,6 @@ import org.usvm.machine.types.mkFakeValue
9397
import org.usvm.memory.ULValue
9498
import org.usvm.memory.URegisterStackLValue
9599
import org.usvm.sizeSort
96-
import org.usvm.util.fieldLookUp
97100
import org.usvm.util.throwExceptionWithoutStackFrameDrop
98101

99102
private 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

usvm-ts/src/main/kotlin/org/usvm/util/Utils.kt

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@ package org.usvm.util
22

33
import io.ksmt.sort.KFp64Sort
44
import org.jacodb.ets.base.EtsType
5-
import org.jacodb.ets.model.EtsFieldSignature
6-
import org.jacodb.ets.model.EtsScene
75
import org.usvm.UBoolSort
86
import org.usvm.UExpr
97
import org.usvm.UHeapRef
@@ -15,12 +13,6 @@ import org.usvm.machine.state.TsState
1513
fun TsContext.boolToFp(expr: UExpr<UBoolSort>): UExpr<KFp64Sort> =
1614
mkIte(expr, mkFp64(1.0), mkFp64(0.0))
1715

18-
// TODO probably this should be written differently
19-
fun EtsScene.fieldLookUp(field: EtsFieldSignature) = projectAndSdkClasses
20-
.first { it.signature == field.enclosingClass }
21-
.fields
22-
.single { it.name == field.name }
23-
2416
fun TsState.throwExceptionWithoutStackFrameDrop(address: UHeapRef, type: EtsType) {
2517
methodResult = TsMethodResult.TsException(address, type)
2618
}

usvm-ts/src/test/kotlin/org/usvm/util/TsMethodTestRunner.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ abstract class TsMethodTestRunner : TestRunner<TsTest, EtsMethod, EtsType?, TsMe
3838

3939
protected fun loadSampleScene(
4040
className: String,
41-
useArkAnalyzerTypeInference: Boolean = true,
41+
useArkAnalyzerTypeInference: Boolean = false,
4242
): EtsScene {
4343
val name = "$className.ts"
4444
val path = getResourcePath("/samples/$name")

0 commit comments

Comments
 (0)