compiler/ir: introduce Fraction type (incomplete)

This commit is contained in:
Sebastien Bourdeauducq 2014-08-19 17:52:55 +08:00
parent 0832507c26
commit 76cef042a5
2 changed files with 93 additions and 0 deletions

View File

@ -107,6 +107,13 @@ class Visitor:
fn = node.func.id fn = node.func.id
if fn in ast_unfuns: if fn in ast_unfuns:
return ast_unfuns[fn](self.visit_expression(node.args[0]), self.builder) return ast_unfuns[fn](self.visit_expression(node.args[0]), self.builder)
elif fn == "Fraction":
r = ir_values.VFraction()
if self.builder is not None:
numerator = self.visit_expression(node.args[0])
denominator = self.visit_expression(node.args[1])
r.set_value_nd(self.builder, numerator, denominator)
return r
elif fn == "syscall": elif fn == "syscall":
return self.env.syscall(node.args[0].s, return self.env.syscall(node.args[0].s,
[self.visit_expression(expr) for expr in node.args[1:]], [self.visit_expression(expr) for expr in node.args[1:]],

View File

@ -186,6 +186,92 @@ class VBool(VInt):
r.set_ssa_value(builder, self.get_ssa_value(builder)) r.set_ssa_value(builder, self.get_ssa_value(builder))
return r return r
# Fraction type
class VFraction(_Value):
def get_llvm_type(self):
return lc.Type.vector(lc.Type.int(64), 2)
def __repr__(self):
return "<VFraction>"
def same_type(self, other):
return isinstance(other, VFraction)
def merge(self, other):
if not isinstance(other, VFraction):
raise TypeError
def _simplify(self, builder):
pass # TODO
def set_value_nd(self, builder, numerator, denominator):
numerator = numerator.o_int64(builder).get_ssa_value(builder)
denominator = denominator.o_int64(builder).get_ssa_value(builder)
value = lc.Constant.undef(lc.Type.vector(lc.Type.int(64), 2))
value = builder.insert_element(value, numerator, lc.Constant.int(lc.Type.int(), 0))
value = builder.insert_element(value, denominator, lc.Constant.int(lc.Type.int(), 1))
self.set_ssa_value(builder, value)
self._simplify(builder)
def set_value(self, builder, n):
if not isinstance(n, VFraction):
raise TypeError
self.set_ssa_value(builder, n.get_ssa_value(builder))
def o_bool(self, builder):
r = VBool()
if builder is not None:
zero = lc.Constant.int(lc.Type.int(64), 0)
numerator = builder.extract_element(self.get_ssa_value(builder), lc.Constant.int(lc.Type.int(), 0))
r.set_ssa_value(builder, builder.icmp(lc.ICMP_NE, numerator, zero))
return r
def o_intx(self, target_bits, builder):
if builder is None:
return VInt(target_bits)
else:
r = VInt(64)
numerator = builder.extract_element(self.get_ssa_value(builder), lc.Constant.int(lc.Type.int(), 0))
denominator = builder.extract_element(self.get_ssa_value(builder), lc.Constant.int(lc.Type.int(), 1))
r.set_ssa_value(builder, builder.sdiv(numerator, denominator))
return r.o_intx(target_bits, builder)
def o_roundx(self, target_bits, builder):
if builder is None:
return VInt(target_bits)
else:
r = VInt(64)
numerator = builder.extract_element(self.get_ssa_value(builder), lc.Constant.int(lc.Type.int(), 0))
denominator = builder.extract_element(self.get_ssa_value(builder), lc.Constant.int(lc.Type.int(), 1))
h_denominator = builder.ashr(denominator, lc.Constant.int(lc.Type.int(), 1))
r_numerator = builder.add(numerator, h_denominator)
r.set_ssa_value(builder, builder.sdiv(r_numerator, denominator))
return r.o_intx(target_bits, builder)
def _o_eq_inv(self, other, builder, invert):
if isinstance(other, VFraction):
r = VBool()
if builder is not None:
ee = []
for i in range(2):
es = builder.extract_element(self.get_ssa_value(builder), lc.Constant.int(lc.Type.int(), i))
eo = builder.extract_element(other.get_ssa_value(builder), lc.Constant.int(lc.Type.int(), i))
ee.append(builder.icmp(lc.ICMP_EQ, es, eo))
ssa_r = builder.and_(ee[0], ee[1])
if invert:
ssa_r = builder.xor(ssa_r, lc.Constant.int(lc.Type.int(1), 1))
r.set_ssa_value(builder, ssa_r)
return r
else:
return NotImplemented
def o_eq(self, other, builder):
return self._o_eq_inv(other, builder, False)
def o_ne(self, other, builder):
return self._o_eq_inv(other, builder, True)
# Operators # Operators
def _make_unary_operator(op_name): def _make_unary_operator(op_name):