from __future__ import absolute_import
from base.instructions import vselect, vsplit, vconcat, iconst, iadd, bint
from base.instructions import b1, icmp, ireduce, iadd_cout
from base.immediates import intcc, imm64
from base.types import i64, i8, b32, i32, i16, f32
from cdsl.typevar import TypeVar
from cdsl.ast import Var
from cdsl.xform import Rtl
from unittest import TestCase
from .elaborate import elaborate
from .primitives import prim_to_bv, bvsplit, prim_from_bv, bvconcat, bvadd, \
bvult, bv_from_imm64, bvite
import base.semantics
def concrete_rtls_eq(r1, r2):
assert r1.is_concrete()
assert r2.is_concrete()
s = r1.substitution(r2, {})
if s is None:
return False
for (v, v1) in s.items():
if v.get_typevar().singleton_type() !=\
v1.get_typevar().singleton_type():
return False
return True
class TestCleanupConcreteRtl(TestCase):
def test_cleanup_concrete_rtl(self):
typ = i64.by(4)
x = Var('x')
lo = Var('lo')
hi = Var('hi')
r = Rtl(
(lo, hi) << vsplit(x),
)
r1 = r.copy({})
s = r.substitution(r1, {})
s[x].set_typevar(TypeVar.singleton(typ))
r1.cleanup_concrete_rtl()
assert s is not None
assert s[x].get_typevar().singleton_type() == typ
assert s[lo].get_typevar().singleton_type() == i64.by(2)
assert s[hi].get_typevar().singleton_type() == i64.by(2)
def test_cleanup_concrete_rtl_fail(self):
x = Var('x')
lo = Var('lo')
hi = Var('hi')
r = Rtl(
(lo, hi) << vsplit(x),
)
with self.assertRaises(AssertionError):
r.cleanup_concrete_rtl()
def test_cleanup_concrete_rtl_ireduce(self):
x = Var('x')
y = Var('y')
r = Rtl(
y << ireduce(x),
)
r1 = r.copy({})
s = r.substitution(r1, {})
s[x].set_typevar(TypeVar.singleton(i8.by(2)))
r1.cleanup_concrete_rtl()
assert s is not None
assert s[x].get_typevar().singleton_type() == i8.by(2)
assert s[y].get_typevar().singleton_type() == i8.by(2)
def test_cleanup_concrete_rtl_ireduce_bad(self):
x = Var('x')
y = Var('y')
x.set_typevar(TypeVar.singleton(i16.by(1)))
r = Rtl(
y << ireduce(x),
)
with self.assertRaises(AssertionError):
r.cleanup_concrete_rtl()
def test_vselect_icmpimm(self):
x = Var('x')
y = Var('y')
z = Var('z')
w = Var('w')
v = Var('v')
zeroes = Var('zeroes')
imm0 = Var("imm0")
r = Rtl(
zeroes << iconst(imm0),
y << icmp(intcc.eq, x, zeroes),
v << vselect(y, z, w),
)
r1 = r.copy({})
s = r.substitution(r1, {})
s[zeroes].set_typevar(TypeVar.singleton(i32.by(4)))
s[z].set_typevar(TypeVar.singleton(f32.by(4)))
r1.cleanup_concrete_rtl()
assert s is not None
assert s[zeroes].get_typevar().singleton_type() == i32.by(4)
assert s[x].get_typevar().singleton_type() == i32.by(4)
assert s[y].get_typevar().singleton_type() == b32.by(4)
assert s[z].get_typevar().singleton_type() == f32.by(4)
assert s[w].get_typevar().singleton_type() == f32.by(4)
assert s[v].get_typevar().singleton_type() == f32.by(4)
def test_bint(self):
x = Var('x')
y = Var('y')
z = Var('z')
w = Var('w')
v = Var('v')
u = Var('u')
r = Rtl(
z << iadd(x, y),
w << bint(v),
u << iadd(z, w)
)
r1 = r.copy({})
s = r.substitution(r1, {})
s[x].set_typevar(TypeVar.singleton(i32.by(8)))
s[z].set_typevar(TypeVar.singleton(i32.by(8)))
s[v].set_typevar(TypeVar('v', '', bools=(1, 1), simd=(8, 8)))
r1.cleanup_concrete_rtl()
assert s is not None
assert s[x].get_typevar().singleton_type() == i32.by(8)
assert s[y].get_typevar().singleton_type() == i32.by(8)
assert s[z].get_typevar().singleton_type() == i32.by(8)
assert s[w].get_typevar().singleton_type() == i32.by(8)
assert s[u].get_typevar().singleton_type() == i32.by(8)
assert s[v].get_typevar().singleton_type() == b1.by(8)
class TestElaborate(TestCase):
def setUp(self):
self.v0 = Var("v0")
self.v1 = Var("v1")
self.v2 = Var("v2")
self.v3 = Var("v3")
self.v4 = Var("v4")
self.v5 = Var("v5")
self.v6 = Var("v6")
self.v7 = Var("v7")
self.v8 = Var("v8")
self.v9 = Var("v9")
self.imm0 = Var("imm0")
self.IxN_nonscalar = TypeVar("IxN_nonscalar", "", ints=True,
scalars=False, simd=True)
self.TxN = TypeVar("TxN", "", ints=True, bools=True, floats=True,
scalars=False, simd=True)
self.b1 = TypeVar.singleton(b1)
def test_elaborate_vsplit(self):
i32.by(4) i32.by(2) r = Rtl(
(self.v0, self.v1) << vsplit.i32x4(self.v2),
)
r.cleanup_concrete_rtl()
sem = elaborate(r)
bvx = Var('bvx')
bvlo = Var('bvlo')
bvhi = Var('bvhi')
x = Var('x')
lo = Var('lo')
hi = Var('hi')
exp = Rtl(
bvx << prim_to_bv.i32x4(x),
(bvlo, bvhi) << bvsplit.bv128(bvx),
lo << prim_from_bv.i32x2(bvlo),
hi << prim_from_bv.i32x2(bvhi)
)
exp.cleanup_concrete_rtl()
assert concrete_rtls_eq(sem, exp)
def test_elaborate_vconcat(self):
i32.by(4) i32.by(2) r = Rtl(
self.v0 << vconcat.i32x2(self.v1, self.v2),
)
r.cleanup_concrete_rtl()
sem = elaborate(r)
bvx = Var('bvx')
bvlo = Var('bvlo')
bvhi = Var('bvhi')
x = Var('x')
lo = Var('lo')
hi = Var('hi')
exp = Rtl(
bvlo << prim_to_bv.i32x2(lo),
bvhi << prim_to_bv.i32x2(hi),
bvx << bvconcat.bv64(bvlo, bvhi),
x << prim_from_bv.i32x4(bvx)
)
exp.cleanup_concrete_rtl()
assert concrete_rtls_eq(sem, exp)
def test_elaborate_iadd_simple(self):
i32.by(2) x = Var('x')
y = Var('y')
a = Var('a')
bvx = Var('bvx')
bvy = Var('bvy')
bva = Var('bva')
r = Rtl(
a << iadd.i32(x, y),
)
r.cleanup_concrete_rtl()
sem = elaborate(r)
exp = Rtl(
bvx << prim_to_bv.i32(x),
bvy << prim_to_bv.i32(y),
bva << bvadd.bv32(bvx, bvy),
a << prim_from_bv.i32(bva)
)
exp.cleanup_concrete_rtl()
assert concrete_rtls_eq(sem, exp)
def test_elaborate_iadd_elaborate_1(self):
i32.by(2) r = Rtl(
self.v0 << iadd.i32x2(self.v1, self.v2),
)
r.cleanup_concrete_rtl()
sem = elaborate(r)
x = Var('x')
y = Var('y')
a = Var('a')
bvx_1 = Var('bvx_1')
bvx_2 = Var('bvx_2')
bvx_5 = Var('bvx_5')
bvlo_1 = Var('bvlo_1')
bvlo_2 = Var('bvlo_2')
bvhi_1 = Var('bvhi_1')
bvhi_2 = Var('bvhi_2')
bva_3 = Var('bva_3')
bva_4 = Var('bva_4')
exp = Rtl(
bvx_1 << prim_to_bv.i32x2(x),
(bvlo_1, bvhi_1) << bvsplit.bv64(bvx_1),
bvx_2 << prim_to_bv.i32x2(y),
(bvlo_2, bvhi_2) << bvsplit.bv64(bvx_2),
bva_3 << bvadd.bv32(bvlo_1, bvlo_2),
bva_4 << bvadd.bv32(bvhi_1, bvhi_2),
bvx_5 << bvconcat.bv32(bva_3, bva_4),
a << prim_from_bv.i32x2(bvx_5)
)
exp.cleanup_concrete_rtl()
assert concrete_rtls_eq(sem, exp)
def test_elaborate_iadd_elaborate_2(self):
i8.by(4) r = Rtl(
self.v0 << iadd.i8x4(self.v1, self.v2),
)
r.cleanup_concrete_rtl()
sem = elaborate(r)
x = Var('x')
y = Var('y')
a = Var('a')
bvx_1 = Var('bvx_1')
bvx_2 = Var('bvx_2')
bvx_5 = Var('bvx_5')
bvx_10 = Var('bvx_10')
bvx_15 = Var('bvx_15')
bvlo_1 = Var('bvlo_1')
bvlo_2 = Var('bvlo_2')
bvlo_6 = Var('bvlo_6')
bvlo_7 = Var('bvlo_7')
bvlo_11 = Var('bvlo_11')
bvlo_12 = Var('bvlo_12')
bvhi_1 = Var('bvhi_1')
bvhi_2 = Var('bvhi_2')
bvhi_6 = Var('bvhi_6')
bvhi_7 = Var('bvhi_7')
bvhi_11 = Var('bvhi_11')
bvhi_12 = Var('bvhi_12')
bva_8 = Var('bva_8')
bva_9 = Var('bva_9')
bva_13 = Var('bva_13')
bva_14 = Var('bva_14')
exp = Rtl(
bvx_1 << prim_to_bv.i8x4(x),
(bvlo_1, bvhi_1) << bvsplit.bv32(bvx_1),
bvx_2 << prim_to_bv.i8x4(y),
(bvlo_2, bvhi_2) << bvsplit.bv32(bvx_2),
(bvlo_6, bvhi_6) << bvsplit.bv16(bvlo_1),
(bvlo_7, bvhi_7) << bvsplit.bv16(bvlo_2),
bva_8 << bvadd.bv8(bvlo_6, bvlo_7),
bva_9 << bvadd.bv8(bvhi_6, bvhi_7),
bvx_10 << bvconcat.bv8(bva_8, bva_9),
(bvlo_11, bvhi_11) << bvsplit.bv16(bvhi_1),
(bvlo_12, bvhi_12) << bvsplit.bv16(bvhi_2),
bva_13 << bvadd.bv8(bvlo_11, bvlo_12),
bva_14 << bvadd.bv8(bvhi_11, bvhi_12),
bvx_15 << bvconcat.bv8(bva_13, bva_14),
bvx_5 << bvconcat.bv16(bvx_10, bvx_15),
a << prim_from_bv.i8x4(bvx_5)
)
exp.cleanup_concrete_rtl()
assert concrete_rtls_eq(sem, exp)
def test_elaborate_iadd_cout_simple(self):
x = Var('x')
y = Var('y')
a = Var('a')
c_out = Var('c_out')
bvc_out = Var('bvc_out')
bc_out = Var('bc_out')
bvx = Var('bvx')
bvy = Var('bvy')
bva = Var('bva')
bvone = Var('bvone')
bvzero = Var('bvzero')
r = Rtl(
(a, c_out) << iadd_cout.i32(x, y),
)
r.cleanup_concrete_rtl()
sem = elaborate(r)
exp = Rtl(
bvx << prim_to_bv.i32(x),
bvy << prim_to_bv.i32(y),
bva << bvadd.bv32(bvx, bvy),
bc_out << bvult.bv32(bva, bvx),
bvone << bv_from_imm64(imm64(1)),
bvzero << bv_from_imm64(imm64(0)),
bvc_out << bvite(bc_out, bvone, bvzero),
a << prim_from_bv.i32(bva),
c_out << prim_from_bv.b1(bvc_out)
)
exp.cleanup_concrete_rtl()
assert concrete_rtls_eq(sem, exp)