Tweak effect-checking rules in rustboot, remove/rewrite/re-auth impure cases in trans.rs

This commit is contained in:
Graydon Hoare 2011-01-21 07:58:16 -08:00
parent 2c27feb76a
commit 8bc57fa85e
3 changed files with 221 additions and 183 deletions

View File

@ -179,8 +179,7 @@ let effect_checking_visitor
then Ast.EFF_pure
else Stack.top auth_stack
in
let next = lower_effect_of e curr in
Stack.push next auth_stack;
Stack.push e auth_stack;
iflog cx
begin
fun _ ->
@ -189,40 +188,62 @@ let effect_checking_visitor
"entering '%a', adjusting auth effect: '%a' -> '%a'"
Ast.sprintf_name name
Ast.sprintf_effect curr
Ast.sprintf_effect next
Ast.sprintf_effect e
end
end;
let report_mismatch declared_effect calculated_effect =
let name = Hashtbl.find cx.ctxt_all_item_names i.id in
err (Some i.id)
"%a claims effect '%a' but calculated effect is '%a'%s"
Ast.sprintf_name name
Ast.sprintf_effect declared_effect
Ast.sprintf_effect calculated_effect
begin
if Stack.is_empty auth_stack
then ""
else
Printf.sprintf " (auth effects are '%s')"
(stk_fold
auth_stack
(fun e s ->
if s = ""
then
Printf.sprintf "%a"
Ast.sprintf_effect e
else
Printf.sprintf "%s, %a" s
Ast.sprintf_effect e) "")
end
in
begin
match i.node.Ast.decl_item with
Ast.MOD_ITEM_fn f
when htab_search cx.ctxt_required_items i.id = None ->
let e =
let calculated_effect =
match htab_search item_effect i.id with
None -> Ast.EFF_pure
| Some e -> e
in
let fe = f.Ast.fn_aux.Ast.fn_effect in
let ae =
if Stack.is_empty auth_stack
then None
else Some (Stack.top auth_stack)
in
if e <> fe && (ae <> (Some e))
let declared_effect = f.Ast.fn_aux.Ast.fn_effect in
if calculated_effect <> declared_effect
then
(* Something's fishy in this case. If the calculated effect
* is equal to one auth'ed by an enclosing scope -- not just
* a lower one -- we accept this mismatch; otherwise we
* complain.
*
* FIXME: this choice of "what constitutes an error" in
* auth/effect mismatches is subjective and could do
* with some discussion. *)
begin
let name = Hashtbl.find cx.ctxt_all_item_names i.id in
err (Some i.id)
"%a claims effect '%a' but calculated effect is '%a'%s"
Ast.sprintf_name name
Ast.sprintf_effect fe
Ast.sprintf_effect e
begin
match ae with
Some ae when ae <> fe ->
Printf.sprintf " (auth effect is '%a')"
Ast.sprintf_effect ae
| _ -> ""
end
match
stk_search auth_stack
(fun e ->
if e = calculated_effect then Some e else None)
with
Some _ -> ()
| None ->
report_mismatch declared_effect calculated_effect
end
| _ -> ()
end;
@ -239,16 +260,16 @@ let effect_checking_visitor
then Ast.EFF_pure
else Stack.top auth_stack
in
iflog cx
begin
fun _ ->
let name = Hashtbl.find cx.ctxt_all_item_names i.id in
log cx
"leaving '%a', restoring auth effect: '%a' -> '%a'"
Ast.sprintf_name name
Ast.sprintf_effect curr
Ast.sprintf_effect next
end
iflog cx
begin
fun _ ->
let name = Hashtbl.find cx.ctxt_all_item_names i.id in
log cx
"leaving '%a', restoring auth effect: '%a' -> '%a'"
Ast.sprintf_name name
Ast.sprintf_effect curr
Ast.sprintf_effect next
end
in
{ inner with
Walk.visit_mod_item_pre = visit_mod_item_pre;

View File

@ -1504,7 +1504,7 @@ fn copy_ty(@block_ctxt cx,
fail;
}
impure fn trans_lit(@block_ctxt cx, &ast.lit lit, &ast.ann ann) -> result {
fn trans_lit(@block_ctxt cx, &ast.lit lit, &ast.ann ann) -> result {
alt (lit.node) {
case (ast.lit_int(?i)) {
ret res(cx, C_int(i));
@ -1547,12 +1547,12 @@ impure fn trans_lit(@block_ctxt cx, &ast.lit lit, &ast.ann ann) -> result {
auto sub = trans_upcall(cx, "upcall_new_str",
vec(p2i(C_str(cx.fcx.ccx, s)),
C_int(len)));
sub.val = sub.bcx.build.IntToPtr(sub.val,
T_ptr(T_str()));
auto val = sub.bcx.build.IntToPtr(sub.val,
T_ptr(T_str()));
auto t = node_ann_type(cx.fcx.ccx, ann);
find_scope_cx(cx).cleanups +=
clean(bind drop_ty(_, sub.val, t));
ret sub;
clean(bind drop_ty(_, val, t));
ret res(sub.bcx, val);
}
}
}
@ -1587,24 +1587,21 @@ fn node_type(@crate_ctxt cx, &ast.ann a) -> TypeRef {
ret type_of(cx, node_ann_type(cx, a));
}
impure fn trans_unary(@block_ctxt cx, ast.unop op,
@ast.expr e, &ast.ann a) -> result {
fn trans_unary(@block_ctxt cx, ast.unop op,
@ast.expr e, &ast.ann a) -> result {
auto sub = trans_expr(cx, e);
alt (op) {
case (ast.bitnot) {
sub.val = cx.build.Not(sub.val);
ret sub;
ret res(sub.bcx, cx.build.Not(sub.val));
}
case (ast.not) {
sub.val = cx.build.Not(sub.val);
ret sub;
ret res(sub.bcx, cx.build.Not(sub.val));
}
case (ast.neg) {
// FIXME: switch by signedness.
sub.val = cx.build.Neg(sub.val);
ret sub;
ret res(sub.bcx, cx.build.Neg(sub.val));
}
case (ast.box) {
auto e_ty = ty.expr_ty(e);
@ -1622,15 +1619,15 @@ impure fn trans_unary(@block_ctxt cx, ast.unop op,
ret res(sub.bcx, box);
}
case (ast.deref) {
sub.val = sub.bcx.build.GEP(sub.val,
vec(C_int(0),
C_int(abi.box_rc_field_body)));
auto val = sub.bcx.build.GEP(sub.val,
vec(C_int(0),
C_int(abi.box_rc_field_body)));
auto e_ty = node_ann_type(sub.bcx.fcx.ccx, a);
if (ty.type_is_scalar(e_ty) ||
ty.type_is_nil(e_ty)) {
sub.val = sub.bcx.build.Load(sub.val);
val = sub.bcx.build.Load(val);
}
ret sub;
ret res(sub.bcx, val);
}
}
fail;
@ -1672,8 +1669,8 @@ fn trans_eager_binop(@block_ctxt cx, ast.binop op,
fail;
}
impure fn trans_binary(@block_ctxt cx, ast.binop op,
@ast.expr a, @ast.expr b) -> result {
fn trans_binary(@block_ctxt cx, ast.binop op,
@ast.expr a, @ast.expr b) -> result {
// First couple cases are lazy:
@ -1769,8 +1766,8 @@ fn join_results(@block_ctxt parent_cx,
ret res(join_cx, phi);
}
impure fn trans_if(@block_ctxt cx, @ast.expr cond,
&ast.block thn, &option.t[ast.block] els) -> result {
fn trans_if(@block_ctxt cx, @ast.expr cond,
&ast.block thn, &option.t[ast.block] els) -> result {
auto cond_res = trans_expr(cx, cond);
@ -1796,8 +1793,8 @@ impure fn trans_if(@block_ctxt cx, @ast.expr cond,
vec(then_res, else_res));
}
impure fn trans_while(@block_ctxt cx, @ast.expr cond,
&ast.block body) -> result {
fn trans_while(@block_ctxt cx, @ast.expr cond,
&ast.block body) -> result {
auto cond_cx = new_scope_block_ctxt(cx, "while cond");
auto body_cx = new_scope_block_ctxt(cx, "while loop body");
@ -1815,8 +1812,8 @@ impure fn trans_while(@block_ctxt cx, @ast.expr cond,
ret res(next_cx, C_nil());
}
impure fn trans_do_while(@block_ctxt cx, &ast.block body,
@ast.expr cond) -> result {
fn trans_do_while(@block_ctxt cx, &ast.block body,
@ast.expr cond) -> result {
auto body_cx = new_scope_block_ctxt(cx, "do-while loop body");
auto next_cx = new_sub_block_ctxt(cx, "next");
@ -1850,8 +1847,8 @@ fn get_pat_union_ptr(@block_ctxt cx, vec[@ast.pat] subpats, ValueRef llval)
ret cx.build.TruncOrBitCast(llblobptr, T_ptr(llunionty));
}
impure fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval,
@block_ctxt next_cx) -> result {
fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval,
@block_ctxt next_cx) -> result {
alt (pat.node) {
case (ast.pat_wild(_)) { ret res(cx, llval); }
case (ast.pat_bind(_, _, _)) { ret res(cx, llval); }
@ -1903,8 +1900,8 @@ impure fn trans_pat_match(@block_ctxt cx, @ast.pat pat, ValueRef llval,
fail;
}
impure fn trans_pat_binding(@block_ctxt cx, @ast.pat pat, ValueRef llval)
-> result {
fn trans_pat_binding(@block_ctxt cx, @ast.pat pat, ValueRef llval)
-> result {
alt (pat.node) {
case (ast.pat_wild(_)) { ret res(cx, llval); }
case (ast.pat_bind(?id, ?def_id, ?ann)) {
@ -1941,8 +1938,8 @@ impure fn trans_pat_binding(@block_ctxt cx, @ast.pat pat, ValueRef llval)
}
}
impure fn trans_alt(@block_ctxt cx, @ast.expr expr, vec[ast.arm] arms)
-> result {
fn trans_alt(@block_ctxt cx, @ast.expr expr, vec[ast.arm] arms)
-> result {
auto expr_res = trans_expr(cx, expr);
auto last_cx = new_sub_block_ctxt(expr_res.bcx, "last");
@ -2068,8 +2065,8 @@ fn trans_path(@block_ctxt cx, &ast.path p, &option.t[ast.def] dopt,
fail;
}
impure fn trans_field(@block_ctxt cx, &ast.span sp, @ast.expr base,
&ast.ident field, &ast.ann ann) -> lval_result {
fn trans_field(@block_ctxt cx, &ast.span sp, @ast.expr base,
&ast.ident field, &ast.ann ann) -> lval_result {
auto lv = trans_lval(cx, base);
auto r = lv.res;
check (lv.is_mem);
@ -2102,8 +2099,8 @@ impure fn trans_field(@block_ctxt cx, &ast.span sp, @ast.expr base,
fail;
}
impure fn trans_index(@block_ctxt cx, &ast.span sp, @ast.expr base,
@ast.expr idx, &ast.ann ann) -> lval_result {
fn trans_index(@block_ctxt cx, &ast.span sp, @ast.expr base,
@ast.expr idx, &ast.ann ann) -> lval_result {
auto lv = trans_expr(cx, base);
auto ix = trans_expr(lv.bcx, idx);
@ -2140,7 +2137,7 @@ impure fn trans_index(@block_ctxt cx, &ast.span sp, @ast.expr base,
// represented as an alloca or heap, hence needs a 'load' to be used as an
// immediate).
impure fn trans_lval(@block_ctxt cx, @ast.expr e) -> lval_result {
fn trans_lval(@block_ctxt cx, @ast.expr e) -> lval_result {
alt (e.node) {
case (ast.expr_path(?p, ?dopt, ?ann)) {
ret trans_path(cx, p, dopt, ann);
@ -2156,7 +2153,7 @@ impure fn trans_lval(@block_ctxt cx, @ast.expr e) -> lval_result {
fail;
}
impure fn trans_cast(@block_ctxt cx, @ast.expr e, &ast.ann ann) -> result {
fn trans_cast(@block_ctxt cx, @ast.expr e, &ast.ann ann) -> result {
auto e_res = trans_expr(cx, e);
auto llsrctype = val_ty(e_res.val);
auto t = node_ann_type(cx.fcx.ccx, ann);
@ -2189,12 +2186,12 @@ impure fn trans_cast(@block_ctxt cx, @ast.expr e, &ast.ann ann) -> result {
// NB: this must match type_of_fn_full and create_llargs_for_fn_args.
impure fn trans_args(@block_ctxt cx,
ValueRef llclosure,
option.t[ValueRef] llobj,
option.t[generic_info] gen,
&vec[@ast.expr] es,
@ty.t fn_ty)
fn trans_args(@block_ctxt cx,
ValueRef llclosure,
option.t[ValueRef] llobj,
option.t[generic_info] gen,
&vec[@ast.expr] es,
@ty.t fn_ty)
-> tup(@block_ctxt, vec[ValueRef], option.t[ValueRef]) {
let vec[ValueRef] vs = vec(cx.fcx.lltaskptr);
let @block_ctxt bcx = cx;
@ -2236,13 +2233,15 @@ impure fn trans_args(@block_ctxt cx,
for (@ast.expr e in es) {
auto mode = args.(i).mode;
auto re;
auto val;
if (ty.type_is_structural(ty.expr_ty(e))) {
re = trans_expr(bcx, e);
auto re = trans_expr(bcx, e);
val = re.val;
bcx = re.bcx;
if (mode == ast.val) {
// Until here we've been treating structures by pointer;
// we are now passing it as an arg, so need to load it.
re.val = re.bcx.build.Load(re.val);
val = bcx.build.Load(val);
}
} else if (mode == ast.alias) {
let lval_result lv;
@ -2252,42 +2251,42 @@ impure fn trans_args(@block_ctxt cx,
auto r = trans_expr(bcx, e);
lv = lval_val(r.bcx, r.val);
}
bcx = lv.res.bcx;
if (!lv.is_mem) {
if (lv.is_mem) {
val = lv.res.val;
} else {
// Non-mem but we're trying to alias; synthesize an
// alloca, spill to it and pass its address.
auto llty = val_ty(lv.res.val);
auto llptr = lv.res.bcx.build.Alloca(llty);
lv.res.bcx.build.Store(lv.res.val, llptr);
re = res(lv.res.bcx, llptr);
} else {
re = lv.res;
val = llptr;
}
} else {
re = trans_expr(bcx, e);
auto re = trans_expr(bcx, e);
val = re.val;
bcx = re.bcx;
}
if (ty.type_has_dynamic_size(args.(i).ty)) {
re.val = re.bcx.build.PointerCast(re.val,
T_typaram_ptr());
val = bcx.build.PointerCast(val, T_typaram_ptr());
}
vs += re.val;
bcx = re.bcx;
vs += val;
i += 1u;
}
ret tup(bcx, vs, llretslot_opt);
}
impure fn trans_bind_thunk(@crate_ctxt cx,
@ty.t incoming_fty,
@ty.t outgoing_fty,
vec[option.t[@ast.expr]] args,
TypeRef llclosure_ty,
vec[@ty.t] bound_tys) -> ValueRef {
fn trans_bind_thunk(@crate_ctxt cx,
@ty.t incoming_fty,
@ty.t outgoing_fty,
vec[option.t[@ast.expr]] args,
TypeRef llclosure_ty,
vec[@ty.t] bound_tys) -> ValueRef {
// Construct a thunk-call with signature incoming_fty, and that copies
// args forward into a call to outgoing_fty.
@ -2371,9 +2370,9 @@ impure fn trans_bind_thunk(@crate_ctxt cx,
ret llthunk;
}
impure fn trans_bind(@block_ctxt cx, @ast.expr f,
vec[option.t[@ast.expr]] args,
&ast.ann ann) -> result {
fn trans_bind(@block_ctxt cx, @ast.expr f,
vec[option.t[@ast.expr]] args,
&ast.ann ann) -> result {
auto f_res = trans_lval(cx, f);
if (f_res.is_mem) {
cx.fcx.ccx.sess.unimpl("re-binding existing function");
@ -2483,8 +2482,8 @@ impure fn trans_bind(@block_ctxt cx, @ast.expr f,
}
}
impure fn trans_call(@block_ctxt cx, @ast.expr f,
vec[@ast.expr] args, &ast.ann ann) -> result {
fn trans_call(@block_ctxt cx, @ast.expr f,
vec[@ast.expr] args, &ast.ann ann) -> result {
auto f_res = trans_lval(cx, f);
auto faddr = f_res.res.val;
auto llclosure = C_null(T_opaque_closure_ptr());
@ -2551,8 +2550,8 @@ impure fn trans_call(@block_ctxt cx, @ast.expr f,
ret res(bcx, retval);
}
impure fn trans_tup(@block_ctxt cx, vec[ast.elt] elts,
&ast.ann ann) -> result {
fn trans_tup(@block_ctxt cx, vec[ast.elt] elts,
&ast.ann ann) -> result {
auto t = node_ann_type(cx.fcx.ccx, ann);
auto llty = type_of(cx.fcx.ccx, t);
auto tup_val = cx.build.Alloca(llty);
@ -2569,8 +2568,8 @@ impure fn trans_tup(@block_ctxt cx, vec[ast.elt] elts,
ret res(r.bcx, tup_val);
}
impure fn trans_vec(@block_ctxt cx, vec[@ast.expr] args,
&ast.ann ann) -> result {
fn trans_vec(@block_ctxt cx, vec[@ast.expr] args,
&ast.ann ann) -> result {
auto t = node_ann_type(cx.fcx.ccx, ann);
auto unit_ty = t;
alt (t.struct) {
@ -2610,8 +2609,8 @@ impure fn trans_vec(@block_ctxt cx, vec[@ast.expr] args,
ret res(sub.bcx, vec_val);
}
impure fn trans_rec(@block_ctxt cx, vec[ast.field] fields,
&ast.ann ann) -> result {
fn trans_rec(@block_ctxt cx, vec[ast.field] fields,
&ast.ann ann) -> result {
auto t = node_ann_type(cx.fcx.ccx, ann);
auto llty = type_of(cx.fcx.ccx, t);
auto rec_val = cx.build.Alloca(llty);
@ -2631,7 +2630,7 @@ impure fn trans_rec(@block_ctxt cx, vec[ast.field] fields,
impure fn trans_expr(@block_ctxt cx, @ast.expr e) -> result {
fn trans_expr(@block_ctxt cx, @ast.expr e) -> result {
alt (e.node) {
case (ast.expr_lit(?lit, ?ann)) {
ret trans_lit(cx, *lit, ann);
@ -2745,7 +2744,7 @@ fn load_scalar_or_boxed(@block_ctxt cx,
}
}
impure fn trans_log(@block_ctxt cx, @ast.expr e) -> result {
fn trans_log(@block_ctxt cx, @ast.expr e) -> result {
auto sub = trans_expr(cx, e);
auto e_ty = ty.expr_ty(e);
@ -2765,7 +2764,7 @@ impure fn trans_log(@block_ctxt cx, @ast.expr e) -> result {
fail;
}
impure fn trans_check_expr(@block_ctxt cx, @ast.expr e) -> result {
fn trans_check_expr(@block_ctxt cx, @ast.expr e) -> result {
auto cond_res = trans_expr(cx, e);
// FIXME: need pretty-printer.
@ -2785,23 +2784,27 @@ impure fn trans_check_expr(@block_ctxt cx, @ast.expr e) -> result {
ret res(next_cx, C_nil());
}
impure fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result {
auto r = res(cx, C_nil());
fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result {
auto bcx = cx;
auto val = C_nil();
alt (e) {
case (some[@ast.expr](?x)) {
auto t = ty.expr_ty(x);
r = trans_expr(cx, x);
auto r = trans_expr(cx, x);
bcx = r.bcx;
val = r.val;
// A return is an implicit copy into a newborn anonymous
// 'return value' in the caller frame.
r.bcx = incr_all_refcnts(r.bcx, r.val, t).bcx;
bcx = incr_all_refcnts(bcx, val, t).bcx;
if (ty.type_is_structural(t)) {
// We usually treat structurals by-pointer; in particular,
// trans_expr will have given us a structure pointer. But in
// this case we're about to return. LLVM wants a first-class
// value here (which makes sense; the frame is going away!)
r.val = r.bcx.build.Load(r.val);
val = r.bcx.build.Load(val);
}
}
case (_) { /* fall through */ }
@ -2811,7 +2814,7 @@ impure fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result {
let bool more_cleanups = true;
auto cleanup_cx = cx;
while (more_cleanups) {
r.bcx = trans_block_cleanups(r.bcx, cleanup_cx);
bcx = trans_block_cleanups(bcx, cleanup_cx);
alt (cleanup_cx.parent) {
case (parent_some(?b)) {
cleanup_cx = b;
@ -2827,80 +2830,87 @@ impure fn trans_ret(@block_ctxt cx, &option.t[@ast.expr] e) -> result {
auto t = ty.expr_ty(ex);
if (ty.type_is_nil(t)) {
r.bcx.build.RetVoid();
r.val = C_nil();
ret r; // FIXME: early return needed due to typestate bug
bcx.build.RetVoid();
val = C_nil();
ret res(bcx, val); // FIXME: early return needed due to
// typestate bug
}
alt (cx.fcx.llretptr) {
case (some[ValueRef](?llptr)) {
// Generic return via tydesc + retptr.
r = copy_ty(r.bcx, true, llptr, r.val, t);
r.bcx.build.RetVoid();
bcx = copy_ty(bcx, true, llptr, val, t).bcx;
bcx.build.RetVoid();
}
case (none[ValueRef]) {
r.val = r.bcx.build.Ret(r.val);
val = bcx.build.Ret(val);
}
}
ret r;
ret res(bcx, val);
}
case (_) { /* fall through */ }
}
// FIXME: until LLVM has a unit type, we are moving around
// C_nil values rather than their void type.
r.bcx.build.RetVoid();
r.val = C_nil();
ret r;
bcx.build.RetVoid();
ret res(bcx, C_nil());
}
impure fn trans_stmt(@block_ctxt cx, &ast.stmt s) -> result {
auto sub = res(cx, C_nil());
fn init_local(@block_ctxt cx, @ast.local local) -> result {
// Make a note to drop this slot on the way out.
check (cx.fcx.lllocals.contains_key(local.id));
auto llptr = cx.fcx.lllocals.get(local.id);
auto ty = node_ann_type(cx.fcx.ccx, local.ann);
auto bcx = cx;
find_scope_cx(cx).cleanups +=
clean(bind drop_slot(_, llptr, ty));
alt (local.init) {
case (some[@ast.expr](?e)) {
auto sub = trans_expr(bcx, e);
bcx = copy_ty(sub.bcx, true, llptr, sub.val, ty).bcx;
}
case (_) {
if (middle.ty.type_has_dynamic_size(ty)) {
auto llsz = size_of(cx, ty);
bcx = call_bzero(cx, llptr, llsz).bcx;
} else {
auto llty = type_of(bcx.fcx.ccx, ty);
auto null = lib.llvm.llvm.LLVMConstNull(llty);
bcx.build.Store(null, llptr);
}
}
}
ret res(bcx, llptr);
}
fn trans_stmt(@block_ctxt cx, &ast.stmt s) -> result {
auto bcx = cx;
alt (s.node) {
case (ast.stmt_log(?a)) {
sub.bcx = trans_log(cx, a).bcx;
bcx = trans_log(cx, a).bcx;
}
case (ast.stmt_check_expr(?a)) {
sub.bcx = trans_check_expr(cx, a).bcx;
bcx = trans_check_expr(cx, a).bcx;
}
case (ast.stmt_ret(?e)) {
sub.bcx = trans_ret(cx, e).bcx;
bcx = trans_ret(cx, e).bcx;
}
case (ast.stmt_expr(?e)) {
sub.bcx = trans_expr(cx, e).bcx;
bcx = trans_expr(cx, e).bcx;
}
case (ast.stmt_decl(?d)) {
alt (d.node) {
case (ast.decl_local(?local)) {
// Make a note to drop this slot on the way out.
check (cx.fcx.lllocals.contains_key(local.id));
auto llptr = cx.fcx.lllocals.get(local.id);
auto ty = node_ann_type(cx.fcx.ccx, local.ann);
find_scope_cx(cx).cleanups +=
clean(bind drop_slot(_, llptr, ty));
alt (local.init) {
case (some[@ast.expr](?e)) {
sub = trans_expr(cx, e);
sub = copy_ty(sub.bcx, true, llptr, sub.val, ty);
}
case (_) {
if (middle.ty.type_has_dynamic_size(ty)) {
auto llsz = size_of(cx, ty);
sub = call_bzero(cx, llptr, llsz);
} else {
auto llty = type_of(cx.fcx.ccx, ty);
auto null = lib.llvm.llvm.LLVMConstNull(llty);
sub = res(cx, cx.build.Store(null, llptr));
}
}
}
bcx = init_local(bcx, local).bcx;
}
case (ast.decl_item(?i)) {
trans_item(cx.fcx.ccx, *i);
@ -2911,7 +2921,7 @@ impure fn trans_stmt(@block_ctxt cx, &ast.stmt s) -> result {
cx.fcx.ccx.sess.unimpl("stmt variant");
}
}
ret sub;
ret res(bcx, C_nil());
}
fn new_builder(BasicBlockRef llbb) -> builder {
@ -2990,19 +3000,24 @@ iter block_locals(&ast.block b) -> @ast.local {
}
}
impure fn trans_block(@block_ctxt cx, &ast.block b) -> result {
fn alloc_local(@block_ctxt cx, @ast.local local) -> result {
auto t = node_ann_type(cx.fcx.ccx, local.ann);
auto val = C_int(0);
if (ty.type_has_dynamic_size(t)) {
auto n = size_of(cx, t);
val = cx.build.ArrayAlloca(T_i8(), n);
} else {
val = cx.build.Alloca(type_of(cx.fcx.ccx, t));
}
cx.fcx.lllocals.insert(local.id, val);
ret res(cx, val);
}
fn trans_block(@block_ctxt cx, &ast.block b) -> result {
auto bcx = cx;
for each (@ast.local local in block_locals(b)) {
auto t = node_ann_type(cx.fcx.ccx, local.ann);
auto val = C_int(0);
if (ty.type_has_dynamic_size(t)) {
auto n = size_of(bcx, t);
val = bcx.build.ArrayAlloca(T_i8(), n);
} else {
val = bcx.build.Alloca(type_of(cx.fcx.ccx, t));
}
cx.fcx.lllocals.insert(local.id, val);
bcx = alloc_local(bcx, local).bcx;
}
auto r = res(bcx, C_nil());
@ -3102,10 +3117,10 @@ fn create_llargs_for_fn_args(&@fn_ctxt cx,
// allocas immediately upon entry; this permits us to GEP into structures we
// were passed and whatnot. Apparently mem2reg will mop up.
impure fn copy_args_to_allocas(@block_ctxt cx,
option.t[TypeRef] ty_self,
vec[ast.arg] args,
vec[ty.arg] arg_tys) {
fn copy_args_to_allocas(@block_ctxt cx,
option.t[TypeRef] ty_self,
vec[ast.arg] args,
vec[ty.arg] arg_tys) {
let uint arg_n = 0u;
@ -3203,9 +3218,9 @@ fn create_llobjfields_for_fields(@block_ctxt cx, ValueRef llself) {
}
}
impure fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid,
option.t[TypeRef] ty_self,
&vec[ast.ty_param] ty_params, &ast.ann ann) {
fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid,
option.t[TypeRef] ty_self,
&vec[ast.ty_param] ty_params, &ast.ann ann) {
auto llfndecl = cx.item_ids.get(fid);
cx.item_names.insert(cx.path, llfndecl);
@ -3234,9 +3249,9 @@ impure fn trans_fn(@crate_ctxt cx, &ast._fn f, ast.def_id fid,
}
}
impure fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty,
&ast._obj ob,
&vec[ast.ty_param] ty_params) -> ValueRef {
fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty,
&ast._obj ob,
&vec[ast.ty_param] ty_params) -> ValueRef {
let vec[ValueRef] methods = vec();
fn meth_lteq(&@ast.method a, &@ast.method b) -> bool {
@ -3279,8 +3294,8 @@ impure fn trans_vtbl(@crate_ctxt cx, TypeRef self_ty,
ret gvar;
}
impure fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid,
&vec[ast.ty_param] ty_params, &ast.ann ann) {
fn trans_obj(@crate_ctxt cx, &ast._obj ob, ast.def_id oid,
&vec[ast.ty_param] ty_params, &ast.ann ann) {
auto llctor_decl = cx.item_ids.get(oid);
cx.item_names.insert(cx.path, llctor_decl);
@ -3442,7 +3457,7 @@ fn trans_tag_variant(@crate_ctxt cx, ast.def_id tag_id,
bcx.build.Ret(lltagval);
}
impure fn trans_item(@crate_ctxt cx, &ast.item item) {
fn trans_item(@crate_ctxt cx, &ast.item item) {
alt (item.node) {
case (ast.item_fn(?name, ?f, ?tps, ?fid, ?ann)) {
auto sub_cx = @rec(path=cx.path + "." + name with *cx);
@ -3469,7 +3484,7 @@ impure fn trans_item(@crate_ctxt cx, &ast.item item) {
}
}
impure fn trans_mod(@crate_ctxt cx, &ast._mod m) {
fn trans_mod(@crate_ctxt cx, &ast._mod m) {
for (@ast.item item in m.items) {
trans_item(cx, *item);
}

View File

@ -34,6 +34,8 @@ mod util {
auth driver.rustc.main = impure;
auth middle.trans = unsafe;
auth middle.trans.copy_args_to_allocas = impure;
auth middle.trans.trans_block = impure;
auth lib.llvm = unsafe;