diff options
| author | Kevin Atkinson <kevina@cs.utah.edu> | 2012-01-10 14:50:40 -0700 |
|---|---|---|
| committer | Graydon Hoare <graydon@mozilla.com> | 2012-01-10 15:59:57 -0800 |
| commit | 08abf8d37fa549ebc67f80d80530f4aa43d716e4 (patch) | |
| tree | f6c9bce62c494a37d989d07be4661f57c0c7eba3 /src/comp/middle | |
| parent | d0fe6723fc2f431205092bda9ec399d932081bd0 (diff) | |
| download | rust-08abf8d37fa549ebc67f80d80530f4aa43d716e4.tar.gz rust-08abf8d37fa549ebc67f80d80530f4aa43d716e4.zip | |
Support explicit discriminant numbers on tag variants.
Addresses issue #1393. For now disallow disr. values unless all variants use nullary contractors (i.e. "enum-like"). Disr. values are now encoded in the crate metadata, but only when it will differ from the inferred value based on the order.
Diffstat (limited to 'src/comp/middle')
| -rw-r--r-- | src/comp/middle/trans.rs | 28 | ||||
| -rw-r--r-- | src/comp/middle/trans_alt.rs | 8 | ||||
| -rw-r--r-- | src/comp/middle/ty.rs | 7 |
3 files changed, 18 insertions, 25 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 6534c7d9b62..998c944b6e0 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1726,17 +1726,15 @@ fn iter_structural_ty(cx: @block_ctxt, av: ValueRef, t: ty::t, Unreachable(unr_cx); let llswitch = Switch(cx, lldiscrim_a, unr_cx.llbb, n_variants); let next_cx = new_sub_block_ctxt(cx, "tag-iter-next"); - let i = 0u; for variant: ty::variant_info in *variants { let variant_cx = new_sub_block_ctxt(cx, "tag-iter-variant-" + - uint::to_str(i, 10u)); - AddCase(llswitch, C_int(ccx, i as int), variant_cx.llbb); + int::to_str(variant.disr_val, 10u)); + AddCase(llswitch, C_int(ccx, variant.disr_val), variant_cx.llbb); variant_cx = iter_variant(variant_cx, llunion_a_ptr, variant, tps, tid, f); Br(variant_cx, next_cx.llbb); - i += 1u; } ret next_cx; } @@ -2745,12 +2743,9 @@ fn trans_var(cx: @block_ctxt, sp: span, def: ast::def, id: ast::node_id) let bcx = alloc_result.bcx; let lltagptr = PointerCast(bcx, lltagblob, T_ptr(lltagty)); let lldiscrimptr = GEPi(bcx, lltagptr, [0, 0]); - let d = if vec::len(*ty::tag_variants(ccx.tcx, tid)) != 1u { - let lldiscrim_gv = lookup_discriminant(bcx.fcx.lcx, vid); - let lldiscrim = Load(bcx, lldiscrim_gv); - lldiscrim - } else { C_int(ccx, 0) }; - Store(bcx, d, lldiscrimptr); + let lldiscrim_gv = lookup_discriminant(bcx.fcx.lcx, vid); + let lldiscrim = Load(bcx, lldiscrim_gv); + Store(bcx, lldiscrim, lldiscrimptr); ret lval_no_env(bcx, lltagptr, temporary); } } @@ -4685,7 +4680,7 @@ fn trans_res_ctor(cx: @local_ctxt, sp: span, dtor: ast::fn_decl, fn trans_tag_variant(cx: @local_ctxt, tag_id: ast::node_id, - variant: ast::variant, index: int, is_degen: bool, + variant: ast::variant, is_degen: bool, ty_params: [ast::ty_param]) { let ccx = cx.ccx; @@ -4735,7 +4730,7 @@ fn trans_tag_variant(cx: @local_ctxt, tag_id: ast::node_id, let lltagptr = PointerCast(bcx, fcx.llretptr, T_opaque_tag_ptr(ccx)); let lldiscrimptr = GEPi(bcx, lltagptr, [0, 0]); - Store(bcx, C_int(ccx, index), lldiscrimptr); + Store(bcx, C_int(ccx, variant.node.disr_val), lldiscrimptr); GEPi(bcx, lltagptr, [0, 1]) }; i = 0u; @@ -5086,10 +5081,8 @@ fn trans_item(cx: @local_ctxt, item: ast::item) { ast::item_tag(variants, tps) { let sub_cx = extend_path(cx, item.ident); let degen = vec::len(variants) == 1u; - let i = 0; for variant: ast::variant in variants { - trans_tag_variant(sub_cx, item.id, variant, i, degen, tps); - i += 1; + trans_tag_variant(sub_cx, item.id, variant, degen, tps); } } ast::item_const(_, expr) { trans_const(cx.ccx, expr, item.id); } @@ -5421,19 +5414,18 @@ fn trans_constant(ccx: @crate_ctxt, it: @ast::item, &&pt: [str], visit::visit_item(it, new_pt, v); alt it.node { ast::item_tag(variants, _) { - let i = 0u; for variant in variants { let p = new_pt + [variant.node.name, "discrim"]; let s = mangle_exported_name(ccx, p, ty::mk_int(ccx.tcx)); + let disr_val = variant.node.disr_val; let discrim_gvar = str::as_buf(s, {|buf| llvm::LLVMAddGlobal(ccx.llmod, ccx.int_type, buf) }); - llvm::LLVMSetInitializer(discrim_gvar, C_int(ccx, i as int)); + llvm::LLVMSetInitializer(discrim_gvar, C_int(ccx, disr_val)); llvm::LLVMSetGlobalConstant(discrim_gvar, True); ccx.discrims.insert( ast_util::local_def(variant.node.id), discrim_gvar); ccx.discrim_symbols.insert(variant.node.id, s); - i += 1u; } } ast::item_impl(tps, some(@{node: ast::ty_path(_, id), _}), _, ms) { diff --git a/src/comp/middle/trans_alt.rs b/src/comp/middle/trans_alt.rs index 6e00521ef3b..a7eb94b9288 100644 --- a/src/comp/middle/trans_alt.rs +++ b/src/comp/middle/trans_alt.rs @@ -16,7 +16,7 @@ import trans_common::*; // An option identifying a branch (either a literal, a tag variant or a range) tag opt { lit(@ast::expr); - var(/* variant id */uint, /* variant dids */{tg: def_id, var: def_id}); + var(/* disr val */int, /* variant dids */{tg: def_id, var: def_id}); range(@ast::expr, @ast::expr); } fn opt_eq(a: opt, b: opt) -> bool { @@ -53,7 +53,7 @@ fn trans_opt(bcx: @block_ctxt, o: opt) -> opt_result { } } } - var(id, _) { ret single_result(rslt(bcx, C_int(ccx, id as int))); } + var(disr_val, _) { ret single_result(rslt(bcx, C_int(ccx, disr_val))); } range(l1, l2) { ret range_result(rslt(bcx, trans::trans_const_expr(ccx, l1)), rslt(bcx, trans::trans_const_expr(ccx, l2))); @@ -64,10 +64,8 @@ fn trans_opt(bcx: @block_ctxt, o: opt) -> opt_result { fn variant_opt(ccx: @crate_ctxt, pat_id: ast::node_id) -> opt { let vdef = ast_util::variant_def_ids(ccx.tcx.def_map.get(pat_id)); let variants = ty::tag_variants(ccx.tcx, vdef.tg); - let i = 0u; for v: ty::variant_info in *variants { - if vdef.var == v.id { ret var(i, vdef); } - i += 1u; + if vdef.var == v.id { ret var(v.disr_val, vdef); } } fail; } diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 76a9b4c69c7..dbd688de402 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -2686,7 +2686,8 @@ fn impl_iface(cx: ctxt, id: ast::def_id) -> option::t<t> { } // Tag information -type variant_info = @{args: [ty::t], ctor_ty: ty::t, id: ast::def_id}; +type variant_info = @{args: [ty::t], ctor_ty: ty::t, id: ast::def_id, + disr_val: int}; fn tag_variants(cx: ctxt, id: ast::def_id) -> @[variant_info] { alt cx.tag_var_cache.find(id) { @@ -2705,7 +2706,9 @@ fn tag_variants(cx: ctxt, id: ast::def_id) -> @[variant_info] { } else { [] }; @{args: arg_tys, ctor_ty: ctor_ty, - id: ast_util::local_def(variant.node.id)} + id: ast_util::local_def(variant.node.id), + disr_val: variant.node.disr_val + } }) } } |
