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); }