Z3 BitVec使用符号高低提取

时间:2018-07-16 19:54:48

标签: python z3 z3py

我一直在尝试使用Z3证明某些SIMD向量化,并且在尝试对有条件地在位或通道(例如Intel _mm_shuffle_epi8)周围移动的SIMD操作进行建模时遇到问题 >

当我尝试将符号highlow与似乎不受支持的Extract一起使用时,会发生问题:

assert a.sort() == BitVecSort(128)
assert b.sort() == BitVecSort(128)
Extract( Extract(i+3,i,b)*8+7, Extract(i+3,i,b)*8, a)

产生

z3.z3types.Z3Exception: Symbolic expressions cannot be cast to concrete Boolean values.

问题似乎有两个方面:

Z3似乎不支持符号大小的BitVecs

>>> a = Int('a')
>>> b = BitVec('b', a)
ctypes.ArgumentError: argument 2: <class 'TypeError'>: wrong type

会很整洁,但是a。结果,Extract需要能够准确知道其返回值的类型BitVec,并要求highlow都是具体的,即使它看起来像唯一真正的要求应该是simplify(high - low)产生具体的价值。

这样做的正确方法是什么?

2 个答案:

答案 0 :(得分:3)

SMTLib位向量逻辑仅针对具体的位大小定义。这不仅是一个疏忽:这是逻辑的基本限制:没有决定程序可以决定可能涉及符号大小的位向量公式的正确性,因为位向量公式的真实性可以根据大小而变化。经典示例是:

x <= 7

如果x是大小<= 3的位向量,则上述内容为true,否则为true。如果这是人为的,请考虑以下因素:

x*x <= x+x+x

同样,如果x为2位宽,则为true,但如果为3位宽,则为true。因此,SMTLib要求所有位向量大小在规范时都是具体的。请注意,您可以 编写适用于任意位大小的高级程序,但是一旦将它们渲染并发送到求解器,所有位向量大小都必须是已知的具体常量。

关于您对Extract的问题。没错,严格来说,最后长度的具体性就足够了。但是z3py是SMTLib之上的一个薄层,并且没有做这样的简化。 “具体”要求来自对相应的SMTLib函数的类似限制:

All function symbols with declaration of the form

  ((_ extract i j) (_ BitVec m) (_ BitVec n))

where
- i, j, m, n are numerals
- m > i ≥ j ≥ 0,
- n = i - j + 1  "

请参见此处:http://smtlib.cs.uiowa.edu/theories-FixedSizeBitVectors.shtml请注意,出于这个原因,即使逻辑本身也被称为“ FixedSizeBitVectors”,而不仅仅是“ BitVectors”。

但是,要提取固定大小的块,只需右移lo,然后掩蔽/提取所需的位数,并不是很困难:

 ((_ extract 7 0) (bvlshr x lo))

如果块的大小不是恒定的,那么您又会进入符号位向量大小的世界,出于上面我提到的原因,SMTLib避免了这种情况。 (这也是extract将具体整数用作参数并以有趣的SMTLib表示法表示该参数为具体值的原因。)

如果必须使用“符号”字长,最好的办法是编写程序,并通过确保每种情况下的具体大小分别证明感兴趣的每个“符号”字长。 (基本上是您感兴趣的所有大小的大小写分隔。)

答案 1 :(得分:1)

是的,高/低必须保持恒定,以便静态知道结果类型。 尽管需要固定输出的最大大小,但您可以使用shift和/或遮罩来执行所需的操作。