static void call_tuple_swap(JITOperations& ops, Inliner& i) { Value* rec = i.recv(); ops.verify_guard(ops.check_is_tuple(rec), i.failure()); Value* left_index = i.arg(0); Value* right_index = i.arg(1); Value* fix_cmp = ops.check_if_fixnums(left_index, right_index); ops.verify_guard(fix_cmp, i.failure()); // Check that index is not over the end of the Tuple Value* tup = ops.upcast(rec, "Tuple"); Value* full_size = ops.get_tuple_size(tup); Value* lindex = ops.fixnum_to_native(left_index); Value* lsize_cmp = ops.create_less_than(lindex, full_size, "is_in_bounds"); Value* rindex = ops.fixnum_to_native(right_index); Value* rsize_cmp = ops.create_less_than(rindex, full_size, "is_in_bounds"); // Combine lsize_cmp and rsize_cmp to validate entry into access code Value* access_cmp = ops.create_and(lsize_cmp, rsize_cmp, "access_cmp"); ops.verify_guard(access_cmp, i.failure()); Value* lidx[] = { ConstantInt::get(ops.state()->Int32Ty, 0), ConstantInt::get(ops.state()->Int32Ty, offset::tuple_field), lindex }; Value* lgep = ops.create_gep(tup, lidx, 3, "field_pos"); Value* ridx[] = { ConstantInt::get(ops.state()->Int32Ty, 0), ConstantInt::get(ops.state()->Int32Ty, offset::tuple_field), rindex }; Value* rgep = ops.create_gep(tup, ridx, 3, "field_pos"); Value* left_val = ops.create_load(lgep, "tuple_swap_left"); Value* right_val = ops.create_load(rgep, "tuple_swap_right"); ops.b().CreateStore(right_val, lgep); ops.b().CreateStore(left_val, rgep); i.exception_safe(); i.set_result(rec); }
static void call_tuple_put(JITOperations& ops, Inliner& i) { Value* rec = i.recv(); Value* cmp = ops.check_type_bits(rec, rubinius::Tuple::type); BasicBlock* is_tuple = ops.new_block("is_tuple"); BasicBlock* access = ops.new_block("tuple_put"); BasicBlock* is_other = i.failure(); ops.create_conditional_branch(is_tuple, is_other, cmp); ops.set_block(is_tuple); Value* index_val = i.arg(0); Value* fix_cmp = ops.check_if_fixnum(index_val); Value* tup = ops.upcast(rec, "Tuple"); Value* index = ops.fixnum_to_native(index_val); Value* full_size = ops.get_tuple_size(tup); Value* size_cmp = ops.create_less_than(index, full_size, "is_in_bounds"); // Combine fix_cmp and size_cmp to validate entry into access code Value* access_cmp = ops.create_and(fix_cmp, size_cmp, "access_cmp"); ops.create_conditional_branch(access, is_other, access_cmp); ops.set_block(access); Value* value = i.arg(1); Value* idx[] = { ConstantInt::get(ops.state()->Int32Ty, 0), ConstantInt::get(ops.state()->Int32Ty, offset::tuple_field), index }; Value* gep = ops.create_gep(tup, idx, 3, "field_pos"); ops.create_store(value, gep); ops.write_barrier(tup, value); i.exception_safe(); i.set_result(value); }