Skip to content

Commit 70a9ce6

Browse files
committed
Implement slice-borrowing on estr-uniq and str values.
1 parent fac7fcc commit 70a9ce6

File tree

4 files changed

+95
-64
lines changed

4 files changed

+95
-64
lines changed

src/rustc/middle/infer.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,12 +810,29 @@ impl assignment for infer_ctxt {
810810
let nr_b = ty::mk_uniq(self.tcx, mt_b);
811811
self.crosspolinate(a_node_id, a, nr_b, r_b)
812812
}
813+
(ty::ty_estr(vs_a),
814+
ty::ty_estr(ty::vstore_slice(r_b)))
815+
if is_borrowable(vs_a) {
816+
let nr_b = ty::mk_estr(self.tcx, vs_a);
817+
self.crosspolinate(a_node_id, a, nr_b, r_b)
818+
}
819+
(ty::ty_str,
820+
ty::ty_estr(ty::vstore_slice(r_b))) {
821+
let nr_b = ty::mk_str(self.tcx);
822+
self.crosspolinate(a_node_id, a, nr_b, r_b)
823+
}
824+
813825
(ty::ty_evec(mt_a, vs_a),
814826
ty::ty_evec(mt_b, ty::vstore_slice(r_b)))
815827
if is_borrowable(vs_a) {
816828
let nr_b = ty::mk_evec(self.tcx, mt_b, vs_a);
817829
self.crosspolinate(a_node_id, a, nr_b, r_b)
818830
}
831+
(ty::ty_vec(mt_a),
832+
ty::ty_evec(mt_b, ty::vstore_slice(r_b))) {
833+
let nr_b = ty::mk_vec(self.tcx, mt_b);
834+
self.crosspolinate(a_node_id, a, nr_b, r_b)
835+
}
819836
_ {
820837
self.sub_tys(a, b)
821838
}

src/rustc/middle/trans/base.rs

Lines changed: 35 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -2257,6 +2257,7 @@ fn trans_rec_field_inner(bcx: block, val: ValueRef, ty: ty::t,
22572257
ret {bcx: bcx, val: val, kind: owned};
22582258
}
22592259

2260+
22602261
fn trans_index(cx: block, ex: @ast::expr, base: @ast::expr,
22612262
idx: @ast::expr) -> lval_result {
22622263
let _icx = cx.insn_ctxt("trans_index");
@@ -2286,43 +2287,17 @@ fn trans_index(cx: block, ex: @ast::expr, base: @ast::expr,
22862287
let scaled_ix = Mul(bcx, ix_val, unit_sz);
22872288
maybe_name_value(cx.ccx(), scaled_ix, "scaled_ix");
22882289

2289-
let (lim, body) = alt ty::get(base_ty).struct {
2290-
ty::ty_estr(ty::vstore_fixed(n)) |
2291-
ty::ty_evec(_, ty::vstore_fixed(n)) {
2292-
// FIXME: support static bounds-check elimination
2293-
// and/or error checking here.
2294-
let lim = C_uint(bcx.ccx(), n);
2295-
let body = GEPi(bcx, v, [0, 0]);
2296-
(lim, body)
2297-
}
2298-
2299-
ty::ty_estr(ty::vstore_slice(_)) |
2300-
ty::ty_evec(_, ty::vstore_slice(_)) {
2301-
let body = Load(bcx, GEPi(bcx, v, [0, abi::slice_elt_base]));
2302-
let lim = Load(bcx, GEPi(bcx, v, [0, abi::slice_elt_len]));
2303-
(lim, body)
2304-
}
2305-
2306-
ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) {
2307-
bcx.sess().unimpl(#fmt("unsupported evec/estr type trans_index"));
2308-
}
2309-
2310-
_ {
2311-
let lim = tvec::get_fill(bcx, v);
2312-
let body = tvec::get_dataptr(bcx, v, type_of(ccx, unit_ty));
2313-
(lim, body)
2314-
}
2315-
};
2290+
let (base, len) = tvec::get_base_and_len(bcx, v, base_ty);
23162291

2317-
#debug("trans_index: lim %s", val_str(bcx.ccx().tn, lim));
2318-
#debug("trans_index: body %s", val_str(bcx.ccx().tn, body));
2292+
#debug("trans_index: base %s", val_str(bcx.ccx().tn, base));
2293+
#debug("trans_index: len %s", val_str(bcx.ccx().tn, len));
23192294

2320-
let bounds_check = ICmp(bcx, lib::llvm::IntUGE, scaled_ix, lim);
2295+
let bounds_check = ICmp(bcx, lib::llvm::IntUGE, scaled_ix, len);
23212296
let bcx = with_cond(bcx, bounds_check) {|bcx|
23222297
// fail: bad bounds check.
23232298
trans_fail(bcx, some(ex.span), "bounds check")
23242299
};
2325-
let elt = InBoundsGEP(bcx, body, [ix_val]);
2300+
let elt = InBoundsGEP(bcx, base, [ix_val]);
23262301
ret lval_owned(bcx, PointerCast(bcx, elt, T_ptr(llunitty)));
23272302
}
23282303

@@ -2543,6 +2518,7 @@ fn trans_loop_body(bcx: block, e: @ast::expr, ret_flag: option<ValueRef>,
25432518
fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef, e: @ast::expr,
25442519
&temp_cleanups: [ValueRef], ret_flag: option<ValueRef>)
25452520
-> result {
2521+
#debug("+++ trans_arg_expr on %s", expr_to_str(e));
25462522
let _icx = cx.insn_ctxt("trans_arg_expr");
25472523
let ccx = cx.ccx();
25482524
let e_ty = expr_ty(cx, e);
@@ -2563,6 +2539,7 @@ fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef, e: @ast::expr,
25632539
let lv = adapt_borrowed_value(lv, arg, e);
25642540
let mut bcx = lv.bcx;
25652541
let mut val = lv.val;
2542+
#debug(" adapted value: %s", val_str(bcx.ccx().tn, val));
25662543
let arg_mode = ty::resolved_mode(ccx.tcx, arg.mode);
25672544
if is_bot {
25682545
// For values of type _|_, we generate an
@@ -2572,50 +2549,52 @@ fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef, e: @ast::expr,
25722549
val = llvm::LLVMGetUndef(lldestty);
25732550
} else if arg_mode == ast::by_ref || arg_mode == ast::by_val {
25742551
let mut copied = false;
2575-
let imm = ty::type_is_immediate(e_ty);
2552+
let imm = ty::type_is_immediate(arg.ty);
25762553
if arg_mode == ast::by_ref && lv.kind != owned && imm {
25772554
val = do_spill_noroot(bcx, val);
25782555
copied = true;
25792556
}
25802557
if ccx.maps.copy_map.contains_key(e.id) && lv.kind != temporary {
25812558
if !copied {
2582-
let alloc = alloc_ty(bcx, e_ty);
2559+
let alloc = alloc_ty(bcx, arg.ty);
25832560
bcx = copy_val(bcx, INIT, alloc,
2584-
load_if_immediate(bcx, val, e_ty), e_ty);
2561+
load_if_immediate(bcx, val, arg.ty), arg.ty);
25852562
val = alloc;
2586-
} else { bcx = take_ty(bcx, val, e_ty); }
2587-
add_clean(bcx, val, e_ty);
2563+
} else { bcx = take_ty(bcx, val, arg.ty); }
2564+
add_clean(bcx, val, arg.ty);
25882565
}
25892566
if arg_mode == ast::by_val && (lv.kind == owned || !imm) {
25902567
val = Load(bcx, val);
25912568
}
25922569
} else if arg_mode == ast::by_copy || arg_mode == ast::by_move {
2593-
let alloc = alloc_ty(bcx, e_ty);
2570+
let alloc = alloc_ty(bcx, arg.ty);
25942571
let move_out = arg_mode == ast::by_move ||
25952572
ccx.maps.last_uses.contains_key(e.id);
25962573
if lv.kind == temporary { revoke_clean(bcx, val); }
2597-
if lv.kind == owned || !ty::type_is_immediate(e_ty) {
2598-
memmove_ty(bcx, alloc, val, e_ty);
2599-
if move_out && ty::type_needs_drop(ccx.tcx, e_ty) {
2600-
bcx = zero_alloca(bcx, val, e_ty);
2574+
if lv.kind == owned || !ty::type_is_immediate(arg.ty) {
2575+
memmove_ty(bcx, alloc, val, arg.ty);
2576+
if move_out && ty::type_needs_drop(ccx.tcx, arg.ty) {
2577+
bcx = zero_alloca(bcx, val, arg.ty);
26012578
}
26022579
} else { Store(bcx, val, alloc); }
26032580
val = alloc;
26042581
if lv.kind != temporary && !move_out {
2605-
bcx = take_ty(bcx, val, e_ty);
2582+
bcx = take_ty(bcx, val, arg.ty);
26062583
}
26072584

26082585
// In the event that failure occurs before the call actually
26092586
// happens, have to cleanup this copy:
2610-
add_clean_temp_mem(bcx, val, e_ty);
2587+
add_clean_temp_mem(bcx, val, arg.ty);
26112588
temp_cleanups += [val];
2612-
} else if ty::type_is_immediate(e_ty) && lv.kind != owned {
2613-
val = do_spill(bcx, val, e_ty);
2589+
} else if ty::type_is_immediate(arg.ty) && lv.kind != owned {
2590+
val = do_spill(bcx, val, arg.ty);
26142591
}
26152592

26162593
if !is_bot && arg.ty != e_ty || ty::type_has_params(arg.ty) {
2594+
#debug(" casting from %s", val_str(bcx.ccx().tn, val));
26172595
val = PointerCast(bcx, val, lldestty);
26182596
}
2597+
#debug("--- trans_arg_expr passing %s", val_str(bcx.ccx().tn, val));
26192598
ret rslt(bcx, val);
26202599
}
26212600

@@ -2642,25 +2621,17 @@ fn adapt_borrowed_value(lv: lval_result, _arg: ty::arg,
26422621
ret lv; // no change needed at runtime (I think)
26432622
}
26442623

2645-
ty::ty_estr(ty::vstore_box) |
2646-
ty::ty_evec(_, ty::vstore_box) {
2647-
bcx.tcx().sess.span_unimpl(
2648-
e.span, #fmt["borrowing a value of type %s",
2649-
ty_to_str(bcx.tcx(), e_ty)]);
2650-
}
2651-
2652-
ty::ty_estr(ty::vstore_uniq) |
2653-
ty::ty_evec(_, ty::vstore_uniq) {
2654-
bcx.tcx().sess.span_unimpl(
2655-
e.span, #fmt["borrowing a value of type %s",
2656-
ty_to_str(bcx.tcx(), e_ty)]);
2657-
}
2658-
2659-
ty::ty_estr(ty::vstore_fixed(_)) |
2660-
ty::ty_evec(_, ty::vstore_fixed(_)) {
2661-
bcx.tcx().sess.span_unimpl(
2662-
e.span, #fmt["borrowing a value of type %s",
2663-
ty_to_str(bcx.tcx(), e_ty)]);
2624+
ty::ty_str | ty::ty_vec(_) |
2625+
ty::ty_estr(_) |
2626+
ty::ty_evec(_, _) {
2627+
let ccx = bcx.ccx();
2628+
let unit_ty = ty::sequence_element_type(ccx.tcx, e_ty);
2629+
let llunit_ty = type_of(ccx, unit_ty);
2630+
let (base, len) = tvec::get_base_and_len(bcx, lv.val, e_ty);
2631+
let p = alloca(bcx, T_struct([T_ptr(llunit_ty), ccx.int_type]));
2632+
Store(bcx, base, GEPi(bcx, p, [0, abi::slice_elt_base]));
2633+
Store(bcx, len, GEPi(bcx, p, [0, abi::slice_elt_len]));
2634+
ret lval_temp(bcx, p);
26642635
}
26652636

26662637
_ {

src/rustc/middle/trans/tvec.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,40 @@ fn trans_vstore(bcx: block, e: @ast::expr,
145145
}
146146
}
147147

148+
fn get_base_and_len(cx: block, v: ValueRef, e_ty: ty::t)
149+
-> (ValueRef, ValueRef) {
150+
151+
let tcx = cx.ccx().tcx;
152+
let vec_ty = ty::type_autoderef(tcx, e_ty);
153+
let unit_ty = ty::sequence_element_type(tcx, vec_ty);
154+
let vstore = alt ty::get(vec_ty).struct {
155+
ty::ty_estr(vst) | ty::ty_evec(_, vst) { vst }
156+
_ { ty::vstore_uniq }
157+
};
158+
159+
alt vstore {
160+
ty::vstore_fixed(n) {
161+
let base = GEPi(cx, v, [0, 0]);
162+
let len = C_uint(cx.ccx(), n);
163+
(base, len)
164+
}
165+
ty::vstore_slice(_) {
166+
let base = Load(cx, GEPi(cx, v, [0, abi::slice_elt_base]));
167+
let len = Load(cx, GEPi(cx, v, [0, abi::slice_elt_len]));
168+
(base, len)
169+
}
170+
ty::vstore_uniq {
171+
let base = tvec::get_dataptr(cx, v,
172+
type_of::type_of(cx.ccx(), unit_ty));
173+
let len = tvec::get_fill(cx, v);
174+
(base, len)
175+
}
176+
ty::vstore_box {
177+
cx.ccx().sess.unimpl("unhandled tvec::get_base_and_len");
178+
}
179+
}
180+
}
181+
148182
fn trans_estr(bcx: block, s: str, vstore: ast::vstore,
149183
dest: dest) -> block {
150184
let _icx = bcx.insn_ctxt("tvec::trans_estr");
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
fn foo(x: str/&) -> u8 {
2+
x[0]
3+
}
4+
5+
fn main() {
6+
let p = "hello"/~;
7+
let r = foo(p);
8+
assert r == 'h' as u8;
9+
}

0 commit comments

Comments
 (0)