From 76cef042a5fdd2cb8fbbfb094bb82f70a83fd143 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Tue, 19 Aug 2014 17:52:55 +0800 Subject: [PATCH] compiler/ir: introduce Fraction type (incomplete) --- artiq/compiler/ir_ast_body.py | 7 +++ artiq/compiler/ir_values.py | 86 +++++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/artiq/compiler/ir_ast_body.py b/artiq/compiler/ir_ast_body.py index 57f3b1018..3437c1b56 100644 --- a/artiq/compiler/ir_ast_body.py +++ b/artiq/compiler/ir_ast_body.py @@ -107,6 +107,13 @@ class Visitor: fn = node.func.id if fn in ast_unfuns: 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": return self.env.syscall(node.args[0].s, [self.visit_expression(expr) for expr in node.args[1:]], diff --git a/artiq/compiler/ir_values.py b/artiq/compiler/ir_values.py index 156b4aac9..b5e9ed85d 100644 --- a/artiq/compiler/ir_values.py +++ b/artiq/compiler/ir_values.py @@ -186,6 +186,92 @@ class VBool(VInt): r.set_ssa_value(builder, self.get_ssa_value(builder)) 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 "" + + 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 def _make_unary_operator(op_name):