Example #1
0
  static void float_compare(MathOperation op, Class* klass,
      JITOperations& ops, Inliner& i)
  {
    Value* self = i.recv();
    ops.check_class(self, klass, i.failure());

    // Support compare against Floats and Fixnums inline
    BasicBlock* do_compare = ops.new_block("float_compare");
    BasicBlock* check_fix =  ops.new_block("check_fixnum");

    Value* arg = i.arg(0);
    ops.check_class(arg, klass, check_fix);

    Value* farg =  ops.b().CreateBitCast(arg, ops.state()->ptr_type("Float"),
        "arg_float");

    Value* unboxed_rhs = ops.b().CreateLoad(
        ops.b().CreateConstGEP2_32(farg,  0, 1, "arg.value_pos"), "farg");

    BasicBlock* unboxed_block = ops.current_block();

    ops.b().CreateBr(do_compare);

    ops.set_block(check_fix);
    ops.verify_guard(ops.check_is_fixnum(arg), i.failure());
    Value* converted_rhs = ops.b().CreateUIToFP(
        ops.fixnum_to_native(arg), unboxed_rhs->getType());

    BasicBlock* converted_block = ops.current_block();

    ops.b().CreateBr(do_compare);

    ops.set_block(do_compare);

    do_compare->moveAfter(converted_block);

    PHINode* rhs = ops.b().CreatePHI(converted_rhs->getType(), "float_rhs");
    rhs->addIncoming(unboxed_rhs, unboxed_block);
    rhs->addIncoming(converted_rhs, converted_block);

    Value* fself = ops.b().CreateBitCast(self, ops.state()->ptr_type("Float"),
        "self_float");
    Value* lhs = ops.b().CreateLoad(
        ops.b().CreateConstGEP2_32(fself, 0, 1, "self.value_pos"), "fself");

    Value* performed = 0;

    switch(op) {
    case cEqual:
      performed = ops.b().CreateFCmpUEQ(lhs, rhs, "float.eq");
      break;
    case cLessThan:
      performed = ops.b().CreateFCmpULT(lhs, rhs, "float.lt");
      break;
    case cLessThanEqual:
      performed = ops.b().CreateFCmpULE(lhs, rhs, "float.le");
      break;
    case cGreaterThan:
      performed = ops.b().CreateFCmpUGT(lhs, rhs, "float.gt");
      break;
    case cGreaterThanEqual:
      performed = ops.b().CreateFCmpUGE(lhs, rhs, "float.ge");
      break;
    default:
      abort();
    }

    Value* imm_value = ops.b().CreateSelect(performed,
            ops.constant(Qtrue), ops.constant(Qfalse), "select_bool");

    i.exception_safe();
    i.set_result(imm_value);
  }