from opcodes import BYTE, SHR, DIV
from rule import Rule
from z3 import BitVec, ULT
"""
byte(A, shr(B, X))
given A < B / 8
->
0
"""

rule = Rule()

n_bits = 256

# Input vars
X = BitVec('X', n_bits)
A = BitVec('A', n_bits)
B = BitVec('B', n_bits)

# Non optimized result
nonopt = BYTE(A, SHR(B, X))
# Optimized result
opt = 0

rule.require(ULT(A, DIV(B, 8)))

rule.check(nonopt, opt)
"""

# Approximation with 16-bit base types.
n_bits = 16
type_bits = 8

while type_bits <= n_bits:

    rule = Rule()

    # Input vars
    X_short = BitVec('X', type_bits)
    Y_short = BitVec('Y', type_bits)

    # Z3's overflow condition
    actual_overflow = Not(BVMulNoOverflow(X_short, Y_short, False))

    # cast to full n_bits values
    X = BVUnsignedUpCast(X_short, n_bits)
    Y = BVUnsignedUpCast(Y_short, n_bits)

    # Constants
    maxValue = BVUnsignedMax(type_bits, n_bits)

    # Overflow check in YulUtilFunction::overflowCheckedIntMulFunction
    overflow_check = AND(ISZERO(ISZERO(X)), GT(Y, DIV(maxValue, X)))

    rule.check(overflow_check != 0, actual_overflow)

    type_bits *= 2
DIV(X, A) -> SHR(k, X)
Requirements:
A == 1 << K
"""

rule = Rule()

n_bits = 32

# Input vars
X = BitVec('X', n_bits)
A = BitVec('A', n_bits)
K = BitVec('K', n_bits)

# Requirements
rule.require(A == SHL(K, 1))

# Non optimized result
nonopt_1 = MUL(X, A)
nonopt_2 = MUL(A, X)
nonopt_3 = DIV(X, A)

# Optimized result
opt_1 = SHL(K, X)
opt_2 = SHL(K, X)
opt_3 = SHR(K, X)

rule.check(nonopt_1, opt_1)
rule.check(nonopt_2, opt_2)
rule.check(nonopt_3, opt_3)
Beispiel #4
0
    X_short = BitVec('X', type_bits)
    Y_short = BitVec('Y', type_bits)

    # Z3's overflow and underflow conditions
    actual_overflow = Not(BVMulNoOverflow(X_short, Y_short, True))
    actual_underflow = Not(BVMulNoUnderflow(X_short, Y_short))

    # cast to full n_bits values
    X = BVSignedUpCast(X_short, n_bits)
    Y = BVSignedUpCast(Y_short, n_bits)

    # Constants
    maxValue = BVSignedMax(type_bits, n_bits)
    minValue = BVSignedMin(type_bits, n_bits)

    # Overflow and underflow checks in YulUtilFunction::overflowCheckedIntMulFunction
    overflow_check_1 = AND(AND(SGT(X, 0), SGT(Y, 0)), GT(X, DIV(maxValue, Y)))
    underflow_check_1 = AND(AND(SGT(X, 0), SLT(Y, 0)),
                            SLT(Y, SDIV(minValue, X)))
    underflow_check_2 = AND(AND(SLT(X, 0), SGT(Y, 0)),
                            SLT(X, SDIV(minValue, Y)))
    overflow_check_2 = AND(AND(SLT(X, 0), SLT(Y, 0)),
                           SLT(X, SDIV(maxValue, Y)))

    rule.check(actual_overflow, Or(overflow_check_1 != 0,
                                   overflow_check_2 != 0))
    rule.check(actual_underflow,
               Or(underflow_check_1 != 0, underflow_check_2 != 0))

    type_bits *= 2
from opcodes import DIV, SHL, SHR
from rule import Rule
from z3 import BitVec

"""
Rule:
DIV(X, SHL(Y, 1)) -> SHR(Y, X)
Requirements:
"""

rule = Rule()

n_bits = 32

# Input vars
X = BitVec('X', n_bits)
Y = BitVec('Y', n_bits)

# Non optimized result
nonopt = DIV(X, SHL(Y, 1))

# Optimized result
opt = SHR(Y, X)

rule.check(nonopt, opt)
Beispiel #6
0
"""

# Approximation with 16-bit base types.
n_bits = 12

for type_bits in [4, 6, 8, 12]:

    rule = Rule()

    # Input vars
    X_short = BitVec('X', type_bits)
    Y_short = BitVec('Y', type_bits)

    # Z3's overflow condition
    actual_overflow = Not(BVMulNoOverflow(X_short, Y_short, False))

    # cast to full n_bits values
    X = BVUnsignedUpCast(X_short, n_bits)
    Y = BVUnsignedUpCast(Y_short, n_bits)
    product_raw = MUL(X, Y)
    #remove any overflown bits
    product = BVUnsignedCleanupFunction(product_raw, type_bits)

    # Overflow check in YulUtilFunction::overflowCheckedIntMulFunctions
    if type_bits > n_bits / 2:
        overflow_check = ISZERO(OR(ISZERO(X), EQ(Y, DIV(product, X))))
    else:
        overflow_check = ISZERO(EQ(product, product_raw))

    rule.check(overflow_check != 0, actual_overflow)
from opcodes import BYTE, DIV, SHR
from rule import Rule
from z3 import BitVec, UGE, ULE, ULT
"""
byte(A, shr(B, X))
given B % 8 == 0 && A < n_bits/8 && B <= n_bits && A >= B / 8
->
byte(A - B / 8, X)
"""

rule = Rule()

n_bits = 256

# Input vars
X = BitVec('X', n_bits)
A = BitVec('A', n_bits)
B = BitVec('B', n_bits)

# Non optimized result
nonopt = BYTE(A, SHR(B, X))
# Optimized result
opt = BYTE(A - B / 8, X)

rule.require(B % 8 == 0)
rule.require(ULT(A, n_bits / 8))
rule.require(ULE(B, n_bits))
rule.require(UGE(A, DIV(B, 8)))

rule.check(nonopt, opt)