コード例 #1
0
ファイル: compiler.py プロジェクト: Abramovuch/parakeet
 def compile_Select(self, expr, builder):
   cond = self.compile_expr(expr.cond, builder)
   cond = llvm_convert.to_bit(cond, builder)
   trueval = self.compile_expr(expr.true_value, builder)
   falseval = self.compile_expr(expr.false_value, builder)
   result =  builder.select(cond, trueval, falseval, "select_result")
   return result 
コード例 #2
0
 def compile_Select(self, expr, builder):
     cond = self.compile_expr(expr.cond, builder)
     cond = llvm_convert.to_bit(cond, builder)
     trueval = self.compile_expr(expr.true_value, builder)
     falseval = self.compile_expr(expr.false_value, builder)
     result = builder.select(cond, trueval, falseval, "select_result")
     return result
コード例 #3
0
ファイル: llvm_backend.py プロジェクト: lucciano/parakeet
  def compile_While(self, stmt, builder):
    # current flow ----> loop --------> exit--> after
    #    |                       skip------------|
    #    |----------------------/

    self.compile_merge_left(stmt.merge, builder)
    loop_bb, body_start_builder = self.new_block("loop_body")

    after_bb, after_builder = self.new_block("after_loop")
    enter_cond = self.compile_expr(stmt.cond, builder)
    enter_cond = llvm_convert.to_bit(enter_cond, builder)
    builder.cbranch(enter_cond, loop_bb, after_bb)

    body_end_builder, body_always_returns = \
        self.compile_block(stmt.body, body_start_builder)
    if not body_always_returns:
      exit_bb, exit_builder = self.new_block("loop_exit")
      self.compile_merge_right(stmt.merge, body_end_builder)
      repeat_cond = self.compile_expr(stmt.cond, body_end_builder)
      repeat_cond = llvm_convert.to_bit(repeat_cond, body_end_builder)
      body_end_builder.cbranch(repeat_cond, loop_bb, exit_bb)
      exit_builder.branch(after_bb)

    return after_builder, False
コード例 #4
0
    def compile_While(self, stmt, builder):
        # current flow ----> loop --------> exit--> after
        #    |                       skip------------|
        #    |----------------------/

        self.compile_merge_left(stmt.merge, builder)
        loop_bb, body_start_builder = self.new_block("loop_body")

        after_bb, after_builder = self.new_block("after_loop")
        enter_cond = self.compile_expr(stmt.cond, builder)
        enter_cond = llvm_convert.to_bit(enter_cond, builder)
        builder.cbranch(enter_cond, loop_bb, after_bb)

        body_end_builder, body_always_returns = \
            self.compile_block(stmt.body, body_start_builder)
        if not body_always_returns:
            exit_bb, exit_builder = self.new_block("loop_exit")
            self.compile_merge_right(stmt.merge, body_end_builder)
            repeat_cond = self.compile_expr(stmt.cond, body_end_builder)
            repeat_cond = llvm_convert.to_bit(repeat_cond, body_end_builder)
            body_end_builder.cbranch(repeat_cond, loop_bb, exit_bb)
            exit_builder.branch(after_bb)

        return after_builder, False
コード例 #5
0
ファイル: llvm_backend.py プロジェクト: lucciano/parakeet
  def compile_If(self, stmt, builder):
    cond = self.compile_expr(stmt.cond, builder)
    cond = llvm_convert.to_bit(cond, builder)

    if len(stmt.true) == 0 and len(stmt.false) == 0:
      # if nothing happens in the loop bodies, just
      # emit select instructions
      for (name, (true_expr, false_expr)) in stmt.merge.iteritems():
        ref = self.vars[name]
        self.initialized.add(name)
        true_val = self.compile_expr(true_expr, builder)
        false_val = self.compile_expr(false_expr, builder)
        select_val = builder.select(cond, true_val, false_val)
        builder.store(select_val, ref)
      return builder, False
    else:
      # compile the two possible branches as distinct basic blocks
      # and then wire together the control flow with branches
      true_bb, true_builder = self.new_block("if_true")
      after_true, true_always_returns = \
        self.compile_block(stmt.true, true_builder)

      false_bb, false_builder = self.new_block("if_false")
      after_false, false_always_returns = \
          self.compile_block(stmt.false, false_builder)

      builder.cbranch(cond, true_bb, false_bb)

      # compile phi nodes as assignments and then branch
      # to the continuation block
      self.compile_merge_left(stmt.merge, after_true)
      self.compile_merge_right(stmt.merge, after_false)

      # if both branches return then there is no point
      # making a new block for more code
      # did both branches end in a return?
      both_always_return = true_always_returns and false_always_returns
      if both_always_return:
        return None, True
      after_bb, after_builder = self.new_block("if_after")
      if not true_always_returns:
        after_true.branch(after_bb)
      if not false_always_returns:
        after_false.branch(after_bb)
      return after_builder, False
コード例 #6
0
    def compile_If(self, stmt, builder):
        cond = self.compile_expr(stmt.cond, builder)
        cond = llvm_convert.to_bit(cond, builder)

        if len(stmt.true) == 0 and len(stmt.false) == 0:
            # if nothing happens in the loop bodies, just
            # emit select instructions
            for (name, (true_expr, false_expr)) in stmt.merge.iteritems():
                ref = self.vars[name]
                self.initialized.add(name)
                true_val = self.compile_expr(true_expr, builder)
                false_val = self.compile_expr(false_expr, builder)
                select_val = builder.select(cond, true_val, false_val)
                builder.store(select_val, ref)
            return builder, False
        else:
            # compile the two possible branches as distinct basic blocks
            # and then wire together the control flow with branches
            true_bb, true_builder = self.new_block("if_true")
            after_true, true_always_returns = \
              self.compile_block(stmt.true, true_builder)

            false_bb, false_builder = self.new_block("if_false")
            after_false, false_always_returns = \
                self.compile_block(stmt.false, false_builder)

            builder.cbranch(cond, true_bb, false_bb)

            # compile phi nodes as assignments and then branch
            # to the continuation block
            self.compile_merge_left(stmt.merge, after_true)
            self.compile_merge_right(stmt.merge, after_false)

            # if both branches return then there is no point
            # making a new block for more code
            # did both branches end in a return?
            both_always_return = true_always_returns and false_always_returns
            if both_always_return:
                return None, True
            after_bb, after_builder = self.new_block("if_after")
            if not true_always_returns:
                after_true.branch(after_bb)
            if not false_always_returns:
                after_false.branch(after_bb)
            return after_builder, False
コード例 #7
0
ファイル: compiler.py プロジェクト: Abramovuch/parakeet
  def prim(self, prim, t, llvm_args, builder, result_name = None):
    if result_name is None:
      result_name = prim.name + "_result"

    if isinstance(prim, prims.Cmp):
      bit = self.cmp(prim, t, llvm_args[0], llvm_args[1], builder)
      return llvm_convert.to_bool(bit,builder)
    
    elif prim == prims.maximum:
      x, y = llvm_args
      bit = self.cmp(prims.greater_equal, t, x, y, builder)
      return builder.select(bit, x, y)
    
    elif prim == prims.minimum:
      x,y = llvm_args
      bit = self.cmp(prims.less_equal, t, x, y, builder)
      return builder.select(bit, x, y)
    
    elif prim == prims.negative:
      if t == Bool: 
        bit = llvm_convert.to_bit(llvm_args[0], builder)
        negated = builder.not_(bit)
        return llvm_convert.to_bool(negated, builder)
      return self.neg(llvm_args[0], builder)
    
    # python's remainder is weird in that it preserve's the sign of 
    # the second argument, whereas LLVM's srem/frem operators preserve
    # the sign of the first 
    elif prim == prims.mod:
      x,y = llvm_args 
      if isinstance(t, (UnsignedT, BoolT)):
        return builder.urem(llvm_args[0], llvm_args[1], "modulo")
      elif isinstance(t, SignedT): 
        rem = builder.srem(x,y, "modulo")
      else:
        assert isinstance(t, FloatT)
        rem = builder.frem(llvm_args[0], llvm_args[1], "modulo")

      y_is_negative = self.lt(t, y, zero(y.type), builder, "second_arg_negative")
      rem_is_negative = self.lt(t, rem, zero(rem.type), builder, "rem_is_negative")
      y_nonzero = self.neq(t, y, zero(y.type), builder, "second_arg_nonzero")
      rem_nonzero = self.neq(t, rem, zero(x.type), builder, "rem_nonzero")
      neither_zero = builder.and_(y_nonzero, rem_nonzero, "neither_zero")
      diff_signs = builder.xor(y_is_negative, rem_is_negative, "different_signs")
      should_flip = builder.and_(neither_zero, diff_signs, "should_flip") 
      flipped_rem = self.add(t, y, rem, builder, "flipped_rem")
      return builder.select(should_flip, flipped_rem, rem)

    elif prim == prims.power:
      x,y = llvm_args
       
      if isinstance(t, FloatT):
        new_t = t 
      else:
        new_t = Float64
      x = llvm_convert.convert(x, t, new_t, builder)
      y = llvm_convert.convert(y, t, new_t, builder)
      llvm_op = llvm_prims.get_float_op(prim, new_t)
      result = builder.call(llvm_op, [x,y])
      return llvm_convert.convert(result, new_t, t, builder)
        
    elif isinstance(prim, prims.Arith) or isinstance(prim, prims.Bitwise):
      if isinstance(t, FloatT):
        instr = llvm_prims.float_binops[prim]
      elif isinstance(t, SignedT):
        instr = llvm_prims.signed_binops[prim]
      elif isinstance(t, UnsignedT):
        instr = llvm_prims.unsigned_binops[prim]
      else:
        assert isinstance(t, BoolT)
        instr = llvm_prims.bool_binops[prim]
      op = getattr(builder, instr)
      return op(name = result_name, *llvm_args)

    elif isinstance(prim, prims.Logical):
      if prim == prims.logical_and:
        result = builder.and_(name = result_name, 
                            lhs = to_bit(llvm_args[0], builder), 
                            rhs = to_bit(llvm_args[1], builder))
        return from_bit(result, t, builder)
      elif prim == prims.logical_not:
        result = builder.not_(to_bit(llvm_args[0], builder), name = result_name)
        return from_bit(result, t, builder)
      else:
        assert prim == prims.logical_or
        result = builder.or_(lhs = to_bit(llvm_args[0], builder), 
                           rhs = to_bit(llvm_args[1], builder), name = result_name)
        return from_bit(result, t, builder)
      
    elif prim == prims.abs:
      x = llvm_args[0]
      bit = self.cmp(prims.greater_equal, t,  x, zero(x.type), builder, "gt_zero")
      neg_value = self.neg(x, builder)
      return builder.select(bit, x, neg_value)
    elif isinstance(prim, prims.Float): 
      llvm_op = llvm_prims.get_float_op(prim, t)
      return builder.call(llvm_op, llvm_args)
    
    else:
      assert False, "UNSUPPORTED PRIMITIVE: %s" % prim
コード例 #8
0
    def prim(self, prim, t, llvm_args, builder, result_name=None):
        if result_name is None:
            result_name = prim.name + "_result"

        if isinstance(prim, prims.Cmp):
            bit = self.cmp(prim, t, llvm_args[0], llvm_args[1], builder)
            return llvm_convert.to_bool(bit, builder)

        elif prim == prims.maximum:
            x, y = llvm_args
            bit = self.cmp(prims.greater_equal, t, x, y, builder)
            return builder.select(bit, x, y)

        elif prim == prims.minimum:
            x, y = llvm_args
            bit = self.cmp(prims.less_equal, t, x, y, builder)
            return builder.select(bit, x, y)

        elif prim == prims.negative:
            if t == Bool:
                bit = llvm_convert.to_bit(llvm_args[0], builder)
                negated = builder.not_(bit)
                return llvm_convert.to_bool(negated, builder)
            return self.neg(llvm_args[0], builder)

        # python's remainder is weird in that it preserve's the sign of
        # the second argument, whereas LLVM's srem/frem operators preserve
        # the sign of the first
        elif prim == prims.mod:
            x, y = llvm_args
            if isinstance(t, (UnsignedT, BoolT)):
                return builder.urem(llvm_args[0], llvm_args[1], "modulo")
            elif isinstance(t, SignedT):
                rem = builder.srem(x, y, "modulo")
            else:
                assert isinstance(t, FloatT)
                rem = builder.frem(llvm_args[0], llvm_args[1], "modulo")

            y_is_negative = self.lt(t, y, zero(y.type), builder,
                                    "second_arg_negative")
            rem_is_negative = self.lt(t, rem, zero(rem.type), builder,
                                      "rem_is_negative")
            y_nonzero = self.neq(t, y, zero(y.type), builder,
                                 "second_arg_nonzero")
            rem_nonzero = self.neq(t, rem, zero(x.type), builder,
                                   "rem_nonzero")
            neither_zero = builder.and_(y_nonzero, rem_nonzero, "neither_zero")
            diff_signs = builder.xor(y_is_negative, rem_is_negative,
                                     "different_signs")
            should_flip = builder.and_(neither_zero, diff_signs, "should_flip")
            flipped_rem = self.add(t, y, rem, builder, "flipped_rem")
            return builder.select(should_flip, flipped_rem, rem)

        elif prim == prims.power:
            x, y = llvm_args

            if isinstance(t, FloatT):
                new_t = t
            else:
                new_t = Float64
            x = llvm_convert.convert(x, t, new_t, builder)
            y = llvm_convert.convert(y, t, new_t, builder)
            llvm_op = llvm_prims.get_float_op(prim, new_t)
            result = builder.call(llvm_op, [x, y])
            return llvm_convert.convert(result, new_t, t, builder)

        elif isinstance(prim, prims.Arith) or isinstance(prim, prims.Bitwise):
            if isinstance(t, FloatT):
                instr = llvm_prims.float_binops[prim]
            elif isinstance(t, SignedT):
                instr = llvm_prims.signed_binops[prim]
            elif isinstance(t, UnsignedT):
                instr = llvm_prims.unsigned_binops[prim]
            else:
                assert isinstance(t, BoolT)
                instr = llvm_prims.bool_binops[prim]
            op = getattr(builder, instr)
            return op(name=result_name, *llvm_args)

        elif isinstance(prim, prims.Logical):
            if prim == prims.logical_and:
                result = builder.and_(name=result_name,
                                      lhs=to_bit(llvm_args[0], builder),
                                      rhs=to_bit(llvm_args[1], builder))
                return from_bit(result, t, builder)
            elif prim == prims.logical_not:
                result = builder.not_(to_bit(llvm_args[0], builder),
                                      name=result_name)
                return from_bit(result, t, builder)
            else:
                assert prim == prims.logical_or
                result = builder.or_(lhs=to_bit(llvm_args[0], builder),
                                     rhs=to_bit(llvm_args[1], builder),
                                     name=result_name)
                return from_bit(result, t, builder)

        elif prim == prims.abs:
            x = llvm_args[0]
            bit = self.cmp(prims.greater_equal, t, x, zero(x.type), builder,
                           "gt_zero")
            neg_value = self.neg(x, builder)
            return builder.select(bit, x, neg_value)
        elif isinstance(prim, prims.Float):
            llvm_op = llvm_prims.get_float_op(prim, t)
            return builder.call(llvm_op, llvm_args)

        else:
            assert False, "UNSUPPORTED PRIMITIVE: %s" % prim