diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 4753850ca59..f43d819891a 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -290,23 +290,66 @@ upcall_shared_realloc(void *ptr, size_t size) { /**********************************************************************/ -struct s_str_new_args { +struct s_str_new_uniq_args { const char *cstr; size_t len; rust_str *retval; }; extern "C" CDECL void -upcall_s_str_new(s_str_new_args *args) { +upcall_s_str_new_uniq(s_str_new_uniq_args *args) { rust_task *task = rust_get_current_task(); LOG_UPCALL_ENTRY(task); - args->retval = make_str(task->kernel, args->cstr, args->len, "str_new"); + args->retval = make_str(task->kernel, args->cstr, args->len, + "str_new_uniq"); } +extern "C" CDECL rust_str* +upcall_str_new_uniq(const char *cstr, size_t len) { + s_str_new_uniq_args args = { cstr, len, 0 }; + UPCALL_SWITCH_STACK(&args, upcall_s_str_new_uniq); + return args.retval; +} + +// FIXME: this is an old compatibility-name for upcall_str_new_uniq +// can remove after next snapshot. extern "C" CDECL rust_str* upcall_str_new(const char *cstr, size_t len) { - s_str_new_args args = { cstr, len, 0 }; - UPCALL_SWITCH_STACK(&args, upcall_s_str_new); + s_str_new_uniq_args args = { cstr, len, 0 }; + UPCALL_SWITCH_STACK(&args, upcall_s_str_new_uniq); + return args.retval; +} + + + +struct s_str_new_shared_args { + const char *cstr; + size_t len; + rust_opaque_box *retval; +}; + +extern "C" CDECL void +upcall_s_str_new_shared(s_str_new_shared_args *args) { + rust_task *task = rust_get_current_task(); + LOG_UPCALL_ENTRY(task); + + size_t str_fill = args->len + 1; + size_t str_alloc = str_fill; + args->retval = (rust_opaque_box *) + task->kernel->malloc(sizeof(rust_opaque_box) + + vec_size(str_fill), + "str_new_shared"); + rust_str *str = (rust_str *)box_body(args->retval); + str->fill = str_fill; + str->alloc = str_alloc; + memcpy(&str->data, args->cstr, args->len); + str->data[args->len] = '\0'; +} + +extern "C" CDECL rust_opaque_box* +upcall_str_new_shared(const char *cstr, size_t len) { + s_str_new_shared_args args = { cstr, len, 0 }; + UPCALL_SWITCH_STACK(&args, upcall_s_str_new_shared); return args.retval; } diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 171718b64f2..aa0082a82be 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -76,6 +76,8 @@ upcall_shared_free upcall_shared_realloc upcall_vec_grow upcall_str_new +upcall_str_new_uniq +upcall_str_new_shared upcall_str_concat upcall_call_shim_on_c_stack upcall_call_shim_on_rust_stack diff --git a/src/rustc/back/abi.rs b/src/rustc/back/abi.rs index c02960deb00..4379a35f5f6 100644 --- a/src/rustc/back/abi.rs +++ b/src/rustc/back/abi.rs @@ -71,6 +71,9 @@ const vec_elt_alloc: int = 1; const vec_elt_elems: int = 2; +const slice_elt_base: int = 0; +const slice_elt_len: int = 1; + const worst_case_glue_call_args: int = 7; const abi_version: uint = 1u; diff --git a/src/rustc/back/upcall.rs b/src/rustc/back/upcall.rs index b1b60c3b127..f43ef4a5c12 100644 --- a/src/rustc/back/upcall.rs +++ b/src/rustc/back/upcall.rs @@ -17,7 +17,8 @@ type upcalls = shared_realloc: ValueRef, mark: ValueRef, vec_grow: ValueRef, - str_new: ValueRef, + str_new_uniq: ValueRef, + str_new_shared: ValueRef, str_concat: ValueRef, cmp_type: ValueRef, log_type: ValueRef, @@ -65,8 +66,10 @@ fn declare_upcalls(targ_cfg: @session::config, d("mark", [T_ptr(T_i8())], int_t), vec_grow: dv("vec_grow", [T_ptr(T_ptr(opaque_vec_t)), int_t]), - str_new: - d("str_new", [T_ptr(T_i8()), int_t], T_ptr(opaque_vec_t)), + str_new_uniq: + d("str_new_uniq", [T_ptr(T_i8()), int_t], T_ptr(opaque_vec_t)), + str_new_shared: + d("str_new_shared", [T_ptr(T_i8()), int_t], T_ptr(T_i8())), str_concat: d("str_concat", [T_ptr(opaque_vec_t), T_ptr(opaque_vec_t)], T_ptr(opaque_vec_t)), diff --git a/src/rustc/middle/trans/alt.rs b/src/rustc/middle/trans/alt.rs index a92385268bb..3ce6d9ed62a 100644 --- a/src/rustc/middle/trans/alt.rs +++ b/src/rustc/middle/trans/alt.rs @@ -49,7 +49,7 @@ fn trans_opt(bcx: block, o: opt) -> opt_result { ast::expr_lit(@{node: ast::lit_str(s), _}) { let strty = ty::mk_str(bcx.tcx()); let cell = empty_dest_cell(); - bcx = tvec::trans_str(bcx, s, by_val(cell)); + bcx = tvec::trans_estr(bcx, s, ast::vstore_uniq, by_val(cell)); add_clean_temp(bcx, *cell, strty); ret single_result(rslt(bcx, *cell)); } diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 849d8af21b4..2a57766d66f 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -673,10 +673,11 @@ fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) { let ccx = bcx.ccx(); let bcx = alt ty::get(t).struct { ty::ty_box(_) | ty::ty_opaque_box | - ty::ty_estr(ty::vstore_box) { + ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) { decr_refcnt_maybe_free(bcx, Load(bcx, v0), t) } - ty::ty_uniq(_) | ty::ty_vec(_) | ty::ty_str { + ty::ty_uniq(_) | ty::ty_vec(_) | ty::ty_str | + ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) { free_ty(bcx, Load(bcx, v0), t) } ty::ty_res(did, inner, tps) { @@ -1328,7 +1329,7 @@ fn trans_lit(cx: block, lit: ast::lit, dest: dest) -> block { let _icx = cx.insn_ctxt("trans_lit"); if dest == ignore { ret cx; } alt lit.node { - ast::lit_str(s) { tvec::trans_str(cx, s, dest) } + ast::lit_str(s) { tvec::trans_estr(cx, s, ast::vstore_uniq, dest) } _ { store_in_dest(cx, trans_crate_lit(cx.ccx(), lit), dest) } @@ -2294,16 +2295,18 @@ fn trans_index(cx: block, ex: @ast::expr, base: @ast::expr, let body = GEPi(bcx, v, [0, 0]); (lim, body) } + ty::ty_estr(ty::vstore_slice(_)) | ty::ty_evec(_, ty::vstore_slice(_)) { - let body = Load(bcx, GEPi(bcx, v, [0, 0])); - let lim = Load(bcx, GEPi(bcx, v, [0, 1])); + let body = Load(bcx, GEPi(bcx, v, [0, abi::slice_elt_base])); + let lim = Load(bcx, GEPi(bcx, v, [0, abi::slice_elt_len])); (lim, body) } - ty::ty_estr(_) | ty::ty_evec(_, _) { + ty::ty_estr(ty::vstore_box) | ty::ty_evec(_, ty::vstore_box) { bcx.sess().unimpl(#fmt("unsupported evec/estr type trans_index")); } + _ { let lim = tvec::get_fill(bcx, v); let body = tvec::get_dataptr(bcx, v, type_of(ccx, unit_ty)); diff --git a/src/rustc/middle/trans/tvec.rs b/src/rustc/middle/trans/tvec.rs index 1008d9ed8c6..50224c0d413 100644 --- a/src/rustc/middle/trans/tvec.rs +++ b/src/rustc/middle/trans/tvec.rs @@ -134,7 +134,7 @@ fn trans_vstore(bcx: block, e: @ast::expr, v: ast::vstore, dest: dest) -> block { alt e.node { ast::expr_lit(@{node: ast::lit_str(s), span: _}) { - ret trans_estr(bcx, s, v, e.span, dest); + ret trans_estr(bcx, s, v, dest); } ast::expr_vec(es, mutbl) { bcx.ccx().sess.span_unimpl(e.span, "unhandled tvec::trans_vstore"); @@ -146,7 +146,7 @@ fn trans_vstore(bcx: block, e: @ast::expr, } fn trans_estr(bcx: block, s: str, vstore: ast::vstore, - sp: span, dest: dest) -> block { + dest: dest) -> block { let _icx = bcx.insn_ctxt("tvec::trans_estr"); let ccx = bcx.ccx(); @@ -165,8 +165,16 @@ fn trans_estr(bcx: block, s: str, vstore: ast::vstore, C_struct([cs, C_uint(ccx, str::len(s))]) } - _ { - bcx.ccx().sess.span_unimpl(sp, "unhandled tvec::trans_estr"); + ast::vstore_uniq { + let cs = PointerCast(bcx, C_cstr(ccx, s), T_ptr(T_i8())); + let len = C_uint(ccx, str::len(s)); + Call(bcx, ccx.upcalls.str_new_uniq, [cs, len]) + } + + ast::vstore_box { + let cs = PointerCast(bcx, C_cstr(ccx, s), T_ptr(T_i8())); + let len = C_uint(ccx, str::len(s)); + Call(bcx, ccx.upcalls.str_new_shared, [cs, len]) } }; @@ -174,15 +182,6 @@ fn trans_estr(bcx: block, s: str, vstore: ast::vstore, base::store_in_dest(bcx, c, dest) } -fn trans_str(bcx: block, s: str, dest: dest) -> block { - let _icx = bcx.insn_ctxt("tvec::trans_str"); - let ccx = bcx.ccx(); - let cs = PointerCast(bcx, C_cstr(ccx, s), T_ptr(T_i8())); - let len = C_uint(ccx, str::len(s)); - let n = Call(bcx, ccx.upcalls.str_new, [cs, len]); - ret base::store_in_dest(bcx, n, dest); -} - fn trans_append(bcx: block, vec_ty: ty::t, lhsptr: ValueRef, rhs: ValueRef) -> block { let _icx = bcx.insn_ctxt("tvec::trans_append"); diff --git a/src/test/run-pass/estr-uniq.rs b/src/test/run-pass/estr-uniq.rs index 178f1c8c26b..07b7fcf58d6 100644 --- a/src/test/run-pass/estr-uniq.rs +++ b/src/test/run-pass/estr-uniq.rs @@ -1,4 +1,8 @@ -// xfail-test fn main() { let x : str/~ = "hello"/~; + let _y : str/~ = "there"/~; + let mut z = "thing"/~; + z = x; + assert z[0] == ('h' as u8); + assert z[4] == ('o' as u8); }