From 8640e67e3ff97f64ab5afdf6c788d335e491696e Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Sat, 17 Sep 2011 10:18:30 -0700 Subject: [PATCH] Add a precondition to GEP_tup_like --- src/comp/middle/trans.rs | 53 +++++++++++++++++++++++++++++--- src/comp/middle/trans_alt.rs | 8 +++++ src/comp/middle/trans_objects.rs | 16 ++++++++++ 3 files changed, 73 insertions(+), 4 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 61040ba44a8..887c8e6a230 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -610,6 +610,8 @@ fn dynamic_size_of(cx: @block_ctxt, t: ty::t) -> result { } fn dynamic_align_of(cx: @block_ctxt, t: ty::t) -> result { +// FIXME: Typestate constraint that shows this alt is +// exhaustive alt ty::struct(bcx_tcx(cx), t) { ty::ty_param(p, _) { let aptr = field_of_tydesc(cx, t, false, abi::tydesc_field_align); @@ -668,9 +670,8 @@ fn bump_ptr(bcx: @block_ctxt, t: ty::t, base: ValueRef, sz: ValueRef) -> // ty::struct and knows what to do when it runs into a ty_param stuck in the // middle of the thing it's GEP'ing into. Much like size_of and align_of, // above. -fn GEP_tup_like(cx: @block_ctxt, t: ty::t, base: ValueRef, ixs: [int]) -> - result { - assert (ty::type_is_tup_like(bcx_tcx(cx), t)); +fn GEP_tup_like(cx: @block_ctxt, t: ty::t, base: ValueRef, ixs: [int]) + : type_is_tup_like(cx, t) -> result { // It might be a static-known type. Handle this. if !ty::type_has_dynamic_size(bcx_tcx(cx), t) { ret rslt(cx, GEPi(cx, base, ixs)); @@ -785,6 +786,8 @@ fn GEP_tag(cx: @block_ctxt, llblobptr: ValueRef, tag_id: ast::def_id, } else { llunionptr = llblobptr; } // Do the GEP_tup_like(). + // Silly check -- postcondition on mk_tup? + check type_is_tup_like(cx, tup_ty); let rs = GEP_tup_like(cx, tup_ty, llunionptr, [0, ix as int]); // Cast the result to the appropriate type, if necessary. @@ -1403,12 +1406,15 @@ fn trans_res_drop(cx: @block_ctxt, rs: ValueRef, did: ast::def_id, let drop_cx = new_sub_block_ctxt(cx, "drop res"); let next_cx = new_sub_block_ctxt(cx, "next"); + // Silly check + check type_is_tup_like(cx, tup_ty); let drop_flag = GEP_tup_like(cx, tup_ty, rs, [0, 0]); cx = drop_flag.bcx; let null_test = IsNull(cx, Load(cx, drop_flag.val)); CondBr(cx, null_test, next_cx.llbb, drop_cx.llbb); cx = drop_cx; + check type_is_tup_like(cx, tup_ty); let val = GEP_tup_like(cx, tup_ty, rs, [0, 1]); cx = val.bcx; // Find and call the actual destructor. @@ -1641,10 +1647,15 @@ fn iter_structural_ty(cx: @block_ctxt, av: ValueRef, t: ty::t, ret cx; } + /* + Typestate constraint that shows the unimpl case doesn't happen? + */ alt ty::struct(bcx_tcx(cx), t) { ty::ty_rec(fields) { let i: int = 0; for fld: ty::field in fields { + // Silly check + check type_is_tup_like(cx, t); let {bcx: bcx, val: llfld_a} = GEP_tup_like(cx, t, av, [0, i]); cx = f(bcx, llfld_a, fld.mt.ty); i += 1; @@ -1653,6 +1664,8 @@ fn iter_structural_ty(cx: @block_ctxt, av: ValueRef, t: ty::t, ty::ty_tup(args) { let i = 0; for arg in args { + // Silly check + check type_is_tup_like(cx, t); let {bcx: bcx, val: llfld_a} = GEP_tup_like(cx, t, av, [0, i]); cx = f(bcx, llfld_a, arg); i += 1; @@ -1663,6 +1676,8 @@ fn iter_structural_ty(cx: @block_ctxt, av: ValueRef, t: ty::t, let inner1 = ty::substitute_type_params(tcx, tps, inner); let inner_t_s = ty::substitute_type_params(tcx, tps, inner); let tup_t = ty::mk_tup(tcx, [ty::mk_int(tcx), inner_t_s]); + // Silly check + check type_is_tup_like(cx, tup_t); let {bcx: bcx, val: llfld_a} = GEP_tup_like(cx, tup_t, av, [0, 1]); ret f(bcx, llfld_a, inner1); } @@ -2543,11 +2558,15 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef], // Copy expr values into boxed bindings. let i = 0u; + // Silly check + check type_is_tup_like(bcx, closure_ty); let bindings = GEP_tup_like(bcx, closure_ty, closure, [0, abi::closure_elt_bindings]); bcx = bindings.bcx; for lv: lval_result in bound_vals { + // Also a silly check + check type_is_tup_like(bcx, bindings_ty); let bound = GEP_tup_like(bcx, bindings_ty, bindings.val, [0, i as int]); bcx = bound.bcx; @@ -2559,6 +2578,8 @@ fn build_environment(bcx: @block_ctxt, lltydescs: [ValueRef], // If necessary, copy tydescs describing type parameters into the // appropriate slot in the closure. + // Silly check as well + check type_is_tup_like(bcx, closure_ty); let ty_params_slot = GEP_tup_like(bcx, closure_ty, closure, [0, abi::closure_elt_ty_params]); @@ -2663,6 +2684,8 @@ fn load_environment(enclosing_cx: @block_ctxt, fcx: @fn_ctxt, envty: ty::t, // If this is an aliasing closure/for-each body, we need to load // the iterbody. if !copying && !option::is_none(enclosing_cx.fcx.lliterbody) { + // Silly check + check type_is_tup_like(bcx, ty); let iterbodyptr = GEP_tup_like(bcx, ty, llclosure, path + [0]); fcx.lliterbody = some(Load(bcx, iterbodyptr.val)); bcx = iterbodyptr.bcx; @@ -2671,6 +2694,8 @@ fn load_environment(enclosing_cx: @block_ctxt, fcx: @fn_ctxt, envty: ty::t, // Load the actual upvars. for upvar_def in *upvars { + // Silly check + check type_is_tup_like(bcx, ty); let upvarptr = GEP_tup_like(bcx, ty, llclosure, path + [i as int]); bcx = upvarptr.bcx; let llupvarptr = upvarptr.val; @@ -2984,7 +3009,10 @@ fn trans_field_inner(cx: @block_ctxt, sp: span, v: ValueRef, t0: ty::t, alt ty::struct(bcx_tcx(cx), t) { ty::ty_rec(fields) { let ix: uint = ty::field_idx(bcx_ccx(cx).sess, sp, field, fields); - let v = GEP_tup_like(r.bcx, t, r.val, [0, ix as int]); + let r_bcx = r.bcx; + // Silly check + check type_is_tup_like(r_bcx, t); + let v = GEP_tup_like(r_bcx, t, r.val, [0, ix as int]); ret lval_no_env(v.bcx, v.val, true); } ty::ty_obj(methods) { @@ -3329,6 +3357,8 @@ fn trans_bind_thunk(cx: @local_ctxt, sp: span, incoming_fty: ty::t, (fptr, C_null(T_opaque_closure_ptr(*bcx_ccx(bcx))), 0) } none. { + // Silly check + check type_is_tup_like(bcx, closure_ty); let {bcx: cx, val: pair} = GEP_tup_like(bcx, closure_ty, llclosure, [0, abi::box_rc_field_body, @@ -3368,6 +3398,8 @@ fn trans_bind_thunk(cx: @local_ctxt, sp: span, incoming_fty: ty::t, // Copy in the type parameters. let i: uint = 0u; while i < ty_param_count { + // Silly check + check type_is_tup_like(copy_args_bcx, closure_ty); let lltyparam_ptr = GEP_tup_like(copy_args_bcx, closure_ty, llclosure, [0, abi::box_rc_field_body, @@ -3391,6 +3423,8 @@ fn trans_bind_thunk(cx: @local_ctxt, sp: span, incoming_fty: ty::t, // Arg provided at binding time; thunk copies it from // closure. some(e) { + // Silly check + check type_is_tup_like(bcx, closure_ty); let bound_arg = GEP_tup_like(bcx, closure_ty, llclosure, [0, abi::box_rc_field_body, @@ -3914,6 +3948,8 @@ fn trans_tup(cx: @block_ctxt, elts: [@ast::expr], id: ast::node_id) -> let e_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, e); let src = trans_lval(bcx, e); bcx = src.bcx; + // FIXME: constraint on argument? + check type_is_tup_like(bcx, t); let dst_res = GEP_tup_like(bcx, t, tup_val, [0, i]); bcx = move_val_if_temp(dst_res.bcx, INIT, dst_res.val, src, e_ty); i += 1; @@ -3943,6 +3979,8 @@ fn trans_rec(cx: @block_ctxt, fields: [ast::field], alt ty::struct(bcx_tcx(cx), t) { ty::ty_rec(flds) { ty_fields = flds; } } for tf: ty::field in ty_fields { let e_ty = tf.mt.ty; + // FIXME: constraint on argument? + check type_is_tup_like(bcx, t); let dst_res = GEP_tup_like(bcx, t, rec_val, [0, i]); bcx = dst_res.bcx; let expr_provided = false; @@ -3956,6 +3994,8 @@ fn trans_rec(cx: @block_ctxt, fields: [ast::field], } } if !expr_provided { + // FIXME: constraint on argument? + check type_is_tup_like(bcx, t); let src_res = GEP_tup_like(bcx, t, base_val, [0, i]); src_res = rslt(src_res.bcx, load_if_immediate(bcx, src_res.val, e_ty)); @@ -5100,6 +5140,8 @@ fn populate_fn_ctxt_from_llself(fcx: @fn_ctxt, llself: val_self_pair) { } i = 0; for f: ast::obj_field in fcx.lcx.obj_fields { + // FIXME: silly check + check type_is_tup_like(bcx, fields_tup_ty); let rslt = GEP_tup_like(bcx, fields_tup_ty, obj_fields, [0, i]); bcx = llstaticallocas_block_ctxt(fcx); let llfield = rslt.val; @@ -5248,9 +5290,12 @@ fn trans_res_ctor(cx: @local_ctxt, sp: span, dtor: ast::_fn, llretptr = BitCast(bcx, llretptr, llret_t); } + // FIXME: silly checks + check type_is_tup_like(bcx, tup_t); let dst = GEP_tup_like(bcx, tup_t, llretptr, [0, 1]); bcx = dst.bcx; bcx = copy_val(bcx, INIT, dst.val, arg, arg_t); + check type_is_tup_like(bcx, tup_t); let flag = GEP_tup_like(bcx, tup_t, llretptr, [0, 0]); bcx = flag.bcx; Store(bcx, C_int(1), flag.val); diff --git a/src/comp/middle/trans_alt.rs b/src/comp/middle/trans_alt.rs index 066f969ba60..eea4704c3d0 100644 --- a/src/comp/middle/trans_alt.rs +++ b/src/comp/middle/trans_alt.rs @@ -342,6 +342,8 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail, for field_name: ast::ident in rec_fields { let ix: uint = ty::field_idx(ccx.sess, dummy_sp(), field_name, fields); + // not sure how to get rid of this check + check type_is_tup_like(bcx, rec_ty); let r = trans::GEP_tup_like(bcx, rec_ty, val, [0, ix as int]); rec_vals += [r.val]; bcx = r.bcx; @@ -359,6 +361,8 @@ fn compile_submatch(bcx: @block_ctxt, m: match, vals: [ValueRef], f: mk_fail, }; let tup_vals = [], i = 0u; while i < n_tup_elts { + // how to get rid of this check? + check type_is_tup_like(bcx, tup_ty); let r = trans::GEP_tup_like(bcx, tup_ty, val, [0, i as int]); tup_vals += [r.val]; bcx = r.bcx; @@ -603,6 +607,8 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef, for f: ast::field_pat in fields { let ix: uint = ty::field_idx(ccx.sess, pat.span, f.ident, rec_fields); + // how to get rid of this check? + check type_is_tup_like(bcx, rec_ty); let r = trans::GEP_tup_like(bcx, rec_ty, val, [0, ix as int]); bcx = bind_irrefutable_pat(r.bcx, f.pat, r.val, table, make_copy); } @@ -611,6 +617,8 @@ fn bind_irrefutable_pat(bcx: @block_ctxt, pat: @ast::pat, val: ValueRef, let tup_ty = ty::node_id_to_monotype(ccx.tcx, pat.id); let i = 0u; for elem in elems { + // how to get rid of this check? + check type_is_tup_like(bcx, tup_ty); let r = trans::GEP_tup_like(bcx, tup_ty, val, [0, i as int]); bcx = bind_irrefutable_pat(r.bcx, elem, r.val, table, make_copy); i += 1u; diff --git a/src/comp/middle/trans_objects.rs b/src/comp/middle/trans_objects.rs index 1b36cbdee74..99eacedaf3b 100644 --- a/src/comp/middle/trans_objects.rs +++ b/src/comp/middle/trans_objects.rs @@ -121,11 +121,14 @@ fn trans_obj(cx: @local_ctxt, sp: span, ob: ast::_obj, ctor_id: ast::node_id, // the types of the object's fields, so that the fields can be freed // later. + // postcondition on create_object_body_type? + check type_is_tup_like(bcx, body_ty); let body_tydesc = GEP_tup_like(bcx, body_ty, body, [0, abi::obj_body_elt_tydesc]); bcx = body_tydesc.bcx; let ti = none; + check type_is_tup_like(bcx, body_ty); let r = GEP_tup_like(bcx, body_ty, body, [0, abi::obj_body_elt_typarams]); bcx = r.bcx; @@ -151,6 +154,8 @@ fn trans_obj(cx: @local_ctxt, sp: span, ob: ast::_obj, ctor_id: ast::node_id, let i: int = 0; for tp: ast::ty_param in ty_params { let typaram = bcx.fcx.lltydescs[i]; + // Silly check + check type_is_tup_like(bcx, typarams_ty); let capture = GEP_tup_like(bcx, typarams_ty, body_typarams, [0, i]); bcx = capture.bcx; @@ -159,6 +164,8 @@ fn trans_obj(cx: @local_ctxt, sp: span, ob: ast::_obj, ctor_id: ast::node_id, } // Copy args into body fields. + // how to get rid of this check? + check type_is_tup_like(bcx, body_ty); let body_fields = GEP_tup_like(bcx, body_ty, body, [0, abi::obj_body_elt_fields]); bcx = body_fields.bcx; @@ -169,6 +176,8 @@ fn trans_obj(cx: @local_ctxt, sp: span, ob: ast::_obj, ctor_id: ast::node_id, let arg = load_if_immediate(bcx, arg1, arg_tys[i].ty); // TODO: can we just get fields_ty out of body_ty instead? let fields_ty: ty::t = ty::mk_tup(ccx.tcx, obj_fields); + // Silly check + check type_is_tup_like(bcx, fields_ty); let field = GEP_tup_like(bcx, fields_ty, body_fields.val, [0, i]); bcx = field.bcx; @@ -314,6 +323,8 @@ fn trans_anon_obj(bcx: @block_ctxt, sp: span, anon_obj: ast::anon_obj, // the user of the object. So the tydesc is needed to keep track of // the types of the object's fields, so that the fields can be freed // later. + // postcondition on create_object_body_type? + check type_is_tup_like(bcx, body_ty); let body_tydesc = GEP_tup_like(bcx, body_ty, body, [0, abi::obj_body_elt_tydesc]); bcx = body_tydesc.bcx; @@ -328,6 +339,7 @@ fn trans_anon_obj(bcx: @block_ctxt, sp: span, anon_obj: ast::anon_obj, // body. (This is something like saving the lexical environment of a // function in its closure: the fields were passed to the object // constructor and are now available to the object's methods. + check type_is_tup_like(bcx, body_ty); let body_fields = GEP_tup_like(bcx, body_ty, body, [0, abi::obj_body_elt_fields]); bcx = body_fields.bcx; @@ -338,6 +350,8 @@ fn trans_anon_obj(bcx: @block_ctxt, sp: span, anon_obj: ast::anon_obj, load_if_immediate(bcx, additional_field_vals[i].val, additional_field_tys[i]); let fields_ty: ty::t = ty::mk_tup(ccx.tcx, additional_field_tys); + // Silly check + check type_is_tup_like(bcx, fields_ty); let field = GEP_tup_like(bcx, fields_ty, body_fields.val, [0, i]); bcx = field.bcx; bcx = @@ -356,6 +370,7 @@ fn trans_anon_obj(bcx: @block_ctxt, sp: span, anon_obj: ast::anon_obj, // value) wrapped in a result. let inner_obj_val: result = trans_expr(bcx, e); + check type_is_tup_like(bcx, body_ty); let body_inner_obj = GEP_tup_like(bcx, body_ty, body, [0, abi::obj_body_elt_inner_obj]); @@ -776,6 +791,7 @@ fn process_fwding_mthd(cx: @local_ctxt, sp: span, m: @ty::method, T_ptr(type_of(cx_ccx, sp, body_ty))); // Now, reach into the body and grab the inner_obj. + check type_is_tup_like(bcx, body_ty); let llinner_obj = GEP_tup_like(bcx, body_ty, llself_obj_body, [0, abi::obj_body_elt_inner_obj]);