@@ -3,13 +3,14 @@ package org.usvm.machine.expr
3
3
import io.ksmt.utils.asExpr
4
4
import org.jacodb.ets.model.EtsArrayType
5
5
import org.jacodb.ets.model.EtsInstanceCallExpr
6
- import org.jacodb.ets.model.EtsType
7
6
import org.usvm.UExpr
7
+ import org.usvm.api.initializeArray
8
+ import org.usvm.api.initializeArrayLength
8
9
import org.usvm.api.memcpy
9
10
import org.usvm.api.typeStreamOf
10
11
import org.usvm.isAllocatedConcreteHeapRef
11
12
import org.usvm.sizeSort
12
- import org.usvm.types.TypesResult
13
+ import org.usvm.types.firstOrNull
13
14
import org.usvm.util.mkArrayIndexLValue
14
15
import org.usvm.util.mkArrayLengthLValue
15
16
@@ -34,58 +35,95 @@ fun TsExprResolver.tryApproximateInstanceCall(expr: EtsInstanceCallExpr): UExpr<
34
35
}
35
36
36
37
val instanceType = if (isAllocatedConcreteHeapRef(resolvedInstance)) {
37
- scope.calcOnState { (memory.typeStreamOf(resolvedInstance).take(1 ) as ? TypesResult .SuccessfulTypesResult <EtsType >)?.types?.single() ? : expr.instance.type }
38
+ scope.calcOnState {
39
+ memory.typeStreamOf(resolvedInstance).firstOrNull() ? : expr.instance.type
40
+ }
38
41
} else {
39
42
expr.instance.type
40
43
}
41
44
42
45
if (instanceType is EtsArrayType ) {
43
- val elementTypeSort = typeToSort(instanceType).takeIf { it !is TsUnresolvedSort } ? : ctx.addressSort
44
- // TODO write tests https://github.com/UnitTestBot/usvm/issues/300
46
+ val elementTypeSort = typeToSort(instanceType.elementType).takeIf { it !is TsUnresolvedSort } ? : ctx.addressSort
47
+
48
+ // push
45
49
if (expr.callee.name == " push" ) {
46
50
return scope.calcOnState {
47
51
val resolvedInstance = resolve(expr.instance)?.asExpr(ctx.addressSort) ? : return @calcOnState null
48
-
49
52
val lengthLValue = mkArrayLengthLValue(resolvedInstance, instanceType)
50
53
val length = memory.read(lengthLValue)
51
-
52
54
val newLength = mkBvAddExpr(length, 1 .toBv())
53
55
memory.write(lengthLValue, newLength, guard = ctx.trueExpr)
54
-
55
56
val resolvedArg = resolve(expr.args.single()) ? : return @calcOnState null
56
-
57
- // TODO check sorts compatibility https://github.com/UnitTestBot/usvm/issues/300
58
57
val newIndexLValue = mkArrayIndexLValue(
59
58
resolvedArg.sort,
60
59
resolvedInstance,
61
60
length,
62
61
instanceType
63
62
)
64
63
memory.write(newIndexLValue, resolvedArg.asExpr(newIndexLValue.sort), guard = ctx.trueExpr)
64
+ newLength
65
+ }
66
+ }
65
67
68
+ // fill
69
+ if (expr.callee.name == " fill" ) {
70
+ return scope.calcOnState {
71
+ val resolvedInstance = resolve(expr.instance)?.asExpr(ctx.addressSort) ? : return @calcOnState null
72
+ val lengthLValue = mkArrayLengthLValue(resolvedInstance, instanceType)
73
+ val length = memory.read(lengthLValue)
74
+ val resolvedArg = resolve(expr.args.single()) ? : return @calcOnState null
75
+
76
+ val artificialArray = memory.allocConcrete(instanceType)
77
+ memory.initializeArrayLength(artificialArray, instanceType, sizeSort, 10_000 .toBv().asExpr(sizeSort))
78
+ memory.initializeArray(artificialArray, instanceType, elementTypeSort, sizeSort, Array (10_000 ) { resolvedArg.asExpr(elementTypeSort) }.asSequence())
79
+ memory.memcpy(artificialArray, resolvedInstance, instanceType, elementTypeSort, 0 .toBv(), 0 .toBv(), length)
80
+
81
+ resolvedInstance
82
+ }
83
+ }
84
+
85
+ // unshift
86
+ if (expr.callee.name == " unshift" ) {
87
+ return scope.calcOnState {
88
+ val resolvedInstance = resolve(expr.instance)?.asExpr(ctx.addressSort) ? : return @calcOnState null
89
+ val lengthLValue = mkArrayLengthLValue(resolvedInstance, instanceType)
90
+ val length = memory.read(lengthLValue)
91
+ val newLength = mkBvAddExpr(length, 1 .toBv())
92
+ memory.write(lengthLValue, newLength, guard = ctx.trueExpr)
93
+ val resolvedArg = resolve(expr.args.single()) ? : return @calcOnState null
94
+ memory.memcpy(
95
+ srcRef = resolvedInstance,
96
+ dstRef = resolvedInstance,
97
+ type = instanceType,
98
+ elementSort = elementTypeSort,
99
+ fromSrc = 0 .toBv().asExpr(sizeSort),
100
+ fromDst = 1 .toBv().asExpr(sizeSort),
101
+ length = length,
102
+ )
103
+ val zeroIndexLValue = mkArrayIndexLValue(
104
+ resolvedArg.sort,
105
+ resolvedInstance,
106
+ 0 .toBv().asExpr(sizeSort),
107
+ instanceType
108
+ )
109
+ memory.write(zeroIndexLValue, resolvedArg.asExpr(zeroIndexLValue.sort), guard = ctx.trueExpr)
66
110
newLength
67
111
}
68
112
}
69
113
70
114
if (expr.callee.name == " shift" ) {
71
115
return scope.calcOnState {
72
116
val resolvedInstance = resolve(expr.instance)?.asExpr(ctx.addressSort) ? : return @calcOnState null
73
-
74
117
val lengthLValue = mkArrayLengthLValue(resolvedInstance, instanceType)
75
118
val length = memory.read(lengthLValue)
76
119
val newLength = mkBvSubExpr(length, 1 .toBv())
77
-
78
120
val indexLValue = mkArrayIndexLValue(
79
121
elementTypeSort,
80
122
resolvedInstance,
81
123
0 .toBv().asExpr(sizeSort),
82
124
instanceType
83
125
)
84
-
85
- // TODO add exception for empty array????
86
-
87
126
val result = memory.read(indexLValue)
88
-
89
127
memory.memcpy(
90
128
srcRef = resolvedInstance,
91
129
dstRef = resolvedInstance,
@@ -95,34 +133,27 @@ fun TsExprResolver.tryApproximateInstanceCall(expr: EtsInstanceCallExpr): UExpr<
95
133
fromDst = 0 .toBv().asExpr(sizeSort),
96
134
length = newLength,
97
135
)
98
-
99
136
memory.write(lengthLValue, newLength, guard = ctx.trueExpr)
100
-
101
137
result
102
138
}
103
139
}
104
140
105
141
if (expr.callee.name == " pop" ) {
106
142
return scope.calcOnState {
107
143
val resolvedInstance = resolve(expr.instance)?.asExpr(ctx.addressSort) ? : return @calcOnState null
108
-
109
144
val lengthLValue = mkArrayLengthLValue(resolvedInstance, instanceType)
110
145
val length = memory.read(lengthLValue)
111
-
112
146
if (length == 0 .toBv().asExpr(sizeSort)) {
113
147
return @calcOnState null // TODO throw exception?
114
148
}
115
-
116
149
val newLength = mkBvSubExpr(length, 1 .toBv())
117
150
memory.write(lengthLValue, newLength, guard = ctx.trueExpr)
118
-
119
151
val indexLValue = mkArrayIndexLValue(
120
152
elementTypeSort,
121
153
resolvedInstance,
122
154
newLength,
123
155
instanceType
124
156
)
125
-
126
157
memory.read(indexLValue)
127
158
}
128
159
}
0 commit comments