11package org.usvm.constraints
22
3- import org.usvm.INITIAL_CONCRETE_ADDRESS
4- import org.usvm.INITIAL_INPUT_ADDRESS
53import org.usvm.NULL_ADDRESS
64import org.usvm.UBoolExpr
75import org.usvm.UConcreteHeapAddress
86import org.usvm.UConcreteHeapRef
97import org.usvm.UHeapRef
108import org.usvm.UNullRef
119import org.usvm.memory.map
12- import org.usvm.types.UTypeSystem
1310import org.usvm.model.UModel
11+ import org.usvm.model.UTypeModel
1412import org.usvm.solver.USatResult
1513import org.usvm.solver.USolverResult
1614import org.usvm.solver.UUnsatResult
1715import org.usvm.types.USingleTypeStream
1816import org.usvm.types.UTypeRegion
1917import org.usvm.types.UTypeStream
18+ import org.usvm.types.UTypeSystem
2019import org.usvm.uctx
2120
2221interface UTypeEvaluator <Type > {
2322 fun evalIs (ref : UHeapRef , type : Type ): UBoolExpr
2423}
2524
26- class UTypeModel <Type >(
27- val typeSystem : UTypeSystem <Type >,
28- typeStreamByAddr : Map <UConcreteHeapAddress , UTypeStream <Type >>,
29- ) : UTypeEvaluator<Type> {
30- private val typeStreamByAddr = typeStreamByAddr.toMutableMap()
31-
32- fun typeStream (ref : UConcreteHeapRef ): UTypeStream <Type > =
33- typeStreamByAddr[ref.address] ? : typeSystem.topTypeStream()
34-
35- override fun evalIs (ref : UHeapRef , type : Type ): UBoolExpr =
36- when (ref) {
37- is UConcreteHeapRef -> {
38- if (ref.address == NULL_ADDRESS ) {
39- ref.ctx.trueExpr
40- } else {
41- require(ref.address <= INITIAL_INPUT_ADDRESS )
42-
43- val evaluatedTypeStream = typeStream(ref)
44- val typeStream = evaluatedTypeStream.filterBySupertype(type)
45- if (! typeStream.isEmpty) {
46- typeStreamByAddr[ref.address] = typeStream
47- ref.ctx.trueExpr
48- } else {
49- ref.ctx.falseExpr
50- }
51- }
52- }
53-
54- else -> error(" Expecting concrete ref, but got $ref " )
55- }
56- }
57-
5825/* *
5926 * A mutable collection of type constraints. Represents a conjunction of constraints of four kinds:
6027 * 1. x <: T, i.e. object referenced in x inherits T (supertype constraints for x)
@@ -79,7 +46,7 @@ class UTypeConstraints<Type>(
7946 }
8047
8148 /* *
82- * Returns if current type and equality constraints are unsatisfiable (syntactically).
49+ * Returns true if the current type and equality constraints are unsatisfiable (syntactically).
8350 */
8451 var isContradicting = false
8552 private set
@@ -117,16 +84,15 @@ class UTypeConstraints<Type>(
11784 */
11885 fun addSupertype (ref : UHeapRef , type : Type ) {
11986 when (ref) {
87+ is UNullRef -> return
88+
12089 is UConcreteHeapRef -> {
121- require(ref.address >= INITIAL_CONCRETE_ADDRESS )
12290 val concreteType = concreteRefToType.getValue(ref.address)
12391 if (! typeSystem.isSupertype(type, concreteType)) {
12492 contradiction()
12593 }
12694 }
12795
128- is UNullRef -> return
129-
13096 else -> {
13197 val constraints = this [ref]
13298 val newConstraints = constraints.addSupertype(type)
@@ -156,16 +122,15 @@ class UTypeConstraints<Type>(
156122 */
157123 fun excludeSupertype (ref : UHeapRef , type : Type ) {
158124 when (ref) {
125+ is UNullRef -> contradiction() // the [ref] can't be equal to null
126+
159127 is UConcreteHeapRef -> {
160- require(ref.address >= INITIAL_CONCRETE_ADDRESS )
161128 val concreteType = concreteRefToType.getValue(ref.address)
162129 if (typeSystem.isSupertype(type, concreteType)) {
163130 contradiction()
164131 }
165132 }
166133
167- is UNullRef -> contradiction() // the [ref] can't be equal to null
168-
169134 else -> {
170135 val constraints = this [ref]
171136 val newConstraints = constraints.excludeSupertype(type)
@@ -178,8 +143,7 @@ class UTypeConstraints<Type>(
178143 for ((key, value) in symbolicRefToTypeRegion.entries) {
179144 // TODO: cache intersections?
180145 if (key != ref && value.intersect(newConstraints).isEmpty) {
181- // If we have two inputs of incomparable reference types, then they are either non equal,
182- // or both nulls
146+ // If we have two inputs of incomparable reference types, then they are non equal
183147 equalityConstraints.makeNonEqual(ref, key)
184148 }
185149 }
@@ -195,7 +159,6 @@ class UTypeConstraints<Type>(
195159 internal fun readTypeStream (ref : UHeapRef ): UTypeStream <Type > =
196160 when (ref) {
197161 is UConcreteHeapRef -> {
198- require(ref.address >= INITIAL_CONCRETE_ADDRESS )
199162 val concreteType = concreteRefToType[ref.address]
200163 val typeStream = if (concreteType == null ) {
201164 typeSystem.topTypeStream()
@@ -310,24 +273,25 @@ class UTypeConstraints<Type>(
310273 // to have the common type with [heapRef], therefore they can't be equal or
311274 // some of them equals null
312275 val disjunct = mutableListOf<UBoolExpr >()
313- potentialConflictingRefs.mapTo(disjunct) { ref ->
314- with (ref.uctx) { ref.neq(heapRef) }
315- }
316- potentialConflictingRefs.mapTo(disjunct) { ref ->
317- with (ref.uctx) { ref.eq(nullRef) }
276+ with (heapRef.uctx) {
277+ // can't be equal to heapRef
278+ potentialConflictingRefs.mapTo(disjunct) { it.neq(heapRef) }
279+ // some of them is null
280+ potentialConflictingRefs.mapTo(disjunct) { it.eq(nullRef) }
281+ disjunct + = heapRef.eq(nullRef)
318282 }
319283 bannedRefEqualities + = heapRef.ctx.mkOr(disjunct)
320284
321285 // start a new group
322286 nextRegion = region
323287 potentialConflictingRefs.clear()
324288 potentialConflictingRefs.add(heapRef)
325- } else if (nextRegion == = region) {
289+ } else if (nextRegion == region) {
326290 // the current [heapRef] gives the same region as the potentialConflictingRefs, so it's better
327291 // to keep only the [heapRef] to minimize the disequalities amount in the result disjunction
328292 potentialConflictingRefs.clear()
329293 potentialConflictingRefs.add(heapRef)
330- } else if (nextRegion != = currentRegion) {
294+ } else if (nextRegion != currentRegion) {
331295 // no conflict detected, but the current region became smaller
332296 potentialConflictingRefs.add(heapRef)
333297 }
@@ -354,9 +318,9 @@ class UTypeConstraints<Type>(
354318 // because if the cluster is bigger, then we called region.isEmpty previously at least once
355319 check(cluster.size == 1 )
356320 return UUnsatResult ()
357- } else {
358- typeStream
359321 }
322+
323+ typeStream
360324 }
361325
362326 val typeModel = UTypeModel (typeSystem, allConcreteRefToType)
@@ -365,5 +329,5 @@ class UTypeConstraints<Type>(
365329}
366330
367331class UTypeUnsatResult <Type >(
368- val expressionsToAssert : List <UBoolExpr >,
332+ val referenceDisequalitiesDisjuncts : List <UBoolExpr >,
369333) : UUnsatResult<UTypeModel<Type>>()
0 commit comments