Example #1
0
def to_bit(llvm_value, builder):
  llvm_t = llvm_value.type

  if llvm_t == int1_t:
    return llvm_value
  if isinstance(llvm_t, llcore.IntegerType):
    return builder.icmp(llcore.ICMP_NE, llvm_value, zero(llvm_t), "ne_zero")
  else:
    return builder.fcmp(llcore.FCMP_ONE, llvm_value, zero(llvm_t), "ne_zero")
Example #2
0
def from_bit(llvm_value, new_ptype, builder):
  llvm_t = llvm_value_type(new_ptype)
  name = "%s.cast.%s" % (llvm_value.name, new_ptype)
  return builder.select(llvm_value, one(llvm_t), zero(llvm_t), name)
Example #3
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
Example #4
0
 def neg(self, x, builder):
   if isinstance(x.type, llc.IntegerType):
     return builder.neg(x, "neg")
   else:
     return builder.fsub(zero(x.type), x, "neg") 
Example #5
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
Example #6
0
 def neg(self, x, builder):
     if isinstance(x.type, llc.IntegerType):
         return builder.neg(x, "neg")
     else:
         return builder.fsub(zero(x.type), x, "neg")