6. false positiveを出さない方針
その条件の元でできるだけfalse negativeを減らす
記号 : A = B op C(オリジナル), A', B', C':shadow
6/11
Shadow propagation rule
命令 ルール
A = load P check P', load (P & shadowMask)
*P = A check P', *(P & shadowMask) = A'
A = const A' = 0
A = undef A' = 0xff
A = B & C A' = (B'&C')|(B&C')|(B'&C)
A = B | C A' = (B'&C')|(~B&C')|(B'&~C)
A = B ^ C A' = B' | C'
A = B << C A' = (sign extend(C'!=0))|(B'<<C)
7. A = B * (C * (1 << D))
A' = B' << Dで代用(一般はA' = B'| C')
bitwiseにやってるとfalse positiveになる例
clangはこれを *(unsigned char*)s > 7と最適化する
X : unsigned, X':対応するshadowのとき
Xのとり得る範囲は[VMin(X, X'), VMax(X, X')]
VMin(X, X') = X & (~X')
VMax(X, X') = X | X'
正確だがベンチマークで50%の速度低下
7/11
複雑なパターン(1/2)
struct S { int a:3; int b:5; };
bool f(S* s) { return s->b; }
8. 等号比較
A = B == Cを
D = B ^ C, A = D == 0に変換
D' = B'|C', A'=(!(D & ~D')) && (D' != 0)
条件演算子
A = B ? C : D
BがundefでもCとDが同じでdefならAはdefになる
A' = B' ? ((C ^ D) | C' | D') : (B ? C' : D')
8/11
複雑なパターン(2/2)