Teach rustc about const tag value, begin work on trans_copy_ty, make uint's to_str routine less clever and thereby resist overflow.

This commit is contained in:
Graydon Hoare 2010-11-09 17:49:20 -08:00
parent 3e482d5f69
commit a404e54261
3 changed files with 84 additions and 25 deletions

View File

@ -1,6 +1,9 @@
const int rc_base_field_refcnt = 0;
// FIXME: import from std.dbg when imported consts work.
const uint const_refcount = 0x7bad_face_u;
const int task_field_refcnt = 0;
const int task_field_stk = 2;
const int task_field_runtime_sp = 3;

View File

@ -394,6 +394,25 @@ fn trans_non_gc_free(@block_ctxt cx, ValueRef v) -> result {
C_int(0)));
}
fn incr_refcnt(@block_ctxt cx, ValueRef box_ptr) -> result {
auto rc_ptr = cx.build.GEP(box_ptr, vec(C_int(0),
C_int(abi.box_rc_field_refcnt)));
auto rc = cx.build.Load(rc_ptr);
auto next_cx = new_extension_block_ctxt(cx);
auto rc_adj_cx = new_empty_block_ctxt(cx.fcx);
auto const_test = cx.build.ICmp(lib.llvm.LLVMIntEQ,
C_int(abi.const_refcount as int), rc);
cx.build.CondBr(const_test, next_cx.llbb, rc_adj_cx.llbb);
rc = rc_adj_cx.build.Add(rc, C_int(1));
rc_adj_cx.build.Store(rc, rc_ptr);
rc_adj_cx.build.Br(next_cx.llbb);
ret res(next_cx, C_nil());
}
fn decr_refcnt_and_if_zero(@block_ctxt cx,
ValueRef box_ptr,
fn(@block_ctxt cx) -> result inner,
@ -401,20 +420,66 @@ fn decr_refcnt_and_if_zero(@block_ctxt cx,
auto rc_ptr = cx.build.GEP(box_ptr, vec(C_int(0),
C_int(abi.box_rc_field_refcnt)));
auto rc = cx.build.Load(rc_ptr);
rc = cx.build.Sub(rc, C_int(1));
cx.build.Store(rc, rc_ptr);
auto test = cx.build.ICmp(lib.llvm.LLVMIntEQ, C_int(0), rc);
auto rc_adj_cx = new_empty_block_ctxt(cx.fcx);
auto next_cx = new_extension_block_ctxt(cx);
auto const_test = cx.build.ICmp(lib.llvm.LLVMIntEQ,
C_int(abi.const_refcount as int), rc);
cx.build.CondBr(const_test, next_cx.llbb, rc_adj_cx.llbb);
rc = rc_adj_cx.build.Sub(rc, C_int(1));
rc_adj_cx.build.Store(rc, rc_ptr);
auto zero_test = rc_adj_cx.build.ICmp(lib.llvm.LLVMIntEQ, C_int(0), rc);
auto then_cx = new_empty_block_ctxt(cx.fcx);
auto then_res = inner(then_cx);
then_res.bcx.build.Br(next_cx.llbb);
cx.build.CondBr(test, then_res.bcx.llbb, next_cx.llbb);
rc_adj_cx.build.CondBr(zero_test, then_res.bcx.llbb, next_cx.llbb);
auto phi = next_cx.build.Phi(t_else,
vec(v_else, then_res.val),
vec(cx.llbb, then_res.bcx.llbb));
vec(v_else, v_else, then_res.val),
vec(cx.llbb,
rc_adj_cx.llbb,
then_res.bcx.llbb));
ret res(next_cx, phi);
}
fn type_is_scalar(@ast.ty t) -> bool {
alt (t.node) {
case (ast.ty_nil) { ret true; }
case (ast.ty_bool) { ret true; }
case (ast.ty_int) { ret true; }
case (ast.ty_uint) { ret true; }
case (ast.ty_machine(_)) { ret true; }
case (ast.ty_char) { ret true; }
}
ret false;
}
fn trans_copy_ty(@block_ctxt cx,
bool is_init,
ValueRef dst,
ValueRef src,
@ast.ty t) -> result {
if (type_is_scalar(t)) {
ret res(cx, cx.build.Store(src, dst));
}
alt (t.node) {
case (ast.ty_str) {
let result r = res(cx, C_nil());
if (is_init) {
r = trans_drop_str(cx, dst);
}
r = incr_refcnt(r.bcx, src);
ret res(r.bcx, r.bcx.build.Store(src, dst));
}
}
cx.fcx.tcx.sess.unimpl("ty variant in trans_copy_ty");
fail;
}
fn trans_drop_str(@block_ctxt cx, ValueRef v) -> result {
ret decr_refcnt_and_if_zero(cx, v,
bind trans_non_gc_free(_, v),
@ -825,6 +890,7 @@ impure fn trans_expr(@block_ctxt cx, &ast.expr e) -> result {
auto lhs_res = trans_lval(cx, *dst);
check (lhs_res._1);
auto rhs_res = trans_expr(lhs_res._0.bcx, *src);
// FIXME: call trans_copy_ty once we have a ty here.
ret res(rhs_res.bcx,
rhs_res.bcx.build.Store(rhs_res.val, lhs_res._0.val));
}

View File

@ -59,30 +59,20 @@ fn to_str(mutable uint n, uint radix) -> str
if (n == 0u) { ret "0"; }
let uint r = 1u;
if (n > r) {
while ((r*radix) <= n) {
r *= radix;
}
}
let str s = "";
while (n > 0u) {
auto i = n/r;
n -= (i * r);
r /= radix;
s += digit(i) as u8;
while (n != 0u) {
s += digit(n % radix) as u8;
n /= radix;
}
while (r > 0u) {
s += '0' as u8;
r /= radix;
let str s1 = "";
let uint len = _str.byte_len(s);
while (len != 0u) {
len -= 1u;
s1 += s.(len);
}
ret s1;
ret s;
}
// Local Variables: