Example #1
0
  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);
  }
Example #2
0
  static void call_tuple_at(JITOperations& ops, Inliner& i) {
    Value* rec = i.recv();

    // bool is_tuple = recv->flags & mask;

    Value* cmp = ops.check_type_bits(rec, rubinius::Tuple::type);

    BasicBlock* is_tuple = ops.new_block("is_tuple");
    BasicBlock* access =   ops.new_block("tuple_at");
    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);
    // Check that index is not over the end of the Tuple

    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* 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");

    i.exception_safe();
    i.set_result(ops.create_load(gep, "tuple_at"));
  }